
在除夕, JC PCIE-7程序员落入我们的手中。 在使用它的过程中,它的功能受到限制,但事实证明,它的作用很小。 在该编程器内部,我们找到了带有特殊调试版本的iPhone 7开发板。 对于“苹果”产品的研究和调试世界中的新年冒险-欢迎您的光临!
也许只有非常懒惰的安全研究人员才亲手感觉不到checkm8和基于它的checkra1n提供的可能性(checkm8的最新评论是在Habré上 )。 当然,我们还测试了我们的智能手机,并在此过程中决定了解对中国“铁”工艺品市场的研究人员有用的东西。 有趣的 事实:如果您想测试任何设备的安全性,那么速卖通已经拥有了自己的玩具。
我们的玩具出现在除夕-JC PCIE-7编程器,可以在AliExpress上找到:

我们假设在该程序员的帮助下,我们可以备份iPhone闪存。 但是在运行过程中发现程序中根本不存在这样的功能! 是的,程序员可以将配置读取和写入闪存并将其连接到手机,但是不支持读取任意块。 然后,我们注意到控制程序的控制台窗口中出现异常行,类似于操作系统启动日志:

培训视频中加载时刻的帧
最后,我们提请注意使用DFU协议将编程器连接到计算机的功能。 在这种模式下,可以在iTunes中将程序员正确地检测为iPhone。 我们决定拆开设备,看看里面是什么,以及如何模拟DFU模式。
在编程器内部,安装了三块板:
- 基于STM32F103的控制板;
- 具有焊接的NVMe芯片和模块的多路复用器板;
- 以及iPhone 7开发板


事实证明,程序员以以下方式切换多路复用器:首先从焊接的闪存中加载iPhone板,然后将需要闪存的NVMe芯片连接到该板上。 通过虚拟COM端口进行管理,首先传输用于切换NVMe芯片的命令,然后开发板转发iPhone调试控制台,模拟DCSD电缆 。 在仔细检查了发送到COM端口的命令之后,我们看到了以下几行:
setenv诊断路径/AppleInternal/Diags/bin/diag.img4
诊断
至此,我们已经意识到iPhone 7板并不十分普通(至少其中有一个AppleInternal文件夹)。 为了查看她在更熟悉的“环境”中的行为,我们将电路板和NVMe芯片重新布置到了供体电话中:

除了加载时的齿轮外,在调试控制台中,我们还看到了BUILD_STYLE行:DEVELOPMENT:

最终下载(使用上面提到的diags命令)之后,我们得到了一个紫色屏幕,并且在按下音量键之后,屏幕上显示了以下菜单:

也就是说,我们组装的设备原来是用于测试和开发的iPhone的特殊版本! 顺便说一句,研究人员甚至收藏家都购买了这类手机 -这是对我们技术收藏的真正礼物! 在成熟的iPhone开发人员中,安装了带有根控制台的特殊iOS程序集,它极大地方便了手机的研究和漏洞的查找:

