看流星社区

 找回密码
 注册账号
查看: 2517|回复: 4

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

[复制链接]

该用户从未签到

发表于 2012-4-2 10:23:53 | 显示全部楼层 |阅读模式
//////////////////////////////////////////////////////////////////////////
//编辑时间:2011-8-22
//整理人:紫色溟渊
//说明:仅供学习技术交流,欢迎转载,转载请注明出处。
//编辑目的:
//     1.加深自己对远线程注入的理解,
//     2.对VC内嵌汇编代码进一步了解
//     3.DEBUG版的函数会有堆栈检测,RELEASE版的函数没有堆栈检测代码
//     4.理解一下汇编代码对应的机器码
//     5.自己打算做一个易语言汇编模块   
//////////////////////////////////////////////////////////////////////////
//汇编代码
  1. PUBLIC  ?AsmInject@@YAXXZ                      ; AsmInject
  2. EXTRN   __chkesp:NEAR
  3. ;      COMDAT ?AsmInject@@YAXXZ
  4. _TEXT    SEGMENT
  5. _dwAddr$ = -4
  6. ?AsmInject@@YAXXZ PROC NEAR                       ; AsmInject, COMDAT

  7. ; 8    : {

  8.   00000  55           push      ebp
  9.   00001  8b ec              mov      ebp, esp
  10.   00003  83 ec 44  sub esp, 68                ; 00000044H
  11.   00006  53           push      ebx
  12.   00007  56           push      esi
  13.   00008  57           push      edi
  14.   00009  8d 7d bc  lea edi, DWORD PTR [ebp-68]
  15.   0000c  b9 11 00 00 00       mov      ecx, 17                ; 00000011H
  16.   00011  b8 cc cc cc cc  mov      eax, -858993460          ; ccccccccH
  17.   00016  f3 ab              rep stosd

  18. ; 9    : DWORD dwAddr =0x0060E8F0 ;

  19.   00018  c7 45 fc f0 e8
  20.        60 00             mov      DWORD PTR _dwAddr$[ebp], 6351088 ; 0060e8f0H

  21. ; 10   : __asm
  22. ; 11   : {
  23. ; 12   :         pushad

  24.   0001f  60           pushad

  25. ; 13   :         mov ecx,0x80000003

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

  27. ; 14   :         mov edx,[0x0AF8450]

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

  29. ; 15   :         push ecx

  30.   0002a  51           push      ecx

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

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

  33. ; 17   :         add ecx,0x0d4

  34.   0002e  81 c1 d4 00 00
  35.        00           add       ecx, 212              ; 000000d4H

  36. ; 18   :         call dwAddr

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

  38. ; 19   :         popad

  39.   00037  61           popad

  40. ; 20   : }
  41. ; 21   : }

  42.   00038  5f           pop       edi
  43.   00039  5e           pop       esi
  44.   0003a  5b           pop       ebx
  45.   0003b  83 c4 44  add       esp, 68                ; 00000044H
  46.   0003e  3b ec              cmp      ebp, esp
  47.   00040  e8 00 00 00 00       call       __chkesp
  48.   00045  8b e5             mov      esp, ebp
  49.   00047  5d           pop       ebp
  50.   00048  c3           ret  0
  51. ?AsmInject@@YAXXZ ENDP                                 ; AsmInject
  52. _TEXT    ENDS
  53. END
复制代码
  1. //////////////////////////////////////////////////////////////////////////
  2. #include "StdAfx.h"
  3. #include "publicfunction.h"

  4. //////////////////////////////////////////////////////////////////////////
  5. //汇编代码注入
  6. void AsmInject()
  7. {
  8.        DWORD dwAddr =0x0060E8F0 ;
  9.        __asm
  10.        {
  11.               pushad
  12.               mov ecx,0x80000003
  13.               mov edx,[0x0AF8450]  
  14.               push ecx
  15.               mov ecx,[edx +0x20]
  16.               add ecx,0x0d4
  17.               call dwAddr
  18.               popad
  19.        }
  20. }
