mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Fix hook with new assembler + fix python3 compat for hook
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
def pretty_print_ctypes_type(t):
|
||||
format = "{0}"
|
||||
if issubclass(t, ctypes.Array):
|
||||
format = "[{0}" + "* {0}]".format(t._length_)
|
||||
t = t._type_
|
||||
|
||||
if issubclass(t, ctypes._Pointer):
|
||||
format = format.format("Pointer({0})")
|
||||
t = t._type_
|
||||
|
||||
if issubclass(t, ctypes.Structure):
|
||||
return format.format(":class:`{0}`".format(t.__name__))
|
||||
return t
|
||||
|
||||
|
||||
def autodoc_ctypes_struct(struct):
|
||||
doc = ["fields:"]
|
||||
for name, type in struct._fields_:
|
||||
doc.append(" {0} -> {1}".format(name, pretty_print_ctypes_type(type)))
|
||||
|
||||
struct.__doc__ = "\n\n".join(doc)
|
||||
return struct
|
||||
@@ -3,7 +3,7 @@ from ctypes import *
|
||||
from ctypes.wintypes import *
|
||||
from .winstructs import *
|
||||
|
||||
functions = ['ExitProcess', 'GetLastError', 'GetCurrentProcess', 'CreateFileA', 'CreateFileW', 'NtQuerySystemInformation', 'VirtualAlloc', 'VirtualAllocEx', 'VirtualProtect', 'VirtualQuery', 'GetModuleFileNameA', 'GetModuleFileNameW', 'CreateThread', 'CreateRemoteThread', 'VirtualProtect', 'CreateProcessA', 'CreateProcessW', 'GetThreadContext', 'SetThreadContext', 'OpenThread', 'OpenProcess', 'CloseHandle', 'ReadProcessMemory', 'WriteProcessMemory', 'CreateToolhelp32Snapshot', 'Thread32First', 'Thread32Next', 'Process32First', 'Process32Next', 'Process32FirstW', 'Process32NextW', 'GetProcAddress', 'LoadLibraryA', 'LoadLibraryW', 'OpenProcessToken', 'LookupPrivilegeValueA', 'LookupPrivilegeValueW', 'AdjustTokenPrivileges', 'FindResourceA', 'FindResourceW', 'SizeofResource', 'LoadResource', 'LockResource', 'GetVersionExA', 'GetVersionExW', 'GetVersion', 'GetCurrentThread', 'GetCurrentThreadId', 'GetCurrentProcessorNumber', 'AllocConsole', 'GetStdHandle', 'SetStdHandle', 'SetThreadAffinityMask', 'WriteFile', 'GetExtendedTcpTable', 'GetExtendedUdpTable', 'SetTcpEntry', 'AddVectoredContinueHandler', 'AddVectoredExceptionHandler', 'TerminateThread', 'ExitThread', 'RemoveVectoredExceptionHandler', 'ResumeThread', 'SuspendThread', 'WaitForSingleObject', 'GetThreadId']
|
||||
functions = ['ExitProcess', 'GetLastError', 'GetCurrentProcess', 'CreateFileA', 'CreateFileW', 'NtQuerySystemInformation', 'VirtualAlloc', 'VirtualAllocEx', 'VirtualProtect', 'VirtualQuery', 'GetModuleFileNameA', 'GetModuleFileNameW', 'CreateThread', 'CreateRemoteThread', 'VirtualProtect', 'CreateProcessA', 'CreateProcessW', 'GetThreadContext', 'SetThreadContext', 'OpenThread', 'OpenProcess', 'CloseHandle', 'ReadProcessMemory', 'WriteProcessMemory', 'CreateToolhelp32Snapshot', 'Thread32First', 'Thread32Next', 'Process32First', 'Process32Next', 'Process32FirstW', 'Process32NextW', 'GetProcAddress', 'LoadLibraryA', 'LoadLibraryW', 'OpenProcessToken', 'LookupPrivilegeValueA', 'LookupPrivilegeValueW', 'AdjustTokenPrivileges', 'FindResourceA', 'FindResourceW', 'SizeofResource', 'LoadResource', 'LockResource', 'GetVersionExA', 'GetVersionExW', 'GetVersion', 'GetCurrentThread', 'GetCurrentThreadId', 'GetCurrentProcessorNumber', 'AllocConsole', 'GetStdHandle', 'SetStdHandle', 'SetThreadAffinityMask', 'WriteFile', 'GetExtendedTcpTable', 'GetExtendedUdpTable', 'SetTcpEntry', 'AddVectoredContinueHandler', 'AddVectoredExceptionHandler', 'TerminateThread', 'ExitThread', 'RemoveVectoredExceptionHandler', 'ResumeThread', 'SuspendThread', 'WaitForSingleObject', 'GetThreadId', 'LoadLibraryExA', 'LoadLibraryExW']
|
||||
|
||||
# ExitProcess(uExitCode):
|
||||
ExitProcessPrototype = WINFUNCTYPE(VOID, UINT)
|
||||
@@ -269,3 +269,11 @@ WaitForSingleObjectParams = ((1, 'hHandle'), (1, 'dwMilliseconds'))
|
||||
GetThreadIdPrototype = WINFUNCTYPE(DWORD, HANDLE)
|
||||
GetThreadIdParams = ((1, 'Thread'),)
|
||||
|
||||
# LoadLibraryExA(lpFileName, hFile, dwFlags):
|
||||
LoadLibraryExAPrototype = WINFUNCTYPE(HMODULE, LPCSTR, HANDLE, DWORD)
|
||||
LoadLibraryExAParams = ((1, 'lpFileName'), (1, 'hFile'), (1, 'dwFlags'))
|
||||
|
||||
# LoadLibraryExW(lpFileName, hFile, dwFlags):
|
||||
LoadLibraryExWPrototype = WINFUNCTYPE(HMODULE, LPCWSTR, HANDLE, DWORD)
|
||||
LoadLibraryExWParams = ((1, 'lpFileName'), (1, 'hFile'), (1, 'dwFlags'))
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ PHANDLE = POINTER(HANDLE)
|
||||
LPCONTEXT = PVOID
|
||||
VOID = DWORD
|
||||
|
||||
structs = ['_LIST_ENTRY', '_PEB_LDR_DATA', '_LSA_UNICODE_STRING', '_RTL_USER_PROCESS_PARAMETERS', '_PEB', '_SECURITY_ATTRIBUTES', '_SYSTEM_VERIFIER_INFORMATION', '_LDR_DATA_TABLE_ENTRY', '_IMAGE_FILE_HEADER', '_IMAGE_DATA_DIRECTORY', '_IMAGE_SECTION_HEADER', '_IMAGE_OPTIONAL_HEADER64', '_IMAGE_OPTIONAL_HEADER', '_IMAGE_NT_HEADERS64', '_IMAGE_NT_HEADERS', '_IMAGE_IMPORT_DESCRIPTOR', '_IMAGE_IMPORT_BY_NAME', '_IMAGE_EXPORT_DIRECTORY', '_MEMORY_BASIC_INFORMATION', '_STARTUPINFOA', '_STARTUPINFOW', '_PROCESS_INFORMATION', '_FLOATING_SAVE_AREA', '_CONTEXT32', '_M128A', '_CONTEXT64', 'tagPROCESSENTRY32W', 'tagPROCESSENTRY32', 'tagTHREADENTRY32', '_LUID', '_LUID_AND_ATTRIBUTES', '_TOKEN_PRIVILEGES', '_OSVERSIONINFOA', '_OSVERSIONINFOW', '_OSVERSIONINFOEXA', '_OSVERSIONINFOEXW', '_OVERLAPPED', '_MIB_TCPROW_OWNER_PID', '_MIB_TCPTABLE_OWNER_PID', '_MIB_UDPROW_OWNER_PID', '_MIB_UDPTABLE_OWNER_PID', '_MIB_UDP6ROW_OWNER_PID', '_MIB_UDP6TABLE_OWNER_PID', '_MIB_TCP6ROW_OWNER_PID', '_MIB_TCP6TABLE_OWNER_PID', '_MIB_TCPROW', '_EXCEPTION_RECORD', '_EXCEPTION_POINTERS64', '_EXCEPTION_POINTERS32', '_DEBUG_PROCESSOR_IDENTIFICATION_X86']
|
||||
structs = ['_LIST_ENTRY', '_PEB_LDR_DATA', '_LSA_UNICODE_STRING', '_RTL_USER_PROCESS_PARAMETERS', '_PEB', '_SECURITY_ATTRIBUTES', '_SYSTEM_VERIFIER_INFORMATION', '_LDR_DATA_TABLE_ENTRY', '_IMAGE_FILE_HEADER', '_IMAGE_DATA_DIRECTORY', '_IMAGE_SECTION_HEADER', '_IMAGE_OPTIONAL_HEADER64', '_IMAGE_OPTIONAL_HEADER', '_IMAGE_NT_HEADERS64', '_IMAGE_NT_HEADERS', '_IMAGE_IMPORT_DESCRIPTOR', '_IMAGE_IMPORT_BY_NAME', '_IMAGE_EXPORT_DIRECTORY', '_MEMORY_BASIC_INFORMATION', '_STARTUPINFOA', '_STARTUPINFOW', '_PROCESS_INFORMATION', '_FLOATING_SAVE_AREA', '_CONTEXT32', '_M128A', '_CONTEXT64', 'tagPROCESSENTRY32W', 'tagPROCESSENTRY32', 'tagTHREADENTRY32', '_LUID', '_LUID_AND_ATTRIBUTES', '_TOKEN_PRIVILEGES', '_OSVERSIONINFOA', '_OSVERSIONINFOW', '_OSVERSIONINFOEXA', '_OSVERSIONINFOEXW', '_OVERLAPPED', '_MIB_TCPROW_OWNER_PID', '_MIB_TCPTABLE_OWNER_PID', '_MIB_UDPROW_OWNER_PID', '_MIB_UDPTABLE_OWNER_PID', '_MIB_UDP6ROW_OWNER_PID', '_MIB_UDP6TABLE_OWNER_PID', '_MIB_TCP6ROW_OWNER_PID', '_MIB_TCP6TABLE_OWNER_PID', '_MIB_TCPROW', '_EXCEPTION_RECORD', '_EXCEPTION_POINTERS64', '_EXCEPTION_POINTERS32', '_DEBUG_PROCESSOR_IDENTIFICATION_ALPHA', '_DEBUG_PROCESSOR_IDENTIFICATION_AMD64', '_DEBUG_PROCESSOR_IDENTIFICATION_IA64', '_DEBUG_PROCESSOR_IDENTIFICATION_X86', '_DEBUG_PROCESSOR_IDENTIFICATION_ARM', '_DEBUG_PROCESSOR_IDENTIFICATION_ALL']
|
||||
|
||||
enums = ['_SYSTEM_INFORMATION_CLASS', '_TCP_TABLE_CLASS', '_UDP_TABLE_CLASS', '_MIB_TCP_STATE']
|
||||
|
||||
@@ -945,6 +945,38 @@ class _EXCEPTION_POINTERS32(Structure):
|
||||
PEXCEPTION_POINTERS32 = POINTER(_EXCEPTION_POINTERS32)
|
||||
EXCEPTION_POINTERS32 = _EXCEPTION_POINTERS32
|
||||
|
||||
# Struct _DEBUG_PROCESSOR_IDENTIFICATION_ALPHA definitions
|
||||
class _DEBUG_PROCESSOR_IDENTIFICATION_ALPHA(Structure):
|
||||
_fields_ = [
|
||||
("Type", ULONG),
|
||||
("Revision", ULONG),
|
||||
]
|
||||
DEBUG_PROCESSOR_IDENTIFICATION_ALPHA = _DEBUG_PROCESSOR_IDENTIFICATION_ALPHA
|
||||
PDEBUG_PROCESSOR_IDENTIFICATION_ALPHA = POINTER(_DEBUG_PROCESSOR_IDENTIFICATION_ALPHA)
|
||||
|
||||
# Struct _DEBUG_PROCESSOR_IDENTIFICATION_AMD64 definitions
|
||||
class _DEBUG_PROCESSOR_IDENTIFICATION_AMD64(Structure):
|
||||
_fields_ = [
|
||||
("Family", ULONG),
|
||||
("Model", ULONG),
|
||||
("Stepping", ULONG),
|
||||
("VendorString", CHAR * 16),
|
||||
]
|
||||
DEBUG_PROCESSOR_IDENTIFICATION_AMD64 = _DEBUG_PROCESSOR_IDENTIFICATION_AMD64
|
||||
PDEBUG_PROCESSOR_IDENTIFICATION_AMD64 = POINTER(_DEBUG_PROCESSOR_IDENTIFICATION_AMD64)
|
||||
|
||||
# Struct _DEBUG_PROCESSOR_IDENTIFICATION_IA64 definitions
|
||||
class _DEBUG_PROCESSOR_IDENTIFICATION_IA64(Structure):
|
||||
_fields_ = [
|
||||
("Model", ULONG),
|
||||
("Revision", ULONG),
|
||||
("Family", ULONG),
|
||||
("ArchRev", ULONG),
|
||||
("VendorString", CHAR * 16),
|
||||
]
|
||||
PDEBUG_PROCESSOR_IDENTIFICATION_IA64 = POINTER(_DEBUG_PROCESSOR_IDENTIFICATION_IA64)
|
||||
DEBUG_PROCESSOR_IDENTIFICATION_IA64 = _DEBUG_PROCESSOR_IDENTIFICATION_IA64
|
||||
|
||||
# Struct _DEBUG_PROCESSOR_IDENTIFICATION_X86 definitions
|
||||
class _DEBUG_PROCESSOR_IDENTIFICATION_X86(Structure):
|
||||
_fields_ = [
|
||||
@@ -956,3 +988,24 @@ class _DEBUG_PROCESSOR_IDENTIFICATION_X86(Structure):
|
||||
DEBUG_PROCESSOR_IDENTIFICATION_X86 = _DEBUG_PROCESSOR_IDENTIFICATION_X86
|
||||
PDEBUG_PROCESSOR_IDENTIFICATION_X86 = POINTER(_DEBUG_PROCESSOR_IDENTIFICATION_X86)
|
||||
|
||||
# Struct _DEBUG_PROCESSOR_IDENTIFICATION_ARM definitions
|
||||
class _DEBUG_PROCESSOR_IDENTIFICATION_ARM(Structure):
|
||||
_fields_ = [
|
||||
("Type", ULONG),
|
||||
("Revision", ULONG),
|
||||
]
|
||||
DEBUG_PROCESSOR_IDENTIFICATION_ARM = _DEBUG_PROCESSOR_IDENTIFICATION_ARM
|
||||
PDEBUG_PROCESSOR_IDENTIFICATION_ARM = POINTER(_DEBUG_PROCESSOR_IDENTIFICATION_ARM)
|
||||
|
||||
# Struct _DEBUG_PROCESSOR_IDENTIFICATION_ALL definitions
|
||||
class _DEBUG_PROCESSOR_IDENTIFICATION_ALL(Union):
|
||||
_fields_ = [
|
||||
("Alpha", DEBUG_PROCESSOR_IDENTIFICATION_ALPHA),
|
||||
("Amd64", DEBUG_PROCESSOR_IDENTIFICATION_AMD64),
|
||||
("Ia64", DEBUG_PROCESSOR_IDENTIFICATION_IA64),
|
||||
("X86", DEBUG_PROCESSOR_IDENTIFICATION_X86),
|
||||
("Arm", DEBUG_PROCESSOR_IDENTIFICATION_ARM),
|
||||
]
|
||||
PDEBUG_PROCESSOR_IDENTIFICATION_ALL = POINTER(_DEBUG_PROCESSOR_IDENTIFICATION_ALL)
|
||||
DEBUG_PROCESSOR_IDENTIFICATION_ALL = _DEBUG_PROCESSOR_IDENTIFICATION_ALL
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import ctypes
|
||||
import mmap
|
||||
import platform
|
||||
import sys
|
||||
|
||||
import windows
|
||||
import windows.k32testing as k32api
|
||||
|
||||
from . import simple_x86 as x86
|
||||
#from . import simple_x64 as x64
|
||||
from . import simple_x64 as x64
|
||||
|
||||
class PyObj(ctypes.Structure):
|
||||
_fields_ = [("ob_refcnt", ctypes.c_size_t),
|
||||
@@ -96,15 +97,16 @@ class CustomAllocator(object):
|
||||
addr = self.maps[-1].addr + self.cur_offset
|
||||
self.cur_offset += size
|
||||
return addr
|
||||
|
||||
allocator = CustomAllocator()
|
||||
|
||||
def get_functions():
|
||||
# Windows only with python27.dll | improve this ?
|
||||
import sys
|
||||
import windows
|
||||
|
||||
PyGILState_Ensure = windows.utils.get_func_addr('python27', 'PyGILState_Ensure')
|
||||
PyObject_CallObject = windows.utils.get_func_addr('python27', 'PyObject_CallObject')
|
||||
PyGILState_Release = windows.utils.get_func_addr('python27', 'PyGILState_Release')
|
||||
version = sys.version_info
|
||||
python_dll = "python" + str(version.major) + str(version.minor)
|
||||
|
||||
PyGILState_Ensure = windows.utils.get_func_addr(python_dll, 'PyGILState_Ensure'.encode())
|
||||
PyObject_CallObject = windows.utils.get_func_addr(python_dll, 'PyObject_CallObject'.encode())
|
||||
PyGILState_Release = windows.utils.get_func_addr(python_dll, 'PyGILState_Release'.encode())
|
||||
return [PyGILState_Ensure, PyObject_CallObject, PyGILState_Release]
|
||||
|
||||
def analyse_callback(callback):
|
||||
@@ -115,18 +117,14 @@ def analyse_callback(callback):
|
||||
raise ValueError("Need a ctypes PyCFuncPtr")
|
||||
return obj_id
|
||||
|
||||
|
||||
|
||||
|
||||
# For windows 32 bits with stdcall
|
||||
def generate_stub_32(callback):
|
||||
|
||||
allocator = windows.current_process.allocator
|
||||
obj_id = analyse_callback(callback)
|
||||
c_callback = get_callback_address_32(callback)
|
||||
|
||||
c_callback = ctypes.c_ulong.from_address(id(callback._objects['0']) + 3 * ctypes.sizeof(ctypes.c_void_p)).value
|
||||
gstate_save_addr = allocator.reserve_int()
|
||||
return_addr_save_addr = 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())
|
||||
save_edx = x86.create_displacement(disp=allocator.reserve_int())
|
||||
@@ -136,7 +134,6 @@ def generate_stub_32(callback):
|
||||
ensure, objcall, release = get_functions()
|
||||
|
||||
code = x86.MultipleInstr()
|
||||
|
||||
### Shellcode ###
|
||||
code += x86.Mov(save_ebx, 'EBX')
|
||||
code += x86.Mov(save_ecx, 'ECX')
|
||||
@@ -182,26 +179,20 @@ def generate_stub_32(callback):
|
||||
code += x86.Ret()
|
||||
return code
|
||||
|
||||
# For windows 32 bits with stdcall
|
||||
|
||||
def generate_stub_64(callback):
|
||||
|
||||
allocator = windows.current_process.allocator
|
||||
obj_id = analyse_callback(callback)
|
||||
|
||||
c_callback = get_callback_address_64(callback)
|
||||
REG_LEN = ctypes.sizeof(ctypes.c_void_p)
|
||||
|
||||
c_callback = ctypes.c_ulong.from_address(id(callback._objects['0']) + 3 * ctypes.sizeof(ctypes.c_void_p)).value
|
||||
|
||||
register_to_save = ("RBX", "RCX", "RDX", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15")
|
||||
|
||||
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 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_rbx = save_register_space_end - REG_LEN
|
||||
save_rcx = save_register_space_end - REG_LEN - REG_LEN
|
||||
save_rdx = save_register_space_end - REG_LEN - (REG_LEN * 2)
|
||||
@@ -210,35 +201,29 @@ def generate_stub_64(callback):
|
||||
save_r8 = save_register_space_end - REG_LEN - (REG_LEN * 5)
|
||||
save_r9 = save_register_space_end - REG_LEN - (REG_LEN * 6)
|
||||
|
||||
gstate_save_addr = x64.create_displacement(disp=allocator.reserve_int())
|
||||
return_addr_save_addr = x64.create_displacement(disp=allocator.reserve_int())
|
||||
return_value_save_addr = x64.create_displacement(disp=allocator.reserve_int())
|
||||
|
||||
gstate_save_addr = create_displacement(disp=allocator.reserve_int())
|
||||
return_addr_save_addr = create_displacement(disp=allocator.reserve_int())
|
||||
return_value_save_addr = create_displacement(disp=allocator.reserve_int())
|
||||
|
||||
Reserve_space_for_call = x64.MultipleInstr([Push('RDI')] * 4)
|
||||
Clean_space_for_call = x64.MultipleInstr([Pop('RDI')] * 4)
|
||||
Do_stack_alignement = MultipleInstr([x64.Push('RDI')] * 1)
|
||||
Remove_stack_alignement = MultipleInstr([x64.Pop('RDI')] * 1)
|
||||
|
||||
Reserve_space_for_call = x64.MultipleInstr([x64.Push('RDI')] * 4)
|
||||
Clean_space_for_call = x64.MultipleInstr([x64.Pop('RDI')] * 4)
|
||||
Do_stack_alignement = x64.MultipleInstr([x64.Push('RDI')] * 1)
|
||||
Remove_stack_alignement = x64.MultipleInstr([x64.Pop('RDI')] * 1)
|
||||
|
||||
ensure, objcall, release = get_functions()
|
||||
|
||||
### Shellcode ###
|
||||
code = MultipleInstr()
|
||||
code = x64.MultipleInstr()
|
||||
code += x64.Mov('RAX', save_register_space_end)
|
||||
# A lazy working xchg RSP <-> RAX
|
||||
code += x64.Push('RAX')
|
||||
code += x64.Push('RSP')
|
||||
code += x64.Pop('RAX')
|
||||
code += x64.Pop('RSP')
|
||||
|
||||
code += push_all_save_register
|
||||
|
||||
# Re-set RSP to its real value
|
||||
code += x64.Push('RAX')
|
||||
code += x64.Pop('RSP')
|
||||
|
||||
|
||||
code += x64.Pop('RAX') # Remove the Push_RAX of lazy xchg
|
||||
# GOOO
|
||||
code += x64.Mov('RAX', ensure)
|
||||
@@ -256,15 +241,14 @@ def generate_stub_64(callback):
|
||||
code += x64.Mov('RCX', x64.create_displacement('RAX'))
|
||||
code += x64.Mov('RAX', save_rdx)
|
||||
code += x64.Mov('RDX', x64.create_displacement('RAX'))
|
||||
code += x64.Mov('RAX', save_r8)
|
||||
code += x64.Mov('R9', x64.create_displacement('RAX'))
|
||||
code += x64.Mov('RAX', save_r9)
|
||||
code += x64.Mov('R9', x64.create_displacement('RAX'))
|
||||
code += x64.Mov('RAX', save_r8)
|
||||
code += x64.Mov('R8', x64.create_displacement('RAX'))
|
||||
# Call python code
|
||||
code += x64.Mov('RAX', c_callback)
|
||||
code += Reserve_space_for_call
|
||||
code += x64.Call('RAX') # no need for stack alignement here as we poped the return addr
|
||||
|
||||
code += Clean_space_for_call
|
||||
# Save return value
|
||||
code += x64.Mov(return_value_save_addr, 'RAX')
|
||||
@@ -272,7 +256,7 @@ def generate_stub_64(callback):
|
||||
code += x64.Mov('RAX', return_addr_save_addr)
|
||||
code += x64.Push('RAX')
|
||||
# Call release(gstate_save)
|
||||
code += x64.Mov_RAX_DX('RAX', gstate_save_addr)
|
||||
code += x64.Mov('RAX', gstate_save_addr)
|
||||
code += x64.Push('RAX')
|
||||
code += x64.Pop('RCX')
|
||||
code += x64.Mov('RAX', release)
|
||||
@@ -288,16 +272,13 @@ def generate_stub_64(callback):
|
||||
code += x64.Push('RSP')
|
||||
code += x64.Pop('RAX')
|
||||
code += x64.Pop('RSP')
|
||||
|
||||
code += pop_all_save_register
|
||||
|
||||
# Re-set RSP to its real value
|
||||
code += x64.Push('RAX')
|
||||
code += x64.Pop('RSP')
|
||||
code += x64.Pop('RAX') # Remove the Push_RAX of lazy xchg
|
||||
|
||||
# Restore return value
|
||||
code += x64.Mov_RAX_DX('RAX', return_value_save_addr)
|
||||
code += x64.Mov('RAX', return_value_save_addr)
|
||||
code += x64.Ret()
|
||||
return code
|
||||
|
||||
@@ -309,7 +290,7 @@ def generate_callback_stub(callback, types):
|
||||
stub = generate_stub_32(c_callable)
|
||||
else:
|
||||
stub = generate_stub_64(c_callable)
|
||||
stub_addr = windows.current_process.allocator.write_code(stub.get_code())
|
||||
stub_addr = allocator.write_code(stub.get_code())
|
||||
generate_callback_stub.l.append((stub, c_callable))
|
||||
return stub_addr
|
||||
|
||||
@@ -324,5 +305,17 @@ def create_function(code, types):
|
||||
:rtype: function
|
||||
"""
|
||||
func_type = ctypes.CFUNCTYPE(*types)
|
||||
addr = windows.current_process.allocator.write_code(code)
|
||||
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.create_displacement(base='ESP', disp=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')
|
||||
raw_code += x64.Ret()
|
||||
get_callback_address_64 = create_function(raw_code.get_code(), [ctypes.c_void_p])
|
||||
|
||||
@@ -331,6 +331,9 @@ class Call(Instruction):
|
||||
class Ret(Instruction):
|
||||
encoding = [(RawBits.from_int(8, 0xc3),)]
|
||||
|
||||
class Int3(Instruction):
|
||||
encoding = [(RawBits.from_int(8, 0xcc),)]
|
||||
|
||||
class Mov(Instruction):
|
||||
default_32_bits = True
|
||||
encoding = [(RawBits.from_int(8, 0x89), ModRM(ModRM_REG64__REG64, ModRM_REG__DEREF_REG)), (RawBits.from_int(5, 0xb8 >> 3), X64RegisterSelector(), Imm64()),
|
||||
|
||||
+49
-11
@@ -92,7 +92,10 @@ class RawBits(BitArray):
|
||||
|
||||
class Imm32(object):
|
||||
def accept_arg(self, previous, args):
|
||||
x = int(args[0])
|
||||
try:
|
||||
x = int(args[0])
|
||||
except TypeError:
|
||||
return (None, None)
|
||||
return (1, BitArray.from_int(32, X86.to_little_endian(x)))
|
||||
|
||||
class ModRM(object):
|
||||
@@ -132,7 +135,10 @@ class X86(object):
|
||||
if not X86.is_mem_acces(mem_access):
|
||||
raise ValueError("mem_access_has_only")
|
||||
for f in mem_access._fields:
|
||||
if getattr(mem_access, f) and f not in names:
|
||||
v = getattr(mem_access, f)
|
||||
if v and f not in names:
|
||||
return False
|
||||
if v is None and f in names:
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -169,7 +175,7 @@ class ModRM_REG__DEREF_REG(object):
|
||||
class ModRM_REG__DEREF_REG_IMM(object):
|
||||
@classmethod
|
||||
def match(cls, arg1, arg2):
|
||||
return X86.is_reg(arg1) and X86.is_mem_acces(arg2) and X86.mem_access_has_only(arg2, ["base", "disp"])
|
||||
return X86.is_reg(arg1) and X86.is_mem_acces(arg2) and X86.mem_access_has_only(arg2, ["base", "disp"]) and arg2.base != "ESP"
|
||||
|
||||
def __init__(self, arg1, arg2, reversed):
|
||||
self.mod = BitArray(2, "10")
|
||||
@@ -178,16 +184,45 @@ class ModRM_REG__DEREF_REG_IMM(object):
|
||||
self.after = BitArray.from_int(32, X86.to_little_endian(arg2.disp))
|
||||
self.direction = not reversed
|
||||
|
||||
class ModRM_REG_IMM(object):
|
||||
class ModRM_REG__DEREF_SIB(object):
|
||||
# Only handle reg, [esp+x] now :(
|
||||
@classmethod
|
||||
def match(cls, arg1, arg2):
|
||||
return arg1 in x86_regs and arg2 in x86_regs
|
||||
return X86.is_reg(arg1) and X86.is_mem_acces(arg2) and X86.mem_access_has_only(arg2, ["base", "disp"]) and arg2.base == "ESP"
|
||||
|
||||
def __init__(self, arg1, arg2):
|
||||
self.mod = BitArray(2, "11")
|
||||
self.reg = X86RegisterSelector.get_reg_bits(arg2)
|
||||
self.rm = X86RegisterSelector.get_reg_bits(arg1)
|
||||
self.direction = 0
|
||||
def __init__(self, arg1, arg2, reversed):
|
||||
self.mod = BitArray(2, "10")
|
||||
self.reg = X86RegisterSelector.get_reg_bits(arg1)
|
||||
self.rm = BitArray(3, "100")
|
||||
|
||||
# Todo -> def sib_from_displacement
|
||||
sib = BitArray(8, "00100100")
|
||||
|
||||
self.after = sib + BitArray.from_int(32, X86.to_little_endian(arg2.disp))
|
||||
self.direction = not reversed
|
||||
|
||||
#class ModRM_REG_IMM(object):
|
||||
# @classmethod
|
||||
# def match(cls, arg1, arg2):
|
||||
# return arg1 in x86_regs and arg2 in x86_regs
|
||||
#
|
||||
# def __init__(self, arg1, arg2):
|
||||
# self.mod = BitArray(2, "11")
|
||||
# self.reg = X86RegisterSelector.get_reg_bits(arg2)
|
||||
# self.rm = X86RegisterSelector.get_reg_bits(arg1)
|
||||
# self.direction = 0
|
||||
|
||||
class ModRM_REG__DEREF_IMM(object):
|
||||
@classmethod
|
||||
def match(cls, arg1, arg2):
|
||||
return X86.is_reg(arg1) and X86.is_mem_acces(arg2) and X86.mem_access_has_only(arg2, ["disp"])
|
||||
|
||||
def __init__(self, arg1, arg2, reversed):
|
||||
self.mod = BitArray(2, "00")
|
||||
self.reg = X86RegisterSelector.get_reg_bits(arg1)
|
||||
self.rm = BitArray(3, "101")
|
||||
self.after = BitArray.from_int(32, X86.to_little_endian(arg2.disp))
|
||||
self.direction = not reversed
|
||||
|
||||
|
||||
class Instruction(object):
|
||||
@@ -219,7 +254,7 @@ class Pop(Instruction):
|
||||
encoding = [(RawBits.from_int(5, 0x58 >> 3), X86RegisterSelector())]
|
||||
|
||||
class Mov(Instruction):
|
||||
encoding = [(RawBits.from_int(8, 0x89), ModRM(ModRM_REG__REG, ModRM_REG__DEREF_REG, ModRM_REG__DEREF_REG_IMM)),
|
||||
encoding = [(RawBits.from_int(8, 0x89), ModRM(ModRM_REG__REG, ModRM_REG__DEREF_REG, ModRM_REG__DEREF_REG_IMM, ModRM_REG__DEREF_IMM, ModRM_REG__DEREF_SIB)),
|
||||
(RawBits.from_int(5, 0xb8 >> 3), X86RegisterSelector(), Imm32())]
|
||||
|
||||
class Call(Instruction):
|
||||
@@ -228,6 +263,9 @@ class Call(Instruction):
|
||||
class Ret(Instruction):
|
||||
encoding = [(RawBits.from_int(8, 0xc3),)]
|
||||
|
||||
class Int3(Instruction):
|
||||
encoding = [(RawBits.from_int(8, 0xcc),)]
|
||||
|
||||
|
||||
class MultipleInstr(object):
|
||||
|
||||
|
||||
+2
-2
@@ -39,7 +39,7 @@ def PEFile(baseaddr):
|
||||
class StringRVa(RVA):
|
||||
@property
|
||||
def str(self):
|
||||
return ctypes.c_char_p(self.addr).value
|
||||
return ctypes.c_char_p(self.addr).value.decode()
|
||||
|
||||
def __repr__(self):
|
||||
return "<DWORD {0} (String RVA to '{1}')>".format(self.value, self.str)
|
||||
@@ -147,7 +147,7 @@ def PEFile(baseaddr):
|
||||
IAT = import_descriptor.get_IAT()
|
||||
if INT is not None:
|
||||
for iat_entry, (ord, name) in zip(IAT, INT):
|
||||
iat_entry.name = name
|
||||
iat_entry.name = name.decode()
|
||||
iat_entry.ord = ord
|
||||
res.setdefault(import_descriptor.Name.str.lower(),[]).extend(IAT)
|
||||
return res
|
||||
|
||||
+11
-3
@@ -38,7 +38,7 @@ class AutoHandle(object):
|
||||
return self._handle
|
||||
|
||||
def __del__(self):
|
||||
if hasattr(self, "_handle"):
|
||||
if hasattr(self, "_handle") and self._handle:
|
||||
kernel32proxy.CloseHandle(self._handle)
|
||||
|
||||
class System(object):
|
||||
@@ -219,9 +219,14 @@ class CurrentThread(AutoHandle):
|
||||
def _get_handle(self):
|
||||
return kernel32proxy.GetCurrentThread()
|
||||
|
||||
def __del__(self):
|
||||
pass
|
||||
|
||||
def exit(self, code=0):
|
||||
"""Exit the thread"""
|
||||
return kernel32proxy.ExitThread(code)
|
||||
|
||||
|
||||
|
||||
class CurrentProcess(Process):
|
||||
"""The current process"""
|
||||
@@ -231,7 +236,7 @@ class CurrentProcess(Process):
|
||||
# ret
|
||||
get_peb_64_code = codecs.decode(b"65488B042560000000C3", 'hex')
|
||||
|
||||
allocator = native_exec.native_function.CustomAllocator()
|
||||
allocator = native_exec.native_function.allocator
|
||||
|
||||
|
||||
def get_peb_builtin(self):
|
||||
@@ -246,6 +251,9 @@ class CurrentProcess(Process):
|
||||
|
||||
def _get_handle(self):
|
||||
return kernel32proxy.GetCurrentProcess()
|
||||
|
||||
def __del__(self):
|
||||
pass
|
||||
|
||||
@property
|
||||
def pid(self):
|
||||
@@ -418,7 +426,7 @@ class LoadedModule(LDR_DATA_TABLE_ENTRY):
|
||||
|
||||
:type: str
|
||||
"""
|
||||
return self.FullDllName.Buffer
|
||||
return self.FullDllName.Buffer.decode()
|
||||
|
||||
def __repr__(self):
|
||||
return '<{0} "{1}" at {2}>'.format(self.__class__.__name__, self.name, hex(id(self)))
|
||||
|
||||
Reference in New Issue
Block a user