我编写了一个程序(.DLL),它将被注入process.exe。
DLL注入器代码:
Bool InjectDll(DWORD pID, const char* dllPath) {
Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
if (!Proc)
{
return false;
}
void* LoadLibAddr = (void*)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
void* RemoteString = (void*)VirtualAllocEx(Proc, NULL, strlen(dllPath), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(Proc, (LPVOID)RemoteString, dllPath, strlen(dllPath), NULL);
HANDLE ret = CreateRemoteThread(Proc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddr, (LPVOID)RemoteString, CREATE_SUSPENDED, NULL);
if (ret) {
return true;
}
}
要注入的.DLL的DllMain()函数:
#include <Windows.h>
extern void vMain();
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&vMain, 0, 0, 0);
return true;
}
return false;
}
VMAIN:
void vMain() {
CreateConsole();
std::cout << "vMain() has executed!\n";
}
当我在visual studio中编译时,要注入的.DLL工作正常,但是当我在QT Creator中编译时,vMain()
永远不会被执行。注入器,.DLL和目标进程都是32位。所以我尝试通过使用CreateRemoteThread()
标志调用.DLL注入器调用CREATE_SUSPENDED
来调试目标进程,这样我就可以在LoadLibraryA()
上设置断点,恢复线程,逐步完成从断点执行,并查看返回值。但是,LoadLibraryA()
上的断点没有被击中。
所以我调试了.DLL注入器应用程序以确保正在创建远程线程。我确认通过在GetThreadID()
的返回值上调用CreateRemoteThread()
,输出它,并在目标进程的线程列表中查看该线程:
请记住线程仍然处于暂停状态。经过进一步检查,EIP指向_RtlUserThreadStart()
中的第一条指令。我在这条指令上设置了一个断点。然后我通过从我的.DLL注入器程序中调用ResumeThread()
来恢复被挂起的线程。断点没有被击中。
值得注意的是,目标应用程序没有任何反断点机制,除了这个实例,断点对我来说还没有用。
那我怎么弄清楚问题是什么?有没有理由我的断点没被击中?有没有更好的方法来调试问题?
答案 0 :(得分:0)
从DLL内部执行控制台输出时,您可能需要将stdout
重定向到控制台:
// AllocConsole() instead of CreateConsole()
AllocConsole();
freopen("CONOUT$", "w", stdout); // <====
std::cout << "vMain() has executed!\n";
此外,在DllMain()
内创建线程并不是一个好主意,原因如下:
相关问题:
我记得我过去遇到过一些麻烦,而且我不再按照建议在DllMain()
内创建线程/窗口。
不过,有些情况下它可行,但我不相信它。
话虽如此,如果上述情况不起作用,请尝试直接调用vMain()
而不用线程,看看会发生什么。