复制代码
第一段代码是VC6.0生成的汇编代码和机器代码
第二段代码是我编写的C代码,内嵌汇编
场景介绍:我尝试这将这个函数AsmInject() 通过远线程注入到 TARGET.EXE(被攻击进程)
发现问题:为什么远线程注入到TARGET.EXE进程会导致TARGET.EXE出现错误?
解决办法:
  1. void AsmInject()
  2. {
  3.        DWORD dwAddr =0x0060E8F0 ;
  4.        __asm
  5.        {
  6.               pushad
  7.               mov ecx,0x80000003
  8.               mov edx,[0x0AF8450]  
  9.               push ecx
  10.               mov ecx,[edx +0x20]
  11.               add ecx,0x0d4
  12.               call dwAddr
  13.               popad
  14.        }
  15. }
复制代码
在以上这个函数中 红色标记的代码 通过观察汇编代码之后和我们想象的并不一样,
; 14   :         mov edx,[0x0AF8450]
00025  ba 50 84 af 00 mov      edx, 11502672             ; 00af8450H
事实上它这里并不是把0x0AF8450里面的内容存放到edx,而是直接将0x0AF8450存放到edx中,和我们事先想象的好像不一样

下面我做了一些改进
  1. PUBLIC  ?AsmInject_New@@YAXXZ                            ; AsmInject_New
  2. ;      COMDAT ?AsmInject_New@@YAXXZ
  3. _TEXT    SEGMENT
  4. _dwAddr$ = -4
  5. ?AsmInject_New@@YAXXZ PROC NEAR                            ; AsmInject_New, COMDAT

  6. ; 26   : {

  7.   00000  55           push      ebp
  8.   00001  8b ec              mov      ebp, esp
  9.   00003  83 ec 44  sub esp, 68                ; 00000044H
  10.   00006  53           push      ebx
  11.   00007  56           push      esi
  12.   00008  57           push      edi
  13.   00009  8d 7d bc  lea edi, DWORD PTR [ebp-68]
  14.   0000c  b9 11 00 00 00       mov      ecx, 17                ; 00000011H
  15.   00011  b8 cc cc cc cc  mov      eax, -858993460          ; ccccccccH
  16.   00016  f3 ab              rep stosd

  17. ; 27   : DWORD dwAddr =0x0060E8F0 ;

  18.   00018  c7 45 fc f0 e8
  19.        60 00             mov      DWORD PTR _dwAddr$[ebp], 6351088 ; 0060e8f0H

  20. ; 28   : __asm
  21. ; 29   : {
  22. ; 30   :         pushad

  23.   0001f  60           pushad

  24. ; 31   :                mov ecx,0x80000003

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

  26. ; 32   :                mov edx,0x0AF8450

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

  28. ; 33   :                mov edx,[edx]

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

  30. ; 34   :                push ecx

  31.   0002c  51           push      ecx

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

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

  34. ; 36   :                add ecx,0x0d4

  35.   00030  81 c1 d4 00 00
  36.        00           add       ecx, 212              ; 000000d4H

  37. ; 37   :                call dwAddr

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

  39. ; 38   :                popad

  40.   00039  61           popad

  41. ; 39   : }
  42. ; 40   : }

  43.   0003a  5f           pop       edi
  44.   0003b  5e           pop       esi
  45.   0003c  5b           pop       ebx
  46.   0003d  83 c4 44  add       esp, 68                ; 00000044H
  47.   00040  3b ec              cmp      ebp, esp
  48.   00042  e8 00 00 00 00       call       __chkesp
  49.   00047  8b e5             mov      esp, ebp
  50.   00049  5d           pop       ebp
  51.   0004a  c3           ret  0
  52. ?AsmInject_New@@YAXXZ ENDP                         ; AsmInject_New
  53. _TEXT    ENDS
  54. END