在我们的情况下,仅诊断实用程序安装在电话上,与之的主要交互是通过调试控制台进行的:
引导日志和帮助输出======================================= :: :: iBoot for d10, Copyright 2007-2016, Apple Inc. :: :: Local boot, Board 0x8 (d10ap)/Rev 0xd :: :: BUILD_TAG: iBoot-3406.1.53.1.4 :: :: BUILD_STYLE: DEVELOPMENT :: :: USB_SERIAL_NUMBER: CPID:8010 CPRV:11 CPFM:03 SCEP:01 BDID:08 ECID:000114422885E526 IBFL:3D :: ======================================= Boot Failure Count: 0 Panic Fail Count: 0 Entering recovery mode, starting command prompt ] setenv diags-path /AppleInternal/Diags/bin/diag.img4 ] diags Unable to load image type 64696167 from flashnx_mount:432: reloading after unclean unmount, checkpoint xid 112, superblock xid 11 jumping into image at 0x810000000 pinot_quiesce() mipi_dsim_quiesce() Console router buffer allocated @ 0x87CB84018, size = 262144 bytes WHO_AM_I doesn't match MPU6700's Chip ID! Expected 0x90 got 0x0 Carbon: MPU6900 is found. Carbon: MPU6900 (south) detected Carbon: MPU6900 (south) selected MPU6900 not found. Expected 0x10, found 0x0 Carbon: MPU6900 (north) not detected Phosphorous: BMP284 is found. mcc-supported : 1 Phosphorous: BMP282 is not found on SPI 4. Expected 0x58, found 0x0 time-train: 26719 uS Link 0 speed negotiate to 3 Link 0 width negotiate to 1 APCIE power on completed Device 00:00:0 config space@0x610000000 Vendor:106B Device:1007 Revision:01 ClassCode:060400 Type:01 PriBus:00 SecBus:01 SubBus:01 Capability 0x01 Offset:0x40 Address:0x610000040 Capability 0x05 Offset:0x50 Address:0x610000050 Capability 0x10 Offset:0x70 Address:0x610000070 Extended Capability 0x0001 Ver:0x02 Offset:0x0100 Address:0x610000100 Extended Capability 0x0019 Ver:0x01 Offset:0x0148 Address:0x610000148 Extended Capability 0x001E Ver:0x01 Offset:0x0160 Address:0x610000160 Found device id 0x2002 Device 01:00:0 config space@0x610100000 Vendor:106B Device:2002 Revision:11 ClassCode:018002 Type:00 BAR0 MEM C0000000/00004000 BAR1 IO 00000000/00000004 Capability 0x01 Offset:0x40 Address:0x610100040 Capability 0x05 Offset:0x50 Address:0x610100050 Capability 0x10 Offset:0x70 Address:0x610100070 Extended Capability 0x0001 Ver:0x02 Offset:0x0100 Address:0x610100100 Extended Capability 0x0002 Ver:0x01 Offset:0x0148 Address:0x610100148 Extended Capability 0x0019 Ver:0x01 Offset:0x0168 Address:0x610100168 Extended Capability 0x0018 Ver:0x01 Offset:0x0178 Address:0x610100178 Extended Capability 0x001E Ver:0x01 Offset:0x0180 Address:0x610100180 APCIE Enumerate on completed ICE BB not supported on this platform D10 Diag (factory_d10_pvt) BuildEng build D10Casaval24C302an (24C302an). Revision 6040f18. Built at 2016/08/20 15:57:53 script: device -k ThermalSensor -e sochot 0 on 120 script: device -k ThermalSensor -e sochot 1 on 125 script: cbcolor Setting Screen Color based on iPX Control Bits: script: alias vbat=pmuadc --sel tigris --read vbat script --cont startup.txt script: alias bbon="meta 'baseband --on --load_firmware; baseband --wait_for_ready --ping'" script: alias bbonbypass="meta 'baseband --on --load_firmware; baseband --wait_for_ready --ping --bypass en'" script: alias bboff=baseband --off script: alias getcd=bblib -e BB_GetCD() script: alias erase_rfcal=smokey Tools/RFCalErase --run script: alias erase_efs=smokey Tools/EFSErase --run script: alias erase_pac=smokey Tools/RFPacErase --run script: alias hdq_en=i2c --devwrite 1 0x75 0x1D 1 script: alias hdq_dis=i2c --devwrite 1 0x75 0x1D 0 script: alias bblib="smokeyshell -p -e 'if BBLib_cfg then print [[no init]] else require [[BBLib.14A]];BB_Init() end'" script: alias wcs=smokey --run WCS --clean LogBehavior=ConsoleOnly script: alias bblibcfg=bblib -e printLibCfg() script: alias bbdebug="meta 'base --debug on;ramlog --on 10;consolerouter --add -s *.{warn,error,print},system.debug.debug -d ramlog --quiet;consoleformat --en --sink serial -o ts'" script: alias gpsdebug="meta 'ramlog --on 10;consolerouter --add -s gps.debug.* -d ramlog'" script: alias updateroot="meta 'usbfs --mount;cp -r usbfs:\AppleInternal nandfs:\;usbfs --unmount;smokeyshell -r'" [00011442:2885E526] :-) help DiagShell builtin commands: "time" time <command-line ...> "echo" echo <arguments ...> "waitfor" waitfor <timeout-milliseconds> <string-to-match> "repeat" repeat <time-spec> <command line ...> "alias" alias [<name>[=<command line>]] "unalias" unalias <name> "true" true "false" false "args" args <command line ...> "shopt" shopt EDK Boot Loader commands (help <command> for more info): "accessory" Command to change power settings as well as identifying accessories connected to the unit "aes" Command for AES encryption/decryption "amux" Analog Mux selection command "audio" General command to hande resetting/blanking/scripting of the audio subsystem "audioparam" Audio parameter retrieval/setting utility "audioreg" Manages register operations on audio blocks in the system "barcode" Show S/N and ECID barcode "baseband" Command to control/test baseband functionality "battery" Command to display basic information about the battery "baud" <baud rate> : Set UART Baud rate "bl" BackLight Test "blockdevice" Show information about boot devices. Bare quantities are in bytes. "bluetooth" Command to control/test bluetooth functionality "boardid" Get the board ID "boardrev" Get the board revision "bonfire" Run Bonfire "bootcfg" Get the boot configuration "buckcheck" Buck voltage check "button" Test individual buttons on the unit "buttoncnt" [--dqe] Count button presses on the unit "camisp" camera command that can run in seperat steps. "cat" Print the contents of a file. "cbcolor" iPX Control Bit - Set screen color based on number of passed stations "cbdump" iPX Control Bit - Dump the CB area from the NAND "cberase" iPX Control Bit - Erase a control bit "cbinit" iPX Control Bit - Initialize control bit area "cbread" iPX Control Bit Read "cbreadall" iPX Control Bit - read all "cbwrite" iPX Control Bit Write "charge" Charge controls for system "chipid" Show ChipID "clkmon" [signal/off]; Set Clock Test out pin to specified signal or switch it off "consoleformat" Command to control the formatting of text display on serial output mediums like the console "consolerouter" Main command that deals with all things console in the system "consolesinkctrl" Manage the console sink controls "cp" cp [-r] <source> ... <dest> "debug" Turns on/off global debug levels in the system "device" Interfaces with a devices of the system. "dfufile" Use dfu protocol to transfer file. "directory" DirDev [*match]; directory listing of dirdev. opt match a substring "DisCfg#" Display CFG systemcfg "DisOpts" Display OPTS systemcfg "display" Command to control display "displayid" Get the display ID "displaytext" Display text on the unit's screen "dt" Provide access to the device tree structure "dumpmemmap" Dumps memory map "dwi" backlight test using DWI "event" Signal EFI event groups "filelog" Log formatted console output to a file "getnonce" iPX Control Bit - generate a salt value for control-bit write authentication "getvol" Gets volume information/values from the various audio blocks "gps" Command to test/control GPS functionality "hash" compute Hash "help" [cmd]; Help on cmd or a list of all commands if cmd is ommited "hid" Command for the hid controllers/sensors "i2c" generic read/write to I2C device "key" Read buttons' status from AP side and PMU side "legal" Outputs the copyright for any libraries used by Diags. "loopaudio" Plays/Record full-duplex audio out/in through selected 'playable' and 'recordable' ports on an audio block "lua" lua [options] [script [args]] "mbt" Menu Button Test "memcat" Read memory into file or a file into memory "memory" Memory Utilities [--info] | [--list] | [--leak] | [--dump] <address> <length> "memrw" Read/write/or/and from memory "menu" Navigate menu items in Display "meta" [cmd]; Execute cmd as if it was entered at the shell (useful for scripting) "mipi" Command to interact with mipi "mkdir" mkdir <directory_name> ... "nand" Command to test nand functionality "nandcsid" Read Nand Chip ID and detect ID mismatch "nandppnfwver" Prints the PPN Firmware version for all populated CE's "nandsize" Nand testing "nanduid" Read Unique ID from each Nand die "network" Command to control network interface "nvram" Print or modify NVRAM variables "pattern" [--iqc [#]|--dqe [#]|--fatp [#]|--other [#]|--fill [rgb #] --list will List available displays --pick <name> will Pick Display name [n]:Test LCD display pattern[n] "pcie" qucik pcie test "physaddr" Decodes a physical address into bank/column/row/etc "playaudio" Plays audio out through a selected 'playable' port "pmuadc" PMU ADC Command for Calibration/Reading/Listing Channels "pmubutton" pmu button test "pmuevent" [all|chipid|btn|vbus|chgr|gpio|misc|temp|fault|ouv|clear] "pmugpio" Set a PMU GPIO to a certain state "pmureg" Print the values of all the pmu registers "pmurw" generic read/write to PMU Registers "pmuset" set the buck and ldo voltages value "pmustat" [all|chipid|btn|vbus|chgr|gpio|misc|temp|fault] "pmutemp" PMU TEMP test "processaudio" Post-processes audio data using various audio filters registered in the system "profile" Turns profiling on/off, dumps data, and resets profiling data. "qrbarcode" Command for showing the QRbarcode "quit" Quit EBL "ramlog" Command to manage the ramlog console sink which can be used for logging text to RAM for timing sensitive issues "recordaudio" Records audio in through a selected 'recordable' port "reset" Resets the system "rm" rm [-f] <path> ... "rmdir" rmdir <directory_name> ... "routeaudio" Sets up audio routing. "rtc" Set or get the RTC from PMU "script" [filename]; Execute the commands in the specified file "sensor" General command that interfaces with the various sensors in the system "sensorreg" General command that allows for reading/writing sensor chipset registers "sep" Manipulate the SEP "setvol" Sets volume levels within the various audio blocks "shutdown" Wait until the unit is unplugged then go to standby "signal" Measure Signal Jitter, Period "sleep" Set system to specified sleep state "smash" Memory smasher "smokey" EFI diag scripting sequencer "smokeyshell" EFI diag scripting sequencer debug shell "sn" Read/Write serial number "soc" Command for displaying SoC info "socgpio" Set a GPIO to a certain state "spi" Test Spi buses "spkid" Return 1 bit Speaker ID "stockholm" Command to control/test stockholm functionality "stopaudio" Stop audio out through a selected 'playable/recordable' port "strobe" Command to control the Strobe on the System "syscfg" [init | add | print | list | type | delete] <KEY> <value1> <value2> ...; System Config "sysinfo" Dumps system information "system" Command to display basic information about the unit "tag" Turns tagging of data on/off. "temperature" Control Settings and Dump Readings from various Temperature Sensors in the System "testCDMADDR" CDMA DDR test "testmemory" Run data and address patterns to exercise DRAM subsystem "testmp" boot up second core for simple tests "thermalmonitor" Command to control/test thermal functionality "touch" Command for the Touch subsystem "tristar" TriStar test commands "uartloopback" Perform a loopback test on the specified uart. Note that you will have to put the chip into loopback mode using separate commands. "uartpassthrough" pass through uart traffic from dock uart to select uart "uartrx" Receive and store message from uart <uart #>. It will send the message back to uart <uart #> when a <ExitString> is detected. "uarttx" send message to the selected uart "usbfs" Enables/Disables UsbFS (Filesystem-over-USB) "usbp" Test USB Present "version" Diag Version "wait" [ms]; Wait ms milliseconds "wakeevent" Select wake event for wakeup for PMU STANDBY or Hibernate mode "wakeeventsmanager" Command to control wakeevents in the system "wfi" Enable/Disable the wfi feature "wifi" Command to control/test wifi functionality "writefile" Write text to a file "zerofile" Zero the contents of an existing file
如您所见,调试程序的功能非常强大。 它主要用于测试设备-大多数团队负责测试设备的各种硬件子系统。 对我们来说最有用的命令是directory , memrw , memory和cat 。
通过运行directory命令,您可以熟悉文件系统的内容:
[00011442:2885E526] :-) dir fs0: --------- <DIR> 2016-08-29 07:01 AppleInternal --------- <DIR> 2016-09-22 11:27 System --------- <DIR> 2016-09-22 11:29 private --------- <DIR> 2016-09-22 11:28 usr
通过运行cat -h ,您可以读取任何文件:
文件读取结果 [00011442:2885E526] :-) cat -h fs0:\AppleInternal\Diags\Logs\Smokey\Shared\ComponentLib\HallSensor\11A\HallSensor.lua 00000000: 2D 2D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D |--==============| 00000010: 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D |================| 00000020: 3D 3D 3D 3D 3D 3D 3D 3D 3D 0A 2D 2D 20 46 69 6C |=========.-- Fil| 00000030: 65 6E 61 6D 65 3A 20 20 48 61 6C 6C 53 65 6E 73 |ename: HallSens| 00000040: 6F 72 2E 6C 75 61 0A 2D 2D 20 44 65 73 63 72 69 |or.lua.-- Descri| 00000050: 70 74 69 6F 6E 3A 20 48 61 6C 6C 53 65 6E 73 6F |ption: HallSenso| 00000060: 72 20 74 65 73 74 20 66 69 6C 65 0A 2D 2D 3D 3D |r test file.--==| 00000070: 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D |================| 00000080: 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D |================| 00000090: 3D 3D 3D 3D 3D 0A 0A 72 65 71 75 69 72 65 20 22 |=====..require "| 000000A0: 43 6F 6D 70 6F 6E 65 6E 74 4C 69 62 2E 43 6F 6D |ComponentLib.Com| 000000B0: 6D 6F 6E 2E 31 31 41 22 0A 0A 6C 6F 63 61 6C 20 |mon.11A"..local | 000000C0: 43 4F 4D 50 4F 4E 45 4E 54 5F 4E 41 4D 45 20 3D |COMPONENT_NAME =| 000000D0: 20 22 48 61 6C 6C 53 65 6E 73 6F 72 22 0A 0A 2D | "HallSensor"..-| 000000E0: 2D 20 48 61 6C 6C 73 65 6E 73 6F 72 20 74 65 73 |- Hallsensor tes| 000000F0: 74 0A 66 75 6E 63 74 69 6F 6E 20 48 61 6C 6C 53 |t.function HallS| 00000100: 65 6E 73 6F 72 54 65 73 74 73 28 29 0A 09 53 51 |ensorTests()..SQ| 00000110: 41 5F 53 68 65 6C 6C 28 22 68 61 6C 6C 73 65 6E |A_Shell("hallsen| 00000120: 73 6F 72 20 2D 2D 6D 65 61 73 20 22 2E 2E 48 41 |sor --meas "..HA| 00000130: 4C 4C 5F 53 45 4E 53 4F 52 5F 4D 45 41 53 2E 2E |LL_SENSOR_MEAS..| 00000140: 22 20 2D 2D 64 65 6C 61 79 20 22 2E 2E 48 41 4C |" --delay "..HAL| 00000150: 4C 5F 53 45 4E 53 4F 52 5F 44 4C 59 29 0A 09 53 |L_SENSOR_DLY)..S| 00000160: 51 41 5F 53 68 65 6C 6C 28 22 68 61 6C 6C 73 65 |QA_Shell("hallse| 00000170: 6E 73 6F 72 20 2D 2D 69 72 71 69 6E 64 65 78 20 |nsor --irqindex | 00000180: 22 2E 2E 48 41 4C 4C 5F 53 45 4E 53 4F 52 5F 49 |"..HALL_SENSOR_I| 00000190: 52 51 5F 49 4E 44 45 58 29 0A 09 53 51 41 5F 53 |RQ_INDEX)..SQA_S| 000001A0: 68 65 6C 6C 28 22 68 61 6C 6C 73 65 6E 73 6F 72 |hell("hallsensor| 000001B0: 20 2D 2D 6F 66 66 20 20 22 29 0A 65 6E 64 0A 0A | --off ").end..|
结合这两个命令,我们从设备读取了所有文件(近150 MB):

