寄存器注入

注入优势
不需要远程创建线程API

API介绍

1挂起线程SuspendThread
2获取对方线程信息

BOOL GetThreadContext( 
    HANDLE hThread,           //线程句柄
    LPCONTEXT lpContext );    //传入传出参数:设备上下文
    
//注意:Context获取的寄存器信息需根据 Context.ContextFlags来决定
//如果ContextFlags为 CONTEXT_INTEGER:拿到的是普通寄存器 eax ebx ecx edx esi edi
//如果ContextFlags为 CONTEXT_CONTROL:拿到的是特殊寄存器 ebp eip eflags esp SegSs SegCs 

3设置线程寄存器信息SetThreadContext,注意点:如果获取的不是主线程的话会出现有时能注入有时不能注入
4恢复线程ResumeThread

代码示例

.386
.model flat, stdcall  ;32 bit memory model
option casemap :none  ;case sensitive

include inject.inc

.code
inject_code:
  pushad		;运行注入代码前请保存寄存器环境
  pushfd
  push 00646c72h
  push 6f57206fh
  push 6c6c6568h
  mov  ebx, esp
  push 00000065h
  push 6c746954h
  mov ecx, esp
  push MB_OK
  push ecx
  push ebx
  push NULL
LABEL1:
  mov  eax, 12345678h
  call eax
  add esp,20
  popfd		;运行完注入的代码之后还原寄存器环境,然后跳转回原来的位置继续执行代码
  popad
REL:		;跳转回原来的位置继续执行
  mov eax, 12345678h  ;注意寄存器eax的破坏,最好不要用寄存器,可以直接写二进制代码,这样的话就用不上寄存器,也就不会破坏寄存器,因为用jmp 内存还是立即数跳转的是偏移,只有jmp 寄存器才会是当直接的地址跳转,所以我为了方便就写寄存器了,这样有可能会崩溃,因为你修改了寄存器,不知道会发送什么事情
  jmp eax
  ret
;



start:

	invoke GetModuleHandle,NULL
	mov		hInstance,eax

  invoke InitCommonControls
	invoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,addr DlgProc,NULL
	invoke ExitProcess,0

;########################################################################

DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
  LOCAL @dwTid:dword
  LOCAL @dwPID:dword
  LOCAL @dwOld:dword
  LOCAL @dwWriteBytes:dword
  LOCAL @hThread:HANDLE
  LOCAL @hProcess:HANDLE
  LOCAL @context:CONTEXT
  LOCAL @pBuffer:dword
  LOCAL @hWnd:HWND
  LOCAL @hSnapshot:HANDLE
  LOCAL @te:THREADENTRY32
  LOCAL @mymd:MODULEENTRY32
  LOCAL @pfnMsgBox:DWORD
  LOCAL @hUser32:DWORD 

	mov		eax,uMsg
	.if eax==WM_INITDIALOG

	.elseif eax==WM_COMMAND
	  mov eax,wParam
	  .if ax == BTN_INJECT
	  
	    ;拿到窗口句柄
      invoke FindWindow, offset g_ClassName, NULL
      .if eax == NULL
        ret
      .endif
      mov @hWnd, eax
      
      ;2.获取进程pid
      invoke GetWindowThreadProcessId, @hWnd, addr @dwPID
      mov @dwTid,eax	;这个api返回值就是创建窗口的线程ID也就是主线程ID
  
      ;3.打开进程
      invoke OpenProcess,PROCESS_ALL_ACCESS, FALSE, @dwPID
      .if eax == NULL
        ret
      .endif
      mov @hProcess, eax
      
      ;遍历模块列表拿到calc的模块基址
      ;创建进程快照 
      invoke CreateToolhelp32Snapshot,TH32CS_SNAPMODULE,@dwPID
      .if eax == INVALID_HANDLE_VALUE
        jmp SAFE_EXIT
      .endif
      
      mov @hSnapshot,eax                              ;保存进程快照
      mov @mymd.dwSize,sizeof @mymd


      ;拿到首个信息结构体  
      invoke  Module32First,@hSnapshot,addr @mymd
      .while 1
        .if eax != 1                                   ;判断是否拿到模块
          jmp SAFE_EXIT
        .endif
      
        invoke StrCmpCA,offset g_User32,addr @mymd.szModule
        .if eax == 0
          push @mymd.modBaseAddr                       ;将模块基址存入栈内
          .break
        .endif
        invoke Module32Next,@hSnapshot,addr @mymd      ;查找下一个模块
        
      .endw
      
      ;修改内存保护属性
      invoke VirtualProtect,offset inject_code, 1000h, PAGE_EXECUTE_READWRITE, addr @dwOld
      
      ;API地址重定位
      invoke GetModuleHandle, offset g_User32
      mov @hUser32, eax
      invoke GetProcAddress,@hUser32, offset g_MessageBox
      mov @pfnMsgBox, eax
      mov esi, @hUser32
      sub eax, esi  ;offset
      pop esi                                         ;获取进程模块的基址
      add eax, esi  ;+base                            ;遍历模块列表
      mov ebx, offset LABEL1
      mov dword ptr [ebx+1], eax
      
      
      ;4.打开线程
      invoke OpenThread,THREAD_ALL_ACCESS, FALSE, @dwTid
      .if eax == NULL
        ret
      .endif
      mov @hThread, eax
      
      ;5.挂起线程
      invoke SuspendThread, eax    
      
      mov @context.ContextFlags,CONTEXT_CONTROL
      ;6.保存eip
      invoke GetThreadContext, @hThread, addr @context
      
      ;7.申请内存
      invoke VirtualAllocEx,@hProcess, NULL, 1000h, MEM_COMMIT, PAGE_EXECUTE_READWRITE
      mov @pBuffer, eax
      
      ;9.重定位
      mov eax,offset REL
      mov ebx,@context.regEip
      mov [eax+1],ebx		;重定位之后,运行完注入代码就会跳转到原来的位置继续执行代码,不影响原来的程序运行
      
      ;10.写入代码
      invoke WriteProcessMemory,@hProcess, @pBuffer, inject_code, start-inject_code, addr @dwWriteBytes

      ;11.修改eip为申请的缓冲区地址
      mov eax, @pBuffer
      mov @context.regEip, eax
      invoke SetThreadContext, @hThread, addr @context
      
      ;12.恢复线程
      invoke ResumeThread, @hThread
      
      
SAFE_EXIT:
      .if @hThread != NULL
        invoke CloseHandle, @hThread
      .endif
  
      .if @hSnapshot != NULL
        invoke CloseHandle, @hSnapshot
      .endif
      
      .if @hProcess != NULL
        invoke CloseHandle,@hProcess
      .endif
      
    .endif
	.elseif eax==WM_CLOSE
		invoke EndDialog,hWin,0
	.else
	mov		eax,FALSE
	ret
	.endif
	mov		eax,TRUE
	ret

DlgProc endp

end start

利用寄存器注入实现代码加密设计思路

编译后加密
流程:
1初始化函数或者在全局区,反正就是在代码入口前设置好筛选机异常,在筛选机异常回调里,将eip改成代码的位置
2记得第一行留个位置用来编译后好修改成int3的,随便写个mov eax,12h,自己记住多大,然后在处理异常函数里面跳过这个字节执行
3编译好文件
4打开二进制文件将代码段第一条预留的指令改成 int3指令,这样你即使nop调的话,其他的指令就会变成花指令,执行肯定错误
优势:
由于调试器会自动在入口下断点,这样没办法单步,所以实现了反调试

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值