复制代码
//汇编代码注入 改进版
  1. void AsmInject_New()
  2. {
  3.        DWORD dwAddr =0x0060E8F0 ;
  4.        __asm
  5.        {
  6.               pushad
  7.                      mov ecx,0x80000003
  8.                      mov edx,0x0AF8450
  9.                      mov edx,[edx]
  10.                      push ecx
  11.                      mov ecx,[edx +0x20]
  12.                      add ecx,0x0d4
  13.                      call dwAddr
  14.                      popad
  15.        }
  16. }
复制代码
远线程注入改进版的汇编代码注入之后 ,可以看到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版本编译试试看。
  1. PUBLIC  ?AsmInject_New@@YAXXZ                            ; AsmInject_New
  2. ;      COMDAT ?AsmInject_New@@YAXXZ
  3. _TEXT    SEGMENT
  4. _dwAddr$ = -4
  5. ?AsmInject_New@@YAXXZ PROC NEAR                            ; AsmInject_New, COMDAT

  6. ; 26   : {

  7.   00000  55           push      ebp
  8.   00001  8b ec              mov      ebp, esp
  9.   00003  51           push      ecx
  10.   00004  53           push      ebx
  11.   00005  56           push      esi
  12.   00006  57           push      edi

  13. ; 27   : DWORD dwAddr =0x0060E8F0 ;

  14.   00007  c7 45 fc f0 e8
  15.        60 00             mov      DWORD PTR _dwAddr$[ebp], 6351088 ; 0060e8f0H

  16. ; 28   : __asm
  17. ; 29   : {
  18. ; 30   :         pushad

  19.   0000e  60           pushad

  20. ; 31   :                mov ecx,0x80000003

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

  22. ; 32   :                mov edx,0x0AF8450

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

  24. ; 33   :                mov edx,[edx]

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

  26. ; 34   :                push ecx

  27.   0001b  51           push      ecx

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

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

  30. ; 36   :                add ecx,0x0d4

  31.   0001f  81 c1 d4 00 00
  32.        00           add       ecx, 212              ; 000000d4H

  33. ; 37   :                call dwAddr

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

  35. ; 38   :                popad

  36.   00028  61           popad

  37. ; 39   : }
  38. ; 40   : }

  39.   00029  5f           pop       edi
  40.   0002a  5e           pop       esi
  41.   0002b  5b           pop       ebx
  42.   0002c  8b e5             mov      esp, ebp
  43.   0002e  5d           pop       ebp
  44.   0002f  c3           ret  0
  45. ?AsmInject_New@@YAXXZ ENDP                         ; AsmInject_New
  46. _TEXT    ENDS
  47. END
复制代码
//////////////////////////////////////////////////////////////////////////
我们远线程注入这段代码
//////////////////////////////////////////////////////////////////////////
//汇编代码注入
  1. void CASMCodeInjectDlg::OnButtonAsmInject()
  2. {
  3.        // TODO: Add your control notification handler code here
  4.        DWORD procid;
  5.        HWND hwnd ;
  6.        hwnd =::FindWindow(NULL ,"Element Client") ;
  7.        if (hwnd ==NULL)
  8.        {
  9.               MessageBox("请先运行游戏") ;
  10.               return ;
  11.        }
  12.        ::GetWindowThreadProcessId(hwnd,&procid);//获得进程ID
  13.        HANDLE prochandle=::OpenProcess(PROCESS_ALL_ACCESS,false,procid);//打开进程
  14.        LPVOID baseaddr=VirtualAllocEx(prochandle,NULL,1024*4,MEM_COMMIT,PAGE_EXECUTE_READWRITE);//分配空间
  15.        if(baseaddr==NULL)
  16.        {
  17.               MessageBox("分配空间出错");
  18.               return;
  19.        }
  20.        if(!::WriteProcessMemory(prochandle,baseaddr,&AsmInject_New,1024*4,NULL))
  21.        {
  22.               MessageBox("将函数写内存出错");
  23.               return ;
  24.        }
  25.        HANDLE tid;
  26.        tid=CreateRemoteThread(prochandle,NULL,0,(LPTHREAD_START_ROUTINE)baseaddr,0,0,NULL);//远程调用函数
  27.        WaitForSingleObject(tid,INFINITE);//等待线程结束
  28.        VirtualFreeEx(prochandle,baseaddr,1024*4,MEM_RELEASE);
  29.        ::CloseHandle(prochandle);
  30. }