文件中有一个“复活节彩蛋”,建议不要开玩笑 苹果手机7 火烧:

通过运行memory -dump命令 ,您可以读取RAM范围:
[00011442:2885E526] :-) memory --dump 0x800000000 0x100 0: 30 83 43 5B 39 16 04 49 4D 47 34 30 83 43 40 14 0.C[9..IMG40.C@ 10: 16 04 49 4D 34 50 16 04 64 69 61 67 16 01 31 04 .C@..".X..@.?.. 20: 83 43 40 00 80 22 00 58 01 04 40 F9 3F 00 00 F1 ..T?...@..T... 30: 20 05 00 54 3F 04 00 F1 40 00 00 54 FA 01 00 14 ....B...B...Bt 40: 02 00 80 D2 42 00 00 91 42 08 00 91 42 CC 74 D3 B...BlBBBp. 50: 42 08 04 91 42 AC 6C D3 42 C0 42 91 42 70 00 91 _...!..R....c.. 60: 5F 00 00 B9 21 00 80 52 03 00 80 D2 63 00 00 91 c...ctc..cl 70: 63 08 00 91 63 CC 74 D3 63 08 04 91 63 AC 6C D3 cBcP..a...... 80: 63 C0 42 91 63 50 00 91 61 00 00 B9 03 00 80 D2 c...c...ctc. 90: 63 00 00 91 63 08 00 91 63 CC 74 D3 63 08 04 91 clcBc@..... A0: 63 AC 6C D3 63 C0 42 91 63 40 00 91 7F 00 00 B9 ...RA.......... B0: 81 00 80 52 41 00 00 B9 7F 00 00 B9 00 00 00 14 @.............. C0: 40 03 00 00 00 00 00 00 B0 03 00 00 00 00 00 00 . ...O...?..... D0: 1F 20 03 D5 DF 4F 03 D5 DF 3F 03 D5 1F 87 08 D5 .?.. .;.!.....! E0: 9F 3F 03 D5 20 E2 3B D5 21 00 80 D2 00 00 21 8A .......a...<.@ F0: 20 E2 1B D5 9B F9 FF 10 61 06 00 10 3C 00 40 F9 z...Y.@........
最后,使用memrw命令, 您可以覆盖RAM:
[00011442:2885E526] :-) memrw 0x800000000 0x12345678abcdef 0x800000000: 0x12345678ABCDEF OK [00011442:2885E526] :-) memory --dump 0x800000000 0x10 0: EF CD AB 78 56 34 12 00 4D 47 34 30 83 43 40 14 ...xV4..MG40.C@
尽管事实上读取内存已经成为一种有用功能的度量,但我们还是决定检查:是否可以覆盖可执行代码的区域并运行我们自己的东西? 毕竟,iPhone是具有发展性的,并且功能仍是自定义的-它将无法正常工作!
无法以标准方式执行此操作,在相当详细的跟踪日志中发生了错误:
发生的异常的日志 [00011442:2885E526] :-) memrw 0x87BF68AA0 0 panic: unhandled exception: 0 x0: 0x00000000 x1: 0x0000000A x2: 0x00000000 x3: 0x87BF68AA0 x4: 0x00000002 x5: 0x00000003 x6: 0x879D52218 x7: 0x00000003 x8: 0x87BF68E30 x9: 0x87BF6908C x10: 0x00000000 x11: 0x000000E0 x12: 0x000000E0 x13: 0x00000001 x14: 0x00000001 x15: 0x00000000 x16: 0x000000FF x17: 0x00000001 x18: 0x810000308 x19: 0x879D52228 x20: 0x00000008 x21: 0x00000000 x22: 0x87BF68AA0 x23: 0x00000007 x24: 0x00000001 x25: 0x87BF68AA0 x26: 0x00000000 x27: 0x00000002 x28: 0x87CA42332 fp: 0x87FBEFC20 lr: 0x87BF68D3C sp: 0x00000000 PC: 0x87BF68E30 SPSR: 0x80000005 ESR: 0x9600004F FAR: 0x87BF68AA0 EC:0x25 - "Data Abort caused by current EL" ISS:0x4F - "Permission Fault Level 3" Memory Access Fault - write to read-only or unmapped address. FAR contains target address. 0x87BF68AA0: /Users/build/archive/casaval_d10_202/src/shasta/BuildResults/D10diag/release/diag/TestDirectMemoryRW.macho + <0x4AA0> : text section stack buffer at 0x87FBEEED0 printing callstack: 15 frames unrolled. #0 0x87BF68E30 TestDirectMemoryRW.macho @ offset 0x4E30 #1 0x87BF68D38 TestDirectMemoryRW.macho @ offset 0x4D38 #2 0x87BF69620 TestDirectMemoryRW.macho @ offset 0x5620 #3 0x879B2C1D0 DiagShell.macho @ offset 0x41D0 #4 0x879B2C7F0 DiagShell.macho @ offset 0x47F0 #5 0x879B2D11C DiagShell.macho @ offset 0x511C #6 0x87FB75494 DxeMain.macho @ offset 0xD494 #7 0x87CAD8214 DiagBds.macho @ offset 0x4214 #8 0x87CAD8260 DiagBds.macho @ offset 0x4260 #9 0x87CAD82CC DiagBds.macho @ offset 0x42CC #10 0x87FB6C604 DxeMain.macho @ offset 0x4604 #11 0x87FB6C0F0 DxeMain.macho @ offset 0x40F0 #12 0x81034AA04 #13 0x81039C7E4 #14 0x81039C39C Please report panic using panic.apple.com hanging here...
在这种情况下,跟踪日志表明,在地址0x87BF68E30执行时,由于写入只读内存地址,导致TestDirectMemoryRW.macho模块发生异常 。 但是除夕夜,技术研究人员没有任何障碍! 注意堆栈上最近的调用: DxeMain.macho 。 缩写DXE和EDK Boot Loader行的出现使我们可以得出结论,该设备正在运行与EFI兼容的系统。 实际上,可以使用UEFITool正确打开系统映像diags.img4 :

