updates docs to explain final sboot boot

This commit is contained in:
Jonathan Herrewijnen 2024-09-25 18:44:44 +02:00
parent 0174b2a4f7
commit 6711ceea27
7 changed files with 56 additions and 83 deletions

View File

@ -331,4 +331,22 @@ The last stage before the kernel boots.
.. figure:: images/bl31_debugger_memory_example.png .. figure:: images/bl31_debugger_memory_example.png
:align: center :align: center
Boot chain with EL3 and EL1 areas Boot chain with EL3 and EL1 areas
To keep access to the debugger, but allow modifications, we need to again load the BL33, but not boot it. We need to set some registers to accomplish this. We continue our bootflow to allow the device to load BL33, and then after it is done loading, let it jump back to the debugger:
- Store BL33 address in X0: ``self.cd.arch_dbg.state.X0 = BL33_ptr``
- Store BL33 link register in LR: ``self.cd.arch_dbg.state.LR = BL33_LR``
- Set LR to debugger: ``self.cd.arch_dbg.state.LR = DEBUGGER_ADDR``
- Jump into the function that loads BL33: ``self.cd.restore_stack_and_jump(hijacked_fun)``
Now we can again load our next boot stage (BL33), send it, and verify a return to the debugger.
At this point, we tried patching something in memory at BL33 - like we did at BL31. But this always failed. After consultation, it seemed most likely that something was checking the integrity of the next boot stages. When we modified and reverted our changes, the boot was proper. The link register to continue our boot flow was at ``0x2024eec``. We did not succeed to manually do a verification, and continue the boot flow. This function at 0x2024eec does also not return, but instead continues onwards.
.. figure:: images/_integrity_check_BL2-BL33.png
:align: center
Possible integrity check of boot stages at BL2 and BL33.
The decompilation is a bit broken, but we noticed that there are multiple calls to the same function, not just at the location where BL33 was returning from. With most specific things related to BL33 already done before this function. A similar verification seemed to have been done at ``0x02024e5c``. At this address, the same function was executed as at ``0x02024eec``, so instead of jumpingo into the function at ``0x02024eec``, we jumped into the function at ``0x02024e5c``. This worked, and allowed us to patch BL33, while continuing our boot flow. I assume, that we're doing an integrity check over BL2, while booting BL33.

View File

