我想做什么:将DLL注入进程以挂钩CreateProcess并监视受害者进程的调用。进行调用时,我检索子进程ID并将相同的DLL注入其中。等等。
我成功完成了第一部分:将我的DLL注入进程,挂钩CreateProcess,监视调用。
挂钩是非常基本的:用jmp将前5个字节覆盖到另一个看起来像这样的函数:
__declspec(naked)
InterceptCreateProc()
{
LPBYTE pJmpAdr;
LPCTSTR lpApplicationName;
LPTSTR lpCommandLine;
LPSECURITY_ATTRIBUTES lpProcessAttributes;
LPSECURITY_ATTRIBUTES lpThreadAttributes;
BOOL bInheritHandles;
DWORD dwCreationFlags;
LPVOID lpEnvironment;
LPCTSTR lpCurrentDirectory;
LPSTARTUPINFO lpStartupInfo;
LPPROCESS_INFORMATION lpProcessInformation;
DWORD retv;
void *inject;
inject = (void* )Inject; // address of the function that should inject the DLL
__asm
{
pop retv // return address
// parameters
pop lpApplicationName
pop lpCommandLine
pop lpProcessAttributes
pop lpThreadAttributes
pop bInheritHandles
pop dwCreationFlags
pop lpEnvironment
pop lpCurrentDirectory
pop lpStartupInfo
pop lpProcessInformation
};
dwCreationFlags = dwCreationFlags | CREATE_SUSPENDED; // change creation flags to create suspended
returnAdr = retv; // save the return address
retv = (DWORD)inject; // redirect CreateProcess to return to the injection function
g_procInfo = lpProcessInformation;
// push back all parameters on the stack
__asm
{
push lpProcessInformation
push lpStartupInfo
push lpCurrentDirectory
push lpEnvironment
push dwCreationFlags
push bInheritHandles
push lpThreadAttributes
push lpProcessAttributes
push lpCommandLine
push lpApplicationName
push retv
};
// the bytes I have over written with my hook
__asm
{
push ebp
mov ebp, esp
};
pJmpAdr = pOldFuncAdr + 5; // the point in CreateProcess where I should jump
__asm
{
jmp pJmpAdr
};
}
现在,执行注入的功能:
__declspec(naked)
void
Inject()
{
DWORD rValue;
LPVOID baseAdr;
HMODULE kernel32;
FARPROC loadLib;
HANDLE hThread;
HANDLE hProc;
__asm
{
mov rValue, eax // save the return value from CreateProcess
};
hProc = NULL;
hProc = OpenProcess(PROCESS_ALL_ACCESS,
0,
g_procInfo->dwProcessId);
if(NULL == hProc)
{
LogErrors("OpenProcess failed ",
GetLastError());
}
baseAdr = NULL;
baseAdr = VirtualAllocEx(hProc,
0,
strlen(dllPath) + 1,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE);
if(NULL == baseAdr)
{
LogErrors("VirtualAllocEx failed ",
GetLastError());
}
if(!WriteProcessMemory(hProc,
baseAdr,
dllPath,
strlen(dllPath) + 1,
0))
{
LogErrors("WriteProcessMemory failed ",
GetLastError());
}
kernel32 = NULL;
kernel32 = LoadLibrary(TEXT("kernel32.dll"));
if(NULL == kernel32)
{
LogErrors("LoadLibrary faild ",
GetLastError());
}
loadLib = NULL;
loadLib = GetProcAddress(kernel32,
"LoadLibraryA");
if(NULL == loadLib)
{
LogErrors("GetProcAddress failed ",
GetLastError());
}
hThread = NULL;
hThread = CreateRemoteThread(hProc,
0,
0,
(LPTHREAD_START_ROUTINE)loadLib,
baseAdr,
0,
0);
if(NULL == hThread)
{
LogErrors("CreateRemoteThread failed ",
GetLastError());
}
ResumeThread(g_procInfo->hThread);
// I'm not sure if this is correct
// it seems to be working -- CreateProcess returns a non zero value
__asm
{
mov eax, rValue // return value
jmp returnAdr // return address
}
}
每次调用CreateProcess时,都会调用Inject,但它唯一要做的就是恢复主线程。子进程没有发生注入。
我在这里犯的重大错误是什么?
编辑:事实证明上面的代码正在运行,问题是我的测试程序。 仍然,反馈表示赞赏。我在这里做了什么有什么好处?怎么了?
EDIT2:我发现了我的第一个问题。有时(经常是),我得到一个堆栈变量startupInformation已损坏。 startupInformation是一个STARTUPINFO结构,它是CreateProcess的out参数。这很奇怪,因为我根本不与startupInformation交互。我改变的唯一事情是创建标志。即使在我收到此错误的情况下,processInformation也具有正确的值。