Files
2023-01-03 19:11:22 -08:00

168 lines
4.1 KiB
Python

#!/usr/bin/env python3
import ctypes
import os
ERROR_SCAN_FAILURE = -1
MAX_PATH = 260
class t_output_filter(ctypes.c_int):
OUT_FULL = 0
OUT_NO_DUMPS = 1
OUT_NO_DIR = 2
OUT_FILTERS_COUNT = 3
class t_imprec_mode(ctypes.c_int):
PE_IMPREC_NONE = 0
PE_IMPREC_AUTO = 1
PE_IMPREC_UNERASE = 2
PE_IMPREC_REBUILD0 = 3
PE_IMPREC_REBUILD1 = 4
PE_IMPREC_REBUILD2 = 5
PE_IMPREC_MODES_COUNT = 6
class t_dump_mode(ctypes.c_int):
PE_DUMP_AUTO = 0
PE_DUMP_VIRTUAL = 1
PE_DUMP_UNMAP = 2
PE_DUMP_REALIGN = 3
PE_DUMP_MODES_COUNT = 4
class t_iat_scan_mode(ctypes.c_int):
PE_IATS_NONE = 0
PE_IATS_CLEAN_SYS_FILTERED = 1
PE_IATS_ALL_SYS_FILTERED = 2
PE_IATS_UNFILTERED = 3
PE_IATS_MODES_COUNT = 4
class t_dotnet_policy(ctypes.c_int):
PE_DNET_NONE = 0
PE_DNET_SKIP_MAPPING = 1
PE_DNET_SKIP_SHC = 2
PE_DNET_SKIP_HOOKS = 3
PE_DNET_SKIP_ALL = 4
PE_DNET_COUNT = 5
class t_data_scan_mode(ctypes.c_int):
PE_DATA_NO_SCAN = 0
PE_DATA_SCAN_DOTNET = 1
PE_DATA_SCAN_NO_DEP = 2
PE_DATA_SCAN_ALWAYS = 3
PE_DATA_SCAN_INACCESSIBLE = 4
PE_DATA_SCAN_INACCESSIBLE_ONLY = 5
PE_DATA_COUNT = 6
class t_json_level(ctypes.c_int):
JSON_BASIC = 0
JSON_DETAILS = 1
JSON_DETAILS2 = 2
JSON_LVL_COUNT = 3
class t_report_type(ctypes.c_int):
REPORT_NONE = 0
REPORT_SCANNED = 1
REPORT_DUMPED = 2
REPORT_ALL = 3
class PARAM_STRING(ctypes.Structure):
_fields_ = [
('length', ctypes.c_ulong),
('buffer', ctypes.c_char_p)
]
class t_params(ctypes.Structure):
_fields_ = [
('pid', ctypes.c_ulong),
('dotnet_policy', t_dotnet_policy),
('imprec_mode', t_imprec_mode),
('quiet', ctypes.c_bool),
('out_filter', t_output_filter),
('no_hooks', ctypes.c_bool),
('shellcode', ctypes.c_bool),
('threads', ctypes.c_bool),
('iat', t_iat_scan_mode),
('data', t_data_scan_mode),
('minidump', ctypes.c_bool),
('dump_mode', t_dump_mode),
('json_output', ctypes.c_bool),
('make_reflection', ctypes.c_bool),
('use_cache', ctypes.c_bool),
('json_lvl', t_json_level),
('output_dir', ctypes.c_char * (MAX_PATH + 1)),
('modules_ignored', PARAM_STRING)
]
class t_report(ctypes.Structure):
_fields_ = [
('pid', ctypes.c_ulong),
('is_managed', ctypes.c_bool),
('is_64bit', ctypes.c_bool),
('is_reflection', ctypes.c_bool),
('scanned', ctypes.c_ulong),
('suspicious', ctypes.c_ulong),
('replaced', ctypes.c_ulong),
('hdr_mod', ctypes.c_ulong),
('unreachable_file', ctypes.c_ulong),
('patched', ctypes.c_ulong),
('iat_hooked', ctypes.c_ulong),
('implanted', ctypes.c_ulong),
('implanted_pe', ctypes.c_ulong),
('implanted_shc', ctypes.c_ulong),
('other', ctypes.c_ulong),
('skipped', ctypes.c_ulong),
('errors', ctypes.c_ulong)
]
lib = None
def init():
global lib
ptr_size = ctypes.sizeof(ctypes.c_voidp)
if ptr_size == 4:
pesieve_dll = "pe-sieve32.dll"
else:
pesieve_dll = "pe-sieve64.dll"
if 'PESIEVE_DIR' in os.environ:
pesieve_dir = os.environ.get('PESIEVE_DIR')
else:
pesieve_dir = os.path.abspath(os.getcwd())
pesieve_path = pesieve_dir + os.path.sep + pesieve_dll
lib = ctypes.cdll.LoadLibrary(pesieve_path)
def PESieve_help():
if not lib:
init()
lib.PESieve_help()
def PESieve_scan(params: t_params) -> t_report:
if not lib:
init()
if (not isinstance(params, t_params)):
raise TypeError
params_size = ctypes.sizeof(t_params)
pp = ctypes.create_string_buffer(bytes(params), params_size)
pr = ctypes.create_string_buffer(ctypes.sizeof(t_report))
lib.PESieve_scan(pr, pp)
report = t_report.from_buffer(pr)
return report
def PESieve_scan_ex(params: t_params, rtype: t_report_type, buf_size: int) -> (t_report, str, int):
if not lib:
init()
if (not isinstance(params, t_params)):
raise TypeError
pp = ctypes.create_string_buffer(bytes(params), ctypes.sizeof(t_params))
pr = ctypes.create_string_buffer(ctypes.sizeof(t_report))
out_size = ctypes.c_ulong(0)
json_buf = ctypes.create_string_buffer(buf_size)
lib.PESieve_scan_ex(pr, pp, rtype, json_buf, buf_size, ctypes.byref(out_size))
report = t_report.from_buffer(pr)
if (out_size.value):
json_str = json_buf.value.decode('UTF-8')
else:
json_str = ""
return (report, json_str, out_size.value)