@Proteas wrote:
这是我在分析 SecureROM 时随手记得笔记。
- 软件环境:基于泄露的 iBoot 的源码,所涉及的二进制是基于源码编译的。
- 硬件环境:T8010。
SecureROM 的功能概览
从下面的简化版的启动流程图上可以看出 SecureROM 的功能相对比较单一:
Form From:https://xerub.github.io/ios/iboot/2018/05/10/de-rebus-antiquis.html NAND/Normal +------+ +-------+ ------------> | LLB | --> | iBoot | --> OS +-----------+ / +------+ +-------+ | SecureROM |< +-----------+ \ +------+ +-------+ ------------> | iBSS | --> | iBEC | --> Restore USB/DFU +------+ +-------+
- 进行基本的外设及内存初始化。
- 枚举预设的块设备,寻找启动设备,加载 LLB。
- 如果无法找到启动设备或者相关针脚指示要进入 DFU(Device Firmware Update) 模式,则加载 iBSS。
Start 函数
__text:0000000100000000 start __text:0000000100000000 __text:0000000100000000 ADRP X0, #start __text:0000000100000004 ADD X0, X0, #start@PAGEOFF __text:0000000100000008 LDR X1, =start __text:000000010000000C BL platform_start __text:0000000100000010 CMP X1, X0 __text:0000000100000014 B.EQ loc_10000003C __text:0000000100000018 MOV X30, X1 __text:000000010000001C LDR X2, =handlers __text:0000000100000020 LDR X3, =start __text:0000000100000024 SUB X2, X2, X3 __text:0000000100000028 __text:0000000100000028 loc_100000028 __text:0000000100000028 LDP X3, X4, [X0],#0x10 __text:000000010000002C STP X3, X4, [X1],#0x10 __text:0000000100000030 SUBS X2, X2, #0x10 __text:0000000100000034 B.NE loc_100000028 __text:0000000100000038 RET
如上的反汇编结果是
start
的起始部分,这部分的主要功能是:确定 SecureROM 是否被加载到固定地址0x100000000
。如果在指定地址,则执行真正的功能代码loc_10000003C
。如果不是,则将返回地址设置到0x100000000
,并返回。platform_start
的汇编代码如下:__text:0000000100009730 platform_start __text:0000000100009730 MRS X2, S3_3_C15_C7_0 __text:0000000100009734 ORR X2, X2, #2 __text:0000000100009738 MSR S3_3_C15_C7_0, X2 __text:000000010000973C __text:000000010000973C loc_10000973C __text:000000010000973C MRS X2, S3_3_C15_C7_0 __text:0000000100009740 AND X2, X2, #0x8000000000000000 __text:0000000100009744 CBZ X2, loc_10000973C __text:0000000100009748 RET __text:0000000100009748 ; End of function platform_start
start
函数主要功能的反编译结果如下:void start() { ... __asm { MSR DAIFSET, #0XF } _WriteStatusReg(ARM64_SYSREG(3, 0, 12, 0, 0), exception_vector_base); for ( i = 0x1800A8000LL; i != 0x1800AC000LL; i += 16LL ) { *i = 0LL; *(i + 8) = 0LL; } for ( j = 0x1800A0000LL; j != 0x1800A8000LL; j += 16LL ) { *j = 0LL; *(j + 8) = 0LL; } __asm { MSR SPSEL, #0 } v13 = 0x100020000LL; v14 = &interrupt_stack_top; if ( &interrupt_stack_top != 0x100020000LL ) { do { v15 = *v13; v16 = *(v13 + 8); v13 += 16LL; v14->handler = v15; v14->arg = v16; v14 = (v14 + 16); } while ( v14 != handlers ); } v17 = handlers; do { v17->handler = 0LL; v17->arg = 0LL; v17 = (v17 + 16); } while ( v17 != &random_pool[12] ); do { LODWORD(v17->handler) = 0; v17 = (v17 + 4); } while ( v17 < 0x180089448LL ); interrupt_stack_top = 0x1800AC000LL; v18 = boot_handoff_trampoline; v19 = 0x1800AC000LL; do { v20 = *v18; v21 = *(v18 + 1); v18 = (v18 + 16); *v19 = v20; *(v19 + 8) = v21; v19 += 16LL; } while ( v18 < apcie_set_s3e_mode ); }
功能包括:设置中断向量表,初始化相关的内存,设置栈。执行完初始化后,
start
函数也是通过设置返回地址的方式跳到main
函数执行。Main 函数
main
函数的反编译结果如下:int __cdecl main() { arch_cpu_init(0); printf("\nSecureROM start\n"); printf("setting up initial clock configuration\n"); platform_init_setup_clocks(); printf("setting up internal memory\n"); platform_init_internal_mem(); printf("setting up default pin configuration\n"); platform_init_hwpins(); force_dfu = platform_get_force_dfu(); request_dfu2 = 0LL; if ( platform_get_request_dfu1() ) request_dfu2 = platform_get_request_dfu2(); sys_init(); sys_init_stack_cookie(); printf("doing early platform hardware init\n"); platform_early_init(); printf("\n\n%s for %s\n", "SecureROM", "d10si"); printf("%s\n", "localbuild...Proteas...ARM64_a99cbd3_dirty...2019/08/01-14:04:30"); printf("%s\n", "DEBUG"); printf("doing platform hardware init\n"); platform_init(); printf("Checking for Force DFU Mode Pin: %x / %x\n", force_dfu, request_dfu2); if ( force_dfu ) force_dfu = platform_get_usb_cable_connected(); printf("Checking for Force DFU Mode request pins: %x / %x\n", force_dfu, request_dfu2); if ( !force_dfu && request_dfu2 && platform_get_usb_cable_connected() ) { v2 = system_time(); while ( platform_get_request_dfu1() && platform_get_request_dfu2() && platform_get_usb_cable_connected() && !time_has_elapsed(v2, 0x5B8D80uLL) ) task_sleep(0x186A0uLL); v3 = system_time(); while ( 1 ) { if ( platform_get_request_dfu1() || !platform_get_request_dfu2() || !platform_get_usb_cable_connected() ) goto LABEL_21; if ( time_has_elapsed(v3, 0x5B8D80uLL) ) break; task_sleep(0x186A0uLL); } printf("Force DFU: %x\n", 1LL); } else { LABEL_21: printf("Force DFU: %x\n", force_dfu); if ( !force_dfu ) { index0 = 0; goto LABEL_24; } } index0 = -1; LABEL_24: index = index0; while ( 1 ) { if ( !platform_get_boot_device(index, &boot_device, &boot_flag, &boot_arg) ) { printf("No valid boot device, resetting.\n"); platform_reset(0); } boot_flag2 = boot_flag; printf("boot_selected: boot_device: %08x, boot_flag: %08x, boot_arg: %08x\n", boot_device, boot_flag, boot_arg); platform_enable_boot_interface(1, boot_device, boot_arg); security_init(1); if ( boot_device == BOOT_DEVICE_USBDFU ) { platform_set_dfu_status(1); v15 = getDFUImage(0x1800B0000LL, 0x100000); if ( v15 & 0x80000000 ) { v16 = "fatal DFU download error"; LABEL_40: printf(v16); goto LABEL_41; } if ( v15 > 0x100000 ) panic("boot_selected", "load overflow"); v13 = v15; v12 = image_create_from_memory(0x1800B0000LL, v15, 0); if ( !v12 ) { v16 = "failed to create image from DFU download\n"; goto LABEL_40; } printf("loaded image from USB-DFU\n"); v14 = 'ibss'; } else { if ( boot_device == BOOT_DEVICE_NVME ) { dev_name = "nvme_firmware0"; } else { if ( boot_device != BOOT_DEVICE_SPI ) goto LABEL_41; printf("SPI NOR boot selected\n"); flash_nor_init(boot_arg); dev_name = "nor0"; } v11 = lookup_image_in_bdev(dev_name, v9); v12 = v11; if ( !v11 ) goto LABEL_41; v13 = LODWORD(v11->next); v14 = 'illb'; } types = v14; load_len = v13; load_addr = 0x1800B0000LL; v12->imageOptions |= (2 * (boot_flag2 & 1)) ^ 0xB; if ( !image_load(v12, &types, 1u, 0LL, &load_addr, &load_len) ) { image_free(v12); platform_enable_boot_interface(0, boot_device, boot_arg); security_consolidate_environment(); // demote security_sidp_seal_rom_manifest(); printf("executing image...\n"); prepare_and_jump(BOOT_UNKNOWN, 0x1800B0000LL, 0LL); } printf("image load failed\n"); image_free(v12); LABEL_41: platform_enable_boot_interface(0, boot_device, boot_arg); printf("failed to load from selected boot device\n"); if ( !(index0 & 0x80000000) ) ++index; } }
从上面的代码中可以看到
main
函数的主要功能可以依据是否进入 DFU 进行分割:
- 如果需要进入 DFU 模式,则初始化 USB,等待 Client 发送 iBSS。 在收到 Client 发送的 iBSS 后,验证其签名的合法性。如果签名合法,则执行 iBSS。
- 如果不需要进入 DFU 模式,则查找启动设备,并从启动设备中寻找 LLB,并验证 LLB 的签名合法性。如果签名合法,则执行 LLB。如果没法找到启动设备,
platform_get_boot_device
会返回BOOT_DEVICE_USBDFU
即:同样会进入 DFU 模式。- 其它:
image_load
函数会校验 img4 的类型及合法性。Reference
- iBoot Source Code
Posts: 1
Participants: 1