cosmetic: fucking linter :(

This commit is contained in:
Clement Rouault
2015-09-23 14:32:27 +02:00
parent 663de130b5
commit f5b0c0294f
23 changed files with 654 additions and 453 deletions
+30 -23
View File
@@ -9,40 +9,40 @@ import windows.winproxy
from . import simple_x86 as x86
from . import simple_x64 as x64
class PyObj(ctypes.Structure):
_fields_ = [("ob_refcnt", ctypes.c_size_t),
("ob_type", ctypes.c_void_p)] #must be cast
("ob_type", ctypes.c_void_p)] # must be cast
class PyMmap(PyObj):
_fields_ = [("ob_addr", ctypes.c_size_t), ("ob_size", ctypes.c_size_t)]
# Specific mmap class for code injection
# Specific mmap class for code injection
class MyMap(mmap.mmap):
""" A mmap that is never unmapped and that contains the page address """
def __init__(self, *args, **kwarg):
#Get the page address by 'introspection' of the C struct
# Get the page address by 'introspection' of the C struct
m = PyMmap.from_address(id(self))
self.addr = m.ob_addr
#Prevent garbage collection (so unmaping) of the page
# Prevent garbage collection (so unmaping) of the page
m.ob_refcnt += 1
@classmethod
def get_map(cls, size):
""" Dispatch to the good mmap implem depending on the current system """
systems = {'windows' : Win32MyMap,
'linux' : UnixMyMap }
systems = {'windows': Win32MyMap,
'linux': UnixMyMap}
x = platform.system().lower()
if x not in systems:
raise ValueError("Unknow system {0}".format(x))
return systems[x].get_map(size)
class Win32MyMap(MyMap):
@classmethod
def get_map(cls, size):
#access = mmap.ACCESS_READ | mmap.ACCESS_WRITE
#return cls(-1, size, access=access)
access = mmap.ACCESS_READ | mmap.ACCESS_WRITE
addr = windows.winproxy.VirtualAlloc(0, size, 0x1000, 0x40)
new_map = (ctypes.c_char * size).from_address(addr)
new_map.addr = addr
@@ -50,6 +50,7 @@ class Win32MyMap(MyMap):
raise ctypes.WinError()
return new_map
class UnixMyMap(MyMap):
@classmethod
def get_map(cls, size):
@@ -58,7 +59,7 @@ class UnixMyMap(MyMap):
class CustomAllocator(object):
int_size = {'32bit' : 4, '64bit' : 8}
int_size = {'32bit': 4, '64bit': 8}
def __init__(self):
self.maps = []
@@ -99,6 +100,7 @@ class CustomAllocator(object):
allocator = CustomAllocator()
def get_functions():
version = sys.version_info
python_dll = "python" + str(version.major) + str(version.minor)
@@ -108,6 +110,7 @@ def get_functions():
PyGILState_Release = windows.utils.get_func_addr(python_dll, 'PyGILState_Release'.encode())
return [PyGILState_Ensure, PyObject_CallObject, PyGILState_Release]
def analyse_callback(callback):
if not callable(callback):
raise ValueError("Need a callable object :)")
@@ -119,10 +122,9 @@ def analyse_callback(callback):
# For windows 32 bits with stdcall
def generate_stub_32(callback):
obj_id = analyse_callback(callback)
c_callback = get_callback_address_32(callback)
gstate_save_addr = x86.create_displacement(disp=allocator.reserve_int())
gstate_save_addr = x86.create_displacement(disp=allocator.reserve_int())
return_addr_save_addr = x86.create_displacement(disp=allocator.reserve_int())
save_ebx = x86.create_displacement(disp=allocator.reserve_int())
save_ecx = x86.create_displacement(disp=allocator.reserve_int())
@@ -133,7 +135,7 @@ def generate_stub_32(callback):
ensure, objcall, release = get_functions()
code = x86.MultipleInstr()
### Shellcode ###
# ## Shellcode ## #
code += x86.Mov(save_ebx, 'EBX')
code += x86.Mov(save_ecx, 'ECX')
code += x86.Mov(save_edx, 'EDX')
@@ -144,7 +146,7 @@ def generate_stub_32(callback):
code += x86.Call('EAX')
code += x86.Mov(gstate_save_addr, 'EAX')
#Save real return addr (for good argument parsing by the callback)
# Save real return addr (for good argument parsing by the callback)
code += x86.Pop('EAX')
code += x86.Mov(return_addr_save_addr, 'EAX')
@@ -177,7 +179,6 @@ def generate_stub_32(callback):
def generate_stub_64(callback):
obj_id = analyse_callback(callback)
c_callback = get_callback_address_64(callback)
REG_LEN = ctypes.sizeof(ctypes.c_void_p)
register_to_save = ("RBX", "RCX", "RDX", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15")
@@ -185,15 +186,18 @@ def generate_stub_64(callback):
push_all_save_register = x64.MultipleInstr([x64.Push(reg) for reg in register_to_save])
pop_all_save_register = x64.MultipleInstr([x64.Pop(reg) for reg in reversed(register_to_save)])
# Reserve parallel `stack`
save_register_space = allocator.reserve_int(len(register_to_save) + 1)
save_register_space += REG_LEN # The + 1 is for the second-stack xchg
save_register_space_end = save_register_space + (ctypes.sizeof(ctypes.c_void_p) * (len(register_to_save) ))
save_register_space = allocator.reserve_int(len(register_to_save))
save_register_space += REG_LEN
save_register_space_end = save_register_space + (ctypes.sizeof(ctypes.c_void_p) * (len(register_to_save)))
save_rbx = save_register_space_end - REG_LEN
save_rbx # Fuck the linter :D
save_rcx = save_register_space_end - REG_LEN - REG_LEN
save_rdx = save_register_space_end - REG_LEN - (REG_LEN * 2)
save_rsi = save_register_space_end - REG_LEN - (REG_LEN * 3)
save_rsi # Fuck the linter :D
save_rdi = save_register_space_end - REG_LEN - (REG_LEN * 4)
save_rdi # Fuck the linter :D
save_r8 = save_register_space_end - REG_LEN - (REG_LEN * 5)
save_r9 = save_register_space_end - REG_LEN - (REG_LEN * 6)
@@ -208,7 +212,7 @@ def generate_stub_64(callback):
ensure, objcall, release = get_functions()
### Shellcode ###
# ## Shellcode ## #
code = x64.MultipleInstr()
# Save all registers
code += x64.Mov('RAX', save_register_space_end)
@@ -223,7 +227,7 @@ def generate_stub_64(callback):
code += Remove_stack_alignement
code += Clean_space_for_call
code += x64.Mov(gstate_save_addr, 'RAX')
#Save real return addr (for good argument parsing by the callback)
# Save real return addr (for good argument parsing by the callback)
code += x64.Pop('RAX')
code += x64.Mov(return_addr_save_addr, 'RAX')
# Restore parameters for real function call
@@ -237,9 +241,9 @@ def generate_stub_64(callback):
code += x64.Mov('R8', x64.mem('[RAX]'))
# Call python code
code += x64.Mov('RAX', c_callback)
code += x64.Call('RAX') # no need for stack alignement here as we poped the return addr
# no need for Reserve_space_for_call as we must use the previous one for
# correct argument parsing
# no need for stack alignement here as we poped the return addr
# no need for Reserve_space_for_call as we must use the previous one for correct argument parsing
code += x64.Call('RAX')
# Save return value
code += x64.Mov(return_value_save_addr, 'RAX')
# Repush real return value
@@ -278,6 +282,7 @@ def generate_callback_stub(callback, types):
generate_callback_stub.l = []
def create_function(code, types):
"""Create a python function that call raw machine code
@@ -290,12 +295,14 @@ def create_function(code, types):
addr = allocator.write_code(code)
return func_type(addr)
# Return First argument for 32 bits code
raw_code = x86.MultipleInstr()
raw_code += x86.Mov('EAX', x86.mem('[ESP + 4]'))
raw_code += x86.Ret()
get_callback_address_32 = create_function(raw_code.get_code(), [ctypes.c_void_p])
# Return First argument for 64 bits code
raw_code = x64.MultipleInstr()
raw_code += x64.Mov('RAX', 'RCX')