Global Keyboard Hook Spy? - c++

I'm writing up a quick tool in C# thats meant to sort of be a virtual keyboard. At the moment I am using SendKeys. I want to know if keyloggers would capture the keys so I found this code but i don't have mfc installed so i cant compile nor run it
How might i key if SendKeys is being logged by keyloggers or how do I get the code (snippet below) running in a single exe to test my code with?
#include <Windows.h>
static UINT uMsg = 0;
static HWND hWndMain = 0;
static HHOOK hKeyHook = NULL ;
#pragma data_seg()
HINSTANCE hInstance = 0;
HOOKPROC lpfnHookProc = 0;
LRESULT __stdcall KeyboardFunc (int nCode, WPARAM wParam, LPARAM lParam)
{
BOOL bPassToChain;
char szDebug [100];
// Check for exception cases...
if (nCode < 0)
return (CallNextHookEx (hKeyHook, nCode, wParam, lParam));
if (nCode == HC_NOREMOVE)
return (CallNextHookEx (hKeyHook, nCode, wParam, lParam));
switch (wParam)
{
case VK_F2:
wsprintf (szDebug, "F2 key message, lparam = 0x%X\n", lParam);
OutputDebugString (szDebug);
// only send on keydown, not keyup (autorepeat)
if (HIWORD (lParam) & 0xC000)
{
OutputDebugString ("F2 Keyup\n");
}
else
{
wsprintf (szDebug, "Sending F2 keydown message %d to hwnd 0x%X\n",
uMsg, hWndMain);
OutputDebugString (szDebug);
PostMessage (hWndMain, uMsg, 0, 0);
}
bPassToChain = FALSE;
break;
default :
bPassToChain = TRUE ;
break ;
}
if (bPassToChain)
return (CallNextHookEx (hKeyHook, nCode, wParam, lParam));
else
return TRUE ; // We have processed this key
}
BOOL __stdcall InstallExampleKeyboardHook (HWND hWnd, UINT uMyMsg)
{
hWndMain = hWnd ;
uMsg = uMyMsg;
lpfnHookProc = (HOOKPROC) KeyboardFunc ;
hKeyHook = SetWindowsHookEx (WH_KEYBOARD, lpfnHookProc, hInstance, NULL);
if (hKeyHook)
return TRUE ;
else
return FALSE ;
}

It's nothing about MFC. Straight native c++ code. If you have Visual Studio, you should be able to make a quick console c++ app, copy and paste that code in, and compile and test. If not, go and get the free but big Windows SDK. Less friendly then VS, but there's a compiler, so should get you in the right direction.
Low level hooks are not quite debugger friendly, so you might need to trace or log out some helpful statements.
Edited: to get the module handle, you will need something like this:
HookModule = LoadLibrary(ModulePath);
HookProc HookFunction = GetProcAddress(HookModule, "GetMessageCallBack");
GetMessageHookHandle = SetWindowsHookEx(HookType.WH_GETMESSAGE, HookFunction, HookModule, 0);

Related

Control OS mouse clicks

