├── .gitignore ├── LICENSE ├── README.md ├── __init__.py ├── iBoot.py └── plugin.json /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 EliseZeroTwo 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 4 | 5 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iBoot-Binja-Loader 2 | ### Author: **EliseZeroTwo** & **matteyeux** 3 | 4 | Binary Ninja Loader for iBoot & SecureROM 5 | 6 | ## Credits 7 | - [argp for iBoot64helper](https://github.com/argp/iBoot64helper) 8 | 9 | ## Installation Instructions 10 | ### Windows 11 | 12 | Clone this repository into `%APPDATA%/Binary Ninja/plugins/` 13 | 14 | ### Darwin 15 | 16 | Clone this repository into `~/Library/Application Support/Binary Ninja/plugins/` 17 | 18 | ### Linux 19 | 20 | Clone this repository into `~/.binaryninja/plugins/` 21 | ## Minimum Version 22 | 23 | Binary Ninja v1200 24 | 25 | 26 | 27 | ## License 28 | 29 | This plugin is released under the [ISC license](https://github.com/EliseZeroTwo/iBoot-Binja-Loader/blob/master/LICENSE) 30 | 31 | ## Metadata Version 32 | 33 | 2 34 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | from binaryninja import * 2 | from .iBoot import * 3 | 4 | iBootView.register() -------------------------------------------------------------------------------- /iBoot.py: -------------------------------------------------------------------------------- 1 | from binaryninja import * 2 | 3 | class iBootView(BinaryView): 4 | long_name = "iBoot" 5 | name = "iBoot" 6 | PROLOGUES = [b"\xBD\xA9", b"\xBF\xA9"] 7 | 8 | def log(self, msg, error=False): 9 | msg = f"[iBoot-Loader] {msg}" 10 | if not error: 11 | log_info(msg) 12 | else: 13 | log_error(msg) 14 | 15 | def __init__(self, data): 16 | self.raw = data 17 | self.reader = BinaryReader(data, Endianness.LittleEndian) 18 | self.writer = BinaryWriter(data, Endianness.LittleEndian) 19 | BinaryView.__init__(self, file_metadata=data.file, parent_view=data) 20 | 21 | @classmethod 22 | def is_valid_for_data(cls, data): 23 | if ( 24 | data.read(0x200, 5) == b'iBoot' 25 | or data.read(0x200, 4) == (b'iBEC' or b'iBSS') 26 | or data.read(0x200, 9) == b'SecureROM' 27 | or data.read(0x200, 9) == b'AVPBooter' 28 | ): 29 | return True 30 | return False 31 | 32 | def set_name_from_func_xref(self, name, addr): 33 | refs = list(self.get_code_refs(addr)) 34 | if len(refs) != 0: 35 | functions = self.get_functions_containing(refs[0].address) 36 | if len(functions) != 0: 37 | functions[0].name = name 38 | return functions[0].lowest_address 39 | return None 40 | 41 | def set_name_from_str_xref(self, name, string, partial=0): 42 | if partial: 43 | string_offset = [str_.start for str_ in self.strings if string in str_.value] 44 | else: 45 | string_offset = [str_.start for str_ in self.strings if str_.value == string] 46 | 47 | if len(string_offset) != 0: 48 | refs = list(self.get_code_refs(string_offset[0])) 49 | if len(refs) != 0: 50 | functions = list(self.get_functions_containing(refs[0].address)) 51 | if len(functions) != 0: 52 | functions[0].name = name 53 | return string_offset 54 | return None 55 | 56 | def set_name_from_pattern(self, name, pattern): 57 | pattern_offset = self.find_next_data(0, pattern) 58 | if pattern_offset is not None: 59 | functions = self.get_functions_containing(pattern_offset) 60 | if len(functions) != 0: 61 | functions[0].name = name 62 | return functions[0].lowest_address 63 | return None 64 | 65 | def on_complete(self): 66 | self.log("AA Complete") 67 | macho_valid_addr = self.set_name_from_pattern( 68 | "_macho_valid", b"\x49\x01\x8B\x9A" 69 | ) 70 | if macho_valid_addr != None: 71 | loaded_kernelcache_addr = self.set_name_from_func_xref( 72 | "_loaded_kernelcache", macho_valid_addr 73 | ) 74 | if loaded_kernelcache_addr != None: 75 | self.set_name_from_func_xref( 76 | "_load_kernelcache", loaded_kernelcache_addr 77 | ) 78 | 79 | self.set_name_from_str_xref("_panic", "double panic in ") 80 | self.set_name_from_str_xref("_platform_get_usb_serial_number_string", "CPID:") 81 | self.set_name_from_str_xref("_platform_get_usb_more_other_string", " NONC:") 82 | self.set_name_from_str_xref("_image4_get_partial", "IMG4") 83 | self.set_name_from_str_xref("_UpdateDeviceTree", "fuse-revision") 84 | self.set_name_from_str_xref("_main_task", "debug-uarts") 85 | self.set_name_from_str_xref("_platform_init_display", "backlight-level") 86 | self.set_name_from_str_xref('_do_printf', '') 87 | self.set_name_from_str_xref('_do_memboot', 'Combo image too large\n') 88 | self.set_name_from_str_xref('_do_go', 'Memory image not valid\n') 89 | self.set_name_from_str_xref("_task_init", "idle task") 90 | self.set_name_from_str_xref( 91 | '_sys_setup_default_environment', 92 | '/System/Library/Caches/com.apple.kernelcaches/kernelcache', 93 | ) 94 | self.set_name_from_str_xref( 95 | '_check_autoboot', 'aborting autoboot due to user intervention.\n' 96 | ) 97 | self.set_name_from_str_xref( 98 | '_do_setpict', 'picture too large, size:%zu\n' 99 | ) 100 | self.set_name_from_str_xref( 101 | '_arm_exception_abort', 'ARM %s abort at 0x%016llx:', 1 102 | ) 103 | self.set_name_from_str_xref( 104 | '_do_devicetree', 'Device Tree image not valid\n' 105 | ) 106 | self.set_name_from_str_xref('_do_ramdisk', 'Ramdisk image not valid\n') 107 | self.set_name_from_str_xref( 108 | '_usb_serial_init', 'Apple USB Serial Interface' 109 | ) 110 | self.set_name_from_str_xref( 111 | '_nvme_bdev_create', 112 | 'Couldn\'t construct blockdev for namespace %d', 113 | ) 114 | self.set_name_from_str_xref( 115 | '_image4_dump_list', 116 | 'image %p: bdev %p type %c%c%c%c offset 0x%llx', 117 | ) 118 | self.set_name_from_str_xref("_prepare_and_jump", "======== End of %s serial output. ========\n") 119 | self.set_name_from_str_xref('_boot_upgrade_system', '/boot/kernelcache') 120 | 121 | self.set_name_from_pattern("_plaform_early_init", b"\x60\x02\x40\x39") 122 | self.set_name_from_pattern("_aes_crypto_cmd", b"\x89\x2C\x00\x72") 123 | 124 | 125 | usb_vendor_id = self.set_name_from_pattern( 126 | "_platform_get_usb_vendor_id", b"\x80\xb5\x80\x52" 127 | ) 128 | usb_core_init = self.set_name_from_func_xref("_usb_core_init", usb_vendor_id) 129 | self.set_name_from_func_xref("_usb_init_with_controller", usb_core_init) 130 | 131 | def init(self): 132 | self.arch = Architecture["aarch64"] 133 | self.platform = Architecture["aarch64"].standalone_platform 134 | self.isSecureROM = self.raw.read(0x200, 9) == b"SecureROM" 135 | 136 | self.log(f"Loading {'SecureROM' if self.isSecureROM else 'iBoot'}") 137 | 138 | self.base = None 139 | for addr in range(0, 0x200, 4): 140 | inst = self.raw.get_disassembly(addr, Architecture['aarch64']) 141 | if "ldr" in inst: 142 | self.reader.seek(int(inst.split(" ")[-1], 16)) 143 | self.base = self.reader.read64() 144 | break 145 | 146 | if self.base == None: 147 | self.log("Failed to find entry point", error=True) 148 | return False 149 | 150 | self.log(f"Found base {hex(self.base)}") 151 | self.add_auto_segment( 152 | self.base, 153 | self.parent_view.length, 154 | 0, 155 | self.parent_view.length, 156 | SegmentFlag.SegmentReadable | SegmentFlag.SegmentExecutable, 157 | ) 158 | self.add_user_section( 159 | self.name, 160 | self.base, 161 | self.raw.length, 162 | SectionSemantics.ReadOnlyCodeSectionSemantics, 163 | ) 164 | self.add_entry_point(self.base) 165 | self.define_auto_symbol(Symbol(SymbolType.FunctionSymbol, self.base, "_start")) 166 | 167 | bin_start = self.start 168 | _next = 0 169 | 170 | if self.find_next_text(0, "pacibsp"): 171 | self.PROLOGUES.append(self.start, b"\x7F\x23\x03\xD5") 172 | 173 | for prologue in self.PROLOGUES: 174 | while True: 175 | _next = self.find_next_data( 176 | bin_start, prologue, FindFlag.FindCaseSensitive 177 | ) 178 | if _next == bin_start: 179 | break 180 | elif _next is None: 181 | continue 182 | else: 183 | self.create_user_function(_next) 184 | bin_start = _next 185 | 186 | AnalysisCompletionEvent(self, self.on_complete) 187 | self.add_entry_point(self.base) 188 | self.get_function_at(self.base).name = "start" 189 | return True 190 | -------------------------------------------------------------------------------- /plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "pluginmetadataversion" : 2, 3 | "name": "iBootLoader", 4 | "type": ["binaryview", "helper"], 5 | "api": ["python3"], 6 | "description": "iBoot/SecureROM Loader", 7 | "longdescription": "iBoot/SecureROM Loader", 8 | "license": { 9 | "name": "ISC", 10 | "text": "Copyright 2020 EliseZeroTwo\n\nPermission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE." 11 | }, 12 | "platforms" : ["Darwin", "Linux", "Windows"], 13 | "installinstructions" : { 14 | "Darwin" : "", 15 | "Linux" : "", 16 | "Windows" : "" 17 | }, 18 | "dependencies": { 19 | "pip": [], 20 | "apt": [], 21 | "installers": [], 22 | "other": [] 23 | }, 24 | "version": "1.0.0", 25 | "author": "EliseZeroTwo", 26 | "minimumbinaryninjaversion": 1200 27 | } 28 | --------------------------------------------------------------------------------