拆卸程序模块表明,所有可执行模块都使用EFI调用约定和标准EDK结构:

每个终端命令对应一个单独的EFI模块,例如, 内存命令对应于TestUtilities.macho模块,该模块以0x87BE10000 (由跟踪日志确定)加载到RAM中。
让我们尝试修改该模块的程序代码以执行我们的代码。
在地址0x87BE1600D处 ,由memory –info命令输出一个文本字符串,我们对其进行修改:
[00011442:2885E526] :-) memory --info Total Memory: 0x80000000, free: 0x79B48000, fragmented: 0x10028000, frags: 5, in use: 0x64B8000 [00011442:2885E526] :-) memory --dump 0x87BE1600D 0x30 7BE1600D: 54 6F 74 61 6C 20 4D 65 6D 6F 72 79 3A 20 30 78 Total Memory: 0 7BE1601D: 25 78 2C 20 66 72 65 65 3A 20 30 78 25 6C 78 2C fragmented: 0x 7BE1602D: 20 66 72 61 67 6D 65 6E 74 65 64 3A 20 30 78 25 x, frags: %d, i
要修改我们需要的存储区域,我们需要将对0x87BE14000处的页面的访问权限从只读/执行更改为读取/写入/执行 。 根据AArch64文档,特殊的转换表负责访问权限。 该表应位于RAM中,并由以下格式的8个字节的记录组成:

