Add 64->32 bits pe/peb parsing + stuff in simple_x86/64

This commit is contained in:
Clement Rouault
2015-11-13 09:25:05 +01:00
parent 2523c8e63e
commit ea78f81468
9 changed files with 351 additions and 70 deletions
+80 -2
View File
@@ -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
-5
View File
@@ -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)
+26 -2
View File
@@ -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):
+8
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+5
View File
@@ -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
View File
@@ -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