I have written a program (.DLL) which is to be injected into process.exe.
DLL injector code:
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;
}
}
DllMain() function of .DLL to be injected:
#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";
}
The .DLL to be injected works fine when I compile it in visual studio, but when I compile in QT Creator, vMain() never gets executed. The injector, .DLL, and target process are all 32-bit. So I have tried to debug the target process by making the .DLL injector call CreateRemoteThread() with the CREATE_SUSPENDED flag, that way I can set a breakpoint on LoadLibraryA(), resume the thread, step through execution from the breakpoint, and view the return value. However, my breakpoint on LoadLibraryA() isn't being hit.
So I debugged the .DLL injector application to make sure that the remote thread was being created. I confirmed that it is by calling GetThreadID() on the return value of CreateRemoteThread(), outputting it, and viewing that thread in the threadlist of the target process:
Keep in mind the thread is still suspended. Upon further inspection, EIP points to the first instruction in _RtlUserThreadStart(). I set a breakpoint on this instruction. I then resume the suspended thread by calling ResumeThread() from my .DLL injector program. The breakpoint is not hit.
It is noteworthy that the target application does not have any anti-breakpoint mechanism, and breakpoints have worked fine for me apart from this instance.
So how can I figure out what the issue is? Is there a reason my breakpoints are not being hit? Is there a better way to debug the problem?
When doing console output from inside a DLL, you may need to redirect stdout to the console:
// AllocConsole() instead of CreateConsole()
AllocConsole();
freopen("CONOUT$", "w", stdout); // <====
std::cout << "vMain() has executed!\n";
Additionally, It's not a good idea to create threads inside DllMain() and here's why:
https://blogs.msdn.microsoft.com/oldnewthing/20070904-00/?p=25283
https://blogs.msdn.microsoft.com/oldnewthing/20040127-00/?p=40873/
Related question:
Creating a thread in DllMain?
I remember I've had some trouble with it in the past and I stopped doing such things as creating threads / windows inside DllMain(), as recommended.
Still, there are cases where it works, but I wouldn't trust it.
That being said, if the above doesn't work, try to call your vMain() directly without a thread and see what happens.
Related
Hi i'm testing dll hijacking scenario for the educational purpose and i have problem when DllMain loaded i want to create something that keeps my method (Thread) running but the problem is even if i create a new thread still when DllMain reaches at the end my thread killed with it !
if i do something like WaitForSingleObject or while (1) {} it causes the deadlock of course
Also i want to prevent the Main Process (executable file) to exit ! because when the applications loads all modules after that it close him self ! and that's not what i want ! i want to keep the application running . as long as the application is running my thread is live
any thoughts or advise ?
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)LiveBackgroundListenerFunction, 0, 0, 0);
}
//while (1) {} #DeadLock !!!
//WaitForSingleObject(hdl, 100); #DeadLock !!!
return TRUE;
void LiveBackgroundListenerFunction()
{
While(1)
{
Sleep(5000);
//Do Somthing......
}
}
thanks in advance
I'm trying to cleanly inject DLL into foreground window's process, call simple function from this DLL and then cleanly unload the DLL. My injection code:
HWND fgwnd = GetForegroundWindow();
DWORD cur_thread = GetCurrentThreadId();
DWORD fg_pid = 0;
DWORD fg_thread = GetWindowThreadProcessId(fgwnd, &fg_pid);
BOOL res = 0;
const char* inj_path = "C:\\Users\\pc\\source\\repos\\hothook\\x64\\Debug\\fground_injector.dll";
// Get process handle to victim
HANDLE victim = OpenProcess(PROCESS_ALL_ACCESS, FALSE, fg_pid);
// Find exact adress of LoadLibraryA function from text space of kernel32.dll loaded by the OS
// and used by victim
PVOID llib = (LPVOID)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
PVOID flib = (LPVOID)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "FreeLibrary");
// Allocate memory inside victim's address space
LPVOID inj_path_victim = (LPVOID)VirtualAllocEx(victim, NULL, strlen(inj_path)+1,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
// Write inject dll's adress into victim
SIZE_T written;
res = WriteProcessMemory(victim, inj_path_victim, inj_path, strlen(inj_path)+1, &written);
// Finally, inject DLL into victim!
// Spawn thread in remote process ================================================================
HANDLE inj_llib_thread = CreateRemoteThread(
/*I*/ victim, // Handle to process where thread will be created
/*I*/ NULL, // SECURITY_ATTRIBUTES for new thread
/*I*/ 0, // Initial stacks size, bytes. 0 -> default size
/*I*/ (LPTHREAD_START_ROUTINE)llib, // User defined callback LPTHREAD_START_ROUTINE
/*I*/ inj_path_victim, // Ptr to variable to be sent as func parameter
/*I*/ 0, // Creation control flags. 0 -> immediate start
/*O|O*/ NULL); // Ptr to variable that recieves thread ID
// ===============================================================================================
// CANNOT WAIT FOR THREAD IN OTHER PROCESS.... OR CAN I?! I CAN!
// Wait for DLL to get properly injected into victim
res = WaitForSingleObject(inj_llib_thread, INFINITE);
// Get executable base address of the loaded DLL
DWORD llib_exit;
res = GetExitCodeThread(inj_llib_thread, &llib_exit);
// Free previously allocated remote memory
res = VirtualFreeEx(victim, inj_path_victim, 0, MEM_RELEASE);
// Call injected DLL's function
HMODULE fg_inj = LoadLibraryA(inj_path);
PVOID inj_t_proc = (LPVOID)GetProcAddress(fg_inj, "injectThread");
PVOID ulib = NULL;
// Spawn thread in remote process ================================================================
HANDLE inj_thread = CreateRemoteThread(
/*I*/ victim, // Handle to process where thread will be created
/*I*/ NULL, // SECURITY_ATTRIBUTES for new thread
/*I*/ 0, // Initial stacks size, bytes. 0 -> default size
/*I*/ (LPTHREAD_START_ROUTINE)inj_t_proc, // User defined callback LPTHREAD_START_ROUTINE
/*I*/ NULL, // Ptr to variable to be sent as func parameter
/*I*/ 0, // Creation control flags. 0 -> immediate start
/*O|O*/ NULL); // Ptr to variable that recieves thread ID
// ===============================================================================================
// Wait before injected DLL's thread finishes before extraction
res = WaitForSingleObject(inj_thread, INFINITE);
// Extract injected DLL from victim
// Spawn thread in remote process ================================================================
HANDLE inj_flib_thread = CreateRemoteThread(
/*I*/ victim, // Handle to process where thread will be created
/*I*/ NULL, // SECURITY_ATTRIBUTES for new thread
/*I*/ 0, // Initial stacks size, bytes. 0 -> default size
/*I*/ (LPTHREAD_START_ROUTINE)flib, // User defined callback LPTHREAD_START_ROUTINE
/*I*/ (LPVOID)llib_exit, // Ptr to variable to be sent as func parameter
/*I*/ 0, // Creation control flags. 0 -> immediate start
/*O|O*/ NULL); // Ptr to variable that recieves thread ID
// ===============================================================================================
// Wait untill injected DLL is fully extracted from the victim
res = WaitForSingleObject(inj_flib_thread, INFINITE);
DWORD flib_exit;
res = GetExitCodeThread(inj_flib_thread, &flib_exit);
// Extract injection DLL from host
FreeLibrary(fg_inj);
// ^^^ This actually does not unload DLL from host app, even if I call it 100 times in a loop...
// Clean up by closing all utilised handles
CloseHandle(victim);
CloseHandle(inj_llib_thread);
CloseHandle(inj_thread);
CloseHandle(inj_flib_thread);
My injection DLL is truly bare-bones:
BOOL APIENTRY DllMain(HMODULE hm,
DWORD call_reas,
LPVOID reserved)
{
switch(call_reas)
{
case DLL_PROCESS_ATTACH:
{
DisableThreadLibraryCalls(hm);
// I thought that threads calling DllMain with case 2-3 cause crash
// But no, same crash with or without this call
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
DWORD injectThread(LPVOID p)
{
//AllowSetForegroundWindow(ASFW_ANY);
// This is what it originally suppose to do
// Let the host "steal" foreground window status from victim
// But even commenting this out results in the same crash
return 0;
}
The crash happens after I create FreeLibrary remote thread to unload injected DLL. This is as much crash details as I could get, as it happens in the system kernel it seems:
Exception thrown at 0x00007FFE598C7170 in maudswch.exe: 0xC0000005: Access violation executing location 0x00007FFE598C7170.
00007ffe598c7170()
kernel32.dll!00007ffe9ac47034()
ntdll.dll!00007ffe9c682651()
Not Flagged 50864 0 Main Thread Main Thread win32u.dll!00007ffe99e51104
Not Flagged 47548 0 Worker Thread ntdll.dll thread ntdll.dll!00007ffe9c6d0794
Not Flagged 41096 0 Worker Thread ntdll.dll thread ntdll.dll!00007ffe9c6d0794
Not Flagged 43456 0 Worker Thread ntdll.dll thread ntdll.dll!00007ffe9c6d0794
Not Flagged > 29820 0 Worker Thread Win64 Thread 00007ffe598c7170
I tested this on many "victims". CMD, Notepad, my other custom GUI program. The result is the same. DLL gets successfully injected, DLL function gets executed, but when unloading it crashes "victim". One more detail, is that FreeLibrary remote thread takes quite long time to finish, about 1.5 seconds sometimes even 7 seconds!
I'm trying to solve this puzzle for days now, I searched all the Internet, but all other similar cases seems to be non-related... And at this point I have no idea what is going on and how to fix this. Of course, I can just bite the bullet and never try to unload my injected DLL, after all it works. But I don't want to leave useless DLLs in other processes after it finished it's job.
Edit:
Some debug prints. As you can see, hm: and func addr: is outputted in DllMain PROCESS_ATTACH. As you can see, I'm lucky to have base DLL address and function address to be exactly the same in host and victim processes. However, passing full base address to FreeLibrary external thread results in exactly the same crash, so truncated base address was not the real reason behind the crash...
Using GetExitCodeThread() to retrieve the HMODULE returned by LoadLibraryA() in the target process will work only if the victim is a 32bit process. Otherwise, the HMODULE will be too large to fit in the remote thread's exit code, so you will have to use a different mechanism to get the DLL's base address in the target process, such as using EnumProcessModules()+GetModuleFileNameEx() or CreateToolhelp32Snapshot()+Module32(First|Next)(), or even injecting stub code that calls LoadLibraryA() and saves the HMODULE into a variable that the injector allocates and can read from via ReadProcessMemory().
More importantly, the way you are calling the DLL's injectThread() function in the target process is wrong. You are using LoadLibraryA()+GetProcAddress() to get a pointer to the injectThread() function within the injector's process, and then you are assuming that the function is located at the same address in the target process. But the DLL in the target process may have been loaded at a different base address than the DLL in the injector process (especially in light of technologies like ALSR, DLL rebasing, etc).
The correct solution is to get the offset of the injectThread() function within the DLL (which the injector can calculate by subtracting its DLL's base address from the function's address), and then add that offset to the base address of the DLL in the target process.
Also, make sure your injectThread() function has the correct signature that CreateRemoteThread() is expecting. What you showed is missing a calling convention specified, so it will use whatever the compiler's default convention is, which is usually __cdecl. But CreateRemoteThread() requires __stdcall instead.
I used to unload an injected library by calling FreeLibraryAndExitThread from a thread that was created using CreateThread.
The need to unload the library from a different thread rendered this approach impossible. Now I'm using TerminateThread (as it doesn't terminate the thread it's called from, but the one that is passed) and FreeLibrary separately. However as the WinAPI docs suggest this creates a "race condition" and crashes the process. Is there any way to fix this?
Old code:
HMODULE g_hModule{ NULL };
BOOL WINAPI DllMain(HMODULE hModule, DWORD fwdReason, LPVOID lpReserved) {
g_hModule = hModule;
if (fwdReason == DLL_PROCESS_ATTACH) {
DisableThreadLibraryCalls(hModule);
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)main, 0, 0, 0);
}
return TRUE;
}
void Unload(int nExitCode) {
FreeLibraryAndExitThread(g_hModule, (DWORD)nExitCode);
}
New code:
HMODULE g_hModule{ NULL };
HANDLE g_hThread{ NULL };
BOOL WINAPI DllMain(HMODULE hModule, DWORD fwdReason, LPVOID lpReserved) {
g_hModule = hModule;
if (fwdReason == DLL_PROCESS_ATTACH) {
DisableThreadLibraryCalls(hModule);
g_hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)main, 0, 0, 0);
}
return TRUE;
}
void Unload(int nExitCode) {
TerminateThread(g_hThread, (DWORD)nExitCode);
FreeLibrary(g_hModule);
}
Thanks in advance for any help!
The only way to terminate a thread safely, in C++ especially, is to have that thread return from the function passed to CreateThread. This is usually done by setting (say) an atomic<bool> that the thread tests regularly to see if it should exit. You might also use a condition variable (or the Win32 equivalent) to wake the thread up, rather than busy-looping.
TerminateThread is deadly dangerous as, for example, the thread might be holding some kind of critical lock (perhaps the one used by malloc) at the time and that would hang the rest of your app. It should never have been provided in the Win32 API in the first place and you should not use it.
I'm trying to hook the DLL onto a notepad process, and then unhook it. When hooked, the DLL should cause the notepad to create a hidden file whenever the user clicks "Save As" (code for this is not shown). When unhooked, that should not be the case.
However, for some reason, while I got the message "DLL unhooking from process", the DLL still is not unhooked from the notepad process, and I know this because the notepad still creates the additional file when it should not have done that.
There are no error messages on the return values whatsover (at least none that I know of), so I removed most return value checks.
Hook
HANDLE hThread;
char * pid = argv[1];
DWORD user_pid = atoi(pid);
LPCSTR Dllpath = "C:\\Users\\xxx\\Desktop....\\MyDll.dll"
LPVOID pDllPath; // Address in remote process where Dllpath will be copied to.
HMODULE hKernel32 = GetModuleHandle("Kernel32");
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, user_pid);
char * command = argv[2];
if (strcmp(command,"hook") == 0){
SIZE_T bytesWritten = 0;
//Allocate memory to target process, and write dll to the allocated memory.
pDllPath = VirtualAllocEx(hProcess, NULL,strlen(DllPath)+1, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
// Write DLL hook name
WriteProcessMemory(hProcess, pDllPath, (LPCVOID)DllPath, strlen(Dllpath)+1,&bytesWritten);
// Load Dll to remote process
hThread = CreateRemoteThread(hProcess, NULL,0,(LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryA"), pDllPath,0,NULL);
WaitForSingleObject(hThread, INFINITE);
//Clean up
CloseHandle(hThread);
VirtualFreeEx(hProcess, pDllPath, strlen(DllPath+1, MEM_RELEASE);
else if (strcmp(command,"unhook")==0){
InlineUnhook(); //Call unhook inside the dll itself
}
}
Unhook (inside the dll itself)
HANDLE __stdcall InlineUnhook(){
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
LoadLibrary("C:\\Users\\xxx\\Desktop...\\MyDll.dll);
HMODULE hLibModule = GetModuleHandleA ("C:\\Users\\xxx\\Desktop...\\MyDll.dll);
HANDLE hThread = CreateRemoteThread(hProcess, NULL,0,(LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "FreeLibraryAndExitThread"), (void *)(hLibModule,0),0,NULL);
if (hThread == NULL){
OutputDebugStringA("CreateRemoteThread failed.");
return -1;
}
else{
WaitForSingleObject(hThread, INFINITE);
//Clean up
CloseHandle(hThread);
OutputDebugStringA("DLL unhooking from process...");
return 0;
}
}
Your injector is calling InlineUnhook() directly, so it will act on the instance of the DLL that is loaded in the injector process, not the hooked process.
FreeLibraryAndExitThread() is not compatible with CreateRemoteThread(), so you can't use a remote thread to call it directly, like you can with LoadLibraryA().
Inside of the DLL itself, there is no need for it to call OpenProcess(), LoadLibrary(), or CreateRemoteThread() for itself. The DLL can simply call FreeLibraryAndExitThread() directly, like any other local function.
HINSTANCE hThisInst;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
hThisInst = hinstDLL;
...
return 1;
}
void __stdcall InlineUnhook()
{
FreeLibraryAndExitThread(hThisInst, 0);
}
Your injector will have to use a remote thread to call InlineUnhook() within the context of the hooked process, rather than calling it directly. That means you need to:
export InlineUnhook() from the DLL.
find the address of the loaded DLL within the hooked process. If your DLL is 32bit being loaded into a 32bit target process, that address can be obtained from GetExitCodeThread() when CreateRemoteThread() is done calling LoadLibraryA(). Otherwise, you will have to go hunting for the loaded address afterwards, such as by EnumProcessModules() or CreateToolhelp32Snapshot(TH32CS_SNAPMODULE).
find the address of the exported InlineUnhook() within the hooked process. Use LoadLibrary() and GetProcAddress() inside the injector to calculate the offset of InlineUnhook() within the DLL, and then apply that offset to the address of the loaded DLL within the hooked process.
use CreateRemoteThread() to call InlineUnhook() at that calculated address. You will have to change the signature of InlineUnhook() to be compatible with CreateRemoteThread(), eg:
DWORD __stdcall InlineUnhook(LPVOID)
{
FreeLibraryAndExitThread(hThisInst, 0);
return 1;
}
That's because your InlineUnhook call above calls the copy of the dll that is loaded into your injection process, not the one in the target process.
I'm trying to call a process from another program, this process being one I've injected via DLL. The first one, where we load the library "Client.dll" works perfectly, this is sown by the MessageBox Debug in DllMain (DLL_PROCESS_ATTACH).
Once the DLL is loaded into the program, I try to call the function MainThread from Client.dll this however using the same method (copied, pasted, edited) doesn't work. Both are posted below, can anyone tell me why? I have removed all code from MainThread but that for debug reasons.
Here is Main Thread:
void MainThread(void * Arguments)
{
MessageBoxA(NULL, "MainThread Started!", "bla", MB_OK); //Not Shown
for (;;)
{
//This loop is here for the main program loop.
}
_endthread();
}
Here is how I load Client.dll and try to call Main Thread, keep in mind the actual injection works but not the starting of Main Thread.
bool InjectDLL(DWORD ProcessID, const char* Path)
{
HANDLE Handle = OpenProcess(PROCESS_ALL_ACCESS, false, ProcessID);
if (!Handle)
{
std::cout << "Could not access process! Inject Failed!";
return false;
}
LPVOID LoadLibraryAddress = (LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
LPVOID Allocate = VirtualAllocEx(Handle, NULL, strlen(Path), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
WriteProcessMemory(Handle, Allocate, Path, strlen(Path), NULL);
HANDLE Thread = CreateRemoteThread(Handle, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryAddress, Allocate, 0, NULL);
WaitForSingleObject(Thread, INFINITE); // WAIT FOREVER!
VirtualFreeEx(Handle, Thread, strlen(Path), MEM_RELEASE);
//Start DLL Main Thread
LPVOID MainThreadAddress = (LPVOID)GetProcAddress(GetModuleHandleA("Client.dll"), "MainThread");
Allocate = VirtualAllocEx(Handle, NULL, 0, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
WriteProcessMemory(Handle, Allocate, Path, strlen(Path), NULL);
HANDLE MainThread = CreateRemoteThread(Handle, NULL, NULL, (LPTHREAD_START_ROUTINE)MainThreadAddress, Allocate, 0, NULL);
WaitForSingleObject(MainThread, INFINITE); // Wait for Main Thread to start
VirtualFreeEx(Handle, MainThread, strlen(Path), MEM_RELEASE);
CloseHandle(MainThread);
CloseHandle(Thread);
CloseHandle(Handle);
return true;
}
Thanks to anyone who can help.
I don't see any error checking - specifically for the case where you're fetching the address of "MainThread". Is this succeeding?
In order for this to work, you're going to need to explicitly export "MainThread" from your DLL either via a .DEF file or by using __declspec( dllexport ). See this SO link for details.