Alright, I'll try to make it quick. I am trying to learn how to inject a DLL in another process. At the moment, I'm only trying to detect when output a message when I open the calculator. I'v written the following DLL:
#include <windows.h>
#include <iostream>
using namespace std;
extern "C"{
LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
cout << "I'M NOT WORKING " << endl;
// Bunch of code...
return CallNextHookEx(0, nCode, wParam, lParam);
}
void ASimpleFunc(){
cout << "DLL WORKING" << endl;
}
}
And here is my injector (well... it's just trying to load the DLL at the moment).
#include <windows.h>
#include <iostream>
using namespace std;
typedef LRESULT (*CBTProc)(int,WPARAM,LPARAM);
typedef void (*ASimpleFunc)();
int main()
{
// My two functions...
LRESULT _CBTProc;
ASimpleFunc _ASimpleFunc;
HMODULE hDll = LoadLibrary("myDLL.dll");
if(!hDll){
cout << "DLL FAILED TO LOAD" << endl;
}else{
cout << "DLL LOAD SUCCESS" << endl;
// This one is working
_ASimpleFunc = (ASimpleFunc)GetProcAddress(hDll, "ASimpleFunc");
// This one is not working
_CBTProc = (CBTProc)GetProcAddress(hDll, "CBTProc");
if(!_ASimpleFunc || !_CBTProc){
cout << "UNABLE TO CALL HOOK" << endl;
}else{
// other code...
}
}
return 1;
}
Any ideas?
EDIT: this is not 100% of the code. I took out the obvious stuff like the DLLMain and everything that doesn't interact directly with my problem.
The CALLBACK macro gives CBTProc stdcall calling convention, so its name will be annotated with a leading underscore and a byte count (e.g., it might be _CBTProc#12). You need to call GetProcAddress with the exact name of the export. The name can be found using the dumpbin tool.
Note that your function pointer must also be annotated with CALLBACK so that when you call the function via the function pointer, the correct calling convention is used.
You need to actually get the DLL to load in the other process for this to work. You do this by creating a remote thread in the other process that will load your DLL.
Then you need to perform your hooks in the loading of the DLLMain to hook the functions you wish to hook.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583(v=vs.85).aspx
http://en.wikipedia.org/wiki/DLL_injection
Those two links should point you in the right direction.
I don't know why one of them would work without this, but if you want a function to be exported from a DLL, you have to explicitly export it. There are two ways to do this:
Tell the compiler through some compiler-specific means.
For Visual C++, use __declspec(dllexport).
Use a module definition file.
Related
I am trying to load a DLL from Console Application. The simple console application is shown below:
#include <iostream>
#include <windows.h>
int main(){
HMODULE handleDll = LoadLibraryA("C:\\Tools\\TestDLL.dll");
if (handleDll)
{
std::cout << "DLL Loaded at Address: " << handleDll << std::endl;
}
FreeLibrary(handleDll);
}
The DLL is supposed to a POP a MessageBox which it does but just flashes on the screen instead of waiting for user input. The DLL code is below:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <Windows.h>
DWORD WINAPI ThreadProc( __in LPVOID lpParameter )
{
MessageBox(NULL, L"Hi From The Thread!", L"Pop a Box!", MB_OK);
return 0;
}
extern "C" __declspec(dllexport)
VOID PopMessageBox()
{
DWORD ThreadID;
HANDLE handleThread;
handleThread = CreateThread(NULL, 0, ThreadProc, 0, 0, &ThreadID);
CloseHandle(handleThread);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
PopMessageBox();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
My question is..how do I make the code in the thread function fully execute without prematurely terminating or causing painful deadlocks? Apologies for my imperfect English and inexperience.
The reason is that you are doing something unsafe in your DllMain: you are calling CreateThread.
You are very limited in what you can do from within DllMain in response to a process attach, a fact that the documentation calls out:
There are significant limits on what you can safely do in a DLL entry point. See General Best Practices for specific Windows APIs that are unsafe to call in DllMain. If you need anything but the simplest initialization then do that in an initialization function for the DLL. You can require applications to call the initialization function after DllMain has run and before they call any other functions in the DLL.
The warning links you to "General Best Pratices" which, among other things, says to "[c]all CreateThread. Creating a thread can work if you do not synchronize with other threads, but it is risky."
Even without the risks associated with synchronizing with other threads, this code is flakey in other ways: for example, your main simply calls FreeLibrary and exits. The thread you had spawned in the DLL, which may literally be mid-execution, will have the code it's supposed to run unmapped. You're literally pulling the rug out from under it!
I've been racking my brain on this for days, and could use some help! I'm able to detect a CBT hook using SetWindowsHookEx when it is hooked to the thread ID of my WPF application, but I'm not able to get it to hook to the Thread ID of another process window when that window becomes the foreground app.
Image 1: Shows that I CAN get the CBT hook for detecting window maximize on the main app's Thread ID
Image 2: Shows that I CANNOT get the CBT hook when listening to another app's Thread ID, and it will crash the app!
I want to avoid sending ThreadId=0 and making it a complete global hook, because I know that I only want to listen to the foreground app, not all apps on the desktop. I want to be able to listen to a few window events before they happen (WH_CBT does this from what I understand) for any window that currently has the foreground focus.
Again, the following code works when the current WPF app becomes the foreground app, but it fails when another app's window becomes the foreground (e.g. Notepad, Internet Explorer, File Explorer, Chrome, etc.).
Full Code: (link to github zip file)
Here are some snippets of the code to show what I did:
DLL that defines the callback (inject.dll):
inject.h: Snippet
typedef void(__stdcall* MYFUNCPTR)(int code, WPARAM wparam, LPARAM lparam);
extern "C" __declspec(dllexport) void Init(MYFUNCPTR funcPtr);
extern "C" __declspec(dllexport) LRESULT CALLBACK CbtProcCallback(int code, WPARAM wparam, LPARAM lparam);
WPARAM wparam, LPARAM lparam);
MYFUNCPTR _handler = 0;
inject.cpp: Snippet
void Init(MYFUNCPTR funcPtr)
{
_handler = funcPtr;
}
LRESULT CALLBACK CbtProcCallback(int code, WPARAM wparam, LPARAM lparam)
{
if (code >= 0)
{
// Only send the code if you are about to MAXIMIZE
if (code == HCBT_MINMAX)
{
if (lparam == SW_MAXIMIZE)
{
_handler(0, wparam, lparam);
}
}
}
return CallNextHookEx(NULL, code, wparam, lparam);
}
DLL that sets the CBT hook (dllwrapper.dll):
dllwrapper.cpp: Snippet
// Load library in which we'll be hooking our functions.
HMODULE dll = LoadLibrary(L"inject.dll");
if (dll == NULL) {
char errorMessage[100];
sprintf_s(errorMessage, "ERR-LoadLibrary failed! ErrorCode=%d", GetLastError());
SendManagedMessage(errorMessage);
return false;
}
SendManagedMessage("LoadLibrary passed!");
// Get the address of the function inside the DLL.
MYPROC iaddr = (MYPROC)GetProcAddress(dll, "Init");
if (iaddr == NULL) {
char errorMessage[100];
sprintf_s(errorMessage, "ERR-GetProcAddress for Init failed! ErrorCode=%d", GetLastError());
SendManagedMessage(errorMessage);
return false;
}
SendManagedMessage("GetProcAddress for Init passed!");
iaddr(OnInjectionCallback);
// Get the address of the function inside the DLL.
HOOKPROC cbtProcAddress = (HOOKPROC)GetProcAddress(dll, "CbtProcCallback");
if (cbtProcAddress == NULL) {
char errorMessage[100];
sprintf_s(errorMessage, "ERR-GetProcAddress for CbtProcCallback failed! ErrorCode=%d", GetLastError());
SendManagedMessage(errorMessage);
return false;
}
SendManagedMessage("GetProcAddress for CbtProcCallback passed!");
// Hook the function
cbtProcHook = SetWindowsHookEx(WH_CBT, cbtProcAddress, dll, _threadId);
if (cbtProcHook == NULL) {
char errorMessage[100];
sprintf_s(errorMessage, "ERR-SetWindowsHookEx cbtProcAddress failed! ErrorCode=%d", GetLastError());
SendManagedMessage(errorMessage);
return false;
}
SendManagedMessage("SetWindowsHookEx for cbtProcAddress passed!");
Snippet exporting to C#
typedef void(__stdcall* CodeCallback)(int code, WPARAM wparam, LPARAM lparam);
typedef void(__stdcall* MessageCallback)(const char* message);
#ifdef __cplusplus
extern "C" { // only need to export C interface if
// used by C++ source code
#endif
__declspec(dllexport) bool StartHooks(unsigned int threadId, MessageCallback messageCallback, CodeCallback codeCallback);
__declspec(dllexport) void StopHooks();
#ifdef __cplusplus
}
#endif
NativeMethods.cs: Snippet of C# dll imports to the WPF app
public delegate void MessageCallback(string message);
public delegate void CodeCallback(int code, IntPtr wParam, IntPtr lParam);
[DllImport("dllwrapper.dll")]
public extern static bool StartHooks(uint threadId, MessageCallback messageHandler, CodeCallback codeHandler);
[DllImport("dllwrapper.dll")]
public extern static void StopHooks();
I can see from the messages in the WPF app window that the hook is passing and not returning any Win32 errors, but it's just not executing the callback when another window has focus (even when using the debugger).
Any help would be greatly appreciated!
Development Environment:
Windows 10 1909
VS2019 16.7.4
C# .NET Framework 4.7.2, C++
When the main app calls Init(), it is calling into its own instance of the DLL, and so is setting its own copy of _handler.
When your hook DLL is injected into another process, that process will get its own copy of the DLL, and thus its own copy of _handler. But Init() is never called on that DLL instance, so its copy of _handler is still 0 when your hook function is invoked inside that process. That is why the process crashes, since the hook is not checking for that condition.
Your DLL in another process can't call a function in your main app across process boundaries. You are going to have to change your hook function to instead use an IPC mechanism of your choosing to communicate with the main app process when _handler is 0. Window messages, pipes, mailslots, sockets, etc can be used for that communication.
I wrote a simple program that does 3 things:
It calls MessageBoxA (MBA) with the text "NOT HOOKED"
Then it loads a dll file that I've created that hooks the MBA function and recalls MBA with the text "HOOKED".
After that, it calls MBA again with the same text ("NOT HOOKED").
Of course, the second MBA call should be hooked and display a message with "HOOKED" text it.
Eventually it calls FreeLibrary and exits.
Here is the .cpp file:
#include <iostream>
#include <Windows.h>
using namespace std;
int main()
{
//Place the path of the dll file here, "DLLs\\HookDLL.dll" is the default path.
char dllPath[] = "HookDLL.dll";
//Display a pop-up message with the "NOT HOOKED" message and title.
MessageBoxA(NULL, "NOT HOOKED", "NOT HOOKED", MB_OK);
//Load the dll file
HMODULE hModule = LoadLibraryA((LPCSTR)dllPath);
//If hModule is null, then the dll wasn't loaded.
//An error message will be printed out to the console.
if (!hModule) {
cout << "Couldn't load the DLL file!" << endl;
return 1;
}
//This is the tricky part.
//This should display a pop-up message like before with the "NOT HOOKED" message and title,
//but the dll that was loaded should hook MessageBoxA function,
//and call a new one with a "HOOKED" message and title instead.
MessageBoxA(NULL, "NOT HOOKED", "NOT HOOKED", MB_OK);
FreeLibrary(hModule);
return 0;
}
here is the .dll file:
#include "pch.h"
#include "detours.h"
#include <iostream>
#include <Windows.h>
using namespace std;
typedef int(WINAPI* MBA)(HWND, LPCSTR, LPCSTR, UINT);
MBA originalMBA = NULL;
int HookedMessageBoxA(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType
) {
return originalMBA(NULL, "HOOKED", "HOOKED", MB_OK);
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD reason,
LPVOID lpReserved
)
{
if (reason == DLL_PROCESS_ATTACH) {
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
originalMBA = (MBA)DetourFindFunction("user32.dll", "MessageBoxA");//Pointer the the original MBA (MessageBoxA) function.
DetourAttach(&(PVOID&)originalMBA, (PVOID)HookedMessageBoxA);
DetourTransactionCommit();
}
return TRUE;
}
When I build and run on Debug mode, it crashes on the second MBA call (in the .cpp file of course):
It displays the hooked MBA with "HOOKED" in it like it should, then the it crashes, printing the error below and the program exits with code 3:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.
This is usually a result of calling a function declared with one calling convention with a function
pointer declared with a different calling convention.
I've checked this error and the exit code and found lots of informative posts and solutions, but I couldn't make any of them work for me (maybe I've done something wrong).
NOTE1:
If I'm on Release mode, I can call as many MBA calls as I want as long as they precedes the FreeLibrary call, and all of them will be hooked fine by the .dll file, and the program will exit correctly.
But if I try to call the MBA function after the FreeLibrary call - the program crashes with this error:
Exception thrown at 0x50011000 in ProgrammingTask.exe: 0xC0000005: Access violation executing location 0x50011000.
NOTE2:
I tried detaching the dll using DetourDetouch, but it didn't solve it, maybe I did it wrong.
Also, I tried reading about CreateRemoteThread, but was too messy for me.
Thanks in advance.
FOUND IT!
Forgot to add __stdcall to the HookedMessageBox function.
So, instead of int HookedMessageBoxA
I rewrote it to this:
int __stdcall HookedMessageBoxA
Thanks all for your help! <3
I use eclipse and mingw compilier (c++).
I would like to create a dll file which contains a lot of strings.
After that I would like to call with LoadString() to read the string (http://msdn.microsoft.com/en-us/library/windows/desktop/ms647486(v=vs.85).aspx)
my dll file:
#define WIN32_LEAN_AND_MEAN
#define DLL_FUNC extern "C" __declspec(dllexport)
DLL_FUNC int __stdcall Hello() {
return 0;
}
my cpp file:
#include <windows.h>
#include <stdio.h>
int main () {
typedef int (__stdcall *HelloProc)();
HMODULE hdll = LoadLibrary("HelloWorld.dll");
if( hdll == NULL){
MessageBox(HWND_DESKTOP, "Wrong dll path", "Message", MB_OK);
}
else {
typedef int (__stdcall *HelloProc)();
HelloProc Hello = (HelloProc)GetProcAddress(hdll, "Hello#0");
if(Hello == NULL){
//LoadString();
MessageBox(HWND_DESKTOP, "Hello is NULL", "Message", MB_OK);
}
else{
Hello();
}
}
return 0;
}
How do I create the strings? And how to call with LoadString()?
I think you want to read about resources so that you can build a resource-only DLL containing a string table. Try searching the MSDN site you referenced for things like resource compiler and maybe how to build a resource only DLL and how to use string tables. I'm sure you will find documentation and examples at Microsoft and, if not, with Google.
Oh, your DLL is not required to be resource only, I got that from your comment "I would like to create a dll file which contains a lot of strings." It is actually even easier (maybe more straightforward) to do if your DLL will also contain code. Then you'd want to search for adding resources to a DLL and things like that.
I have created a global Keyboard hook.
Hook is created in a DLL.
#pragma comment(linker, "/SECTION:.SHARED,RWS")
#pragma data_seg(".SHARED")
static HHOOK hkb=NULL;
static CMyFile *pLF;
#pragma data_seg()
HINSTANCE hins = NULL;
extern "C"
LRESULT __declspec(dllexport) __stdcall CALLBACK KeyBoardHookProc(
int nCode,
WPARAM wParam,
LPARAM lParam)
{
if (nCode < 0) {
return CallNextHookEx(0, nCode, wParam, lParam);
}
return CallNextHookEx(hkb, nCode, wParam, lParam);
}
extern "C"
LRESULT __declspec(dllexport) __stdcall CALLBACK Install()
{
pLF = new CMyFile(L"c:\\1.txt");
hkb = SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyBoardHookProc,hins,0);
return 0;
}
extern "C"
BOOL __declspec(dllexport) __stdcall CALLBACK UnInstall()
{
return UnhookWindowsHookEx(hkb);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH :
hins = (HINSTANCE) hModule;
break;
case DLL_THREAD_ATTACH :
break;
case DLL_THREAD_DETACH :
break;
case DLL_PROCESS_DETACH :
break;
}
return TRUE;
}
I have craeted one EXe that loads this dll and calls install function of the hook dll.
HMODULE hMod = LoadLibrary(L"hk.dll");
if(hMod!=NULL)
{
typedef LRESULT (__stdcall CALLBACK *_installhk)() ;
_installhk installProc;
installProc = (_installhk) GetProcAddress(hMod,"Install");
if(installProc!=NULL)
{
installProc();
}
}
While debugging breakpoint on KeyBoardHookProc is being hit only once when I launch the exe.
The exe keeps on running unless I close it but if I enter anything else from keyboard the hook procedure not getting called.
What could be the reason for this?
Is this not the right way to setup global keyboard hook?
How did you test that the hook procedure is not called ? If you tried to check it with a breakpoint, you have to take care that your hook dll is loaded in every process but your breakpoint is only put in your current process.
If you have any window in your application, focus on it before hitting keys or debug it using logs.
Another solution is to hook with WH_KEYBOARD_LL which does not require an extra DLL. You can hook directly from your process.
Have a look at the late Paul DiLascia's code which installs a global keyboard hook to trap the Ctrl+Alt+Del, Task Manager. MSDN September 2002 'Disabling keys in XP with TrapKeys'
Hope this helps,
Best regards,
Tom.
This may not be directly related to your main problem, but your use of the CMyFile object has several issues:
The CMyFile object is allocated dynamically using new CMyFile(...). This will create it only in the memory space of one process.
The pLF pointer is uninitialized. This means it will be placed in the BSS segment instead of the shared data segment. To fix this, declare it with CMyFile *pLF = NULL;.
CMyFile itself probably has members containing file handles and/or pointers which won't work properly in other processes.
Regarding your main question:
You seem to be creating the hook correctly as far as I can see.
There is no need to cast to HOOKPROC in the call to SetWindowsHookEx. If you get a warning without it, there is a problem with your function type.
There's no need for the if statement in the hook proc - the first parameter to CallNextHookEx is ignored anyway on modern Windows, so both branches effectively do the same thing.
I don't know if I'd trust debugger breakpoints on a hook procedure called from different processes - it's possible that the procedure is called but the debugger isn't catching it.
extern "C" is good it will get rid of the name mangling mentioned above but __stdcall will conflict with this.
You should use the RegisterHoyKey API call instead - it's much less hassle (as I found out myself recently when I replaced a similar keyboard hook DLL!).
Check your export section for DLL and see what name linker exported your "Install" function. C++ mangles with export function names. I bet you anything it is not "Install" but rather _Install#12 or something like that.