远线程注入代码时,应该注意些细节

 

//

//编辑时间:2011-8-22

//整理人:紫色溟渊

//说明:仅供学习技术交流,欢迎转载,转载请注明出处。

//编辑目的:

//     1.加深自己对远线程注入的理解,

//     2.对VC内嵌汇编代码进一步了解

//     3.DEBUG版的函数会有堆栈检测,RELEASE版的函数没有堆栈检测代码

//     4.理解一下汇编代码对应的机器码

//     5.自己打算做一个易语言汇编模块   

//

//汇编代码

PUBLIC  ?AsmInject@@YAXXZ                      ; AsmInject

EXTRN   __chkesp:NEAR

;      COMDAT ?AsmInject@@YAXXZ

_TEXT    SEGMENT

_dwAddr$ = -4

?AsmInject@@YAXXZ PROC NEAR                       ; AsmInject, COMDAT

 

; 8    : {

 

  00000  55           push      ebp

  00001  8b ec              mov      ebp, esp

  00003  83 ec 44  sub esp, 68                ; 00000044H

  00006  53           push      ebx

  00007  56           push      esi

  00008  57           push      edi

  00009  8d 7d bc  lea edi, DWORD PTR [ebp-68]

  0000c  b9 11 00 00 00       mov      ecx, 17                ; 00000011H

  00011  b8 cc cc cc cc  mov      eax, -858993460          ; ccccccccH

  00016  f3 ab              rep stosd

 

; 9    : DWORD dwAddr =0x0060E8F0 ;

 

  00018  c7 45 fc f0 e8

       60 00             mov      DWORD PTR _dwAddr$[ebp], 6351088 ; 0060e8f0H

 

; 10   : __asm

; 11   : {

; 12   :         pushad

 

  0001f  60           pushad

 

; 13   :         mov ecx,0x80000003

 

  00020  b9 03 00 00 80       mov      ecx, -2147483645 ; 80000003H

 

; 14   :         mov edx,[0x0AF8450]

 

  00025  ba 50 84 af 00 mov      edx, 11502672             ; 00af8450H

 

; 15   :         push ecx

 

  0002a  51           push      ecx

 

; 16   :         mov ecx,[edx +0x20]

 

  0002b  8b 4a 20  mov      ecx, DWORD PTR [edx+32]

 

; 17   :         add ecx,0x0d4

 

  0002e  81 c1 d4 00 00

       00           add       ecx, 212              ; 000000d4H

 

; 18   :         call dwAddr 

 

  00034  ff 55 fc   call       DWORD PTR _dwAddr$[ebp]

 

; 19   :         popad

 

  00037  61           popad

 

; 20   : }

; 21   : }

 

  00038  5f           pop       edi

  00039  5e           pop       esi

  0003a  5b           pop       ebx

  0003b  83 c4 44  add       esp, 68                ; 00000044H

  0003e  3b ec              cmp      ebp, esp

  00040  e8 00 00 00 00       call       __chkesp

  00045  8b e5             mov      esp, ebp

  00047  5d           pop       ebp

  00048  c3           ret  0

?AsmInject@@YAXXZ ENDP                                 ; AsmInject

_TEXT    ENDS

END


 

//

#include "StdAfx.h"

#include "publicfunction.h"

 

//

//汇编代码注入

void AsmInject()

{

       DWORD dwAddr =0x0060E8F0 ;

       __asm

       {

              pushad

              mov ecx,0x80000003

              mov edx,[0x0AF8450]  

              push ecx

              mov ecx,[edx +0x20]

              add ecx,0x0d4

              call dwAddr 

              popad

       }

}


 

//

第一段代码是VC6.0生成的汇编代码和机器代码

第二段代码是我编写的C代码,内嵌汇编

场景介绍:我尝试这将这个函数AsmInject() 通过远线程注入到 TARGET.EXE(被攻击进程)

发现问题:为什么远线程注入到TARGET.EXE进程会导致TARGET.EXE出现错误?

解决办法:

 

void AsmInject()

{

       DWORD dwAddr =0x0060E8F0 ;

       __asm

       {

              pushad

              mov ecx,0x80000003

              mov edx,[0x0AF8450]  

              push ecx

              mov ecx,[edx +0x20]

              add ecx,0x0d4

              call dwAddr 

              popad

       }

}


在以上这个函数中 红色标记的代码 通过观察汇编代码之后和我们想象的并不一样,

; 14   :         mov edx,[0x0AF8450]

 

  00025  ba 50 84 af 00 mov      edx, 11502672             ; 00af8450H

事实上它这里并不是把0x0AF8450里面的内容存放到edx,而是直接将0x0AF8450存放到edx中,和我们事先想象的好像不一样。

 

 

 

//

下面我做了一些改进

PUBLIC  ?AsmInject_New@@YAXXZ                            ; AsmInject_New

;      COMDAT ?AsmInject_New@@YAXXZ

_TEXT    SEGMENT

_dwAddr$ = -4

