Start Application within a DLL - c++

So I want to create a Dll that contains an application. My code:
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
StartApp();
break;
}
return TRUE;
}
And the StartApp function:
void StartApp()
{
//some declartions
iPtr->Start();
}
The thing is that the function Start() is running in a continuous loop (sth like while(true)) and I think that's the problem cause the dll never gets to break and return true. I tried to run it in a different thread but this isn't working.
So my question is what can I do to use the dll?
Is there a problem if DllMain doesnt finish and doesn't return TRUE?

Yes, there is a problem is DllMain doesn't return, as the documentation states:
When a DLL entry-point function is called because a process is loading, the function returns TRUE to indicate success. For processes using load-time linking, a return value of FALSE causes the process initialization to fail and the process terminates. For processes using run-time linking, a return value of FALSE causes the LoadLibrary or LoadLibraryEx function to return NULL, indicating failure. (The system immediately calls your entry-point function with DLL_PROCESS_DETACH and unloads the DLL.) The return value of the entry-point function is disregarded when the function is called for any other reason.
Source.
You may create a wrapper function for the StartApp function, and expose it via your dll. After that you can call the exported StartApp function from your executable (after you loaded the dll). Make sure you call it from a different thread as it will block.

Related

Unhooking a hook set with SetWindowsHookEx more than once crashes the hooked process

