- 注册时间
 - 2021-4-16
 
- 最后登录
 - 2023-9-18
 
- 在线时间
 - 2 小时
 
 
 
 
 
编程入门 
  
	- 龙马币
 - 40 
 
 
 
 
 | 
 
 
获得目标进程句柄就从略了。直接从注射开始: 
 
- HANDLE CRemoteCodeDlg::InjetionCode(HANDLE hProcess, LPVOID pCode, LPVOID pParam)
 
 - {
 
 -     HANDLE RemoteThand;
 
 -     LPVOID CodeAddress = NULL;
 
 -     LPVOID DataAddress = NULL;
 
 -     DWORD  RetByte,Tid,CodeSize,AllRemoteMemSize;
 
  
-     if(! hProcess || INVALID_HANDLE_VALUE == hProcess)
 
 -     {
 
 -         return HANDLE(0);
 
 -     }
 
 -      
 
 -     CodeSize = DWORD(PCHAR(GETVCPROC_ADDRESS(GetVCProcAddress)) - PCHAR(GETVCPROC_ADDRESS(ISee)));
 
 -     AllRemoteMemSize = CodeSize +  MEMCODEPARAM_SIZE + sizeof(DWORD);
 
  
-     CodeAddress = VirtualAllocEx(hProcess,NULL,AllRemoteMemSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
 
 -     if(! CodeAddress)
 
 -     {         
 
 -         return HANDLE(0);
 
 -     }
 
 -      
 
 -     if(! WriteProcessMemory(hProcess,CodeAddress,pCode,CodeSize,&RetByte))
 
 -     {         
 
 -         VirtualFreeEx(hProcess,CodeAddress,AllRemoteMemSize,MEM_DECOMMIT);
 
 -         CodeAddress = NULL;
 
 -         return HANDLE(0);
 
 -     }
 
 -     DataAddress = LPVOID(DWORD(CodeAddress) + sizeof(DWORD) & ~3);
 
  
-     if(! WriteProcessMemory(hProcess,DataAddress,pParam,MEMCODEPARAM_SIZE,&RetByte))
 
 -     {         
 
 -         VirtualFreeEx(hProcess,CodeAddress,AllRemoteMemSize,MEM_DECOMMIT);
 
 -         CodeAddress = NULL;
 
 -         return HANDLE(0);
 
 -     }
 
  
-     RemoteThand = CreateRemoteThread(hProcess,NULL,0,LPTHREAD_START_ROUTINE(CodeAddress),
 
 -         DataAddress,CREATE_SUSPENDED,&Tid);
 
  
-     m_pRemoteAllocMem = CodeAddress;
 
 -     m_RemoteMemSize = AllRemoteMemSize;
 
  
-     return RemoteThand;
 
 - }
 
  复制代码 
 
        首先说说这个被注射代码的大小问题,这个问题我在很多论坛上看到过。但是回答的人都是用估计值作答。实际上这个难题也很好理解,因为你写得不是机器代码,自然无法计算最后生成的执行的机器代码字节数。(玩笑话,编译器知道,但他不会告诉你。呵呵)。 
 
    汇编语言可以很轻松的获得这个值,原因同上。 
 
    难道我们就无法确定了吗?NO,让编译器告诉我们,不要吃惊,方法如下: 
int Func1(void) 
{ 
  ------------------------------- 
  -------------------------------- 
} 
 
void Func2(void) 
{ 
 
} 
 
    假设Func1是要注射的代码,要求的Func1编译后的代码大小:Func1Size = Func2 - Func2; 
 
原理: 
    
  实际上如果你对编译器比较熟悉的话,就会知道实际上函数名就是编译过程中的一个地址标号。因此用高地址标号减去低的就是我们想要得。有人要问:你怎末知道编译器一定会把Func2放在Func1之后哪?我的回答是:可能有反向的。但目前我见到的VC \ BC \ BCB \ SC(赛门铁克)都是这末做的。 
 
我的码如下: 
 
CodeSize = DWORD(PCHAR(GETVCPROC_ADDRESS(GetVCProcAddress)) - PCHAR(GETVCPROC_ADDRESS(ISee))); 
 
这个GETVCPROC_ADDRESS是一个宏,定义如下: 
 
#ifdef _DEBUG      
    #define GETVCPROC_ADDRESS(Fn)  GetVCProcAddress(Fn) 
#else 
    #define GETVCPROC_ADDRESS(Fn)  Fn 
#endif 
 
    为什莫定义这个?直接用Fn2 - Fn1不就好了吗?NO,这又引出了一个概念:VC的编译器有个特点从6.0到现在的9.0都是如此。在你选择Debug版本编译时,所有的函数调用都会被编译为一个间接的调转指令。就像调用系统API一样。在编译器内部型如: 
 
JMP @IAT_Fn1@ 这个鬼样子。 
 
而在Release版本时就变成了直接调用。所以为了调试方便就定义了此宏。Debug宏实现如下: 
 
- LPVOID GetVCProcAddress(LPVOID pFn)
 
 - {
 
 -     PCHAR pAddRess = (PCHAR)pFn;
 
  
-     pAddRess ++;        //跳过@IAT的第一个指令jmp
 
  
-     pAddRess +=  *(DWORD *)pAddRess;
 
 -     pAddRess += 4;        //修正指针类型偏移
 
  
-     return pAddRess;
 
 - }
 
  复制代码 
 
好了,再看看这个: 
 
AllRemoteMemSize = CodeSize +  MEMCODEPARAM_SIZE + sizeof(DWORD); 
 
        全部分配的内存大小为什用代码尺寸大小(CodeSize) + 参数块大小(MEMCODEPARAM_SIZE)还要再加一个sizeof(DWORD)哪?我只说是为了数据对齐,如何保证后拷贝的数据块能正好放在一个4字节对齐的开始地址哪?看看下面这行代码你就明白了。 
 
DataAddress = LPVOID(DWORD(CodeAddress) + sizeof(DWORD) & ~3); 
 
        至于经常有人说直接注射的代码无法调用API的问题,我觉得更加荒谬。他们的理由无非是,本地进程的API地址跟目标进程的API地址不一致。是的,这个我也承认。但是你可以用LoadLibRary和GetProcAddress来获取目标进程中的API地址。你不用跟我说这两个地址怎末来?实际上 Kernel32.dll在每个进程中的加载地址都一样。 
 
 |   
 
 
 
 |