I can't seem to find what I am looking for which is a way to alter the OS's mouse clicks. To specify this would be on Windows.
The goal is to limit the number of mouse clicks a user can register within a period of time.
I think the function that you are looking for is SetWindowsHookEx. Here is a quick example.
#include <windows.h>
const DWORD desireddelay = 10;
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
static DWORD previoustimestamp = 0;
if ((nCode == 0) && (wParam == WM_RBUTTONDOWN))
{
if ((((MSLLHOOKSTRUCT*)lParam)->time - previoustimestamp) < desireddelay)
{
return 1; //Non-Zero Swallows the keystroke. 0 Allows it. Always CallNextHookEx if you are not swallowing it.
}
else
{
previoustimestamp = ((MSLLHOOKSTRUCT*)lParam)->time;
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
int main()
{
HHOOK hook = SetWindowsHookEx(WH_MOUSE_LL, MouseProc, GetModuleHandle(NULL), NULL);
MSG msg;
bool done = false;
while (GetMessage(&msg, NULL, NULL, NULL)) {}
UnhookWindowsHookEx(hook);
return 0;
}

CBT Hook receiving only some events

I created a DLL to hook some events using a CBT hook. It seems to work only for the windows created by the process launching the hook...
My system is Windows 7 x64, but the behaviour is the same also on the x32.
This is the code (sorry but I'm no C++ expert):
#include "windows.h"
extern "C"
{
static LRESULT CALLBACK CbtProcCb(int nCode, WPARAM wParam, LPARAM lParam);
HINSTANCE g_hDll = NULL;
HWND g_hNotifyWin = NULL;
DWORD g_uNotifyMsg = NULL;
HHOOK g_hHook = NULL;
__declspec(dllexport) HHOOK SetCbtHook(HWND hWnd, LPCWSTR lStrMsg, DWORD threadId)
{
g_hNotifyWin = hWnd;
g_uNotifyMsg = RegisterWindowMessage(lStrMsg);
g_hHook = SetWindowsHookEx(WH_CBT, (HOOKPROC)CbtProcCb, g_hDll, threadId);
return g_hHook;
}
__declspec(dllexport) int UnsetCbtHook()
{
if ( !g_hHook )
return 0;
return UnhookWindowsHookEx(g_hHook);
}
}
static LRESULT CALLBACK CbtProcCb(int nCode, WPARAM wParam, LPARAM lParam)
{
SendNotifyMessage(g_hNotifyWin, g_uNotifyMsg, nCode, wParam); // Send nCode to check the received event
return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if ( fdwReason == DLL_PROCESS_ATTACH )
g_hDll = hinstDLL;
return true;
}
Any hints?
When Windows installs globals hook, the DLL implementing the hook function is often loaded in other processes. In those processes, the g_hNotifyWin and g_uNotifyMsg global variables are NULL. That global variables are only not NULL in the context of the process in which the SetCbtHook call took place.
You must have a way to retrieve the correct value for g_hNotifyWin and 'g_uNotifyMsg', in an arbitrary process.
Add:
const char * g_pszClassName = "MyClassName";
const char * g_pszRegisteredMsg = "MyMessage";
to your DLL, and replace "MyClassName" by the class name of the g_hNotifyWin window. See the RegisterClass call in your EXE. Update also "MyMessage".
Then, use the following CbtProcCb function:
static LRESULT CALLBACK CbtProcCb(int nCode, WPARAM wParam, LPARAM lParam)
{
if ( nCode >= 0 ) {
if ( g_hNotifyWin == NULL ) g_hNotifyWin = FindWindow( g_pszClassName, NULL );
if ( g_uNotifyMsg == 0) g_uNotifyMsg = RegisterWindowMessage(g_pszRegisteredMsg);
if ( g_hNotifyWin && g_uNotifyMsg )
SendNotifyMessage(g_hNotifyWin, g_uNotifyMsg, nCode, wParam); // Send nCode to check the received event
}
return CallNextHookEx(NULL, nCode, wParam, lParam); // first arg useless see MSDN
}
EDIT:
As you noted in comment, same problem for g_uNotifyMsg See updated function. You could set up those variables in DllMain, indeed.
The first argument to CallNextHookEx may be NULL.
I guess your ThreadId is not zero, so hook is attached only to the calling process / thread respectively. Read documentation:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx

Confusion about mouse hooks in c++

I am trying to get global mouse position. I have a hook working that can get the mouse position, however it only has access to it inside the hook code. Trying to access the data inside main doesn't work.
The best way to explain this is with code:
LRESULT CALLBACK mouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
PMSLLHOOKSTRUCT p = (PMSLLHOOKSTRUCT) lParam;
position.x = p->pt.x;
position.y = p->pt.y;
std::cout<<position.x<<std::endl;
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszArgument,int nCmdShow)
{
HHOOK mouseHook = SetWindowsHookEx(WH_MOUSE_LL,mouseHookProc,hInstance,NULL);
MessageBox(NULL, "Press OK to close.", "", MB_OK);
return 0;
}
With the above code, moving the mouse will show the new position in the console window. However, if I put the std::cout<<position.x<<std::endl; inside of main, it will just say 0. position is a global variable.
Code when the output is inside of main:
LRESULT CALLBACK mouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
PMSLLHOOKSTRUCT p = (PMSLLHOOKSTRUCT) lParam;
position.x = p->pt.x;
position.y = p->pt.y;
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszArgument,int nCmdShow)
{
HHOOK mouseHook = SetWindowsHookEx(WH_MOUSE_LL,mouseHookProc,hInstance,NULL);
for(;;)
{
std::cout<<position.x<<std::endl;
}
MessageBox(NULL, "Press OK to close.", "", MB_OK);
return 0;
}
The first chunk of code works fine, it detects the mouse position, I just don't know how to get the x,y data into my main.
re this posted code:
LRESULT CALLBACK mouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
PMSLLHOOKSTRUCT p = (PMSLLHOOKSTRUCT) lParam;
position.x = p->pt.x;
position.y = p->pt.y;
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszArgument,int nCmdShow)
{
HHOOK mouseHook = SetWindowsHookEx(WH_MOUSE_LL,mouseHookProc,hInstance,NULL);
std::cout<<position.x<<std::endl;
MessageBox(NULL, "Press OK to close.", "", MB_OK);
return 0;
}
Here's what the main function specifies should happen:
First, a call to SetWindowsHookEx (this happens once).
Then, outputting position (this happens once).
Then, displaying a MessageBox (this happens once).
That's all.
During the call to MessageBox the hook procedure is called (whenever you move your mouse), but it doesn't do anything visible, just an internal update.
Why did you expect more?
How to fix:
Instead of relying on the internal message loop in MessageBox, which doesn't do any output, code up your own.
Not to do with functionality, but just because the current code is like very dirty clothing that does serve its purpose but feels ungood to wear: replace Microsoft's WinMain monstrosity with a standard C and C++ main.
For global hook the hook procedure mouseHookProc should be in a DLL so that it can be injected into processes.
Check this:
http://www.codeproject.com/Articles/1037/Hooks-and-DLLs

