自 iPhone 6s 之後,iPhone 就開始使用內建主控 NVME Flash,後續 Mac 也採用了相同的晶片。
原文作者 @key2fr 於 2017 年想研究 FBI 解鎖 iPhone 的方法,因此想要分析 iPhone 的 Flash(想要實現暴力破解而不被鎖機)
步驟如下:
- 先嘗試直接拆下 Flash。
- 客製特定 BGA70 轉接 PCI-E 轉卡。
- 解決特殊 NVME 驅動問題。
- 使用電腦進行 Dump 後進行數據分析。
(無論是 iPhone 或 Mac,這類設備均涉及硬體與軟體層的加密,因此無法直接掛載資料。)
因此 OSSLab 處理 Mac 故障導致無法開機、需要資料救援時,需要將 Flash 與 T2 晶片一併移動好電腦上,才能完成資料恢復。
Mac mini M4 跟Studio雖然有分離硬碟模組,如果需要讀取資料將他拔下後去別台Mini或Studio讀取 是不可行的。
文內iphone 6S 為BGA 70
BGA110:
iPhone 8 / 8Plus / X
iPhone Xr / XS / XS Max
iPhone 11 / 11Pro /11Pro Max
iPhone Se 2nd
iPad mini5
iPad Air3
iPad 8(2020)
iPad 9(2021)
iPad Pro 11/12.9(3)
iPad Pro 11(2)/12.9(4)
BGA110(2代):
iPhone 12 / 12Mini / 12Pro / 12Pro Max
iPhone 13 / 13Mini / 13Pro / 13Pro Max
iPad Pro 11(3)/12.9(5)
iPad Air 4
iPad Air 5
Mac M1 Apple Silicon
BGA 110 (2代) 同於BGA 512可用轉版轉換 但目前市場價格BGA 315比較便宜
BAG315:
iPhone Se 3rd
iPhone 14 / 14Plus / 14Pro /14Pro Max
iPhone 15 / 15Plus / 15Pro /15Pro Max
iPhone 16 / 16Plus / 16Pro /16Pro Max
iPad 10
iPad Pro 11(4)/ 12.9(6)-M2 M4
Mac M2~M4 Apple Silicon 設備
其他老款Mac onboard flash請參考
https://logi.wiki/index.php/MacBook_NAND_List#MacBooks_Pro_/_Air_M1_(A2337_/_A2338)_NANDs_configurations
BGA 315 厚只有Mac可以用 比較厚 SDSFGKLKH 單顆1TB M2 M3 M4 可用
BGA 315 薄K5A4 256G M2 M3 M4 iphone 14 15 16 都可用
BGA 315 Flash轉給BGA 110機器用的轉版(植錫球要二次)
本文iphone 6s 的BGA 70 Flash
NVMexpress是嵌入式設備中使用的下一代存儲技術。主要想法是直接在PCIexpress級別安裝儲存控制器,避免了大量協議轉換。
該技術基於PCIe。我們可以在最近的Macbook 12 retina上看到它在控制面板上的詳細信息:
最近,Macrumers在這個屏幕截圖上展示了這個特點:
2015 Macbook用的都是獨立控制器 ,
關於Macbook用的NVME控制器可以參考OSSLab文
解焊Nand
這裡有幾個視頻,顯示了Nand Flash是如何被移除或替換的。
物理接口
網路上有流出的iPhone 6S 電路圖, 這顆Flash芯片的引腳如圖。
我們可以看到它需要3個主電壓:0.9v,1.8v和3.0v。我們有一個帶有TX [0..1] +/-和RX [0..1] +/-以及CLK +/-引腳的2個PCIe接口。請注意那些是差分對。我認為他們是用90R阻抗路由的。最重要的是,我們可以找到一些PCIe控制引腳,例如CLKREQ,NRST。還有其他一些配置引腳,如低功耗模式,固件綁定和SWD jtag。另一個有趣的部分是Clkc頻率直接由SoC PLL本身控制。為了讓芯片在其他地方工作,人們需要知道頻率。用範圍很容易做到的事情:
所以需要24Mhz 1.8v。
自己做的Apple iOhone NVMe讀取器
為了讀取NVMe,我為此開發了帶有零插入力讀卡器的PCIe卡。我將JTAG部分引入20pin頭部。
這裡的難點在於差分對的信號完整性。為了做到這一點,我不得不使用多層PCB,並且通過了解疊層,用於prepeg的材料等來進行阻抗匹配。
由於我不打算自己出售這些設備,所以我想要感謝同意進行一小部分製作的Itead Studio。吟遊詩人目前正在預購。請注意,為這個項目製作的套接字不是通用的,而是為LGA70定制的,這解釋了這個價格。 https://www.itead.cc/nvme-reader.html
NVMe枚舉
# lspci -d 106b:2002 -vvv
09:00.0 Mass storage controller: Apple Inc. Device 2002 (rev 11) (prog-if 02)
Subsystem: Apple Inc. Device 2002
Physical Slot: 1-2
Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0
Interrupt: pin A routed to IRQ 19
Region 0: Memory at a0800000 (64-bit, non-prefetchable) [size=16K]
Capabilities: [40] Power Management version 3
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [50] MSI: Enable- Count=1/8 Maskable- 64bit+
Address: 0000000000000000 Data: 0000
Capabilities: [70] Express (v2) Endpoint, MSI 00
DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s <4us, L1 <32us
ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset+
DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+ FLReset-
MaxPayload 128 bytes, MaxReadReq 512 bytes
DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr+ TransPend-
LnkCap: Port #0, Speed 2.5GT/s, Width x2, ASPM L0s L1, Exit Latency L0s <1us, L1 <8us
ClockPM- Surprise- LLActRep- BwNot- ASPMOptComp+
LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- CommClk+
ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
LnkSta: Speed 2.5GT/s, Width x2, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
DevCap2: Completion Timeout: Not Supported, TimeoutDis+, LTR+, OBFF Not Supported
DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled
LnkCtl2: Target Link Speed: 8GT/s, EnterCompliance- SpeedDis-
Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
Compliance De-emphasis: -6dB
LnkSta2: Current De-emphasis Level: -3.5dB, EqualizationComplete-, EqualizationPhase1-
EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
Capabilities: [100 v2] Advanced Error Reporting
UESta: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
UEMsk: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
CEMsk: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
AERCap: First Error Pointer: 00, GenCap- CGenEn- ChkCap- ChkEn-
Capabilities: [148 v1] Virtual Channel
Caps: LPEVC=0 RefClk=100ns PATEntryBits=1
Arb: Fixed- WRR32- WRR64- WRR128-
Ctrl: ArbSelect=Fixed
Status: InProgress-
VC0: Caps: PATOffset=00 MaxTimeSlots=1 RejSnoopTrans-
Arb: Fixed- WRR32- WRR64- WRR128- TWRR128- WRR256-
Ctrl: Enable+ ID=0 ArbSelect=Fixed TC/VC=ff
Status: NegoPending- InProgress-
Capabilities: [168 v1] #19
Capabilities: [178 v1] Latency Tolerance Reporting
Max snoop latency: 0ns
Max no snoop latency: 0ns
Capabilities: [180 v1] L1 PM Substates
L1SubCap: PCI-PM_L1.2+ PCI-PM_L1.1+ ASPM_L1.2+ ASPM_L1.1+ L1_PM_Substates+
PortCommonModeRestoreTime=25us PortTPowerOnTime=10us
正如我們所看到的,該設備使用Apple的VID:0x106b,PID是0x2002。請記住,mac book air中的版本是0x2001!在具有NVMe驅動程序的Mac書中使用此卡時,我無法使其工作。它看起來像驅動程序不工作。
驅動逆向工程
為了讓它工作,我必須設法讓驅動工作。NVMe是在Linux中實現的,Matthew Wilcox(給了我很大的支持)做了一件非常棒的Linux的NVMe驅動程序開發。其他一些人已經做了porting轉移,以便讓Driver 為MacbookAir工作。所以在將PID添加到驅動程序並重新編譯後,發現還是無法正常工作。它看起來像減少所需的大小,NVMe核心使用主機DDR為了工作。因此,蘋果並不嚴格遵循有關初始化的規範。臨時區域從一開始就被保留,它的地址和長度都在設備樹中。為了設置這些值,NVMe有一些從地址BAR0 + 0x1800開始的特殊寄存器。例如,寄存器偏移量0x1910 0x1914 0x1918 0x191c接縫包含有關錯誤代碼的信息,當NVMe在其STATUS(CSTS)寄存器中設置錯誤位時。當處於BFH模式時,一些其他有趣的寄存器位於0x1b00附近。我們將在稍後回复。
# nvme list
Node SN Model Version NS Usage Format FW Rev
---------------- -------------------- -------------------- -------- -- -------------------------- ---------------- ---------
/dev/nvme0n1 01061019E5C211EB0 APPLE SSD AP0016K 1.0 1 16,00 GB / 16,00 GB 4 KiB + 0 B 11.90.01
/dev/nvme0n2 01061019E5C211EB0 APPLE SSD AP0016K 1.0 2 8,39 MB / 8,39 MB 4 KiB + 0 B 11.90.01
/dev/nvme0n3 01061019E5C211EB0 APPLE SSD AP0016K 1.0 3 131,07 kB / 131,07 kB 4 KiB + 0 B 11.90.01
/dev/nvme0n4 01061019E5C211EB0 APPLE SSD AP0016K 1.0 4 8,19 kB / 8,19 kB 4 KiB + 0 B 11.90.01
/dev/nvme0n5 01061019E5C211EB0 APPLE SSD AP0016K 1.0 5 8,19 kB / 8,19 kB 4 KiB + 0 B 11.90.01
/dev/nvme0n6 01061019E5C211EB0 APPLE SSD AP0016K 1.0 6 4,10 kB / 4,10 kB 4 KiB + 0 B 11.90.01
/dev/nvme0n7 01061019E5C211EB0 APPLE SSD AP0016K 1.0 7 1,05 MB / 1,05 MB 4 KiB + 0 B 11.90.01
如你所見,nand包含7個分區。他們通常是第一個帶有系統的HFS,第二個是llb + iboot(當然GID加密)。第三個是syscfg …等等。
名字空間的解析。
NS1
NS1用於’fsys’,並包含一個LwVM格式的分區,其中包含三個卷 – 系統(/),數據(/ private / var)和Baseband。這些對iOS都是可見的,分別為/dev/disk0s1s1..s3 (注意 這邊會有HFS +加密)
00000000 6a 90 88 cf 8a fd 63 0a e3 51 e2 48 87 e0 b9 8b |j.....c..Q.H....|
00000010 a3 a2 64 6b a1 b1 41 9b 89 49 95 75 61 74 53 31 |..dk..A..I.uatS1|
00000020 00 80 b2 e6 0e 00 00 00 03 00 00 00 1d 4f 5c b9 |.............O\.|
00000030 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000200 48 46 53 00 00 00 11 aa aa 11 00 30 65 43 ec ac |HFS........0eC..|
00000210 a9 49 c9 cf 91 41 43 bc bc c3 2a 80 c9 71 e1 79 |.I...AC...*..q.y|
00000220 00 60 00 00 00 00 00 00 00 f0 16 da 00 00 00 00 |.`..............|
00000230 00 00 00 00 00 00 00 00 53 00 79 00 73 00 74 00 |........S.y.s.t.|
00000240 65 00 6d 00 00 00 00 00 00 00 00 00 00 00 00 00 |e.m.............|
00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000280 48 46 53 00 00 00 11 aa aa 11 00 30 65 43 ec ac |HFS........0eC..|
00000290 6b a9 57 fb 7e 21 46 78 96 16 b5 15 4f df 4d 3e |k.W.~!Fx....O.M>|
000002a0 00 f0 16 da 00 00 00 00 00 10 61 c3 0e 00 00 00 |..........a.....|
000002b0 00 00 00 00 00 00 03 00 44 00 61 00 74 00 61 00 |........D.a.t.a.|
000002c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000300 48 46 53 00 00 00 11 aa aa 11 00 30 65 43 ec ac |HFS........0eC..|
00000310 7a 69 fe f8 7f 82 45 23 b0 75 e8 1a 43 36 90 b2 |zi....E#.u..C6..|
00000320 00 10 61 c3 0e 00 00 00 00 60 00 c4 0e 00 00 00 |..a......`......|
00000330 00 00 00 00 00 00 00 00 42 00 61 00 73 00 65 00 |........B.a.s.e.|
00000340 62 00 61 00 6e 00 64 00 20 00 44 00 61 00 74 00 |b.a.n.d. .D.a.t.|
00000350 61 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |a...............|
00000360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
NS2
第二個NameSpace包含illb和iBoot。從我們在這個十六進制轉儲中可以看到的。它使用GID密鑰加密
00000000 30 83 03 96 1e 16 04 49 4d 47 34 30 83 03 80 99 |0......IMG40....|
00000010 16 04 49 4d 34 50 16 04 69 6c 6c 62 16 10 69 42 |..IM4P..illb..iB|
00000020 6f 6f 74 2d 32 38 31 37 2e 32 30 2e 32 36 04 83 |oot-2817.20.26..|
00000030 03 80 00 9f 1c 04 9b 76 e3 d6 d3 70 15 99 89 b7 |.......v...p....|
00000040 8a 73 4e dd f8 00 d8 e7 5c 5a b4 55 85 2a 03 e1 |.sN.....\Z.U.*..|
00000050 6b 4a 38 0a 59 6e 28 9d f1 be c5 41 1b 17 bd dd |kJ8.Yn(....A....|
00000060 89 0c 69 63 54 ed bd 72 a1 3d 4f 97 04 de 28 fc |..icT..r.=O...(.|
00000070 94 58 29 b4 45 67 23 ae cc d7 be 59 bc 07 3f fc |.X).Eg#....Y..?.|
00000080 ba 55 03 71 a4 a2 86 dd 23 8f 5a ce 67 18 6e 1e |.U.q....#.Z.g.n.|
00000090 8a 6a ec 83 f8 d6 8c 32 ca 24 36 50 77 76 1e bd |.j.....2.$6Pwv..|
000000a0 4f a9 ac d3 5e 15 70 4e 32 58 a8 34 16 22 0c d3 |O...^.pN2X.4."..|
...
NS3
第三個NS是SysCFG分區。SysCFG通過AppleDiagnosticDataAccessReadOnly IOregistry節點的AppleDiagnosticDataSysCfg屬性在IORegistry中可見。(由com.apple.driver.AppleDiagnosticDataAccessReadOnly kext提供)。(如Jonathan Levin的* OS Internals Volumes III和II中所討論的)
00000000 67 66 43 53 04 05 00 00 00 00 02 00 02 00 02 00 |gfCS............|
00000010 00 00 00 00 3f 00 00 00 42 54 4e 43 23 42 4c 4d |....?...BTNC#BLM|
00000020 11 00 00 00 ec ff 01 00 ff ff ff ff 23 47 46 43 |............#GFC|
00000030 2f 2f 2f 2f 2a 2f 2a 00 00 00 00 00 00 00 00 00 |////*/*.........|
00000040 63 61 4d 57 38 71 de 30 82 ff 00 00 00 00 00 00 |caMW8q.0........|
00000050 00 00 00 00 63 61 4d 42 38 71 de 30 83 00 00 00 |....caMB8q.0....|
00000060 00 00 00 00 00 00 00 00 42 54 4e 43 56 43 41 50 |........BTNCVCAP|
00000070 29 00 00 00 c0 ff 01 00 ff ff ff ff 42 54 4e 43 |)...........BTNC|
00000080 54 41 42 43 31 00 00 00 8c ff 01 00 ff ff ff ff |TABC1...........|
00000090 54 53 42 56 09 00 00 00 00 00 00 00 00 00 00 00 |TSBV............|
000000a0 00 00 00 00 52 42 50 56 0b 00 00 00 00 00 00 00 |....RBPV........|
000000b0 00 00 00 00 00 00 00 00 42 54 4e 43 41 43 42 56 |........BTNCACBV|
000000c0 14 00 00 00 78 ff 01 00 ff ff ff ff 42 54 4e 43 |....x.......BTNC|
000000d0 4c 41 43 57 ac 02 00 00 cc fc 01 00 ff ff ff ff |LACW............|
NS4
第四個NameSpace包含WiFi信息。實際上,即使在未解鎖的情況下,它也允許電話訪問密碼以激活網絡
00000000 69 50 43 42 00 01 00 00 01 00 00 00 80 00 00 00 |iPCB............|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000002e0 fc ff ef ff af ec 22 08 57 69 50 41 53 58 4e 65 |......".WiPASXNe|
000002f0 78 74 20 31 38 41 41 64 4d 32 00 00 00 00 00 00 |xt 18AAdM2......|
00000300 fc ff ef ff 97 76 22 08 57 69 50 41 53 20 31 43 |.....v".WiPAS 1C|
00000310 4d 50 32 37 00 00 00 00 00 00 00 00 00 00 00 00 |MP27............|
00000320 fc ff ef ff 79 79 22 08 57 69 50 41 53 20 31 43 |....yy".WiPAS 1C|
00000330 4d 50 32 37 00 00 00 00 00 00 00 00 00 00 00 00 |MP27............|
NS5
第五個分區是NVRAM,可通過相應的Kext作為邏輯鍵/值訪問
00000000 5a 82 02 00 6e 76 72 61 6d 00 00 00 00 00 00 00 |Z...nvram.......|
00000010 fd 20 e6 d3 58 01 00 00 00 00 00 00 00 00 00 00 |. ..X...........|
00000020 70 7c 80 00 63 6f 6d 6d 6f 6e 00 00 00 00 00 00 |p|..common......|
00000030 61 75 74 6f 2d 62 6f 6f 74 3d 74 72 75 65 00 62 |auto-boot=true.b|
00000040 61 63 6b 6c 69 67 68 74 2d 6c 65 76 65 6c 3d 31 |acklight-level=1|
00000050 34 39 37 00 62 6f 6f 74 2d 61 72 67 73 3d 00 00 |497.boot-args=..|
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000820 a1 15 81 00 41 50 4c 2c 4f 53 58 50 61 6e 69 63 |....APL,OSXPanic|
00000830 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00001030 7f 17 fd 00 77 77 77 77 77 77 77 77 77 77 77 77 |....wwwwwwwwwwww|
00001040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00002000
NS6
第六個分區是PLOG。kbag信息存儲在哪裡。當您使用加密引擎解鎖手機時會使用該功能。此外,超過10次錯誤的密碼,這會得到擦除。
00000000 4e 0b 2a 02 c5 30 09 f8 ae 0e ca 8d 8f c1 88 8c |N.*..0..........|
00000010 2b 68 4b 44 c4 30 09 f8 af 0e ca 8d 8f c1 88 8c |+hKD.0..........|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000030 00 00 00 00 00 00 00 00 1b 00 00 00 0c 97 b4 a8 |................|
00000040 6b 4c 50 00 4d 56 77 4c 2b a0 ab f1 3e 62 df a6 |kLP.MVwL+...>b..|
00000050 66 93 52 4e 2a da 12 f9 17 ba 37 ea 08 f2 cd 62 |f.RN*.....7....b|
00000060 d8 02 71 b3 a7 a9 38 b8 a1 db 0e 47 29 50 e9 41 |..q...8....G)P.A|
00000070 eb 57 88 e9 76 7a f7 c3 8f 77 bd c8 08 0f 83 3c |.W..vz...w.....<|
00000080 b7 96 20 46 71 a7 ad 59 e1 e3 b4 cc 1b cf 83 83 |.. Fq..Y........|
00000090 5e 60 c8 be f3 20 8c f5 6b 4c 34 00 31 47 41 42 |^`... ..kL4.1GAB|
000000a0 31 47 41 42 18 1b 7c 83 11 63 64 95 96 0d 0e fc |1GAB..|..cd.....|
000000b0 09 30 c0 3e c5 f6 48 70 a8 f4 86 f8 52 77 49 20 |.0.>..Hp....RwI |
000000c0 57 ad 7e 21 23 38 b0 dd 4a aa 21 05 6e 20 0a 8e |W.~!#8..J.!.n ..|
000000d0 76 24 55 fc 6b 4c 28 00 79 65 6b c4 6a dc ee 85 |v$U.kL(.yek.j...|
000000e0 f3 1e d2 0f 66 f8 25 e1 97 bd ef 61 7e 9a 7b 18 |....f.%....a~.{.|
000000f0 d3 60 89 d8 57 43 3c d8 44 30 e3 1a e6 eb 0c 3e |.`..WC<.D0.....>|
00000100 9b 65 f4 69 6b 4c 00 00 45 4e 4f 44 00 00 00 00 |.e.ikL..ENOD....|
00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
....
NS7
第七個分區目前看起來是空的
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00100000
解析Filesystem
Jonathan Levin的HFSleuth可以讀取原始設備文件並檢查其中的HFS +文件系統。 http://NewOSXBook.com/tools/hfsleuth.html
Review上面
A9以下的裝置中,BootROM會將引導權交給LLB,而在之後的版本中,BootROM會直接交棒給iBoot。根據解包發現,在這些裝置上,ipsw韌體中LLB、iBoot、iBEC、iBSS本質上均為iBoot鏡像。既然iBoot能直接完成所有操作,為什麼蘋果在最初設計的時候要拆分成LLB和iBoot
OS Internal 的一份資料說,LLB主要存放FTL和32位元相關驅動。
第二個問題,iPhone 6s實質上有7個物理分區,而LLB+iBoot存放在NS2中,在實際系統上被映射為/dev/disk1(iBoot)和/dev/disk2(LLB)。
重新利用NAND
如果你有一個適當的JIG使用彈簧針來接觸墊,那麼該NAND可以在iphone中重新使用。當想要例如從外部修改NAND然後開始測試,它非常方便。
JTAG / SWD
如前所述,NVMe芯片具有JTAG / SWD接口。將OpenOCD放在它上面看看發生了什麼是很有趣的。
使用帶有OpenOCD的KT-Link接口,我們可以有一個TAP枚舉。
Open On-Chip Debugger 0.10.0-dev-00212-g50d4f76 (2016-02-15-18:11)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
debug_level: 2
Info : FTDI SWD mode enabled
adapter speed: 10000 kHz
Info : clock speed 10000 kHz
Info : SWD IDCODE 0x5ba02477
Info : SWD IDCODE 0x5ba02477
Info : SWD IDCODE 0x5ba02477
Info : SWD IDCODE 0x5ba02477
Info : mynvme.cpu: hardware has 3 breakpoints, 2 watchpoints
Info : mynvme.cpu rev 1, partnum c05, arch f, variant 0, implementor 41
Info : mynvme.cpu cluster 0 core 0 multi core
看了一會兒之後,它首先看到0x5ba02477是一個Cortex M,但實際上它是一個皮層A.
> dap info
AP ID register 0x44770002
Type is MEM-AP APB
MEM-AP BASE 0x80000000
ROM table in legacy format
MEMTYPE system memory not present: dedicated debug bus
ROMTABLE[0x0] = 0x40000002
Component not present
ROMTABLE[0x4] = 0x74300003
Component base address 0xf4300000, start address 0xf4300000
Component class is 0x1, ROM table
Peripheral ID[4..0] = hex 00 00 0c 85 33
Unrecognized (Part 0x533, designer 0xc8)
[L01] ROM table in legacy format
[L01] MEMTYPE system memory not present: dedicated debug bus
[L01] ROMTABLE[0x0] = 0x1003
Component base address 0xf4301000, start address 0xf4301000
Component class is 0xf, PrimeCell or System component
Peripheral ID[4..0] = hex 00 00 4c 80 00
Unrecognized (Part 0x0, designer 0xc8)
[L01] ROMTABLE[0x4] = 0x10003
Component base address 0xf4310000, start address 0xf4310000
Component class is 0x9, CoreSight component
Type is 0x15, Debug Logic, Processor
Peripheral ID[4..0] = hex 04 00 1b bc 05
Part is Cortex-A5 Debug (Debug Unit)
[L01] ROMTABLE[0x8] = 0x11002
Component not present
[L01] ROMTABLE[0xc] = 0x12003
Component base address 0xf4312000, start address 0xf4312000
Component class is 0x9, CoreSight component
Type is 0x13, Trace Source, Processor
Peripheral ID[4..0] = hex 04 00 2b b9 55
Part is Cortex-A5 ETM (Embedded Trace)
[L01] ROMTABLE[0x10] = 0x13003
Component base address 0xf4313000, start address 0xf4313000
Component class is 0x9, CoreSight component
Type is 0x21, Trace Sink, Buffer
Peripheral ID[4..0] = hex 04 00 3b b9 07
Part is CoreSight ETB (Trace Buffer)
[L01] ROMTABLE[0x14] = 0x14003
Component base address 0xf4314000, start address 0xf4314000
Component class is 0x9, CoreSight component
Type is 0x14, Debug Control, Trigger Matrix
Peripheral ID[4..0] = hex 04 00 4b b9 06
Part is CoreSight CTI (Cross Trigger)
[L01] ROMTABLE[0x18] = 0x15003
Component base address 0xf4315000, start address 0xf4315000
Component class is 0x9, CoreSight component
Type is 0x14, Debug Control, Trigger Matrix
Peripheral ID[4..0] = hex 04 00 4b b9 06
Part is CoreSight CTI (Cross Trigger)
[L01] ROMTABLE[0x1c] = 0x20003
Component base address 0xf4320000, start address 0xf4320000
Component class is 0x9, CoreSight component
Type is 0x15, Debug Logic, Processor
Peripheral ID[4..0] = hex 04 00 4b bc 15
Part is Cortex-R5 Debug (Debug Unit)
[L01] ROMTABLE[0x20] = 0x21002
Component not present
[L01] ROMTABLE[0x24] = 0x22003
Component base address 0xf4322000, start address 0xf4322000
Component class is 0x9, CoreSight component
Type is 0x13, Trace Source, Processor
Peripheral ID[4..0] = hex 04 00 0b b9 31
Part is Cortex-R5 ETM (Embedded Trace)
[L01] ROMTABLE[0x28] = 0x23003
Component base address 0xf4323000, start address 0xf4323000
Component class is 0x9, CoreSight component
Type is 0x21, Trace Sink, Buffer
Peripheral ID[4..0] = hex 04 00 3b b9 07
Part is CoreSight ETB (Trace Buffer)
[L01] ROMTABLE[0x2c] = 0x24003
Component base address 0xf4324000, start address 0xf4324000
Component class is 0x9, CoreSight component
Type is 0x14, Debug Control, Trigger Matrix
Peripheral ID[4..0] = hex 04 00 4b b9 06
Part is CoreSight CTI (Cross Trigger)
[L01] ROMTABLE[0x30] = 0x25003
Component base address 0xf4325000, start address 0xf4325000
Component class is 0x9, CoreSight component
Type is 0x14, Debug Control, Trigger Matrix
Peripheral ID[4..0] = hex 04 00 4b b9 06
Part is CoreSight CTI (Cross Trigger)
[L01] ROMTABLE[0x34] = 0x26003
Component base address 0xf4326000, start address 0xf4326000
Component class is 0x9, CoreSight component
Type is 0x12, Trace Link, Funnel, router
Peripheral ID[4..0] = hex 04 00 2b b9 08
Part is CoreSight CSTF (Trace Funnel)
[L01] ROMTABLE[0x38] = 0xffe00002
Component not present
[L01] ROMTABLE[0x3c] = 0x0
[L01] End of ROM table
ROMTABLE[0x8] = 0x0
End of ROM table
在這個階段,為了找到芯片的工作方式,轉儲他們的bootrom非常有趣。
從現在開始,可以使用IDA將其附加到它上面,就好像它是3333端口上的GDB一樣。
固件分析
有趣的是,蘋果在ramrod OTA更新中有固件升級工具。為拿到它,為實現它:
# wget http://appldnld.apple.com/iOS9.3/031-28353-20160321-9904D9BA-EA47-11E5-9069-7170BD379832/com_apple_MobileAsset_SoftwareUpdate/352b7321dda0925f84c7beb6128a3dbdb71476fe.zip
# unzip 352b7321dda0925f84c7beb6128a3dbdb71476fe.zip AssetData/payload/replace/usr/standalone/update/ramdisk/H8SURamDisk.dmg
# dd if=AssetData/payload/replace/usr/standalone/update/ramdisk/H8SURamDisk.dmg of=update.dmg bs=27 skip=1
# file update.dmg
update.dmg: Macintosh HFS Extended version 4 data last mounted by: '10.0', created: Fri Mar 15 00:27:05 2148, last modified: Fri Mar 15 09:31:59 2148, block size: 4096, number of blocks: 17228, free blocks: 1
# mkdir d
# mount -o loop,ro update.dmg d
。
├──./ BFH│├──./
BFH/ s3e
- bfh
- loader.bin│└──./ BFH/ version.plist├──./ Hynix - mlc - 1y - bdie -
2p│├── ./Hynix-mlc-1y-bdie-2p/FWUpdate-Hynix-mlc-1y-bdie-2p-1dpc-2ch-NonCES.pak
│├── ./Hynix-mlc-1y-bdie-2p/FWUpdate-Hynix -mlc-1Y-bdie-2P-2dpc-2 CH-NonCES.pak - > fwupdate子-力士-MLC-1Y-bdie-2P-1dpc-2 CH-NonCES.pak
│├── ./Hynix-mlc-1y-bdie -2p / FWUpdate-Hynix-mlc-1y-bdie-2p-4dpc-2ch-NonCES.pak → FWUpdate-Hynix-mlc-1y-bdie-2p-1dpc-2ch-NonCES.pak│├──.
/ Hynix -mlc-1y-bdie-2p / FWUpdate-Hynix-mlc-1y-bdie-2p.pak - >fwupdate子-力士-MLC-1Y-bdie-2P-1dpc-2 CH-NonCES.pak
│└── ./Hynix-mlc-1y-bdie-2p/version.plist
├── ./Hynix-mlc-1y-cdie -2p│├──./
Hynix -
mlc- 1y- cdie - 2p/ FWUpdate- Hynix - mlc- 1y- cdie - 2p- 1dpc- 2ch - NonCES.pak│├──./ Hynix- mlc - 1y- cdie -2p / FWUpdate-Hynix-mlc-1y-cdie-2p-2dpc-2ch-NonCES.pak - > FWUpdate-Hynix-mlc-1y-cdie-2p-1dpc-2ch-NonCES.pak│├──.
/ Hynix -mlc-1Y-cdie-2P / fwupdate子-力士-MLC-1Y-cdie-2P-4dpc-2 CH-NonCES.pak - > fwupdate子-力士-MLC-1Y-cdie-2P-1dpc-2 CH-NonCES.pak
│ ├── ./Hynix-mlc-1y-cdie-2p/FWUpdate-Hynix-mlc-1y-cdie-2p.pak - > fwupdate子-力士-MLC-1Y-cdie-2P-1dpc-2 CH-NonCES.pak
│ └──./Hynix-mlc-1y-cdie-2p/version.plist
├── ./Hynix-tlc-1y-2p
│├── ./Hynix-tlc-1y-2p/FWUpdate-Hynix-tlc-1y-2p -1dpc-2 CH-NonCES.pak
│├── ./Hynix-tlc-1y-2p/FWUpdate-Hynix-tlc-1y-2p-2dpc-2ch-NonCES.pak - > fwupdate子-力士型TLC-1Y-2P -1dpc-2 CH-NonCES.pak
│├── ./Hynix-tlc-1y-2p/FWUpdate-Hynix-tlc-1y-2p-4dpc-2ch-NonCES.pak - > fwupdate子-力士型TLC-1Y-2P -1dpc-2 CH-NonCES.pak
│├── ./Hynix-tlc-1y-2p/FWUpdate-Hynix-tlc-1y-2p.pak - > fwupdate子-力士型TLC-1Y-2P-1dpc-2 CH-隨機數.pak
│└── ./Hynix-tlc-1y-2p/version.plist
├── ./Sandisk-mlc-1y-2p
│├──./Sandisk-mlc-1y-2p/FWUpdate-Sandisk-mlc-1y-2p-1dpc-2ch-NonCES.pak
│├── ./Sandisk-mlc-1y-2p/FWUpdate-Sandisk-mlc-1y-2p -2dpc-2 CH-NonCES.pak - > fwupdate子-的Sandisk-MLC-1Y-2P-1dpc-2 CH-NonCES.pak
│├── ./Sandisk-mlc-1y-2p/FWUpdate-Sandisk-mlc-1y-2p -4dpc-2 CH-NonCES.pak - > fwupdate子-的Sandisk-MLC-1Y-2P-1dpc-2 CH-NonCES.pak
│├── ./Sandisk-mlc-1y-2p/FWUpdate-Sandisk-mlc-1y-2p .pak - > fwupdate子-的Sandisk-MLC-1Y-2P-1dpc-2 CH-NonCES.pak
│└── ./Sandisk-mlc-1y-2p/version.plist
├── ./Sandisk-tlc-1y-2p
│├──./ Sandisk-
tlc-1y- 2p/ FWUpdate- Sandisk- tlc- 1y- 2p- 1dpc- 2ch- NonCES.pak│├──./Sandisk-tlc-1y-2p/FWUpdate-Sandisk-tlc-1y-2p-2dpc-2ch-NonCES.pak - > FWUpdate-Sandisk -tlc-1y-2p-1dpc-2ch-
NonCES.pak│├── ./Sandisk-tlc-1y-2p/FWUpdate-Sandisk-tlc-1y-2p-4dpc-2ch-NonCES.pak - > FWUpdate-Sandisk -tlc-1y-2p-1dpc-2ch-
NonCES.pak│├── ./Sandisk-tlc-1y-2p/FWUpdate-Sandisk-tlc-1y-2p.pak - > fwupdate子-晟碟型TLC-1Y-2P-1dpc-2 CH-NonCES.pak
│└── ./Sandisk-tlc- 1y-2p / version.plist├──./
Sandisk - tlc - 1z - 2p│├── ./ Sandisk - tlc - 1z -2p/ FWUpdate - Sandisk - tlc - 1z -2p- 1dpc - 2ch
- NonCES.pak
│├──./ Sandisk - tlc- 1z - 2p/ FWUpdate - Sandisk- tlc - 1z - 2p- 2dpc - 2ch- NonCES.pak - >fwupdate子-晟碟型TLC-1Z-2P-1dpc-2 CH-NonCES.pak
│├── ./Sandisk-tlc-1z-2p/FWUpdate-Sandisk-tlc-1z-2p-4dpc-2ch-NonCES.pak - > fwupdate子-晟碟型TLC-1Z-2P-1dpc-2 CH-NonCES.pak
│├── ./Sandisk-tlc-1z-2p/FWUpdate-Sandisk-tlc-1z-2p.pak - > fwupdate子-的SanDisk TLC- 1Z-2P-1dpc-2 CH-NonCES.pak
│└── ./Sandisk-tlc-1z-2p/version.plist
├── ./Sandisk-tlc-1z-2p-8dpc
│├── ./Sandisk- TLC-1Z-2P-8dpc / fwupdate子-晟碟型TLC-1Z-2P-8dpc-2 CH-CES.pak
│└── ./Sandisk-tlc-1z-2p-8dpc/version.plist
├├── ./ Toshiba-mlc-1y-
2p│├──. / Toshiba-mlc-1y-2p / FWUpdate -Toshiba-mlc-1y-2p- 1dpc - 2ch - NonCES.pak
│├── ./Toshiba-mlc-1y-2p/FWUpdate-Toshiba-mlc-1y-2p-2dpc-2ch-NonCES.pak - > fwupdate子東芝-MLC-1Y-2P-1dpc-2 CH-NonCES.pak
│├── ./Toshiba-mlc-1y-2p/FWUpdate-Toshiba-mlc-1y-2p-4dpc-2ch-NonCES.pak - > fwupdate子東芝-MLC-1Y-2P-1dpc-2 CH-NonCES.pak
│├── ./Toshiba-mlc-1y-2p/FWUpdate-Toshiba-mlc-1y-2p.pak - > fwupdate子東芝-MLC-1Y-2P-1dpc-2 CH-NonCES.pak
│└── ./ Toshiba-mlc-1y-2p / version.plist├──./Toshiba-mlc-
1z - 2p│├── ./Toshiba-mlc- 1z -2p/ FWUpdate -Toshiba-mlc- 1z -2p- 1dpc
- 2ch -NonCES.pak│├──.
/ Toshiba - mlc- 1z - 2p/ FWUpdate - Toshiba- mlc - 1z- 2p - 2dpc - 2ch- NonCES.pak - >fwupdate子東芝-MLC-1Z-2P-1dpc-2 CH-NonCES.pak
│├── ./Toshiba-mlc-1z-2p/FWUpdate-Toshiba-mlc-1z-2p-4dpc-2ch-NonCES.pak - > fwupdate子東芝-MLC-1Z-2P-1dpc-2 CH-NonCES.pak
│├── ./Toshiba-mlc-1z-2p/FWUpdate-Toshiba-mlc-1z-2p.pak - > fwupdate子東芝-MLC- 1Z-2P-1dpc-2 CH-NonCES.pak
│└── ./Toshiba-mlc-1z-2p/version.plist
├── ./Toshiba-tlc-1z-2p
│├── ./Toshiba-tlc- 1Z-2P / fwupdate子東芝型TLC-1Z-2P-1dpc-2 CH-NonCES.pak
│├── ./Toshiba-tlc-1z-2p/FWUpdate-Toshiba-tlc-1z-2p-2dpc-2ch-NonCES .pak - > FWUpdate-Toshiba-tlc-1z-2p-1dpc-2ch-
NonCES.pak│├──./Toshiba-tlc-1z-2p/FWUpdate-Toshiba-tlc-1z-2p-4dpc-2ch-NonCES.pak - > FWUpdate-Toshiba-tlc-1z-2p-1dpc-2ch-
NonCES.pak│├── ./Toshiba-tlc-1z-2p/FWUpdate-Toshiba-tlc-1z-2p.pak - > fwupdate子-東芝TLC-1Z-2P-1dpc-2 CH-NonCES.pak
│└── ./Toshiba-tlc- 1z-2p / version.plist├──./
Toshiba - tlc -1z-2p- 8dpc│├── ./ Toshiba - tlc -1z-2p- 8dpc / FWUpdate - Toshiba - tlc -1z-2p- 8dpc
- 2ch -CES.pak└──./
Toshiba- tlc- 1z - 2p - 8dpc/ version.plist
讓我們看看任何.pak的hexdump的頭部
00000000 46 57 55 42 00 0e 40 01 00 00 00 00 00 00 00 00 |FWUB..@.........|
00000010 10 be 05 00 11 63 6f e7 c0 1f 04 00 1e 56 ea f7 |.....co......V..|
00000020 00 00 00 00 00 00 00 00 20 0d 00 00 ac c9 02 a3 |........ .......|
00000030 10 1d 00 00 8e 17 3c 92 5e 98 b3 ff 46 57 55 45 |......<.^...FWUE|
00000040 02 00 00 00 00 10 0b 51 01 17 01 64 02 08 87 04 |.......Q...d....|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000440 00 00 00 00 0f 09 84 54 46 57 55 65 00 00 00 00 |.......TFWUe....|
00000450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00001000 41 54 4f 43 36 03 00 00 00 00 00 0e 40 01 00 00 |ATOC6.......@...|
00001010 40 00 00 00 00 80 80 ce 01 00 00 08 b0 21 00 f0 |@............!..|
00001020 05 00 e0 de 03 00 00 1a d8 10 00 20 14 00 10 00 |........... ....|
00001030 00 00 45 54 4f 43 00 00 00 00 00 00 00 00 00 00 |..ETOC..........|
00001040 8e 0a 00 fa 13 00 00 ea 04 00 00 ea 4d 00 00 ea |............M...|
00001050 31 00 00 ea fe ff ff ea 80 5e 00 ea 64 00 00 ea |1........^..d...|
00001060 00 30 4f e1 20 00 13 e3 04 30 1e 05 02 30 5e 15 |.0O. ....0...0^.|
看起來文件中有一些關鍵字[FWUB,FWUE,FWUe,ATOC,ETOC …]到目前為止,有趣的是看到有一個名為“BFH”的目錄。用一個文件“s3e-bfh-loader.bin”。“S3E”之前是在iphone截圖中看起來像是NVMe便宜的代號。看它時:
00000000 0e 00 00 ea fe ff ff ea fe ff ff ea fe ff ff ea |................|
00000010 fe ff ff ea fe ff ff ea 00 00 00 ea fe ff ff ea |................|
這表明該文件實際上是具有中斷向量的原始ARM固件。從近距離觀察IDA時,我們可以看到一些有趣的CMP:
正如人們可以看到的那樣,這些關鍵字顯示為小端。所以看起來bfh文件是一個引導加載程序,它被加載到NVMe中以便安裝.pak,因為它可以清楚地解析它。當更多關注驅動程序時,看起來芯片可以處於正常模式,或稱為“BFH”模式。實際上,在這種模式下,在地址BAR0 + 0x1b18處,值為0xBFBFBFBF。加載的s3e二進製文件讓固件更新工具獲取nand信息並找出需要加載的文件。
int nvme_identify(struct nvme_dev * dev) {
int p;
int brand;
int tech;
int non;
int plane;
int flag;
int dpc;
int dch;
char directory[200];
int dsize;
int die;
const char * brand_list[] = {
"Invalid",
"Hynix",
"Invalid",
"Sandisk",
"Samsung",
"Toshiba"
}; //350
const char * tech_list[] = {
"slc",
"mlc",
"tlc"
}; // 380
const char * plane_list[] = {
"1x",
"1y",
"1z"
}; // 398
const char * die_list[] = {
"a",
"b"
}; //3b0
const int size_list[] = {
64,
128,
256,
512,
1024,
2048
};
const char * non_list[] = {
"Non",
""
};
u32 tst32;
u64 tst64;
u64 tmp;
u64 val;
tst32 = readl(dev - > bar + 0x1b20);
printk("REG1B20 (nand info) %08x\n", tst32);
tst64 = tst32;
if (!(tst32 >> 25)) {
printk("val >> 25 NOK !!!\n");
return 0;
}
tst32 = readl(dev - > bar + 0x1b24);
printk("REG1B24 (nand info )%08x\n", tst32);
tmp = tst32;
tmp = tmp << 32;
tst64 |= tmp;
val = tst64;
p = 1 << ((val >> 12) & 3);
brand = val & 7;
tech = (val >> 7) & 3;
flag = (val >> 25) & 0x7F;
plane = (val >> 3) & 0xF;
die = (val >> 20) & 0xF;
if (!flag) {
dpc = 1;
dch = 1;
non = 0;
} else {
dpc = 1 << ((val >> 32) & 0xf);
dch = 1 << ((val >> 36) & 0x3);
non = ((val >> 38) & 1);
}
if (brand == 1 && tech == 1)
sprintf(directory, "%s-%s-%s-%sdie-%dp", brand_list[brand], tech_list[tech], plane_list[plane], die_list[die], p);
else
sprintf(directory, "%s-%s-%s-%dp", brand_list[brand], tech_list[tech], plane_list[plane], p);
if (!flag) {
printk("%s/FWUpdate-%s.pak\n", directory, directory);
} else {
dsize = (val >> 14) & 0x3;
if (non)
non = 1;
if (((size_list[dsize] >> 3) * dpc * dch) < 0x100)
printk("%s/FWUpdate-%s-%ddpc-%dch-%sCES.pak\n", directory, directory, dpc, dch, non_list[non]);
else
printk("%s-%ddpc/FWUpdate-%s-%ddpc-%dch-%sCES.pak\n", directory, dpc, directory, dpc, dch, non_list[non]);
}
return 0;
}
在那個階段,我添加到我的驅動程序中的示例函數能夠告訴我需要上傳哪個文件。關於上傳過程,地址和長度被設置在2個特殊寄存器中,1被發送到寄存器0x1b10。文件上傳後,寄存器0x1b14變為0x10,這意味著芯片已準備好繼續。通過向0x1b10寫入2,下一步就會發生。該過程首先在BFH模式下發生,一旦s3e二進製文件上傳,NVMe被識別。完成後,.pak會再次上傳,然後可以進行升級。
直接存儲器存取(DMA)
首先,在Bootrom方面,當NVMe啟動並運行在BFH模式下,並等待主機給它啟動DMA的命令時,我們就在這張圖中看到的循環中。如果發現告知DMA的寄存器沒有被設置,那麼當到達發生奇怪事件時,我們會再次分支。
一旦完成,如果一切順利,我們最終會等待主機告訴我們它已準備就緒。請注意“MOVS R0,#0x10”,“STR R0,[R5,#0x2C]”,這正是我們的寄存器告訴我們DMA發生的地方,如前所述,這些寄存器得到的設置為0x10。
最後,DMA如上圖所示在地址0x76828000處複製我們想要的緩衝區。然後,當主機說它準備好了,它跳轉到這個地址:“MOV R0,#0x76828000”,“BLX R0”順便說一下,在s3e-bfh.bin加載器中,我們可以清楚地看到代碼立即自行重新定位到0x00101000(拇指模式為+1)
這裡的想法是查看是否有可能通過JTAG控制NVMe,以便要求它通過PCIe總線執行DMA讀操作。為此,必須將PCI_COMMAND_BUS_MASTER設置為1.我們可以假設,由於芯片使用的是遠程RAM,因此可以充當PCIe主設備。這是內核驅動程序探測功能的一個片段。
sstatic int bfh_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
u64 dma_addr = 0;
void *cpu_addr = NULL;
pci_enable_device(pdev);
pci_set_master(pdev);
cpu_addr = dma_alloc_coherent(NULL, 0x10000, &dma_addr, GFP_DMA32);
memset(cpu_addr, 0x41, 0x10000);
printk("ADDR mem %016llx\n", dma_addr);
return 0;
}
我們的目標是強制DMA發生,只需通過JTAG控制NVMe的ARM,以便讓它轉儲我們在內核中分配的區域,看看我們是否從中獲得數據。