@ -213,3 +213,25 @@ There's an odd space at 0x14kk. With things like deadcafe:
1c0000000000000000000000fecaadde00000000fecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddef 1c0000000000000000000000fecaadde00000000fecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddefecaaddef
Week 37 - 2024
--------------
A few days ago, I noticed that the memory is no longer being cleared between boots. After some discussion, it seems most likely, that this is because I'm booting the device further, eventually into recovery mode. At some point, it doesn't clear the memory anymore (or it's not being cleared). This is interesting, as it allows me to see what was loaded into memory, before I start booting the device.
So, I've written something to dump the location of thte TTBR0_EL3 table, before booting any of BL1, but after loading the initial debugger. The read bytes are fluctuating, strongly, but there seems to be a pattern. I'm hoping that after enough boots, I'll have enough data to reconstruct the table.
.. code-block:: python
import pandas as pd
blub = self.cd.memdump_region(0x02035000, 0x1000)
try:
df = pd.read_pickle('ttbr0_el3.pkl')
# Concat data to existing dataframe
df = pd.concat([df, pd.Series([blub])], ignore_index=True)
except:
df = pd.DataFrame()
df['TTBR0_EL3'] = [blub]
df.to_pickle('ttbr0_el3.pkl')

Binary file not shown.

After

Width:  |  Height:  |  Size: 685 KiB

View File

@ -5,7 +5,7 @@ start,end,name,order,comment,X0,LR
0x000064e0,0x0000658c,_boot_usb,,,, 0x000064e0,0x0000658c,_boot_usb,,,,
0x020c0000,0x020c0004,_frederic_dest_ptr,,,, 0x020c0000,0x020c0004,_frederic_dest_ptr,,,,
0x000002c0,0x000002c4,_jump_bl1,,,, 0x000002c0,0x000002c4,_jump_bl1,,,,
0x02022000,0x02023fff,BL1,,,, 0x02021800,0x02023800,BL1,,,,
0x02024000,0x02047fff,BL31,,,, 0x02024000,0x02047fff,BL31,,,,
0x02048000,0x0206ed10,BL2,,,, 0x02048000,0x0206ed10,BL2,,,,
0x02069000,0x0206f000,Debugger,,,, 0x02069000,0x0206f000,Debugger,,,,

1 start end name order comment X0 LR
5 0x000064e0 0x0000658c _boot_usb
6 0x020c0000 0x020c0004 _frederic_dest_ptr
7 0x000002c0 0x000002c4 _jump_bl1
8 0x02022000 0x02021800 0x02023fff 0x02023800 BL1
9 0x02024000 0x02047fff BL31
10 0x02048000 0x0206ed10 BL2
11 0x02069000 0x0206f000 Debugger

View File

@ -1,63 +0,0 @@
TTBR0_EL3: 0xbc46508b2f1462
Bits: 0000000010111100010001100101000010001011001011110001010001100010
root | INFO | Connection is working
Connected device! 0x4e8 0x1234
[+] Sent stage
TTBR0_EL3: 0xbc46508b2f1462
Bits: 0000000010111100010001100101000010001011001011110001010001100010
Connected device! 0x4e8 0x1234
[+] Sent stage
TTBR0_EL3: 0xbc46508b2f1462
Bits: 0000000010111100010001100101000010001011001011110001010001100010
TTBR0_EL3: 0xbc42508b2f1462
Bits: 0000000010111100010000100101000010001011001011110001010001100010
root | INFO | Connection is working
Connected device! 0x4e8 0x1234
[+] Sent stage
TTBR0_EL3: 0xbc42508b2f1462
Bits: 0000000010111100010000100101000010001011001011110001010001100010
Connected device! 0x4e8 0x1234
[+] Sent stage
TTBR0_EL3: 0xbc42508b2f1462
Bits: 0000000010111100010000100101000010001011001011110001010001100010
TTBR0_EL3: 0xbc42508b2f1462
Bits: 0000000010111100010000100101000010001011001011110001010001100010
root | INFO | Connection is working
Connected device! 0x4e8 0x1234
[+] Sent stage
TTBR0_EL3: 0xbc42508b2f1462
Bits: 0000000010111100010000100101000010001011001011110001010001100010
Connected device! 0x4e8 0x1234
[+] Sent stage
TTBR0_EL3: 0xbc42508b2f1462
Bits: 0000000010111100010000100101000010001011001011110001010001100010
TTBR0_EL3: 0xbc46508b2f1462
Bits: 0000000010111100010001100101000010001011001011110001010001100010
root | INFO | Connection is working
Connected device! 0x4e8 0x1234
[+] Sent stage
TTBR0_EL3: 0xbc46508b2f1462
Bits: 0000000010111100010001100101000010001011001011110001010001100010
Connected device! 0x4e8 0x1234
[+] Sent stage
TTBR0_EL3: 0xbc46508b2f1462
Bits: 0000000010111100010001100101000010001011001011110001010001100010
TTBR0_EL3: 0xbc46508b2f1460
Bits: 0000000010111100010001100101000010001011001011110001010001100000
root | INFO | Connection is working
Connected device! 0x4e8 0x1234
[+] Sent stage
TTBR0_EL3: 0xbc46508b2f1460
Bits: 0000000010111100010001100101000010001011001011110001010001100000
Connected device! 0x4e8 0x1234
[+] Sent stage
TTBR0_EL3: 0xbc46508b2f1460
Bits: 0000000010111100010001100101000010001011001011110001010001100000

View File

@ -632,6 +632,18 @@ class ExynosDevice():
self.cd.arch_dbg.state.print_ctx() self.cd.arch_dbg.state.print_ctx()
DEBUGGER_ADDR = 0x2069000 # 0x2069000 DEBUGGER_ADDR = 0x2069000 # 0x2069000
# Dump contents of TTBR0_EL3 from memory into a pandas dataframe and write it to a pickle file
import pandas as pd
blub = self.cd.memdump_region(0x02035000, 0x1000)
try:
df = pd.read_pickle('ttbr0_el3.pkl')
# Concat data to existing dataframe
df = pd.concat([df, pd.Series([blub])], ignore_index=True)
except:
df = pd.DataFrame()
df['TTBR0_EL3'] = [blub]
df.to_pickle('ttbr0_el3.pkl')
# Relocate debugger # Relocate debugger
debugger = open("../../dump/reloc_debugger_0x11200000.bin", "rb").read() debugger = open("../../dump/reloc_debugger_0x11200000.bin", "rb").read()
self.relocate_debugger(debugger=debugger, entry=0x11200000, storage=0x11203000, g_data_received=0x11204000) self.relocate_debugger(debugger=debugger, entry=0x11200000, storage=0x11203000, g_data_received=0x11204000)
@ -659,18 +671,6 @@ class ExynosDevice():
self.send_normal_stage(bl1) self.send_normal_stage(bl1)
assert self.usb_read(0x200) == b"GiAs", "Failed to jump back to debugger" assert self.usb_read(0x200) == b"GiAs", "Failed to jump back to debugger"
# Dump contents of TTBR0_EL3 from memory into a pandas dataframe and write it to a pickle file
import pandas as pd
blub = self.cd.memdump_region(0x02035000, 0x1000)
try:
df = pd.read_pickle('ttbr0_el3.pkl')
# Concat data to existing dataframe
df = pd.concat([df, pd.Series([blub])], ignore_index=True)
except:
df = pd.DataFrame()
df['TTBR0_EL3'] = [blub]
df.to_pickle('ttbr0_el3.pkl')
# Setup jump and bl_auth # Setup jump and bl_auth
AUTH_BL1 = 0x00012848 # Location of the authentication function AUTH_BL1 = 0x00012848 # Location of the authentication function
def auth_bl1(lr=0x2069000, x0=1, x1=1): def auth_bl1(lr=0x2069000, x0=1, x1=1):
@ -801,20 +801,16 @@ class ExynosDevice():
print(self.cd.arch_dbg.state.print_ctx()) print(self.cd.arch_dbg.state.print_ctx())
# Trying to patch BL33 but continuing good boot flow
# auth_bl1(DEBUGGER_ADDR, 0, 0)
# # Modify something in BL33 # # Modify something in BL33
print(self.cd.memdump_region(0x8f063710, 0x8)) print(self.cd.memdump_region(0x8f063710, 0x8))
# Samsung == SaMtung
self.cd.memwrite_region(0x8f063710, struct.pack('>I', 0x53614d74)) self.cd.memwrite_region(0x8f063710, struct.pack('>I', 0x53614d74))
# Modify USB Recovyer mode string to something else # Modify USB Recovyer mode string to something else
self.cd.memwrite_region(0x8f06ab10, b'\x50\x41\x54\x43\x48\x49\x4e\x47\x20\x42\x4c\x33\x33\x3a\x2d\x29\x0a\x00') self.cd.memwrite_region(0x8f06ab10, b'\x4e\x46\x49\x20\x50\x61\x74\x63\x68\x69\x6e\x67\x20\x42\x4c\x33\x33')
print(self.cd.memdump_region(0x8f063710, 0x8)) print(self.cd.memdump_region(0x8f063710, 0x8))
# Do signature verification on BL2 instead of BL33 and proceed to boot (original is jump to 0x2024eec) # Do signature verification on BL2 instead of BL33 and proceed to boot (original is jump to 0x2024eec)
self.cd.restore_stack_and_jump(0x02024e58) self.cd.restore_stack_and_jump(0x02024e5c)
pass pass

Binary file not shown.