I'm trying to unload a dll after inject it to a remote process,I use CreateRemoteThread to invoke "LoadLibraryA" in that remote process, which means the thread function is "LoadLibraryA". Now, I'm using the "GetExitCodeThread" to get the exitcode of the thread.
code snippets:
// create remote thread to invoke LoadLibraryA
HANDLE tThread = CreateRemoteThread(remoteProcess, NULL, 0, LoadLibraryAAddr, remoteAddress, 0, NULL);
if (!tThread) {
cout << "failed to create remote thread" << endl;
return 1;
}
// wait for remote thread stop
HMODULE exitCode;
WaitForSingleObject(tThread, INFINITE);
cout << "successfully load library" << endl;
GetExitCodeThread(tThread, (LPDWORD)&exitCode);
// clean up, call FreeLibrary to unload dll
LPTHREAD_START_ROUTINE freeLibraryAddr = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "FreeLibrary");
if (NULL == freeLibraryAddr) {
cout << "failed to get freeLibrary address" << endl;
return 1;
}
declaration of "GetExitCodeThread":
BOOL GetExitCodeThread(
[in] HANDLE hThread,
[out] LPDWORD lpExitCode
);
document for GetExitCodeThread from ms
According to the description of the document, the lpExitCode shoud take the return value of "LoadLibraryA", other words, the base address of dll loaded by "LoadLibraryA". And then I create another remote process to invoke "FreeLibrary" to unload this dll, but failed.
After debugging, I found the problem: lpExitCode just hold the low 32-bit value of which that "LoadLibraryA" returned.
the high 32-bit is 0xcccccccc, because the variable "exitCode" is in stack, which was initialized with 0xcc. This result is easy to explain: the type of "lpExitCode" is LPDWORD, which is a pointer to a 32-bit value, so it can just influence the low 32-bit of "exitCode"
The code from the beginning would run well in x86 environment, cause the address in x86 environment is 32-bit long, which can be pass correctly. However, I run it in x64 environment and the "exitCode" just get low 32-bit of the dll base address, which then passed to FreeLibrary and making the invoke failed. As a result, the dll still lay in the memory of that remote process, which doesn't match my expectation.
So is there any way to get a 64-bit retuen value using GetExitCodeThread or some other windows api, hope someone can reply.
Use
EnumProcessModulesandGetModuleBaseNameAto traverse and compare the name of loaded modules, you can find the target module and return it's base address, then pass the base address toFreeLibraryto unload the module.The above code is just a simple example, without error handling:
moduleHandleListmay out of range when it holds the result, so take care of it.You can check the return values of
EnumProcessModulesandGetModuleBaseNameAto determine whether to call those API functions again with a larger array.