Adding ghidra BL31 file for later inspection

This commit is contained in:
Jonathan Herrewijnen 2024-09-05 20:18:05 +02:00
parent 20ad0cdb45
commit c03af09de2
4 changed files with 217 additions and 11 deletions

View File

@ -17,6 +17,4 @@ What is interesting about the ROM is that it starts by checking MPIDR_EL1 regist
Week 35 - 2024 Week 35 - 2024
=============== ===============
After booting BL31, the MMU seems to be set up, and we're unable to do get any data off of spaces we're not 'allowed' to access. Interestingly, one of the setups is at After booting BL31, the MMU seems to be set up, and we're unable to do get any data off of spaces we're not 'allowed' to access. Patching the if-statement at 0x020244e8, disables the bit that says that the MMU is setup, but booting into recovery is possible (meaning the MMU is setup). Additionally, the memory at 0x02035600 is still not dumpable. At 0x02048000 is still accessible.
Patching the if-statement at 0x020244e8, and in doing so, disabling this function.

View File

@ -2631,6 +2631,170 @@
"# Save to html\n", "# Save to html\n",
"fig.write_html(\"../_static/stack_and_functions.html\")" "fig.write_html(\"../_static/stack_and_functions.html\")"
] ]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Layered blocks"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import plotly.graph_objects as go\n",
"import random\n",
"\n",
"tickpointers = []\n",
"vertical_len = len(data['overlap_with'].unique())\n",
"vertical_gap_percentage = 0.08\n",
"horizontal_gap = 0.1\n",
"labels = pd.DataFrame()\n",
"\n",
"def random_color():\n",
" return f'#{random.randint(0, 0xFFFFFF):06x}'\n",
"\n",
"fig = go.Figure()\n",
"\n",
"for i, d in data.iterrows():\n",
" fillcolor = random_color()\n",
" data.at[i, 'fillcolor'] = fillcolor\n",
" \n",
" x0=1\n",
" x1=4\n",
"\n",
" if d['overlap'] == False:\n",
" y0=d['overlap_with']\n",
" y1=d['overlap_with']+1\n",
" elif d['overlap'] == True:\n",
" overlaps = data.loc[data['overlap_with'] == d['overlap_with']].shape[0]\n",
"\n",
" # Calculate relative size of the overlap\n",
" overlap_sizes = data.loc[data['overlap_with'] == d['overlap_with']].iloc[1:]['size'].sum()\n",
"\n",
" if d['overlap_with'] == i:\n",
" y0=i\n",
" y1=overlaps+i\n",
" if i != data.shape[0]+1:\n",
" if d['end'] > data.iloc[i+1].start and d['end'] < data.iloc[i+1].end:\n",
" y1=overlaps+i-0.5\n",
" x0=x0-horizontal_gap\n",
" x1=x1+horizontal_gap\n",
" else:\n",
" y0=0.02+i\n",
" y1=0.87+i\n",
" else:\n",
" print(f'Something went wrong with {d}. Skipping')\n",
" continue\n",
"\n",
" fig.add_shape(\n",
" type=\"rect\",\n",
" x0=x0,\n",
" x1=x1,\n",
" y0=y0+vertical_gap_percentage,\n",
" y1=y1-vertical_gap_percentage,\n",
" line=dict(width=2),\n",
" fillcolor=fillcolor,\n",
" opacity=0.5,\n",
" layer=\"below\",\n",
" )\n",
"\n",
" # Add middle text\n",
" fig.add_trace(go.Scatter\n",
" (\n",
" x=[(x0+x1)/2],\n",
" y=[y0+0.5],\n",
" text=d['name'],\n",
" mode=\"text\",\n",
" textposition=\"middle center\",\n",
" name=d['name'],\n",
" marker=dict(\n",
" color=fillcolor,\n",
" ),\n",
" ))\n",
"\n",
" # Add top-left text with d['end']\n",
" fig.add_trace(go.Scatter\n",
" (\n",
" x=[(x0+0.14+horizontal_gap)],\n",
" y=[y1-0.16],\n",
" text=hex(d['end']),\n",
" mode=\"text\",\n",
" textposition=\"middle center\",\n",
" marker=dict(\n",
" color=fillcolor,\n",
" ),\n",
" showlegend=False,\n",
" ))\n",
"\n",
" # Add bottom-left text with d['end']\n",
" fig.add_trace(go.Scatter\n",
" (\n",
" x=[(x0+0.14+horizontal_gap)],\n",
" y=[y0+0.14],\n",
" text=hex(d['start']),\n",
" mode=\"text\",\n",
" textposition=\"middle center\",\n",
" marker=dict(\n",
" color=fillcolor,\n",
" ),\n",
" showlegend=False,\n",
" ))\n",
"\n",
"fig.update_xaxes(\n",
" range=[0, 5],\n",
" tickvals=[0, 1, 2, 3, 4, 5],\n",
")\n",
"\n",
"start_values = data['start'].sort_values()\n",
"end_values = data['end'].sort_values()\n",
"\n",
"labels = []\n",
"\n",
"for i, d in data.iterrows():\n",
" if i == 0:\n",
" labels.append(f'{hex(start_values.iloc[i])}')\n",
" elif i == len(data)-1:\n",
" labels.append(f'{hex(end_values.iloc[i])}')\n",
" else:\n",
" labels.append(f'{hex(start_values.iloc[i])}<br>{hex(end_values.iloc[i-1])}')\n",
"\n",
"tickpointers = [i for i in range(len(data))]\n",
"\n",
"fig.update_yaxes(\n",
" # tickvals=[i for i in range(len(data)+1)], \n",
" tickvals = tickpointers,\n",
" # ticktext= labels,\n",
" griddash=\"longdashdot\",\n",
" gridwidth=0,\n",
" gridcolor=\"black\",\n",
" showgrid=False,\n",
" showticklabels=True,\n",
" autorange='reversed',\n",
")\n",
"\n",
"fig.update_xaxes(\n",
" showgrid=False,\n",
" showticklabels=False,\n",
")\n",
"\n",
"fig.update_layout(\n",
" width=1200,\n",
" height=1200,\n",
" autosize=True,\n",
" margin=dict(l=200, r=20, t=20, b=20),\n",
" font=dict(\n",
" size=18,\n",
" ),\n",
" # Legend being the name of the function\n",
" legend_title_text=\"Function/Locations\",\n",
")\n",
"\n",
"fig.show()"
]
} }
], ],
"metadata": { "metadata": {

View File

@ -623,6 +623,19 @@ class ExynosDevice():
assert self.usb_read(0x200) == b"PONG", "Failed to jump back to debugger" assert self.usb_read(0x200) == b"PONG", "Failed to jump back to debugger"
print(f'Jumped to {hex(address)} and back') print(f'Jumped to {hex(address)} and back')
def get_all_special_regs(self):
"""
Get all special registers from the device.
"""
self.cd.fetch_special_regs()
# Get all valeus from self.cd.arch_dbg.state
self.cd.arch_dbg.state.print_ctx()
pass
def debugger_boot(self): def debugger_boot(self):
""" """
@ -742,15 +755,13 @@ class ExynosDevice():
TTBR0_EL3 = 0x02035600 # Zeroed out TTBR0_EL3 = 0x02035600 # Zeroed out
# Modifies/disables setting up MMU (but is set up eventually) -> MMU says 0x0 instead of 0x1, but still little access (and proper USB recovyer boot!?) # Modifies/disables setting up MMU (but is set up eventually) -> MMU says 0x0 instead of 0x1, but still little access (and proper USB recovyer boot!?)
# self.cd.memwrite_region(0x020244e8, struct.pack('>I', 0x1f0c00f1)) # Change check to always false
# Overwrite jump back at 0202f810
# self.cd.memwrite_region(0x020242a8, struct.pack('>I', 0x568f0094)) # Last succesful jump back to debugger, while still having access to 0x02035600
# self.cd.memwrite_region(0x02032008, struct.pack('>I', 0x1f2003d5)) # Overwrite MAIR to NOP # self.cd.memwrite_region(0x02032008, struct.pack('>I', 0x1f2003d5)) # Overwrite MAIR to NOP
# self.cd.memwrite_region(0x0203203c, struct.pack('>I', 0xf1570094)) # Return to debugger. (not working, it continues booting..) # self.cd.memwrite_region(0x0202ee74, struct.pack('>I', 0x63650094)) # Return to debugger. (not working, it continues booting..)
# self.cd.memwrite_region(0x0203200c, struct.pack('>I', 0xfd570094)) # -> X1=0x18800, X30=0x20241a0. Device crashes when writing here. # self.cd.memwrite_region(0x0202eb74, struct.pack('>I', 0x1f2003d5)) # Change check to always false
# Jump back to debugger, after TTBR0 is no longer accessible
self.cd.memwrite_region(0x020308a4, struct.pack('>I', 0xd75d0014)) # Change check to always false
# Jump into BL31 and execute it # Jump into BL31 and execute it
self.cd.restore_stack_and_jump(0x02024010) self.cd.restore_stack_and_jump(0x02024010)
@ -759,13 +770,46 @@ class ExynosDevice():
time.sleep(2) time.sleep(2)
self.connect_device() self.connect_device()
self.usb_read(0x200) # GiAs self.usb_read(0x200) # GiAs
BL31_ra = self.cd.arch_dbg.state.LR
self.cd.arch_dbg.fetch_special_regs()
print(f'MMU is {hex(self.cd.arch_dbg.state.R_SCTLR_EL3.mmu)} (0x1=enabled, 0x0=disabled)')
# self.cd.arch_dbg.fetch_special_regs() # -> Does not work with original debugger (??). Only with relocated debugger. # self.cd.arch_dbg.fetch_special_regs() # -> Does not work with original debugger (??). Only with relocated debugger.
VBAR_EL3 = self.cd.arch_dbg.state.VBAR_EL3 VBAR_EL3 = self.cd.arch_dbg.state.VBAR_EL3
# Disable MMU and branch to 0x02048000
shellcode=f"""
mrs x0, sctlr_el3
bic x0, x0, #1
msr sctlr_el3, x0
ldr x0, =0x2048000
br x0
"""
shellcode = ks.asm(shellcode, as_bytes=True)[0]
self.cd.memwrite_region(0x02060000, shellcode)
self.cd.jump_to(0x02060000)
time.sleep(1)
self.usb_read(0x200) # GiAs
self.cd.arch_dbg.fetch_special_regs()
# Print status of MMU # Print status of MMU
print(f'MMU is {hex(self.cd.arch_dbg.state.R_SCTLR_EL3.mmu)} (0x1=enabled, 0x0=disabled)') print(f'MMU is {hex(self.cd.arch_dbg.state.R_SCTLR_EL3.mmu)} (0x1=enabled, 0x0=disabled)')
BL31_ra = self.cd.arch_dbg.state.LR
# # Change the values of MAIR_EL3 to a different value
# shellcode=f"""
# mov x0, #0x000000ff
# msr mair_el3, x0
# ldr x0, =0x2048000
# br x0
# """
# shellcode = ks.asm(shellcode, as_bytes=True)[0]
# self.cd.memwrite_region(0x02060000, shellcode)
# self.cd.jump_to(0x02060000)
# time.sleep(1)
# self.usb_read(0x200) # GiAs
# self.cd.arch_dbg.fetch_special_regs()
# print(self.cd.arch_dbg.state.R_MAIR_EL3)
# Again restore bootflow # Again restore bootflow
self.cd.memwrite_region(0x020200dc, p32(hijacked_fun)) self.cd.memwrite_region(0x020200dc, p32(hijacked_fun))

Binary file not shown.