?AsmInject_New@@YAXXZ PROC NEAR                            ; AsmInject_New, COMDAT

 

; 26   : {

 

  00000  55           push      ebp

  00001  8b ec              mov      ebp, esp

  00003  83 ec 44  sub esp, 68                ; 00000044H

  00006  53           push      ebx

  00007  56           push      esi

  00008  57           push      edi

  00009  8d 7d bc  lea edi, DWORD PTR [ebp-68]

  0000c  b9 11 00 00 00       mov      ecx, 17                ; 00000011H

  00011  b8 cc cc cc cc  mov      eax, -858993460          ; ccccccccH

  00016  f3 ab              rep stosd

 

; 27   : DWORD dwAddr =0x0060E8F0 ;

 

  00018  c7 45 fc f0 e8

       60 00             mov      DWORD PTR _dwAddr$[ebp], 6351088 ; 0060e8f0H

 

; 28   : __asm

; 29   : {

; 30   :         pushad

 

  0001f  60           pushad

 

; 31   :                mov ecx,0x80000003

 

  00020  b9 03 00 00 80       mov      ecx, -2147483645 ; 80000003H

 

; 32   :                mov edx,0x0AF8450

 

  00025  ba 50 84 af 00 mov      edx, 11502672             ; 00af8450H

 

; 33   :                mov edx,[edx]

 

  0002a  8b 12             mov      edx, DWORD PTR [edx]

 

; 34   :                push ecx

 

  0002c  51           push      ecx

 

; 35   :                mov ecx,[edx +0x20]

 

  0002d  8b 4a 20  mov      ecx, DWORD PTR [edx+32]

 

; 36   :                add ecx,0x0d4

 

  00030  81 c1 d4 00 00

       00           add       ecx, 212              ; 000000d4H

 

; 37   :                call dwAddr 

 

  00036  ff 55 fc   call       DWORD PTR _dwAddr$[ebp]

 

; 38   :                popad

 

  00039  61           popad

 

; 39   : }

; 40   : }

 

  0003a  5f           pop       edi

  0003b  5e           pop       esi

  0003c  5b           pop       ebx

  0003d  83 c4 44  add       esp, 68                ; 00000044H

  00040  3b ec              cmp      ebp, esp

  00042  e8 00 00 00 00       call       __chkesp

  00047  8b e5             mov      esp, ebp

  00049  5d           pop       ebp

  0004a  c3           ret  0

?AsmInject_New@@YAXXZ ENDP                         ; AsmInject_New

_TEXT    ENDS

END


 

//

//汇编代码注入 改进版

void AsmInject_New()

{

       DWORD dwAddr =0x0060E8F0 ;

       __asm

       {

              pushad

                     mov ecx,0x80000003

                     mov edx,0x0AF8450

                     mov edx,[edx]

                     push ecx

                     mov ecx,[edx +0x20]

                     add ecx,0x0d4

                     call dwAddr 

                     popad

       }

}


 

远线程注入改进版的汇编代码注入之后 ,可以看到TARGET.EXE进程确实存在效果,但是TARGET.EXE任然会报错,这又是为什么呢???

  0003d  83 c4 44  add       esp, 68                ; 00000044H

  00040  3b ec              cmp      ebp, esp

  00042  e8 00 00 00 00       call       __chkesp


 

据说是DEBUG版本的堆栈检测机制,只有在DEBUG版本里面才会有,那么我们使用RELEASE版本编译试试看。

PUBLIC  ?AsmInject_New@@YAXXZ                            ; AsmInject_New

;      COMDAT ?AsmInject_New@@YAXXZ

_TEXT    SEGMENT

_dwAddr$ = -4

?AsmInject_New@@YAXXZ PROC NEAR                            ; AsmInject_New, COMDAT

 

; 26   : {

 

  00000  55           push      ebp

  00001  8b ec              mov      ebp, esp

  00003  51           push      ecx

  00004  53           push      ebx

  00005  56           push      esi

  00006  57           push      edi

 

; 27   : DWORD dwAddr =0x0060E8F0 ;

 

  00007  c7 45 fc f0 e8

       60 00             mov      DWORD PTR _dwAddr$[ebp], 6351088 ; 0060e8f0H

 

; 28   : __asm

; 29   : {

; 30   :         pushad

 

  0000e  60           pushad

 

; 31   :                mov ecx,0x80000003

 

  0000f  b9 03 00 00 80       mov      ecx, -2147483645 ; 80000003H

 

; 32   :                mov edx,0x0AF8450

 

  00014  ba 50 84 af 00 mov      edx, 11502672             ; 00af8450H

 

; 33   :                mov edx,[edx]

 

  00019  8b 12             mov      edx, DWORD PTR [edx]

 

; 34   :                push ecx

 

  0001b  51           push      ecx

 

; 35   :                mov ecx,[edx +0x20]

 

  0001c  8b 4a 20  mov      ecx, DWORD PTR [edx+32]

 

; 36   :                add ecx,0x0d4

 

  0001f  81 c1 d4 00 00

       00           add       ecx, 212              ; 000000d4H

 

; 37   :                call dwAddr 

 

  00025  ff 55 fc   call       DWORD PTR _dwAddr$[ebp]

 

; 38   :                popad

 

  00028  61           popad

 

; 39   : }

; 40   : }

 

  00029  5f           pop       edi

  0002a  5e           pop       esi

  0002b  5b           pop       ebx

  0002c  8b e5             mov      esp, ebp

  0002e  5d           pop       ebp

  0002f  c3           ret  0

