mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Add 64->32 bits pe/peb parsing + stuff in simple_x86/64
This commit is contained in:
@@ -32,9 +32,9 @@ REGSAM = ACCESS_MASK
|
||||
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', '_TOKEN_ELEVATION', '_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', '_SYMBOL_INFO', '_MODLOAD_DATA', '_SYSTEM_MODULE32', '_SYSTEM_MODULE64', '_SYSTEM_MODULE_INFORMATION32', '_SYSTEM_MODULE_INFORMATION64']
|
||||
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', '_TOKEN_ELEVATION', '_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', '_SYMBOL_INFO', '_MODLOAD_DATA', '_SYSTEM_MODULE32', '_SYSTEM_MODULE64', '_SYSTEM_MODULE_INFORMATION32', '_SYSTEM_MODULE_INFORMATION64', 'tagSAFEARRAYBOUND', 'tagSAFEARRAY']
|
||||
|
||||
enums = ['_SYSTEM_INFORMATION_CLASS', '_TCP_TABLE_CLASS', '_UDP_TABLE_CLASS', '_MIB_TCP_STATE', '_TOKEN_INFORMATION_CLASS', '_IMAGEHLP_SYMBOL_TYPE_INFO']
|
||||
enums = ['_SYSTEM_INFORMATION_CLASS', '_TCP_TABLE_CLASS', '_VARENUM', '_UDP_TABLE_CLASS', '_MIB_TCP_STATE', '_TOKEN_INFORMATION_CLASS', '_IMAGEHLP_SYMBOL_TYPE_INFO']
|
||||
|
||||
# Enum _SYSTEM_INFORMATION_CLASS definitions
|
||||
_SYSTEM_INFORMATION_CLASS = DWORD
|
||||
@@ -138,6 +138,63 @@ TCP_TABLE_OWNER_MODULE_LISTENER = 0x6
|
||||
TCP_TABLE_OWNER_MODULE_CONNECTIONS = 0x7
|
||||
TCP_TABLE_OWNER_MODULE_ALL = 0x8
|
||||
|
||||
# Enum _VARENUM definitions
|
||||
_VARENUM = DWORD
|
||||
VARENUM = _VARENUM
|
||||
|
||||
VT_EMPTY = 0x0
|
||||
VT_NULL = 0x1
|
||||
VT_I2 = 0x2
|
||||
VT_I4 = 0x3
|
||||
VT_R4 = 0x4
|
||||
VT_R8 = 0x5
|
||||
VT_CY = 0x6
|
||||
VT_DATE = 0x7
|
||||
VT_BSTR = 0x8
|
||||
VT_DISPATCH = 0x9
|
||||
VT_ERROR = 0xa
|
||||
VT_BOOL = 0xb
|
||||
VT_VARIANT = 0xc
|
||||
VT_UNKNOWN = 0xd
|
||||
VT_DECIMAL = 0xe
|
||||
VT_I1 = 0x10
|
||||
VT_UI1 = 0x11
|
||||
VT_UI2 = 0x12
|
||||
VT_UI4 = 0x13
|
||||
VT_I8 = 0x14
|
||||
VT_UI8 = 0x15
|
||||
VT_INT = 0x16
|
||||
VT_UINT = 0x17
|
||||
VT_VOID = 0x18
|
||||
VT_HRESULT = 0x19
|
||||
VT_PTR = 0x1a
|
||||
VT_SAFEARRAY = 0x1b
|
||||
VT_CARRAY = 0x1c
|
||||
VT_USERDEFINED = 0x1d
|
||||
VT_LPSTR = 0x1e
|
||||
VT_LPWSTR = 0x1f
|
||||
VT_RECORD = 0x24
|
||||
VT_INT_PTR = 0x25
|
||||
VT_UINT_PTR = 0x26
|
||||
VT_FILETIME = 0x40
|
||||
VT_BLOB = 0x41
|
||||
VT_STREAM = 0x42
|
||||
VT_STORAGE = 0x43
|
||||
VT_STREAMED_OBJECT = 0x44
|
||||
VT_STORED_OBJECT = 0x45
|
||||
VT_BLOB_OBJECT = 0x46
|
||||
VT_CF = 0x47
|
||||
VT_CLSID = 0x48
|
||||
VT_VERSIONED_STREAM = 0x49
|
||||
VT_BSTR_BLOB = 0xfff
|
||||
VT_VECTOR = 0x1000
|
||||
VT_ARRAY = 0x2000
|
||||
VT_BYREF = 0x4000
|
||||
VT_RESERVED = 0x8000
|
||||
VT_ILLEGAL = 0xffff
|
||||
VT_ILLEGALMASKED = 0xfff
|
||||
VT_TYPEMASK = 0xfff
|
||||
|
||||
# Enum _UDP_TABLE_CLASS definitions
|
||||
_UDP_TABLE_CLASS = DWORD
|
||||
UDP_TABLE_CLASS = _UDP_TABLE_CLASS
|
||||
@@ -1196,3 +1253,24 @@ class _SYSTEM_MODULE_INFORMATION64(Structure):
|
||||
PSYSTEM_MODULE_INFORMATION64 = POINTER(_SYSTEM_MODULE_INFORMATION64)
|
||||
SYSTEM_MODULE_INFORMATION64 = _SYSTEM_MODULE_INFORMATION64
|
||||
|
||||
# Struct tagSAFEARRAYBOUND definitions
|
||||
class tagSAFEARRAYBOUND(Structure):
|
||||
_fields_ = [
|
||||
("cElements", ULONG),
|
||||
("lLbound", LONG),
|
||||
]
|
||||
SAFEARRAYBOUND = tagSAFEARRAYBOUND
|
||||
LPSAFEARRAYBOUND = POINTER(tagSAFEARRAYBOUND)
|
||||
|
||||
# Struct tagSAFEARRAY definitions
|
||||
class tagSAFEARRAY(Structure):
|
||||
_fields_ = [
|
||||
("cDims", USHORT),
|
||||
("fFeatures", USHORT),
|
||||
("cbElements", ULONG),
|
||||
("cLocks", ULONG),
|
||||
("pvData", PVOID),
|
||||
("rgsabound", SAFEARRAYBOUND * 1),
|
||||
]
|
||||
SAFEARRAY = tagSAFEARRAY
|
||||
|
||||
|
||||
@@ -128,10 +128,5 @@ def inject_python_command(process, code_injected, PYDLL="python27.dll\x00"):
|
||||
|
||||
|
||||
def execute_python_code(process, code):
|
||||
print("me = {0}".format(windows.current_process.bitness))
|
||||
print("him = {0}".format(process.bitness))
|
||||
if windows.current_process.bitness != process.bitness:
|
||||
if windows.current_process.bitness == 64 and process.bitness == 32:
|
||||
raise NotImplementedError("Cannot perform 64 -> 32 injection")
|
||||
shellcode_remote_addr = inject_python_command(process, code)
|
||||
return process.create_thread(shellcode_remote_addr, 0)
|
||||
|
||||
@@ -473,8 +473,30 @@ class Slash(object):
|
||||
return arg_consum, value
|
||||
return arg_consum - 1, value
|
||||
|
||||
instr_state = collections.namedtuple('instr_state', ['previous', 'prefixes'])
|
||||
class ControlRegisterModRM(object):
|
||||
def __init__(self, writecr = False):
|
||||
self.writecr = writecr
|
||||
|
||||
def accept_arg(self, args, instr_state):
|
||||
writecr = self.writecr
|
||||
if len(args) < 2:
|
||||
return None, None
|
||||
reg = args[writecr]
|
||||
cr = args[not writecr]
|
||||
if not cr.lower().startswith("cr"):
|
||||
return None, None
|
||||
try:
|
||||
cr_number = int(cr[2:], 10)
|
||||
except ValueError as e:
|
||||
raise ValueError("Invalid ControlRegister {0}".format(cr))
|
||||
if cr_number > 7:
|
||||
raise ValueError("Invalid ControlRegister {0}".format(cr))
|
||||
|
||||
modrm_params = [reg, x86_regs[cr_number]] + args[2:]
|
||||
return ModRM([ModRM_REG__REG], has_direction_bit=False).accept_arg(modrm_params, instr_state)
|
||||
|
||||
|
||||
instr_state = collections.namedtuple('instr_state', ['previous', 'prefixes'])
|
||||
|
||||
class Instruction(object):
|
||||
"""Base class of instructions, use `encoding` to find a valid way to assemble the instruction"""
|
||||
@@ -610,7 +632,9 @@ class Sub(Instruction):
|
||||
|
||||
class Mov(Instruction):
|
||||
encoding = [(RawBits.from_int(8, 0x89), ModRM([ModRM_REG__REG, ModRM_REG__MEM])),
|
||||
(RawBits.from_int(5, 0xb8 >> 3), X86RegisterSelector(), Imm32())]
|
||||
(RawBits.from_int(5, 0xb8 >> 3), X86RegisterSelector(), Imm32()),
|
||||
(RawBits.from_int(16, 0x0f20), ControlRegisterModRM(writecr=False)),
|
||||
(RawBits.from_int(16, 0x0f22), ControlRegisterModRM(writecr=True))]
|
||||
|
||||
|
||||
class Movsb(Instruction):
|
||||
|
||||
@@ -80,6 +80,14 @@ class TestInstr(object):
|
||||
raise AssertionError("Expected mem.disp {0} got {1}".format(memaccess.disp, cap_mem.disp))
|
||||
|
||||
|
||||
TestInstr(Mov)('EAX', 'CR3')
|
||||
TestInstr(Mov)('EDX', 'CR0')
|
||||
TestInstr(Mov)('EDI', 'CR7')
|
||||
|
||||
TestInstr(Mov)('CR3', 'EAX')
|
||||
TestInstr(Mov)('CR0', 'EDX')
|
||||
TestInstr(Mov)('CR7', 'EDI')
|
||||
|
||||
TestInstr(Mov)('EAX', 'ESP')
|
||||
TestInstr(Mov)('ECX', mem('[EAX]'))
|
||||
TestInstr(Mov)('EDX', mem('[ECX + 0x10]'))
|
||||
|
||||
+28
-21
@@ -26,30 +26,37 @@ def transform_ctypes_fields(struct, replacement):
|
||||
return [(name, replacement.get(name, type)) for name, type in struct._fields_]
|
||||
|
||||
|
||||
def get_structure_transformer_for_target(target):
|
||||
current_bitness = windows.current_process.bitness
|
||||
if target is None:
|
||||
ctypes_structure_transformer = lambda x:x
|
||||
create_structure_at = lambda structcls, addr: structcls.from_address(addr)
|
||||
return ctypes_structure_transformer, create_structure_at
|
||||
|
||||
if target.bitness == 32 and current_bitness == 64:
|
||||
ctypes_structure_transformer = rctypes.transform_type_to_remote32bits
|
||||
elif target.bitness == 64 and current_bitness == 32:
|
||||
ctypes_structure_transformer = rctypes.transform_type_to_remote64bits
|
||||
elif target.bitness == current_bitness:
|
||||
ctypes_structure_transformer = rctypes.transform_type_to_remote
|
||||
else:
|
||||
raise NotImplementedError("Parsing {0} PE from {1} Process".format(targetedbitness, proc_bitness))
|
||||
|
||||
def create_structure_at(structcls, addr):
|
||||
return ctypes_structure_transformer(structcls)(addr, target)
|
||||
return ctypes_structure_transformer, create_structure_at
|
||||
|
||||
|
||||
def PEFile(baseaddr, target=None):
|
||||
# TODO: 32 with target 32
|
||||
# 64 with target 64
|
||||
# For now you can do it by injecting a remote python..
|
||||
proc_bitness = windows.current_process.bitness
|
||||
if target is None:
|
||||
targetedbitness = proc_bitness
|
||||
else:
|
||||
targetedbitness = target.bitness
|
||||
|
||||
if targetedbitness == 32 and proc_bitness == 64:
|
||||
raise NotImplementedError("Parse 32bits PE with 64bits current_process")
|
||||
elif targetedbitness == 64 and proc_bitness == 32:
|
||||
ctypes_structure_transformer = rctypes.transform_type_to_remote64bits
|
||||
transformers = get_structure_transformer_for_target(target)
|
||||
ctypes_structure_transformer, create_structure_at = transformers
|
||||
|
||||
def create_structure_at(structcls, addr):
|
||||
return rctypes.transform_type_to_remote64bits(structcls)(addr, target)
|
||||
elif targetedbitness == proc_bitness: # Does not handle remote of same bitness..
|
||||
ctypes_structure_transformer = lambda x: x
|
||||
|
||||
def create_structure_at(structcls, addr):
|
||||
return structcls.from_address(addr)
|
||||
else:
|
||||
raise NotImplementedError("Parsing {0} PE from {1} Process".format(targetedbitness, proc_bitness))
|
||||
|
||||
if targetedbitness == 32:
|
||||
IMAGE_ORDINAL_FLAG = IMAGE_ORDINAL_FLAG32
|
||||
@@ -65,14 +72,14 @@ def PEFile(baseaddr, target=None):
|
||||
return "<DWORD {0} (RVA to '{1}')>".format(self.value, hex(self.addr))
|
||||
|
||||
class StringRVa(RVA):
|
||||
if proc_bitness == 32 and targetedbitness == 64:
|
||||
@property
|
||||
def str(self):
|
||||
return rctypes.Remote_c_char_p64(self.addr, target=target).value
|
||||
else:
|
||||
if target is None:
|
||||
@property
|
||||
def str(self):
|
||||
return ctypes.c_char_p(self.addr).value.decode()
|
||||
else:
|
||||
@property
|
||||
def str(self):
|
||||
return create_structure_at(ctypes.c_char_p, self.addr).value.decode()
|
||||
|
||||
def __repr__(self):
|
||||
return "<DWORD {0} (String RVA to '{1}')>".format(self.value, self.str)
|
||||
|
||||
+154
-34
@@ -1,3 +1,6 @@
|
||||
"""remote ctypes, a try to a ctypes wrapper that accept a target object for every ready operation
|
||||
Some code is copy-paste, might be userful to rewrite some part later"""
|
||||
|
||||
import _ctypes
|
||||
import ctypes
|
||||
import ctypes.wintypes
|
||||
@@ -49,6 +52,20 @@ class c_char_p64(_SimpleCData):
|
||||
class c_wchar_p64(_SimpleCData):
|
||||
_type_ = "Q"
|
||||
|
||||
|
||||
# # 32bits pointer types # #
|
||||
class c_void_p32(_SimpleCData):
|
||||
_type_ = "I"
|
||||
|
||||
|
||||
class c_char_p32(_SimpleCData):
|
||||
_type_ = "I"
|
||||
|
||||
|
||||
class c_wchar_p32(_SimpleCData):
|
||||
_type_ = "I"
|
||||
|
||||
|
||||
# standard type translation
|
||||
# don't know how to handle size_t since it's non-distinguable from c_ulong
|
||||
# maybe force import before ctypes and modif stuff into ctypes ?
|
||||
@@ -142,6 +159,7 @@ def create_remote_array(subtype, len):
|
||||
|
||||
|
||||
# 64bits pointers
|
||||
|
||||
class RemotePtr64(RemoteValue):
|
||||
def __init__(self, value, target):
|
||||
self.target = target
|
||||
@@ -198,6 +216,64 @@ type_32_64_translation_table = {
|
||||
}
|
||||
|
||||
|
||||
# 32bits pointers
|
||||
|
||||
class RemotePtr32(RemoteValue):
|
||||
def __init__(self, value, target):
|
||||
self.target = target
|
||||
super(RemotePtr32, self).__init__(value)
|
||||
|
||||
@property
|
||||
def raw_value(self):
|
||||
# Bypass our own 'value' implementation
|
||||
# Even if we are a subclass of c_ulonglong
|
||||
my_addr = ctypes.addressof(self)
|
||||
return ctypes.c_ulong.from_address(my_addr).value
|
||||
|
||||
|
||||
class Remote_c_void_p32(RemotePtr32, c_void_p32):
|
||||
pass
|
||||
|
||||
|
||||
# base explanation:
|
||||
# RemotePtr64 for the good `raw_value` implem
|
||||
# RemoteCCharP for the good `value` implem
|
||||
# c_char_p64 for the good _type_ (ctypes size)
|
||||
class Remote_c_char_p32(c_char_p32, RemotePtr32, RemoteCCharP):
|
||||
def __repr__(self):
|
||||
return "<Remote_c_char_p32({0})>".format(self.raw_value)
|
||||
|
||||
|
||||
class Remote_w_char_p32(c_wchar_p32, RemotePtr32, RemoteWCharP):
|
||||
def __repr__(self):
|
||||
return "<Remote_c_char_p32({0})>".format(self.raw_value)
|
||||
|
||||
|
||||
class RemoteStructurePointer32(Remote_c_void_p32):
|
||||
@property
|
||||
def raw_value(self):
|
||||
return self.value
|
||||
|
||||
@classmethod
|
||||
def from_buffer_with_target_and_ptr_type(cls, buffer, offset=0, target=None, ptr_type=None):
|
||||
x = cls.from_buffer(buffer)
|
||||
x.target = target
|
||||
x.real_pointer_type = ptr_type
|
||||
return x
|
||||
|
||||
@property
|
||||
def contents(self):
|
||||
remote_pointed_type = transform_type_to_remote32bits(self.real_pointer_type._sub_ctypes_)
|
||||
return remote_pointed_type(self.raw_value, self.target)
|
||||
|
||||
|
||||
type_64_32_translation_table = {
|
||||
ctypes.c_void_p: Remote_c_void_p32,
|
||||
ctypes.c_char_p: Remote_c_char_p32,
|
||||
ctypes.c_wchar_p: Remote_w_char_p32,
|
||||
}
|
||||
|
||||
|
||||
class RemoteStructureUnion(object):
|
||||
"""Target is a process object"""
|
||||
_reserved_name = ["_target", "_fields_", "_fields_dict_", "_base_addr", "_get_field_by_name",
|
||||
@@ -209,7 +285,10 @@ class RemoteStructureUnion(object):
|
||||
ctypes.c_wchar_p: RemoteWCharP,
|
||||
Remote_c_void_p64: Remote_c_void_p64,
|
||||
Remote_c_char_p64: Remote_c_char_p64,
|
||||
Remote_w_char_p64: Remote_w_char_p64
|
||||
Remote_w_char_p64: Remote_w_char_p64,
|
||||
Remote_c_void_p32: Remote_c_void_p32,
|
||||
Remote_c_char_p32: Remote_c_char_p32,
|
||||
Remote_w_char_p32: Remote_w_char_p32
|
||||
}
|
||||
|
||||
def __init__(self, base_addr, target):
|
||||
@@ -234,6 +313,8 @@ class RemoteStructureUnion(object):
|
||||
return RemoteStructurePointer.from_buffer_with_target_and_ptr_type(bytearray(s), target=self._target, ptr_type=ftype)
|
||||
if issubclass(ftype, RemotePtr64): # Pointer to remote64 bits process
|
||||
return RemoteStructurePointer64.from_buffer_with_target_and_ptr_type(bytearray(s), target=self._target, ptr_type=ftype)
|
||||
if issubclass(ftype, RemotePtr32): # Pointer to remote32 bits process
|
||||
return RemoteStructurePointer32.from_buffer_with_target_and_ptr_type(bytearray(s), target=self._target, ptr_type=ftype)
|
||||
if issubclass(ftype, RemoteStructureUnion): # Structure|Union already transfomed in remote
|
||||
return ftype(self._base_addr + fosset, self._target)
|
||||
if issubclass(ftype, ctypes.Structure): # Structure that must be transfomed
|
||||
@@ -290,37 +371,76 @@ class RemoteUnion(RemoteStructureUnion, ctypes.Union):
|
||||
|
||||
remote_struct = RemoteStructure.from_structure
|
||||
|
||||
# ctypes 32 -> 64 methods
|
||||
def MakePtr64(type):
|
||||
class PointerToStruct64(Remote_c_void_p64):
|
||||
_sub_ctypes_ = (type)
|
||||
return PointerToStruct64
|
||||
|
||||
def transform_structure_to_remote64bits(structcls):
|
||||
"""Create a remote structure for a 64bits target process"""
|
||||
new_fields = []
|
||||
for fname, ftype in structcls._fields_:
|
||||
ftype = transform_type_to_remote64bits(ftype)
|
||||
new_fields.append((fname, ftype))
|
||||
return RemoteStructure.from_fields(new_fields, base_cls=structcls)
|
||||
|
||||
def transform_union_to_remote64bits(structcls):
|
||||
"""Create a remote union for a 64bits target process"""
|
||||
new_fields = []
|
||||
for fname, ftype in structcls._fields_:
|
||||
ftype = transform_type_to_remote64bits(ftype)
|
||||
new_fields.append((fname, ftype))
|
||||
return RemoteUnion.from_fields(new_fields, base_cls=structcls)
|
||||
|
||||
def transform_type_to_remote64bits(ftype):
|
||||
if is_pointer_type(ftype):
|
||||
return MakePtr64(ftype._type_)
|
||||
if is_array_type(ftype):
|
||||
return create_remote_array(transform_type_to_remote64bits(ftype._type_), ftype._length_)
|
||||
if is_structure_type(ftype):
|
||||
return transform_structure_to_remote64bits(ftype)
|
||||
if is_union_type(ftype):
|
||||
return transform_union_to_remote64bits(ftype)
|
||||
# Normal types
|
||||
return type_32_64_translation_table.get(ftype, ftype)
|
||||
|
||||
|
||||
# ctypes 64 -> 32 methods
|
||||
def MakePtr32(type):
|
||||
class PointerToStruct32(Remote_c_void_p32):
|
||||
_sub_ctypes_ = (type)
|
||||
return PointerToStruct32
|
||||
|
||||
def transform_structure_to_remote32bits(structcls):
|
||||
"""Create a remote structure for a 32bits target process"""
|
||||
new_fields = []
|
||||
for fname, ftype in structcls._fields_:
|
||||
ftype = transform_type_to_remote32bits(ftype)
|
||||
new_fields.append((fname, ftype))
|
||||
return RemoteStructure.from_fields(new_fields, base_cls=structcls)
|
||||
|
||||
def transform_union_to_remote32bits(structcls):
|
||||
"""Create a remote union for a 32bits target process"""
|
||||
new_fields = []
|
||||
for fname, ftype in structcls._fields_:
|
||||
ftype = transform_type_to_remote32bits(ftype)
|
||||
new_fields.append((fname, ftype))
|
||||
return RemoteUnion.from_fields(new_fields, base_cls=structcls)
|
||||
|
||||
def transform_type_to_remote32bits(ftype):
|
||||
if is_pointer_type(ftype):
|
||||
return MakePtr32(ftype._type_)
|
||||
if is_array_type(ftype):
|
||||
return create_remote_array(transform_type_to_remote32bits(ftype._type_), ftype._length_)
|
||||
if is_structure_type(ftype):
|
||||
return transform_structure_to_remote32bits(ftype)
|
||||
if is_union_type(ftype):
|
||||
return transform_union_to_remote32bits(ftype)
|
||||
# Normal types
|
||||
return type_64_32_translation_table.get(ftype, ftype)
|
||||
|
||||
if ctypes.sizeof(ctypes.c_void_p) == 4:
|
||||
# ctypes 32 -> 64 methods
|
||||
def MakePtr(type):
|
||||
class PointerToStruct64(Remote_c_void_p64):
|
||||
_sub_ctypes_ = (type)
|
||||
return PointerToStruct64
|
||||
|
||||
def transform_structure_to_remote64bits(structcls):
|
||||
"""Create a remote structure for a 64bits target process"""
|
||||
new_fields = []
|
||||
for fname, ftype in structcls._fields_:
|
||||
ftype = transform_type_to_remote64bits(ftype)
|
||||
new_fields.append((fname, ftype))
|
||||
return RemoteStructure.from_fields(new_fields, base_cls=structcls)
|
||||
|
||||
def transform_union_to_remote64bits(structcls):
|
||||
"""Create a remote structure for a 64bits target process"""
|
||||
new_fields = []
|
||||
for fname, ftype in structcls._fields_:
|
||||
ftype = transform_type_to_remote64bits(ftype)
|
||||
new_fields.append((fname, ftype))
|
||||
return RemoteUnion.from_fields(new_fields, base_cls=structcls)
|
||||
|
||||
def transform_type_to_remote64bits(ftype):
|
||||
if is_pointer_type(ftype):
|
||||
return MakePtr(ftype._type_)
|
||||
if is_array_type(ftype):
|
||||
return create_remote_array(transform_type_to_remote64bits(ftype._type_), ftype._length_)
|
||||
if is_structure_type(ftype):
|
||||
return transform_structure_to_remote64bits(ftype)
|
||||
if is_union_type(ftype):
|
||||
return transform_union_to_remote64bits(ftype)
|
||||
# Normal types
|
||||
return type_32_64_translation_table.get(ftype, ftype)
|
||||
transform_type_to_remote = transform_type_to_remote32bits
|
||||
if ctypes.sizeof(ctypes.c_void_p) == 8:
|
||||
transform_type_to_remote = transform_type_to_remote64bits
|
||||
|
||||
+5
-3
@@ -157,8 +157,8 @@ class WindowsTestCase(unittest.TestCase):
|
||||
k32 = mods[0]
|
||||
get_current_proc_id = k32.pe.exports['GetCurrentProcessId']
|
||||
# TODO: check get_current_proc_id value (but we cannot do 64->32 injection for now)
|
||||
if is_process_64_bits:
|
||||
raise NotImplementedError("Python execution 64->32")
|
||||
#if is_process_64_bits:
|
||||
# raise NotImplementedError("Python execution 64->32")
|
||||
data = calc.virtual_alloc(0x1000)
|
||||
remote_python_code = """
|
||||
import ctypes
|
||||
@@ -232,4 +232,6 @@ class WindowsTestCase(unittest.TestCase):
|
||||
if __name__ == '__main__':
|
||||
alltests = unittest.TestSuite()
|
||||
alltests.addTest(unittest.makeSuite(WindowsTestCase))
|
||||
unittest.TextTestRunner(verbosity=2).run(alltests)
|
||||
alltests.debug()
|
||||
tester = unittest.TextTestRunner(verbosity=2)
|
||||
tester.run(alltests)
|
||||
|
||||
@@ -30,6 +30,7 @@ def get_remote_func_addr(target, dll_name, func_name):
|
||||
|
||||
|
||||
def is_wow_64(hProcess):
|
||||
import ipdb;ipdb.set_trace()
|
||||
try:
|
||||
fnIsWow64Process = get_func_addr("kernel32.dll", "IsWow64Process")
|
||||
except winproxy.Kernel32Error:
|
||||
@@ -190,10 +191,14 @@ class VirtualProtected(object):
|
||||
class DisableWow64FsRedirection(object):
|
||||
"""A context manager that disable the Wow64 Fs Redirection"""
|
||||
def __enter__(self):
|
||||
if windows.current_process.bitness == 64:
|
||||
return self
|
||||
self.OldValue = PVOID()
|
||||
winproxy.Wow64DisableWow64FsRedirection(ctypes.byref(self.OldValue))
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
if windows.current_process.bitness == 64:
|
||||
return False
|
||||
winproxy.Wow64RevertWow64FsRedirection(self.OldValue)
|
||||
return False
|
||||
|
||||
+45
-3
@@ -158,7 +158,6 @@ class WinThread(THREADENTRY32, AutoHandle):
|
||||
@staticmethod
|
||||
def _from_handle(handle):
|
||||
tid = winproxy.GetThreadId(handle)
|
||||
print(tid)
|
||||
try:
|
||||
return [t for t in System().threads if t.tid == tid][0]
|
||||
except IndexError:
|
||||
@@ -462,6 +461,8 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
def peb(self):
|
||||
if windows.current_process.bitness == 32 and self.bitness == 64:
|
||||
return RemotePEB64(self.get_peb_addr(), self)
|
||||
if windows.current_process.bitness == 64 and self.bitness == 32:
|
||||
return RemotePEB32(self.get_peb_addr(), self)
|
||||
return RemotePEB(self.get_peb_addr(), self)
|
||||
|
||||
def exit(self, code=0):
|
||||
@@ -569,12 +570,20 @@ class PEB(Structure):
|
||||
|
||||
import windows.remotectypes as rctypes
|
||||
|
||||
class RemoteLoadedModule(rctypes.RemoteStructure.from_structure(LoadedModule)):
|
||||
@property
|
||||
def pe(self):
|
||||
"""A PE representation of the module
|
||||
|
||||
:type: :class:`windows.pe_parse.PEFile`
|
||||
"""
|
||||
return pe_parse.PEFile(self.baseaddr, target=self._target)
|
||||
|
||||
|
||||
class RemotePEB(rctypes.RemoteStructure.from_structure(PEB)):
|
||||
RemoteLoadedModule = rctypes.RemoteStructure.from_structure(LoadedModule)
|
||||
|
||||
def ptr_flink_to_remote_module(self, ptr_value):
|
||||
return self.RemoteLoadedModule(ptr_value - ctypes.sizeof(ctypes.c_void_p) * 2, self._target)
|
||||
return RemoteLoadedModule(ptr_value - ctypes.sizeof(ctypes.c_void_p) * 2, self._target)
|
||||
|
||||
@property
|
||||
def modules(self):
|
||||
@@ -623,3 +632,36 @@ if CurrentProcess().bitness == 32:
|
||||
list_entry_ptr = current_dll.InMemoryOrderLinks.Flink.raw_value
|
||||
current_dll = self.ptr_flink_to_remote_module(list_entry_ptr)
|
||||
return res
|
||||
|
||||
if CurrentProcess().bitness == 64:
|
||||
|
||||
class RemoteLoadedModule32(rctypes.transform_type_to_remote32bits(LoadedModule)):
|
||||
@property
|
||||
def pe(self):
|
||||
"""A PE representation of the module
|
||||
|
||||
:type: :class:`windows.pe_parse.PEFile`
|
||||
"""
|
||||
return pe_parse.PEFile(self.baseaddr, target=self._target)
|
||||
|
||||
class RemotePEB32(rctypes.transform_type_to_remote32bits(PEB)):
|
||||
|
||||
def ptr_flink_to_remote_module(self, ptr_value):
|
||||
return RemoteLoadedModule32(ptr_value - ctypes.sizeof(rctypes.c_void_p32) * 2, self._target)
|
||||
|
||||
@property
|
||||
def modules(self):
|
||||
"""The loaded modules present in the PEB
|
||||
|
||||
:type: [:class:`LoadedModule`] -- List of loaded modules
|
||||
"""
|
||||
res = []
|
||||
#import pdb;pdb.set_trace()
|
||||
list_entry_ptr = self.Ldr.contents.InMemoryOrderModuleList.Flink.raw_value
|
||||
|
||||
current_dll = self.ptr_flink_to_remote_module(list_entry_ptr)
|
||||
while current_dll.DllBase:
|
||||
res.append(current_dll)
|
||||
list_entry_ptr = current_dll.InMemoryOrderLinks.Flink.raw_value
|
||||
current_dll = self.ptr_flink_to_remote_module(list_entry_ptr)
|
||||
return res
|
||||
|
||||
Reference in New Issue
Block a user