复制代码
确实没有堆栈检测机制,然后我们再次注入这段代码,很好,TARGET.EXE并没有出现错误,一切都是如此的正常,如此的和谐。

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

//////////////////////////////////////////////////////////////////////////
//机器码函数注入
  1. void CASMCodeInjectDlg::OnButtonMachinecodeInject()
  2. {
  3.        // TODO: Add your control notification handler code here
  4.        DWORD procid;
  5.        HWND hwnd ;
  6.        hwnd =::FindWindow(NULL ,"Element Client") ;
  7.        if (hwnd ==NULL)
  8.        {
  9.               MessageBox("请先运行游戏") ;
  10.               return ;
  11.        }
  12.        ::GetWindowThreadProcessId(hwnd,&procid);//获得进程ID
  13.        HANDLE prochandle=::OpenProcess(PROCESS_ALL_ACCESS,false,procid);//打开进程
  14.        LPVOID baseaddr=VirtualAllocEx(prochandle,NULL,1024*4,MEM_COMMIT,PAGE_EXECUTE_READWRITE);//分配空间
  15.        if(baseaddr==NULL)
  16.        {
  17.               MessageBox("分配空间出错");
  18.               return;
  19.        }
  20.        //////////////////////////////////////////////////////////////////////////
  21.        //待注入的机器指令
  22.        char cMachineCode[] ={
  23.               0x55,      
  24.                      0x8b, 0xec,     
  25.                      0x51,      
  26.                      0x53,      
  27.                      0x56,      
  28.                      0x57,
  29.                      0xc7, 0x45, 0xfc, 0xf0, 0xe8, 0x60, 0x00,
  30.                      0x60,
  31.                      0xb9, 0x03, 0x00, 0x00, 0x80,
  32.                      0xba, 0x50, 0x84, 0xaf, 0x00,
  33.                      0x8b, 0x12,
  34.                      0x51,
  35.                      0x8b, 0x4a, 0x20,
  36.                      0x81, 0xc1, 0xd4, 0x00, 0x00, 0x00,
  37.                      0xff, 0x55, 0xfc,
  38.                      0x61,
  39.                      0x5f,
  40.                      0x5e,
  41.                      0x5b,
  42.                      0x8b, 0xe5,
  43.                      0x5d,
  44.                      0xc3
  45.        } ;
  46.        if(!::WriteProcessMemory(prochandle,baseaddr,cMachineCode,1024*4,NULL))
  47.        {
  48.               MessageBox("将函数写内存出错");
  49.               return ;
  50.        }
  51.        HANDLE tid;
  52.        tid=CreateRemoteThread(prochandle,NULL,0,(LPTHREAD_START_ROUTINE)baseaddr,0,0,NULL);//远程调用函数
  53.        WaitForSingleObject(tid,INFINITE);//等待线程结束
  54.        VirtualFreeEx(prochandle,baseaddr,1024*4,MEM_RELEASE);
  55.        ::CloseHandle(prochandle);
  56. }
复制代码
事实上,上面的机器码是直接copy AsmInject_New这个函数的机器码,没有做任何修改,把这些机器码存放到cMachineCode 缓冲区中。进行远线程注入依然可以行的,如此的和谐,TARGET.EXE也不会给我一个 READ MEMORY ERROR !

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

该用户从未签到

发表于 2012-4-3 11:04:13 | 显示全部楼层
说了下远线程注入的细节问题。

该用户从未签到

发表于 2012-4-16 11:00:48 | 显示全部楼层
光速浏览此贴!

该用户从未签到

发表于 2013-9-28 08:24:55 | 显示全部楼层
不要等到人人都说你丑时才发现自己真的丑。 ▓

该用户从未签到

发表于 2013-9-28 14:49:52 | 显示全部楼层
扯淡啊,感觉你在开玩笑啊。
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-5-14 05:32

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表