How to safely call TerminateThread and FreeLibrary (WinAPI, C++) - c++

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.

Related

Prevent exit from DllMain with dll hijacking in c++

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

Where should I add my own code in the service template?

Microsoft provides a complete service sample to start with writing Windows services. However, I do not understand the following part from this file :
ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 );
// TO_DO: Perform work until service stops.
while(1)
{
// Check whether to stop the service.
WaitForSingleObject(ghSvcStopEvent, INFINITE);
ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
return;
}
I don't understand the point of the infinite loop containing a return statement. Doesn't it defeat the purpose ?
It seems to encourage to write the service content before the while loop but then, if we do not reach the following line :
WaitForSingleObject(ghSvcStopEvent, INFINITE);
... The service will not able to stop when the proper event is triggered, would it ?
Is this template flawed ? How can I make my service wait for an external trigger without making it impervious to stop calls ?
Yes, that example is not particularly well-written. The main loop of the service is better written (conceptually) as:
// Main processing loop
while (!quit)
do_work ();
ReportSvcStatus (SERVICE_STOPPED, NO_ERROR, 0);
return;
And in the service's control handler, you would have:
// CtrlHandler callback
DWORD WINAPI CtrlHandler (DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
...
if (dwControl == SERVICE_CONTROL_STOP)
quit = true;
return NO_ERROR;
}
Where quit is a global variable.
In practise (to avoid busy looping), the service probably normally sits around waiting on some sort of waitable object for something to do. Let's imagine, for the sake of argument, that's a HANDLE called, say, ghWakeupEvent, created via CreateEvent(), and again stored in a global variable.
Then, the code becomes something like:
// Main processing loop
while (1)
{
WaitForSingleObject (ghWakeupEvent, INFINITE);
if (quit)
{
ReportSvcStatus (SERVICE_STOPPED, NO_ERROR, 0);
return;
}
if (something_to_do)
do_work ();
}
// CtrlHandler callback
DWORD WINAPI CtrlHandler (DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
...
if (dwControl == SERVICE_CONTROL_STOP)
{
quit = true; // do this first!!
SetEvent (ghWakeupEvent);
}
return NO_ERROR;
}
Note: no need for (or point in) ghSvcStopEvent. The MSDN sample is a mixed-up mess.

Debugging .DLL Injection Issue - Breakpoint On Supposedly Executing Code Not Being Hit

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.

c++ Run-Time Check Failure #0 - The value of ESP was not properly saved across ... Points to check for simple worker thread