I am trying to hook the keyboard and mouse events of a target application.
I followed the SO question How to hook external process with SetWindowsHookEx and WH_KEYBOARD, and the hooks are installed and uninstalled correctly the first time. However, after I uninstall the hook once and then install it again, trying to uninstall the hook the second time crashes the target application. The purpose of the hook is to monitor application idle time, so that I can do some tasks when the application is idle.
I apologize for the length of the question, but I tried to put in all the details that might help
Thanks
I need to be able to install and uninstall the hooks based on menu commands from a system tray icon. I have a console application [HookApp] which calls the install and uninstall methods in a DLL [HookDLL]. The console application also creates a window to handle menu events. I use the thread of the window to actually install and uninstall the hooks, because the same thread that installed the hook must uninstall it. The Console and the window both must be invisible. Only the system tray icon and its associated menu must be visible.
I start the hooking application from the command line with the parameters
i. ProcessId of the target process
ii. Process Name
iii. Idle time [in seconds] -Idle time before starting the action in the DLL
I am wondering if the timer I start in the HookProcs is responsible for the crash.
Event Viewer Logs
Faulting application name: notepad.exe, version: 10.0.17134.1, time stamp: 0x9d4727c2
Faulting module name: HookDLL_x64.dll_unloaded, version: 0.0.0.0, time stamp: 0x5c31aabd
Exception code: 0xc0000005
Fault offset: 0x00000000000ba505
Faulting process id: 0x2bac
The exception code seems to suggest a memory access violation.
I have tried the following
I.
a. Call the SendMessageTimeout API with HWND_BROADCAST from HookApp
b. Call the SendMessageTimeout API with HWND_BROADCAST from HookDLL
based on Unloading DLL from all processes after unhooking global CBT hook
II.
a. call FreeLibraryAndExitThread API in the DLLMain method on DLL_PROCESS_DETACH AND DLL_THREAD_DETACH -both together and singly
based on http://www.rohitab.com/discuss/topic/42505-unloading-dll-crashes-exe/
III. Made the HookApp console and the window visible and hidden to see if it makes any difference
IV. Was unable to try the following because of 64 bit architecture
https://www.unknowncheats.me/forum/programming-for-beginners/73377-unload-injected-dll-thread-process.html
Other Links I referred to
a. Several programs crash when unhooking with UnhookWindowsHookEx()
b. How to correctly use SetWindowsHookEx & CallNextHookEx
c. Unloading an Injected DLL
d. FreeLibraryAndExitThread crashes program when unloading injected DLL
//Code in the DLL
extern "C" __declspec(dllexport) void install(unsigned long threadID,int _nIdleTime) {
nIdleTime = _nIdleTime;
Log(L"install proc called from app: _nIdleTime", _nIdleTime);
hhKeyboard = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hinst, threadID);
hhMouse = SetWindowsHookEx(WH_MOUSE, MouseProc, hinst, threadID);
logger->Log("Install");
logger->Log("Keyboard", (LONG)hhKeyboard);
logger->Log("Mouse", (LONG)hhMouse);
}
//Uninstall the dll from the Target Process
DWORD WINAPI UnInjectDLLFromTarget() {
uninstall();
//DWORD_PTR dwResult = 0;
//SendMessageTimeout(HWND_BROADCAST, WM_NULL, 0, 0, SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG, 1000, &dwResult);
return TRUE;
}
LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam) {
if (code < 0) {
return CallNextHookEx(0, code, wParam, lParam);
}
StartTimer();
Beep(1000, 20);
return CallNextHookEx(hhKeyboard, code, wParam, lParam);
}
LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam) {
if (code < 0) {
return CallNextHookEx(0, code, wParam, lParam);
}
// StartTimer();
//Beep(1000, 20);
return CallNextHookEx(hhMouse, code, wParam, lParam);
}
BOOL WINAPI DllMain(__in HINSTANCE hinstDLL, __in DWORD fdwReason, __in LPVOID lpvReserved) {
if (fdwReason == DLL_PROCESS_DETACH || fdwReason==DLL_THREAD_DETACH) {
FreeLibraryAndExitThread(hinstDLL, 0);
return 0;
}
}
//Code in the Application [HookApp]
Similar to [But not exactly the same - It is a bit more involved because of the need to create the message pump and the menu event handling window]
HINSTANCE hinst = LoadLibrary(_T("MyDLL.dll"));
if (hinst) {
typedef void (*Install)(unsigned long);
typedef void (*Uninstall)();
Install install = (Install) GetProcAddress(hinst, "install");
Uninstall uninstall = (Uninstall) GetProcAddress(hinst, "uninstall");
install(threadID);
Sleep(20000);
uninstall();
}
SendMessageTimeout in the DLL [HookDLL] method Uninstall immediately crashes the application
SendMessageTimeout in the application [HookApp] doesnt appear to do anything useful.
FreeLibraryAndExitThread does not appear to do anything useful.
However, with 2 and 3, I think I am able to install the hook for the second time. Without them, the first unhook crashes the application.
I was unable to try the suggestion using assembly language inline because of 64 bit architecture.
Please help.
for uninstall hook and unload your dll all what you need - call UnhookWindowsHookEx for every hook handle obtained by a previous call to SetWindowsHookEx. all. you not need call FreeLibrary[AndExitThread] yourself. system auto call FreeLibrary on your hook dll after UnhookWindowsHookEx callend, when first (any) message will be received by target application thread and this thread call GetMessage or PeekMessage. so for just unload your dll after several UnhookWindowsHookEx - you need post message to thread, for which you install hook. if you do this for concrete single thread (dwThreadId) - you need PostThreadMessageW(dwThreadId, WM_NULL, 0, 0); - system yourself call FreeLibrary ( called from user32!__ClientFreeLibrary which called from ntdll!KiUserCallbackDispatcher - called inside GetMessage or PeekMessage when thread (or it window) got any message)
call FreeLibrary from dll for yourself - always error - if assume dll will be unloaded by this call - to where we return after call ? to unloaded place. call FreeLibraryAndExitThread exist sense in some cases, but only from thread, which you create yourself. call FreeLibraryAndExitThread from dll entry point at all fatal error - you kill not self thread, thread which you kill - hold critical section (loader lock) inside which called dll entry point - so fatal error. and at all absolute senseless call here - if you say receive DLL_PROCESS_DETACH this mean that dll already in unload process. DLL_THREAD_DETACH - arbitrary point, why and how many time you try call unload for self here ? exit thread while holding process wide critical section without release it. fatal error.
also because the same thread that installed the hook must uninstall it. - this is not true. another thread from also can do this.
also StartTimer(); in your code look like suspicious here. what this code is do ? are and where you cancel timer ?

