- 注册时间
- 2011-3-6
- 最后登录
- 1970-1-1
该用户从未签到
|
//////////////////////////////////////////////////////////////////////////
//编辑时间: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 !
以上说了下远线程注入的细节问题。 |
|