这是我在分析 SecureROM 时随手记得笔记。
从下面的简化版的启动流程图上可以看出 SecureROM 的功能相对比较单一:
如上的反汇编结果是 start
的起始部分,这部分的主要功能是:确定 SecureROM 是否被加载到固定地址 0x100000000
。如果在指定地址,则执行真正的功能代码 loc_10000003C
。如果不是,则将返回地址设置到 0x100000000
,并返回。platform_start
的汇编代码如下:
start
函数主要功能的反编译结果如下:
功能包括:设置中断向量表,初始化相关的内存,设置栈。执行完初始化后,start
函数也是通过设置返回地址的方式跳到 main
函数执行。
main
函数的反编译结果如下:
从上面的代码中可以看到 main
函数的主要功能可以依据是否进入 DFU 进行分割:
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 +------+ +-------+
__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
__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
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 );
}
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;
}
}
- 软件环境:基于泄露的 iBoot 的源码,所涉及的二进制是基于源码编译的。
- 硬件环境:T8010。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)