I have a dialog. in this dialog ::OnInitDialog() I create a thread AfxBeginThread((AFX_THREADPROC)MyThreadProc, NULL); It crashes when I close the dialog with run time check failure, and it is pointing to thrdcore.cpp file (Microsoft Foundation Classes C++ library)
// first -- check for simple worker thread
DWORD nResult = 0;
if (pThread->m_pfnThreadProc != NULL)
{
nResult = (*pThread->m_pfnThreadProc)(pThread->m_pThreadParams);
ASSERT_VALID(pThread);
}
I have a code to kill the thread OnClose function, but it doesn't solve the issue. Can some help, what I am missing? My code for
HANDLE m_hExit;
DWORD dwResult = 0;
unsigned threadID = 0;
...
OnInitDialog()
{...
m_hExit = (HANDLE)AfxBeginThread((AFX_THREADPROC)MyThreadProc, NULL);
}
OnClose()
{
dwResult = WaitForSingleObject(m_hExit, 0);
if (dwResult == WAIT_TIMEOUT)
{
printf("The thread is still running...\n");
}
else
{
printf("The thread is no longer running...\n");
}
Sleep(10000);
dwResult = WaitForSingleObject(m_hExit, 0);
if (dwResult == WAIT_TIMEOUT)
{
printf("The thread is still running...\n");
}
else
{
printf("The thread is no longer running...\n");
}
CDialog::OnClose();
}
thread function is very big((((
AfxBeginThread is documented as requiring the threadproc to be
UINT __cdecl MyControllingFunction( LPVOID pParam );
Your comment says your function is
UINT WINAPI MyThreadProc( LPVOID pParam )
WINAPI is defined as _stdcall (see here)
So you have a mismatch of calling conventions. As others already commented, the cast is suspicious. In fact, that's the only reason your code is compiling. If you remove the cast, the compiler should show an error.
The solution is to remove the cast and then fix the calling convention of your function. Once that code compiles correctly without the cast, it should run properly without corrupting the stack.

Calling a function in an injected DLL?

Using C++, I have an application which creates a remote process and injects a DLL into it. Is there a way to get the remote application to execute a function exported from the DLL, from the application which created it? And is it possible to send parameters to that function? Please note that I am trying to stay away from doing anything within DllMain.
Note:
For a much better answer, please see my update posted below!
Okay so here's how I was able to accomplish this:
BOOL RemoteLibraryFunction( HANDLE hProcess, LPCSTR lpModuleName, LPCSTR lpProcName, LPVOID lpParameters, SIZE_T dwParamSize, PVOID *ppReturn )
{
LPVOID lpRemoteParams = NULL;
LPVOID lpFunctionAddress = GetProcAddress(GetModuleHandleA(lpModuleName), lpProcName);
if( !lpFunctionAddress ) lpFunctionAddress = GetProcAddress(LoadLibraryA(lpModuleName), lpProcName);
if( !lpFunctionAddress ) goto ErrorHandler;
if( lpParameters )
{
lpRemoteParams = VirtualAllocEx( hProcess, NULL, dwParamSize, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
if( !lpRemoteParams ) goto ErrorHandler;
SIZE_T dwBytesWritten = 0;
BOOL result = WriteProcessMemory( hProcess, lpRemoteParams, lpParameters, dwParamSize, &dwBytesWritten);
if( !result || dwBytesWritten < 1 ) goto ErrorHandler;
}
HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpFunctionAddress, lpRemoteParams, NULL, NULL );
if( !hThread ) goto ErrorHandler;
DWORD dwOut = 0;
while(GetExitCodeThread(hThread, &dwOut)) {
if(dwOut != STILL_ACTIVE) {
*ppReturn = (PVOID)dwOut;
break;
}
}
return TRUE;
ErrorHandler:
if( lpRemoteParams ) VirtualFreeEx( hProcess, lpRemoteParams, dwParamSize, MEM_RELEASE );
return FALSE;
}
//...
CStringA targetDll = "injected.dll"
// Inject the target library into the remote process
PVOID lpReturn = NULL;
RemoteLibraryFunction( hProcess, "kernel32.dll", "LoadLibraryA", targetDll.GetBuffer(MAX_PATH), targetDll.GetLength(), &lpReturn );
HMODULE hInjected = reinterpret_cast<HMODULE>( lpReturn );
// Call our exported function
lpReturn = NULL;
RemoteLibraryFunction( hProcess, targetDll, "Initialize", NULL, 0, &lpReturn );
BOOL RemoteInitialize = reinterpret_cast<BOOL>( lpReturn );
This can also be used to send parameters to a remote function via a pointer to a struct or union, and gets around having to write anything in DllMain.
So after some elaborate testing, it would seem that my previous answer is anything but foolproof(or even 100% functional, for that matter), and is prone to crashes. After giving it some thought, I've decided to take an entirely different approach to this... using Interprocess Communication.
Be aware... this method utilizes code in DllMain.
So don't go overboard, and be sure to follow safe practices when doing this, so that you don't end up in a deadlock...
Most notably, the Win32 API offers the following useful functions:
CreateFileMapping
MapViewOfFile
OpenFileMapping
With the use of these, we can simply tell our Launcher process exactly where our remote init function resides, straight from the injected dll itself...
dllmain.cpp:
// Data struct to be shared between processes
struct TSharedData
{
DWORD dwOffset = 0;
HMODULE hModule = nullptr;
LPDWORD lpInit = nullptr;
};
// Name of the exported function you wish to call from the Launcher process
#define DLL_REMOTEINIT_FUNCNAME "RemoteInit"
// Size (in bytes) of data to be shared
#define SHMEMSIZE sizeof(TSharedData)
// Name of the shared file map (NOTE: Global namespaces must have the SeCreateGlobalPrivilege privilege)
#define SHMEMNAME "Global\\InjectedDllName_SHMEM"
static HANDLE hMapFile;
static LPVOID lpMemFile;
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
TSharedData data;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hModule);
// Get a handle to our file map
hMapFile = CreateFileMappingA(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, SHMEMSIZE, SHMEMNAME);
if (hMapFile == nullptr) {
MessageBoxA(nullptr, "Failed to create file mapping!", "DLL_PROCESS_ATTACH", MB_OK | MB_ICONERROR);
return FALSE;
}
// Get our shared memory pointer
lpMemFile = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (lpMemFile == nullptr) {
MessageBoxA(nullptr, "Failed to map shared memory!", "DLL_PROCESS_ATTACH", MB_OK | MB_ICONERROR);
return FALSE;
}
// Set shared memory to hold what our remote process needs
memset(lpMemFile, 0, SHMEMSIZE);
data.hModule = hModule;
data.lpInit = LPDWORD(GetProcAddress(hModule, DLL_REMOTEINIT_FUNCNAME));
data.dwOffset = DWORD(data.lpInit) - DWORD(data.hModule);
memcpy(lpMemFile, &data, sizeof(TSharedData));
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
// Tie up any loose ends
UnmapViewOfFile(lpMemFile);
CloseHandle(hMapFile);
break;
}
return TRUE;
UNREFERENCED_PARAMETER(lpReserved);
}
Then, from our Launcher application, we will do the usual CreateProcess + VirtualAllocEx + CreateRemoteThread trick to inject our Dll, making sure to pass in a pointer to a proper SECURITY_DESCRIPTOR as the 3rd parameter to CreateProcess, as well as passing the CREATE_SUSPENDED flag in the 6th parameter.
This is to help ensure that your child process will have the proper privileges to read and write to a global shared memory namespace, though there are also other ways to achieve this (or you could test without the global path altogether).
The CREATE_SUSPENDED flag will ensure that the dllmain entry point function would have finished writing to our shared memory before other libraries are loaded, which allows easier local hooking later on...
Injector.cpp:
SECURITY_ATTRIBUTES SecAttr, *pSec = nullptr;
SECURITY_DESCRIPTOR SecDesc;
if (InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION) &&
SetSecurityDescriptorDacl(&SecDesc, TRUE, PACL(nullptr), FALSE))
{
SecAttr.nLength = sizeof(SecAttr);
SecAttr.lpSecurityDescriptor = &SecDesc;
SecAttr.bInheritHandle = TRUE;
pSec = &SecAttr;
}
CreateProcessA(szTargetExe, nullptr, pSec, nullptr, FALSE, CREATE_SUSPENDED, nullptr, nullptr, &si, &pi);
After injecting the DLL into the target process, all you need to do is use the same (more or less) file mapping code from your DLL project into your Launcher project (except for the part where you set the shared memory's contents, of course).
Then, calling your remote function is just a simple matter of:
// Copy from shared memory
TSharedData data;
memcpy(&data, lpMemFile, SHMEMSIZE);
// Clean up
UnmapViewOfFile(lpMemFile);
CloseHandle(hMapFile);
// Call the remote function
DWORD dwThreadId = 0;
auto hThread = CreateRemoteThread(hProcess, nullptr, 0, LPTHREAD_START_ROUTINE(data.lpInit), nullptr, 0, &dwThreadId);
Then you can ResumeThread on the target process's main thread, or from your remote function.
As an added bonus... Using this form of communication can also open up several doors for our Launcher process, as it can now directly communicate with the target process.
But again, be sure that you don't do too much in DllMain and, if at all possible, simply use your remote init function (where it is also safe to use named mutexes, for example) to create a separate shared memory map and continue communication from there.
Hope this helps someone! =)