getting the 'name of the application' along with the key taps

To record the key taps I install the hook as :
BOOL WINAPI installHook(HINSTANCE hinstDLL, DWORD fwdReason, LPVOID lpvReserved) {
handleKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hinstDLL, 0);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
// write here
}
Is there any way I can know the application name where the keys are currently being tapped ? Like I have opened notepad an writing something , can I get the name of the application which is notepad along with the key taps ? Same goes for some other application like mozilla firefox.
The inside of your hook should look like so:
static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
// if it is not a keydown event, continue the chain
if(HC_ACTION != nCode || WM_KEYDOWN != wParam)
return CallNextHookEx(0, nCode, wParam, lParam);
const KBDLLHOOKSTRUCT* messageInfo = reinterpret_cast<const KBDLLHOOKSTRUCT*>(lParam);
// add more code here...
// tell Windows we processed the hook
return 1;
}
messageinfo.vkCode will contain the key codes your looking for. The official list of these codes is at: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
Keys usually get typed into the foreground window (although sometimes strange window layouts happens). You can get the title of the foreground window like this:
TCHAR title[100]; // increase size for longer titles
GetWindowText(GetForegroundWindow(), title, 100);
If you want to get the name of the program instead, use:
TCHAR title[100]; // increase size for longer program names
GetWindowModuleFileName(GetForegroundWindow(), title, 100);
And, remember to add error checking and check the documentation.

Crashes during UnhookWindowsHookEx()

I made hook for calculator and want to get messages which calculator receives. To do that, I set my own window procedure, but during unhooking if I use SetWindowLong(..) to recover the old window procedure program crushes.
DLL code:
#define EXPORT_API extern "C" __declspec(dllexport)
EXPORT_API void InstallHook();
EXPORT_API void UninstallHook();
#pragma data_seg("Shared")
HHOOK g_hHook = NULL;
WNDPROC g_OldWndProc = NULL;
#pragma data_seg()
#pragma comment(linker, "/section:Shared,rws")
HWND GetTargetWindowHwnd()
{
return ::FindWindowA(0, "Calculator");
}
// my new wnd procedure to catch messages
LRESULT CALLBACK NewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = 0;
switch(uMsg)
{
case WM_CLOSE:
{
MessageBoxA(0, "Here we are!", "", 0);
}
break;
default:
lResult = CallWindowProc(g_OldWndProc, hwnd, uMsg, wParam, lParam);
break;
}
lResult = CallWindowProc(g_OldWndProc, hwnd, uMsg, wParam, lParam);
return lResult;
}
// hook procedure
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
MSG *pMsg = (MSG *)lParam;
HWND hWnd = GetTargetWindowHwnd();
bool flagIn = false;
if( hWnd == pMsg->hwnd )
{// if messege was sent to my target window
if(g_OldWndProc == NULL)
{
// save the adress of old wnd procedure to recover it later
g_OldWndProc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);
// set my wnd procedure
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)NewWndProc);
}
}
return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
EXPORT_API void InstallHook()
{
try
{
g_hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, g_hInstance, 0);
}
catch(...)
{
MessageBoxA(0, "Hook error", "Error", 0);
}
}
EXPORT_API void UninstallHook()
{
if(g_OldWndProc)
{
// recovering old wnd proc
HWND hWnd = GetTargetWindowHwnd();
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)g_OldWndProc);
g_OldWndProc = NULL;
}
if (g_hHook)
{
UnhookWindowsHookEx(g_hHook);
g_hHook = NULL;
}
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_hInstance = (HINSTANCE) hModule;
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
EXE CODE:
void CHookTestDlg::OnBnClickedBtnInstall()
{
InstallHook();
}
void CHookTestDlg::OnBnClickedBtnUninstall()
{
UninstallHook();
}
If I don't use my wnd procedure it works normal. If I use SetWindowLong(..) to recover the old window procedure program crushes during unhook. What is wrong?
The problem is that you are setting the window proc on the target window from within the target process (calc), and in that case, it is succeeding. But when you call UninstallHook, that code runs in your own exe's process; and in that case, SetWindowLong will fail.
(Putting the hook values in shared memory won't help; SetWindowLong will still refuse to change the window proc across a process boundary - see MSDN for details.)
To get this to work, you would need to communicate to the hooked instance of the DLL and ask it to reset the wndproc from within that target process, and once that is done, then unhook the hook.
(atzz's advice on unhooking is also valid. Hooking windows that you don't own is generally best avoided.)
When unsubclassing, always check that the window was not subclassed by someone else after you. I.e. before restoring WindowProc, you should read it again and compare against expected value (NewWndProc). If it is different, you must not unload the DLL, because another subclasser has a pointer to your DLL code stored, and this pointer will become dangling as soon as your DLL is unloaded.