Beispiel #1
0
    def test_write_fat_binary(self) -> None:
        # Given I add a load command to the arm64 slice of an armv7/arm64 FAT file
        parser = MachoParser(self.FAT_PATH)
        binary = parser.get_arm64_slice()
        assert binary
        original_dylibs = [binary.dylib_name_for_library_ordinal(i + 1) for i in range(len(binary.load_dylib_commands))]
        new_dylib_name = "@rpath/Frameworks/Interject.framework/Interject"
        modified_binary = binary.insert_load_dylib_cmd(new_dylib_name)

        with TemporaryDirectory() as tempdir:
            output_binary_path = pathlib.Path(tempdir) / "modified_fat"
            armv7_binary = parser.get_armv7_slice()
            assert armv7_binary
            # If I write the FAT to disk with both slices, then parse the on-disk version
            MachoBinary.write_fat([armv7_binary, modified_binary], output_binary_path)
            on_disk_fat_parser = MachoParser(output_binary_path)

            assert len(on_disk_fat_parser.slices) == 2

            # Then I get a FAT with valid slices
            armv7 = on_disk_fat_parser.get_armv7_slice()
            assert armv7 is not None
            assert len(armv7.segments) == 4

            arm64 = on_disk_fat_parser.get_arm64_slice()
            assert arm64 is not None
            assert len(arm64.segments) == 4
            # And the arm64 segment contains the new load command
            new_dylibs = [arm64.dylib_name_for_library_ordinal(i + 1) for i in range(len(arm64.load_dylib_commands))]
            assert new_dylibs == original_dylibs + [new_dylib_name]
Beispiel #2
0
 def test_protocol_32bit(self) -> None:
     parser = MachoParser(TestObjcRuntimeDataParser.PROTOCOL_32BIT_PATH)
     binary = parser.get_armv7_slice()
     assert binary
     dyld_info_parser = DyldInfoParser(binary)
     objc_parser = ObjcRuntimeDataParser(binary, dyld_info_parser)
     assert len(objc_parser.classes) == 66
     test_cls = [
         x for x in objc_parser.classes
         if x.name == "Pepsico_iPhoneAppDelegate"
     ][0]
     assert len(test_cls.protocols) == 2
     proto_names = [x.name for x in test_cls.protocols]
     assert proto_names == [
         "UIApplicationDelegate", "UITabBarControllerDelegate"
     ]
Beispiel #3
0
from strongarm.macho import CPU_TYPE, MachoAnalyzer, MachoParser


def find_selector_implementations(binary):
    print(f"Analyzing Mach-O slice built for {CPU_TYPE(binary.cpu_type).name}")
    analyzer = MachoAnalyzer(binary)

    desired_selector = "URLSession:didReceiveChallenge:completionHandler:"
    implementations = analyzer.get_imps_for_sel(desired_selector)
    for imp_function in implementations:
        instruction_size = 4
        instruction_count = int(
            (imp_function.end_address - imp_function.start_address) /
            instruction_size)
        print(
            f"Found implementation of @selector({desired_selector}) at [{hex(imp_function.start_address)}"
            f" - {hex(imp_function.end_address)}] ({instruction_count} instructions)"
        )


parser = MachoParser("./tests/bin/TestBinary4")
binary_64 = parser.get_arm64_slice()
binary_32 = parser.get_armv7_slice()
for binary in [binary_64, binary_32]:  # equivalent to parser.slices
    find_selector_implementations(binary)