diff --git a/Config.py b/Config.py index e1a31bc..d3901e5 100644 --- a/Config.py +++ b/Config.py @@ -40,8 +40,8 @@ ###################################################### # Logging ###################################################### -ENABLE_LOGGING = True -ENABLE_DEBUG_LOGGING = True +ENABLE_LOGGING = False +ENABLE_DEBUG_LOGGING = False # If set to True the user will get a prompt to choose the logging directory LOG_FILES_DETERMINED_BY_USER = True diff --git a/RttiInfomation/BaseClassDescriptor.py b/RttiInfomation/BaseClassDescriptor.py index ada3827..852e69f 100644 --- a/RttiInfomation/BaseClassDescriptor.py +++ b/RttiInfomation/BaseClassDescriptor.py @@ -79,9 +79,9 @@ def GetClassDescriptor(self): return self.bv.read_int(self.base_addr + 0x18, 0x4) + base_of_file def IsInheritenceTypeSupported(self): - # if the pDisp field is -1 then we are dealing with normal inheritence, otherwise - # we have multiple virtual inheritence which is not supported at the moment: - # TODO: Support multiple virtual inheritence + # if the pDisp field is -1 then we are dealing with normal inheritance, otherwise + # we have multiple virtual inheritance which is not supported at the moment: + # TODO: Support multiple virtual inheritance # For now we return True no matter what, in order to keep the processing of further base classes. # return self.pmd_pdisp == -1 return True @@ -119,6 +119,7 @@ def DefineDataVar(self): ) return True except Exception as e: + Utils.LogToFile(f'BaseClassDescriptor: Exception while trying to define data var at {hex(self.base_addr)}') return False def DefineRecursiveChd(self) -> bool: diff --git a/RttiInfomation/ClassHierarchyDescriptor.py b/RttiInfomation/ClassHierarchyDescriptor.py index d0eee44..74d4d15 100644 --- a/RttiInfomation/ClassHierarchyDescriptor.py +++ b/RttiInfomation/ClassHierarchyDescriptor.py @@ -48,11 +48,14 @@ def VerifyChdSignature(self): return False def VerifyChdAttributes(self) -> bool: + # attributes is a bitfield, with the following possible values defined in rttidata.h: # attributes = 0 - normal inheritance # attributes = 1 - multiple inheritance # attributes = 2 - virtual inheritance # attributes = 3 - multiple and virtual inheritance - if self.attributes == 0x0 or self.attributes == 0x1: + # attributes = 5 - Ambiguous, this option seems to be fine for our purposes + # TODO: Check what attribute = 5 actually means + if self.attributes == 0x0 or self.attributes == 0x1 or self.attributes == 0x5: # TODO: Add a better verification system return True elif self.attributes == 0x2 or self.attributes == 0x3: diff --git a/RttiInfomation/CompleteObjectLocator.py b/RttiInfomation/CompleteObjectLocator.py index e957ff7..b2937ce 100644 --- a/RttiInfomation/CompleteObjectLocator.py +++ b/RttiInfomation/CompleteObjectLocator.py @@ -4,7 +4,6 @@ from ..Common import Utils from .. import Config from typing import * -import pysnooper class CompleteObjectLocator: @@ -97,7 +96,7 @@ def DefineDataVarForCol(self): def GetChdAddr(self) -> int: """ - Get the address of the Class Hierarchy Desctriptor pointed to by this Col + Get the address of the Class Hierarchy Descriptor pointed to by this Col :return: address of CHD """ return self.class_hierarchy_descriptor_address @@ -144,11 +143,13 @@ def VerifyClassHierarchyDescriptor(self) -> bool: if class_hierarchy_descriptor.verified: self.class_hierarchy_descriptor_address = class_hierarchy_descriptor.base_addr Utils.LogToFile( - f'VerifyClassHierarchyDescriptor: Succesfully defined CHD at - {hex(class_hierarchy_descriptor.base_addr)}.') + f'VerifyClassHierarchyDescriptor: Successfully defined CHD at - ' + f'{hex(class_hierarchy_descriptor.base_addr)}.') return True else: Utils.LogToFile( - f'VerifyClassHierarchyDescriptor: FAILED to defined CHD at - {hex(class_hierarchy_descriptor.base_addr)}.') + f'VerifyClassHierarchyDescriptor: FAILED to defined CHD at - ' + f'{hex(class_hierarchy_descriptor.base_addr)}.') return False def DefineVirtualFuncTable(self) -> bool: @@ -192,7 +193,7 @@ def GetvTableFunctions(self) -> List[int]: def VerifyCol(self) -> bool: """ Verify this is really a Complete Object Locator. - :return: Verification Succeed \ Fail + :return: Verification Succeed / Fail """ Utils.LogToFile(f'VerifyCol: Verifying {self.__repr__()}') diff --git a/RttiInfomation/VirtualTableInference/VirtualFunctionTable.py b/RttiInfomation/VirtualTableInference/VirtualFunctionTable.py index 6c26928..4fcad3c 100644 --- a/RttiInfomation/VirtualTableInference/VirtualFunctionTable.py +++ b/RttiInfomation/VirtualTableInference/VirtualFunctionTable.py @@ -2,7 +2,6 @@ from ...Common import Utils from typing import * -import pysnooper # {vfTable_addr: [ContainedFunctions]} global_vfTables: Dict[int, List[int]] = dict() @@ -62,28 +61,31 @@ def DefineVFT(self) -> bool: else: return False + def GetBinjaVoidPointerType(self) -> bn.types.PointerType: + return bn.Type.pointer(self.bv.arch, self.bv.parse_type_string("void")[0]) + def GetPointer(self, pointer_addr: int) -> Optional[bn.DataVariable]: # Sometimes binja parses PDB information incorrectly, and instead of a pointer to a vTable # it just defines the struct that the PDB says defines the vTable. # If this happens - we dont change the PDB struct, we just say this is a pointer to the PDB struct. - pointer: bn.DataVariable = self.bv.get_data_var_at(pointer_addr) - if type(pointer) != bn.types.PointerType: - if not pointer: - pointer_name = " " - else: - pointer_name = pointer.name - try: - Utils.LogToFile(f"VirtualFunction_GetPointer: Overriding original type for Vtable -\n" - f"pointer_addr: {hex(pointer_addr)}\n" - f"attempt pointer type: {bn.Type.pointer(self.bv.arch, pointer.type)}\n" - f"pointer name: {pointer.name}") - self.bv.define_user_data_var(pointer_addr, - bn.Type.pointer(self.bv.arch, self.bv.parse_type_string("void")[0]), - pointer_name) - return self.bv.get_data_var_at(pointer_addr) - except Exception as e: - return None - return pointer + pointer: bn.DataVariable + if pointer := self.bv.get_data_var_at(pointer_addr): + if type(pointer) != bn.types.PointerType: + try: + Utils.LogToFile(f"GetPointer: Overriding original type for Vtable -\n" + f"pointer_addr: {hex(pointer_addr)}\n" + f"current pointer type: {pointer.type}\n" + f"pointer name: {pointer.name}") + self.bv.define_user_data_var(pointer_addr, + self.GetBinjaVoidPointerType(), + pointer.name) + return self.bv.get_data_var_at(pointer_addr) + except Exception as e: + Utils.LogToFile(f"GetPointer: Exception while trying to define pointer at addr {pointer_addr}.\n" + f"Exception: {e}") + return None + return pointer + return None def IsPointerToFunction(self, pointer_addr: int) -> bool: try: @@ -95,8 +97,8 @@ def IsPointerToFunction(self, pointer_addr: int) -> bool: self.contained_functions.append(pointer.value) return True except Exception as e: - pass - + Utils.LogToFile(f"IsPointerToFunction: Failed to determine if pointer to function at {pointer_addr}.\n" + f"Exception: {e}") return False def GetLength(self):