2929 objc_property_list_t ,
3030 objc_property_t ,
3131 objc_protocol_list_t ,
32- objc_protocol_t
32+ objc_protocol_t ,
33+ relative_list_list_t ,
34+ relative_list_t
3335)
3436
3537from DyldExtractor .macho .macho_structs import (
@@ -415,6 +417,15 @@ def run(self):
415417 else :
416418 self ._logger .error ("Unable to find libobjc.A.dylib" )
417419 return
420+
421+ # Get image index
422+ imageAddr = self ._machoCtx .segments [b"__TEXT" ].seg .vmaddr
423+ for i , image in enumerate (self ._dyldCtx .images ):
424+ if image .address == imageAddr :
425+ self ._imageIndex = i
426+ break
427+ pass
428+
418429
419430 self ._checkMethodNameStorage ()
420431
@@ -918,17 +929,22 @@ def _processClassData(self, classDataAddr: int, isStubClass=False) -> int:
918929 classDataDef .name = self ._processString (classDataDef .name )
919930 pass
920931
921- if classDataDef .baseMethods :
932+ baseMethodsAddr = classDataDef .baseMethods
933+ if baseMethodsAddr & 0x1 :
934+ baseMethodsAddr = self ._findInImageRelList (baseMethodsAddr & ~ 0x1 )
935+ if baseMethodsAddr :
922936 classDataDef .baseMethods = self ._processMethodList (
923- classDataDef . baseMethods ,
937+ baseMethodsAddr ,
924938 noImp = isStubClass
925939 )
926940 pass
941+
927942
928- if classDataDef .baseProtocols :
929- classDataDef .baseProtocols = self ._processProtocolList (
930- classDataDef .baseProtocols
931- )
943+ baseProtocolsAddr = classDataDef .baseProtocols
944+ if baseProtocolsAddr & 0x1 :
945+ baseProtocolsAddr = self ._findInImageRelList (baseProtocolsAddr & ~ 0x1 )
946+ if baseProtocolsAddr :
947+ classDataDef .baseProtocols = self ._processProtocolList (baseProtocolsAddr )
932948 pass
933949
934950 if classDataDef .ivars :
@@ -942,10 +958,11 @@ def _processClassData(self, classDataAddr: int, isStubClass=False) -> int:
942958 )
943959 pass
944960
945- if classDataDef .baseProperties :
946- classDataDef .baseProperties = self ._processPropertyList (
947- classDataDef .baseProperties
948- )
961+ basePropertiesAddr = classDataDef .baseProperties
962+ if basePropertiesAddr & 0x1 :
963+ basePropertiesAddr = self ._findInImageRelList (basePropertiesAddr & ~ 0x1 )
964+ if basePropertiesAddr :
965+ classDataDef .baseProperties = self ._processPropertyList (basePropertiesAddr )
949966 pass
950967
951968 # add or update data
@@ -1219,12 +1236,13 @@ def _processMethodList(self, methodListAddr: int, noImp=False) -> int:
12191236 pass
12201237
12211238 # check if size is correct
1222- if usesRelativeMethods and entsize != objc_method_small_t .SIZE :
1223- self ._logger .error (f"Small method list at { hex (methodListAddr )} , has an entsize that doesn't match the size of objc_method_small_t" ) # noqa
1224- return 0
1225- elif not usesRelativeMethods and entsize != objc_method_large_t .SIZE :
1226- self ._logger .error (f"Large method list at { hex (methodListAddr )} , has an entsize that doesn't match the size of objc_method_large_t" ) # noqa
1227- return 0
1239+ if methodListDef .count != 0 :
1240+ if usesRelativeMethods and entsize != objc_method_small_t .SIZE :
1241+ self ._logger .error (f"Small method list at { hex (methodListAddr )} , has an entsize that doesn't match the size of objc_method_small_t" ) # noqa
1242+ return 0
1243+ elif not usesRelativeMethods and entsize != objc_method_large_t .SIZE :
1244+ self ._logger .error (f"Large method list at { hex (methodListAddr )} , has an entsize that doesn't match the size of objc_method_large_t" ) # noqa
1245+ return 0
12281246
12291247 methodListData = bytearray (methodListDef )
12301248
@@ -1376,6 +1394,38 @@ def _processMethodName(self, stringAddr: int) -> int:
13761394 self ._methodNameCache [stringAddr ] = ptrAddr
13771395 return ptrAddr
13781396
1397+ def _findInImageRelList (self , relListListAddr : int ) -> int :
1398+ """Find the in image list in a relative list list.
1399+
1400+ Args:
1401+ relListListAddr: Address to the relative_list_list_t
1402+
1403+ returns:
1404+ The address to the in image list, or 0 if not found.
1405+ """
1406+
1407+ relListList = self ._slider .slideStruct (relListListAddr , relative_list_list_t )
1408+
1409+ # Check entsize
1410+ if relListList .entsize != relative_list_t .SIZE :
1411+ self ._logger .error (f"relative_list_list_t at { hex (relListListAddr )} has an entsize that doesn't match relative_list_t" ) # noqa
1412+ return 0
1413+
1414+ for i in range (relListList .count ):
1415+ relListAddr = (
1416+ relListListAddr
1417+ + relative_list_list_t .SIZE
1418+ + (i * relative_list_t .SIZE )
1419+ )
1420+ relList = self ._slider .slideStruct (relListAddr , relative_list_t )
1421+ if (
1422+ relList .getImageIndex () == self ._imageIndex
1423+ and (offset := relList .getOffset ()) != 0
1424+ ):
1425+ return relListAddr + offset
1426+
1427+ return 0
1428+
13791429 def _finalizeFutureClasses (self ) -> None :
13801430 extraSegStart = self ._extraDataHead - len (self ._extraData )
13811431
0 commit comments