【发布时间】:2019-04-19 21:59:41
【问题描述】:
我正在尝试学习一些手动 dll 注入,但似乎无法让 dll 代码的执行工作。我是 Windows C++ 的新手,因此对改进我的代码的任何提示表示赞赏。我也只贴了相关代码。
喷油器程序:
hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, getPID(TARGET_NAME));
DWORD gotDLL = GetFullPathName(DLL_NAME, MAX_PATH, dllPath, NULL);
hFile = CreateFile(dllPath, GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
dllFileSize = GetFileSize(hFile, NULL);
memAddrForDLL = VirtualAllocEx(hProcess, NULL, dllFileSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
loadedDLL = HeapAlloc(GetProcessHeap(), NULL, dllFileSize);
// Load dll into allocated memory in current process
ReadFile(hFile, loadedDLL, dllFileSize, &bytesRead, NULL))
// Find offset of dll entry point
IMAGE_NT_HEADERS* pOldNtHeader = reinterpret_cast<IMAGE_NT_HEADERS*>(reinterpret_cast<BYTE*>(loadedDLL) + reinterpret_cast<IMAGE_DOS_HEADER*>(loadedDLL)->e_lfanew);
IMAGE_OPTIONAL_HEADER* pOldOptHeader = &pOldNtHeader->OptionalHeader;
entryPointOffset = pOldOptHeader->AddressOfEntryPoint;
// Load dll into allocated memory in target process
WriteProcessMemory(hProcess, memAddrForDLL, loadedDLL, bytesRead, NULL)
LPTHREAD_START_ROUTINE entryPoint = (LPTHREAD_START_ROUTINE)((unsigned __int64)memAddrForDLL + entryPointOffset);
CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibrary, entryPoint, NULL, NULL)
DLL:
DWORD WINAPI OnDllAttach(LPVOID base){
typedef void func(void);
func* f = (func*)0x00007FF605EC5835;
f();
FreeLibraryAndExitThread(static_cast<HMODULE>(base),1);
}
BOOL WINAPI OnDllDetach(){
return TRUE;
}
BOOL WINAPI DllMain(_In_ HINSTANCE hinstDll,
_In_ DWORD fdwReason,
_In_opt_ LPVOID lpvReserved){
typedef void func(void);
func* f = (func*)0x00007FF605EC5835;
f();
switch(fdwReason) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDll);
CreateThread(nullptr, 0, OnDllAttach, hinstDll, 0, nullptr);
return TRUE;
case DLL_PROCESS_DETACH:
if(lpvReserved == nullptr)
return OnDllDetach();
return TRUE;
default:
return TRUE;
}
}
目标程序包含这个函数:
void printer(){
cout << "test" << endl;
}
我的注射器产生以下输出
1. Attempting to attatch to process target.exe
--- Got target.exe PID: 14640
--- Got target.exe Handle: 0x0000000000000084
2. Attempting to allocate memory
--- Found dll: D:\projects\injector\hack.dll
--- Got hack.dll Handle: 0x0000000000000088
--- Allocated memory in target.exe at 0x0000017BEB690000
3. Attempting to copy dll to target.exe
--- Allocated memory at 0x00000226A060FFE0
--- Loaded hack.dll in current process at 0x00000226A060FFE0
--- hack.dll is a valid DLL
--- Loaded hack.dll into target.exe at 0x0000017BEB690000
4. Attempting to execute dll
--- Offset from start of file to entrypoint: 0x3cf6
--- Began execution of hack.dll in target.exe at 0x0000017BEB693CF6
使用 Ghidra 我可以确认这是 dll 入口点的正确偏移量。但是当运行我的注入器时,目标进程没有任何反应,我也尝试使用 cout 从 dll 打印一条消息,但我什么也没得到(我认为它甚至不会工作,因为没有任何东西被重新定位)
我正在使用
CreateRemoteThread(hProcess, NULL, NULL, entryPoint, memAddrForDLL, NULL, NULL)
在第 4 个参数被称为 lpStartAddress 之前,我认为这应该需要入口点,但它会导致目标进程崩溃,并且我看到的每个示例都使用了我目前在代码中使用的方式。
在我的 dll 中,我通过地址调用目标进程中的函数。
编辑:我正在我自己的控制台应用程序上对此进行测试。
【问题讨论】:
-
您只是真正证明了 std::cout 不起作用。这是完全正常的,最糟糕的证明注入有效的方法。可能不是您要注入的控制台应用程序。注入的进程可能不使用您正在使用的相同 C++ 库。使用保证相同的函数,例如 CreateFile()。
-
在我的测试用例中,它是一个控制台程序,它将使用与我编译它们相同的库。我将编辑帖子以明确
-
不要在 DllMain 中创建线程
-
@Anders 我刚刚在其他示例中看到了这一点。但无论如何,这并不能解释为什么调用该函数不起作用
标签: c++ windows dll dll-injection