?AsmInject_New@@YAXXZ ENDP                         ; AsmInject_New

_TEXT    ENDS

END


 

//

我们远线程注入这段代码

//

//汇编代码注入

void CASMCodeInjectDlg::OnButtonAsmInject() 

{

       // TODO: Add your control notification handler code here

       DWORD procid;

       HWND hwnd ;

       hwnd =::FindWindow(NULL ,"Element Client") ;

       if (hwnd ==NULL)

       {

              MessageBox("请先运行游戏") ;

              return ;

       }

       ::GetWindowThreadProcessId(hwnd,&procid);//获得进程ID

       HANDLE prochandle=::OpenProcess(PROCESS_ALL_ACCESS,false,procid);//打开进程

       LPVOID baseaddr=VirtualAllocEx(prochandle,NULL,1024*4,MEM_COMMIT,PAGE_EXECUTE_READWRITE);//分配空间

       if(baseaddr==NULL)

       {

              MessageBox("分配空间出错");

              return;

       }

       if(!::WriteProcessMemory(prochandle,baseaddr,&AsmInject_New,1024*4,NULL))

       {

              MessageBox("将函数写内存出错");

              return ;

       }

       HANDLE tid;

       tid=CreateRemoteThread(prochandle,NULL,0,(LPTHREAD_START_ROUTINE)baseaddr,0,0,NULL);//远程调用函数

       WaitForSingleObject(tid,INFINITE);//等待线程结束

       VirtualFreeEx(prochandle,baseaddr,1024*4,MEM_RELEASE);

       ::CloseHandle(prochandle);

}

 

确实没有堆栈检测机制,然后我们再次注入这段代码,很好,TARGET.EXE并没有出现错误,一切都是如此的正常,如此的和谐。

 

//

如果我们直接向TARGET.EXE写入机器指令该怎么做呢?

//

//机器码函数注入

void CASMCodeInjectDlg::OnButtonMachinecodeInject() 

{

       // TODO: Add your control notification handler code here

       DWORD procid;

       HWND hwnd ;

       hwnd =::FindWindow(NULL ,"Element Client") ;

       if (hwnd ==NULL)

       {

              MessageBox("请先运行游戏") ;

              return ;

       }

       ::GetWindowThreadProcessId(hwnd,&procid);//获得进程ID

       HANDLE prochandle=::OpenProcess(PROCESS_ALL_ACCESS,false,procid);//打开进程

       LPVOID baseaddr=VirtualAllocEx(prochandle,NULL,1024*4,MEM_COMMIT,PAGE_EXECUTE_READWRITE);//分配空间

       if(baseaddr==NULL)

       {

              MessageBox("分配空间出错");

              return;

       }

       //

       //待注入的机器指令

       char cMachineCode[] ={

              0x55,      

                     0x8b, 0xec,     

                     0x51,      

                     0x53,      

                     0x56,      

                     0x57,

                     0xc7, 0x45, 0xfc, 0xf0, 0xe8, 0x60, 0x00,

                     0x60,

                     0xb9, 0x03, 0x00, 0x00, 0x80,

                     0xba, 0x50, 0x84, 0xaf, 0x00,

                     0x8b, 0x12,

                     0x51,

                     0x8b, 0x4a, 0x20,

                     0x81, 0xc1, 0xd4, 0x00, 0x00, 0x00,

                     0xff, 0x55, 0xfc,

                     0x61,

                     0x5f,

                     0x5e,

                     0x5b,

                     0x8b, 0xe5,

                     0x5d,

                     0xc3

       } ;

       if(!::WriteProcessMemory(prochandle,baseaddr,cMachineCode,1024*4,NULL))

       {

              MessageBox("将函数写内存出错");

              return ;

       }

       HANDLE tid;

       tid=CreateRemoteThread(prochandle,NULL,0,(LPTHREAD_START_ROUTINE)baseaddr,0,0,NULL);//远程调用函数

       WaitForSingleObject(tid,INFINITE);//等待线程结束

       VirtualFreeEx(prochandle,baseaddr,1024*4,MEM_RELEASE);

       ::CloseHandle(prochandle);

}


 

事实上,上面的机器码是直接copy AsmInject_New这个函数的机器码,没有做任何修改,把这些机器码存放到cMachineCode 缓冲区中。进行远线程注入依然可以行的,如此的和谐,TARGET.EXE也不会给我一个 READ MEMORY ERROR !

 

以上说了下远线程注入的细节问题。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值