第二级转换表位于0x87FBF4000 ,位于可重写的内存范围内。 在此级别上,每个条目对应于32 MB(0x2000000)的地址空间,因此我们需要范围0x87A000000-0x87BFFFFFF的记录位于0x87FBF4000 +(0x87A000000 / 0x2000000)* 8 = 0x87FBF61E8 :
[00011442:2885E526] :-) memory --dump 0x87FBF61E8 0x8 7FBF61E8: 03 C0 CE 7F 08 00 00 00
该记录的类型为table ,即它指向地址为0x87FCEC000的第三级转换表。 在此表中,每个条目对应于一个16 Kb(0x4000)页面的地址空间,并且属于block类型。 我们需要页面0x87BE14000的记录位于0x87FCEC000 +(0x87BE14000-0x87A000000)/ 0x4000 * 8 = 0x87FCEFC28:
[00011442:2885E526] :-) memory --dump 0x87FCEFC28 8 7FCEFC28: AB 47 E1 7B 08 00 00 00 .G.{....+..{..`
由于此条目的类型为block ,因此它指向物理内存页并包含访问属性。 我们对低级块属性感兴趣,即数据访问权限位字段:

要允许写入页面,请将此字段的值设置为0:
[00011442:2885E526] :-) memrw 0x87FCEFC28 --64 0x000000087BE1472B 0x87FCEFC28: 0x87BE1472B OK
之后,我们应该对所需区域具有写访问权限。 进行所需的更改后,我们将获得所需的结果:
[00011442:2885E526] :-) memrw 0x87BE16008 0x6C6548000A535341 0x87BE16008: 0x6C6548000A535341 OK [00011442:2885E526] :-) memrw 0x87BE16010 0x0072626148206F6C 0x87BE16010: 0x72626148206F6C OK [00011442:2885E526] :-) memory --info Hello Habr
道德:使用所描述的方法,我们可以在开发的iPhone上的UEFI环境中修改任何系统应用程序并执行任意代码。
这项研究对旧版iPhone没有实用价值,但是整理未知和稀有的东西很有趣,尤其是当它突然作为新年礼物出现时。
PS但是,要研究最新的iPhone版本并获取SecureROM,所描述的方法可能会有用:checkm8漏洞已得到修复,并且基于iPhone XR和iPhone 11的AliExpress上的类似“程序员”已经在销售中 。

Raccoon Security是位于火山科学技术中心的特殊专家团队,负责实践信息安全,密码学,电路,逆向工程和低级软件的创建。