Why does DLL_THREAD_DETACH happen twice?

I am learning COM. I wrote a simple COM component in the DLL and registered it in the registry. Then I created a simple client and tried to use my COM component. But I don't understand the DllMain behaviour (I read this also).
extern "C" BOOL WINAPI DllMain(
_In_ HINSTANCE hinstDLL,
_In_ DWORD fdwReason,
_In_ LPVOID lpvReserved){
pDll = hinstDLL;
if (DLL_PROCESS_ATTACH == fdwReason){
trace("DllMain(): DLL_PROCESS_ATTACH");
}
else if (DLL_THREAD_ATTACH == fdwReason){
trace("DllMain(): DLL_THREAD_ATTACH");
}
else if (DLL_PROCESS_DETACH == fdwReason){
trace("DllMain(): DLL_PROCESS_DETACH");
}
else if (DLL_THREAD_DETACH == fdwReason){
trace("DllMain(): DLL_THREAD_DETACH");
}
else{
trace("DllMain(): unknown variant...");
}
return TRUE;
}
I expected for each DLL_PROCESS_ATTACH one DLL_PROCESS_DETACH to be called and for each DLL_THREAD_ATTACH one DLL_THREAD_DETACH to be called (if the exception doesn't happen).
But I see for a single DLL_PROCESS_ATTACH there are two DLL_THREAD_DETACH:
Why does it happen?
About DLL_THREAD_ATTACH :
Note that a DLL's entry-point function is called with this value only by threads created after the DLL is loaded by the process. When a DLL is loaded using LoadLibrary, existing threads do not call the entry-point function of the newly loaded DLL.
There is no relation between the number of DLL_THREAD_ATTACH and DLL_THREAD_DETACH. It's all about loading and creation time. When a thread is created while a DLL is loaded, DLL_THREAD_ATTACH will be called. When a thread exits while a DLL is loaded, DLL_THREAD_DETACH will be called. A thread will never be preempted by a DLL, so the THREAD calls can only happen at creation and end of a thread.
In you case, the log only says that you didn't create a thread after loading the DLL, but two thread exited before unloading the DLL.

How to get function address from loader DLL?

I have got 2 DLLs. DLL1 will be presented as MyDLL.dll and DLL2 is just a DLL containing extensions to MyDLL.
So to get these extensions from DLL2 to MyDLL, I need to load DLL2 inside MyDLL using LoadLibrary(). But here comes the problem. MyDLL contains one function, which will be very important in DLL2. And I need to reach that function. How do I do it?
#include <Windows.h>
#include <stdio.h>
#include "DLL1API.h"
typedef DLL1API* (*PGetDLL1API)();
DLL1API *g_API;
void Init();
BOOL WINAPI DllMain(HINSTANCE hMod, DWORD dwReason, LPVOID reserve){
switch(dwReason){
case DLL_PROCESS_ATTACH:
Init();
break;
}
}
void Init(){
PGetDLL1API GetDLL1API;
HMODULE mainDllMod=GetModuleHandleA("MyDLL.dll"); //how do I reach module of DLL1?
GetDLL1API=(PGetDLL1API)GetProcAddress(mainDllMod,"GetDLL1API");
if(GetDLL1API){
g_API=GetDLL1API();
printf("DLL1API: %p",g_API);
} else { //always gets to this result :(
printf("Error, failed to get GetDLL1API()!\n");
}
}
Other thing is, that I am scared to use LoadLibrary("MyDLL.dll") inside DLL2, because I think it would cause one big infinite loadLibrary loop (MyDll => DLL2 => MyDLL ...)
Calling LoadLibrary from inside DllMain is not recommended. Fix that, and your circular loading concerns will go away as well.
BTW DLL2 doesn't need to load DLL1. It can use GetModuleHandle to find the already-loaded DLL to pass to GetProcAddress, use a static import, or DLL1 can call a function exported from DLL2 passing a function pointer.
More suggested reading, with specific notes on LoadLibrary: http://blog.barthe.ph/2009/07/30/no-stdlib-in-dllmai/
You are right to not want to use LoadLibrary in DllMain. Using LoadLibrary in DllMain is expressly forbidden according to this Microsoft page. Also, GetModuleHandle only works if the DLL has already been loaded by the current process.
Are you really sure you need to load the DLL from your DllMain? You could just call GetModuleHandle from your exported functions, assuming of course that the module has been loaded by the program already.

How to get a DLL loading process handle

I'm trying to get the handle to the process which loaded a dll from the dll.
My approach is:
in DLL_PROCESS_ATTACH I call EnumWindows(EnumWindowsProc,NULL);
my EnumWindowsProc implementation is the following:
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) {
if(GetCurrentProcessId() == GetWindowThreadProcessId(hWnd,NULL)){
MessageBox(hWnd,L"I loaded your dll!",L"it's me",MB_OK);
return TRUE;
}
return FALSE;
}
the problem is that GetCurrentProcessId() == GetWindowThreadProcessId(hWnd,NULL) is never true (if i place the messagebox call outside the if block everything works but it gets called once for every listed window).
Is there any other way to get to the point? Is this approach totally wrong or am I just missing something?
Thanx in advance
Use GetCurrentProcess, which returns a pseudo-handle to the current process. If you need a real handle, pass in the pseudo-handle to DuplicateHandle.
Note that it is very dangerous to do too much in DllMain. Calling anything other than KERNEL32 functions is quite dangerous, and even then there are some KERNEL32 functions that you shouldn't be calling. See the DllMain documentation, this document, and several blog posts from Microsoft developers recommending against doing too much in DllMain.
Easiest way would be to simply use GetCurrentProcess whenever you need the handle.
Try calling GetProcessHandleFromHwnd().
You made a mistake:
GetWindowThreadProcessId does not return the process ID but the thread ID.
Your program must be written like this:
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) {
DWORD process;
GetWindowThreadProcessId(hWnd,&process);
if(GetCurrentProcessId() == process){
MessageBox(hWnd,L"I loaded your dll!",L"it's me",MB_OK);
return TRUE;
}
return FALSE;
}

