基于挂起进程修改eip办法dll注入笔记

主要思想:

在进程启动时候,用CREATE_SUSPENDED挂起方式创建进程,或者打开进程之后把它挂起,然后申请一个内存空间,把shellcode 写到该内存中,之后修改进程eip为shellcode的地址,即可。

汇编码:

pushad
pushfd
push "dllPath"
call LoadLibary
popfd
popad
jmp Old Eip

 

实现:(程序省去了出错的处理)

 

STARTUPINFOW si = { 0 };
 PROCESS_INFORMATION pi = { 0 };
 si.cb = sizeof(STARTUPINFOW);

 

::CreateProcessW(pProcessPath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);

 CONTEXT ct = { 0 };
 ct.ContextFlags = CONTEXT_ALL;
 GetThreadContext(pi.hThread, &ct);

 DWORD dwSize = sizeof(WCHAR) * 1024;

 BYTE *pProcessMem = (BYTE *)::VirtualAllocEx(pi.hProcess, NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 
 DWORD dwWrited = 0;
 ::WriteProcessMemory(pi.hProcess, (pProcessMem + 0x100), pDllPath, (wcslen(pDllPath) + 1) * sizeof(WCHAR), &dwWrited);

 

 FARPROC pLoadLibraryW = (FARPROC)::GetProcAddress(::GetModuleHandle(L"Kernel32"), "LoadLibraryW");

 BYTE ShellCode[32] = { 0 };

 DWORD *pdwAddr = NULL;
 
 ShellCode[0] = 0x60; // pushad
 ShellCode[1] = 0x9c; // pushfd
 ShellCode[2] = 0x68; // push

 pdwAddr = (DWORD *)&ShellCode[3]; // ShellCode[3/4/5/6]
 *pdwAddr = (DWORD)(pProcessMem + 0x100);

 ShellCode[7] = 0xe8;
 pdwAddr = (DWORD *)&ShellCode[8]; // ShellCode[8/9/10/11]
 *pdwAddr = (DWORD)pLoadLibraryW - (DWORD)(pProcessMem + 7) - 5;

 ShellCode[12] = 0x9d; // popfd
 ShellCode[13] = 0x61; // popad
 ShellCode[14] = 0xe9; // jmp
 
 pdwAddr = (DWORD *)&ShellCode[15]; // ShellCode[15/16/17/18]
 *pdwAddr = ct.Eip - (DWORD)(pProcessMem + 14) - 5;

 ::WriteProcessMemory(pi.hProcess, pProcessMem, ShellCode, sizeof(ShellCode), &dwWrited);

 ct.Eip = (DWORD)pProcessMem;
 ::SetThreadContext(pi.hThread, &ct);

 

 ::ResumeThread(pi.hThread);

 ::CloseHandle(pi.hProcess);
 ::CloseHandle(pi.hThread);

 

上面的

 *pdwAddr = (DWORD)pLoadLibraryW - (DWORD)(pProcessMem + 7) - 5;

 *pdwAddr = ct.Eip - (DWORD)(pProcessMem + 14) - 5;

两句的说明,

因为0xe8 (call) 和0xe9(jmp)跳指令,eip改变格式如下:

eip + 5 + x = newEip,其中5为一个字节的指令长度加上四个字节的地址长度

所以得
x = newEip - eip - 5

故得上面两句。 

 

如果不想计算偏移,这段shellCode可以变形一下,就不用计算偏移地址了。

主要做法是用push addr 加上retn 来代替 call

汇编代码如下:

 pushad
 pushfd
 push "dllPath"
 push Addr1
 push LoadLibary
 retn

Addr1:
 popfd
 popad
 push OldEip
 retn

 

 

shellcode如下:(地址用0x90 填充,后面再修正)
 BYTE ShellCode[32] =
 {
  
  0x60, // pushad
  0x9c, // pushfd
       
  // push DllPath 地址
  0x68, 0x90,0x90,0x90,0x90,  
  
  // push Addr1:
  0x68, 0x90,0x90,0x90,0x90,   
  
  // push LoadLibraryW 地址
  0x68, 0x90,0x90,0x90,0x90,
  
  0xc3, // retn 这个指令使得跳转到 LoadLibraryW,LoadLibraryW返回地址有上一个指令指出
  
  0x9d, // popfd
  0x61, // popad
  
  // push OldEip 地址
  0x68, 0x90,0x90,0x90,0x90,
  
  0xc3, // retn
  0x00
 };

  *((DWORD *)&ShellCode[3]) = (DWORD)(pProcessMem + 0x100); // ShellCode[3/4/5/6] LoadLibraryW 的参数
 *((DWORD *)&ShellCode[8]) = (DWORD)pProcessMem+0x12;      // ShellCode[8/9/10/11] LoadLibraryW 返回的地址 
 *((DWORD *)&ShellCode[13]) = (DWORD)pLoadLibraryW;        // ShellCode[13/14/15/16] LoadLibraryW的地址
 *((DWORD *)&ShellCode[21]) = (DWORD)ct.Eip;               // ShellCode[21/22/23/24] ct.Eip的地址

你可能感兴趣的:(基于挂起进程修改eip办法dll注入笔记)