无DLL注入(函数直接注入)

在第三中方法中,我们启动远程线程时,线程函数是我们从Kernel32.dll中取得的

LoadLibrary
函数的地址为线程函数的地址,其实我们可以直接将线程函数体和函数参数写入目标

进程的地址空间,然后创建远程线程。
    
使用这个方法时,需要注意以下几个问题:
    (1) 
远程线程函数体不得使用kernel32.dlluser32.dll以外的函数。因为这个两个模块在各个进程的相对地址是一样的,如果一定要使用其它函数,则必须将函数体写入目标进程空间。
    (2) 
不能使用任何字符串常量,因为字符串常量是存放在PE文件里.data这个段里面的,函数里保存的只是相对地址。
    (3) 
去掉编译器的/GZ编译选项,这个选项是用来Enable Stack Frame Run-Time Error Checking。当这个选项打开时,编译器会在每个函数中加入一些代码,用来检验ESP在函数体中是否被改变,但是这些检验函数的地址在不同PE文件中有可能是不一样的。
    (4) 
不得使用增量链接(incremental linking)。增量链接是编译器为了减少链接时间做的处理,把函数体用一个JMP指令代替,这样就可以随意改变函数的内容,而不用修改CALL指令。
    (5) 
不要在函数体内使用超过4kb的局部变量。局部变量是存放在栈中的,例如下面这个函数
void Dummy(void) {
      BYTE var[256];
      var[0] = 0;
      var[1] = 1;
      var[255] = 255;
}
在分配局部变量空间时是这样的
:00401000    push ebp
:00401001    mov   ebp, esp
:00401003    sub   esp, 00000100            ; change ESP as storage for
                                           ; local variables is needed
:00401006    mov   byte ptr [esp], 00       ; var[0] = 0;
:0040100A    mov   byte ptr [esp+01], 01    ; var[1] = 1;
:0040100F    mov   byte ptr [esp+FF], FF    ; var[255] = 255;
:00401017    mov   esp, ebp                 ; restore stack pointer
:00401019    pop   ebp
:0040101A    ret
但是当局部变量的大小超过4kb时,栈指针并不直接改版,而是调用另一个函数来分配内存,这个函数有可能在不同进程中的地址不一样。

     (6) 函数体内switch语句中的case不要超过3个,否则编译器会在PE文件中使用跳转表,而这个跳转表有可能在目标进程中并不存在。


    
下面是一个无DLL注入的例子:

 

[cpp]  view plain copy
  1. //定义输出函数结构体  
  2. typedef struct _RemotePara{   
  3.     PVOID dwMessageBox;         //函数体指针  
  4.     wchar_t strMessageBox[12];  //参数  
  5. }RemotePara;   
  6. // 远程线程执行体  
  7. DWORD __stdcall ThreadProc(RemotePara *Para)  
  8. {  
  9.     typedef int (/*__stdcall*/ *PMessageBox) ( HWND , LPCTSTR , LPCTSTR , UINT );  
  10.     PMessageBox MessageBoxFunc = (PMessageBox)Para->dwMessageBox;  
  11.     MessageBoxFunc(NULL, Para->strMessageBox, Para->strMessageBox, MB_OK);  
  12.     return 0 ;  
  13. }  
  14. DWORD THREADSIZE=1024;  
  15. DWORD pID = 4688;  
  16. DWORD byte_write;   
  17. HANDLE hRemoteProcess,hThread;  
  18. RemotePara myRemotePara,*pRemotePara;   
  19. void *pRemoteThread;  
  20. HINSTANCE hUser32 ;  
  21. hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pID);   
  22. if(!hRemoteProcess)return 0;   
  23. // 在远程进程地址空间分配虚拟内存  
  24. pRemoteThread = VirtualAllocEx(hRemoteProcess, 0, THREADSIZE, MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);  
  25. if(!pRemoteThread)return 0;   
  26. // 将线程执行体ThreadProc写入远程进程  
  27. if(!WriteProcessMemory(hRemoteProcess, pRemoteThread, &ThreadProc, THREADSIZE,0))return 0;  
  28. ZeroMemory(&myRemotePara,sizeof(RemotePara));   
  29. hUser32 = LoadLibrary(L"user32.dll");  
  30. myRemotePara.dwMessageBox = (PVOID)GetProcAddress(hUser32, "MessageBoxW");   
  31. wcscat(myRemotePara.strMessageBox,L"Hello!"); //复制MessageBox函数的参数  
  32. //写进目标进程   
  33. pRemotePara =(RemotePara *)VirtualAllocEx (hRemoteProcess ,0,sizeof(RemotePara),MEM_COMMIT,PAGE_READWRITE);  
  34. if(!pRemotePara)return 0;   
  35. if(!WriteProcessMemory (hRemoteProcess ,pRemotePara,&myRemotePara,sizeof(myRemotePara),0))return 0;   
  36. // 启动线程   
  37. hThread = CreateRemoteThread(hRemoteProcess ,0,0,(LPTHREAD_START_ROUTINE)pRemoteThread ,pRemotePara,0,&byte_write);  
  38. FreeLibrary(hUser32);  
  39. CloseHandle(hRemoteProcess);   
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值