Explicit Linking DLL and Program Hangs

I've the following piece of code in my program which dynamically links wtsapi32.dll file for session notifications like WTS_SESSION_LOCK and WTS_SESSION_UNLOCK and runs in background. After the first lock/unlock the program hangs and not responding.
Is this a right way of doing explicit linking ?
void RegisterSession(HWND hwnd)
{
typedef DWORD (WINAPI *tWTSRegisterSessionNotification)( HWND,DWORD );
tWTSRegisterSessionNotification pWTSRegisterSessionNotification=0;
HINSTANCE handle = ::LoadLibrary("wtsapi32.dll");
pWTSRegisterSessionNotification = (tWTSRegisterSessionNotification) :: GetProcAddress(handle,"WTSRegisterSessionNotification");
if (pWTSRegisterSessionNotification)
{
pWTSRegisterSessionNotification(hwnd,NOTIFY_FOR_THIS_SESSION);
}
::FreeLibrary(handle);
handle = NULL;
}
Edited:
I have another method UnRegisterSession() function which calls WTSUnRegisterSessionNotification, I am calling the RegisterSession() in WinMain method ( removed FreeLibrary as suggested by 1800) and calling UnRegisterSession() in WM_DESTROY of CALLBACK WindowProcedure function. But still the application hangs.
I'd say you probably cannot safely call FreeLibrary like that - you will be unloading the code you want to have call you. You should probably ensure not to free the dll until after you are finished getting notifications.
MS documentation suggests that you must call WTSUnRegisterSessionNotification before re-registering the session - as it only happens on your second attempt to lock it perhaps this is your issue?
With 1800 wrt the free library - you must keep this library loaded while you use it.
According to the documentation (http://msdn.microsoft.com/en-us/library/aa383841(VS.85).aspx):
"When a window no longer requires these notifications, it must call WTSUnRegisterSessionNotification before being destroyed."
I would try unregistering the notification during WM___CLOSE instead of WM_DESTROY.