Skip to main content

自iPhone 6s 之後iphone就開始使用NVME SSD
但是若透過iPhone 主控來處理,受到限制會很多. 這篇文章為逆向iPhone 6S NVME SSD方法
轉自http://ramtin-amin.fr/#nvmepcie
OSSLab翻譯與編修

NVMexpress是嵌入式設備中使用的下一代存儲技術。主要想法是直接在PCIexpress級別安裝儲存控制器,避免了大量協議轉換。
該技術基於PCIe。我們可以在最近的Macbook 12 retina上看到它在控制面板上的詳細信息:

最近,Macrumers在這個屏幕截圖上展示了這個特點:

所以這實際上是非常有趣的去看看它,
關於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

 

導航到nand

Jonathan Levin的HFSleuth可以讀取原始設備文件並檢查其中的HFS +文件系統。 http://NewOSXBook.com/tools/hfsleuth.html(謝來@Morpheus_____

重用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.pakFWUpdate-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,以便讓它轉儲我們在內核中分配的區域,看看我們是否從中獲得數據。

 

Thx Chang

Author Thx Chang

More posts by Thx Chang