From 4ab063cc71d3d05d1a7505c45611c8bae502a36e Mon Sep 17 00:00:00 2001 From: Jonathan Herrewijnen Date: Thu, 22 Aug 2024 19:50:46 +0200 Subject: [PATCH] Unable to get firmware loader to return to debugger (yet) --- documentation/exynos_exploit_chain.odg | Bin 0 -> 29120 bytes documentation/source/_ignore/draw_boot.ipynb | 510 ++++++++++-------- .../source/_ignore/stack_and_functions.csv | 12 + requirements.txt | 4 +- source/exploit/exploit.py | 51 +- source/exploit/modify_bin.py | 8 - 6 files changed, 308 insertions(+), 277 deletions(-) create mode 100644 documentation/exynos_exploit_chain.odg create mode 100644 documentation/source/_ignore/stack_and_functions.csv delete mode 100644 source/exploit/modify_bin.py diff --git a/documentation/exynos_exploit_chain.odg b/documentation/exynos_exploit_chain.odg new file mode 100644 index 0000000000000000000000000000000000000000..7e314342858e9706fbd7e028e5129fb33a39a136 GIT binary patch literal 29120 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 XBRque30x2c0", + "0xb4e0
0x64e0", + "0x17848
0x12848", + "0x1e310
0x19310", + "0x211000
0x20c000", + "0x2025f60
0x2020f60", + "0x2026578
0x2021578", + "0x2026800
0x2021800", + "0x206e000
0x2069000", + "0x2070000
0x206b000", + [ + "0x0", + "0x20000", + "0x2c0", + "0x52c0", + "0x64e0", + "0xb4e0", + "0x12848", + "0x17848", + "0x19310", + "0x1e310", + "0x20c000", + "0x211000", + "0x2020f60", + "0x2025f60", + "0x2021578", + "0x2026578", + "0x2021800", + "0x2026800", + "0x2069000", + "0x206e000", + "0x206b000", + "0x2070000" + ] ], "tickvals": [ 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11 + 4.2926829268292686, + 4.963414634146342, + 5.634146341463415, + 6.3048780487804885, + 6.975609756097562, + 7.646341463414636, + 8.31707317073171, + 8.987804878048784, + 9.658536585365857, + 10.329268292682931 ] } } @@ -1212,45 +1279,22 @@ ], "source": [ "import plotly.graph_objects as go\n", - "\n", - "# Sample data structure\n", - "data = [\n", - " {'start': 0x00000000, 'end': 0x00020000, 'name': 'BootROM'},\n", - " {'start': 0x000002c0, 'name': 'BL1 boot entry point'},\n", - " {'start': 0x000064e0, 'name': 'Boot USB function'},\n", - " {'start': 0x00012848, 'name': 'bootrom authentication function'},\n", - " {'start': 0x00019310, 'name': 'BL1 boot function'},\n", - " {'start': 0x02069000, 'name': 'First debugger location'},\n", - " {'end': 0x02070000, 'name': 'End of memory stack'},\n", - " {'start': 0x02021578, 'name': 'Event buffer pointer'},\n", - " {'start': 0x02020f60, 'name': 'Boot USB return address'},\n", - " {'start': 0x02021800, 'name': 'BL1 pointer'},\n", - " {'start': 0x020c0000, 'name': 'Frederic Destination pointer'},\n", - "]\n", - "\n", - "# _evtbuf_ptr: .dword 0x02021578\n", - "# _boot_usb_ra: .dword 0x02020f60\n", - "# _bl1_ptr: .dword 0x02021800\n", - "# _original_ra: .dword 0x00007c68\n", - "# _boot_usb: .dword 0x000064e0\n", - "# _dst_ptr: .dword 0x020c0000\n", - "# _auth_bl1: .dword 0x00012848\n", - "# _jmp_bl1: .dword 0x000002c0\n", + "import random\n", "\n", "# If there is no end, set it to start + 0x1000\n", "for d in data:\n", " if 'end' not in d:\n", - " d['end'] = d['start'] + 0x1000\n", + " d['end'] = d['start'] + 0x5000\n", "\n", "# If there is no start, set it to end - 0x1000\n", "for d in data:\n", " if 'start' not in d:\n", - " d['start'] = d['end'] - 0x1000\n", + " d['start'] = d['end'] - 0x5000\n", "\n", "# Sort the data by start\n", "data = sorted(data, key=lambda x: x['start'])\n", - "\n", - "import random\n", + "total_used_len = sum([d['end']-d['start'] for d in data]) # Length of all blocks described\n", + "tickpointers = []\n", "\n", "def random_color():\n", " return f'#{random.randint(0, 0xFFFFFF):06x}'\n", @@ -1258,33 +1302,46 @@ "# Create a square for each index\n", "fig = go.Figure()\n", "for i, d in enumerate(data):\n", + " if i == 0:\n", + " prev_y = 0\n", + " max_y = (prev_y + ((d['end'] - d['start']) / total_used_len))\n", + " fillcolor = random_color()\n", + "\n", + " if d['Order'] == \"ENTRY\":\n", + " x0 = 0\n", + " else:\n", + " x0 = 0.1\n", + "\n", " fig.add_shape(\n", " type=\"rect\",\n", - " x0=0,\n", - " y0=i,\n", + " x0=x0,\n", + " y0=prev_y * len(data),\n", " x1=0 + 1,\n", - " y1=i+1,\n", + " y1=max_y * len(data),\n", " line=dict(width=2),\n", - " fillcolor=random_color(),\n", + " fillcolor=fillcolor,\n", " opacity=0.5,\n", - " layer=\"below\"\n", + " layer=\"below\",\n", " )\n", "\n", + " tickpoint = [(prev_y + (max_y - prev_y) / 2) * len(data)]\n", + " tickpointers.extend([prev_y * len(data)])\n", + "\n", " fig.add_trace(go.Scatter\n", " (\n", " x=[0.5],\n", - " y=[i+ 0.5],\n", + " y=tickpoint,\n", " text=d['name'],\n", " mode=\"text\",\n", - " textposition=\"middle center\"\n", + " textposition=\"middle center\",\n", + " name=d['name'],\n", + " # Set color to\n", + " marker=dict(\n", + " color=fillcolor,\n", + " ),\n", " ))\n", - "\n", - "fig.update_layout(\n", - " width=800,\n", - " height=1200,\n", - " autosize=True,\n", - " margin=dict(l=200, r=20, t=20, b=20)\n", - ")\n", + " \n", + " prev_y = max_y\n", "\n", "fig.update_xaxes(\n", " range=[0, 1],\n", @@ -1301,59 +1358,38 @@ " elif i == len(labels) - 1:\n", " labelset.append(labels[i])\n", " else:\n", - " labelset.append(f\"{labels[i]} \\n {labels[i+1]}\")\n", - "labelset.append(labels[-1])\n", + " labelset.append(f\"{labels[i+1]}
{labels[i]}\")\n", + "labelset.append(labels)\n", "\n", "fig.update_yaxes(\n", - " tickvals=[i for i in range(len(data)+1)], \n", - " ticktext=labelset\n", + " # tickvals=[i for i in range(len(data)+1)], \n", + " tickvals = tickpointers,\n", + " ticktext=labelset,\n", + " griddash=\"longdashdot\",\n", + " gridwidth=0,\n", + " gridcolor=\"black\",\n", + " showgrid=False,\n", + ")\n", + "\n", + "fig.update_xaxes(\n", + " # Disable ticks\n", + " showticklabels=False,\n", + ")\n", + "\n", + "fig.update_layout(\n", + " width=1000,\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()" ] - }, - { - "cell_type": "code", - "execution_count": 111, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['0x0',\n", - " '0x2c0 - 0x12c0',\n", - " '0x12848 - 0x13848',\n", - " '0x19310 - 0x1a310',\n", - " '0x2069000 - 0x206a000',\n", - " '0x206f000 - 0x2070000']" - ] - }, - "execution_count": 111, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 115, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'0x2070000'" - ] - }, - "execution_count": 115, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "labels[-1]" - ] } ], "metadata": { diff --git a/documentation/source/_ignore/stack_and_functions.csv b/documentation/source/_ignore/stack_and_functions.csv new file mode 100644 index 0000000..0fe150f --- /dev/null +++ b/documentation/source/_ignore/stack_and_functions.csv @@ -0,0 +1,12 @@ +start,end,name,Order,Comment +0,131072,BootROM,, +704,21184,BL1 boot entry point,ENTRY, +25824,46304,Boot USB function,, +75848,96328,bootrom authentication function,, +103184,123664,BL1 boot function,, +2146304,2166784,Frederic Destination pointer,, +33689440,33709920,Boot USB return address,, +33691000,33711480,Event buffer pointer,, +33691648,33712128,BL1 pointer,, +33984512,34004992,First debugger location,, +33992704,34013184,End of memory stack,, diff --git a/requirements.txt b/requirements.txt index 67292be..fdeb438 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,5 +14,7 @@ sphinxcontrib.drawio sphinx_wagtail_theme plotly numpy -nbformat>4.2.0 +nbformat==5.10.4 +pandas +xvfbwrapper #Required for sphinx drawio source/ghidra_assistant/ghidra_assistant-0.0.1-py3-none-any.whl \ No newline at end of file diff --git a/source/exploit/exploit.py b/source/exploit/exploit.py index d351f59..0726320 100644 --- a/source/exploit/exploit.py +++ b/source/exploit/exploit.py @@ -620,12 +620,9 @@ class ExynosDevice(): auth_bl1(DEBUGGER_ADDR) self.usb_write(b"FLSH") # Flush cache hijacked_fun = u32(self.cd.memdump_region(0x020200dc, 4)) - # INSERT YOUR BL1 PATCHES HERE + self.cd.memwrite_region(0x020200dc, p32(DEBUGGER_ADDR)) # hijack ROM_DOWNLOAD_USB for BL31 - self.cd.memwrite_region(0x02021880, self.cd.arch_dbg.sc.branch_absolute(DEBUGGER_ADDR, branch_ins="br")) - - # END jump_bl1(DEBUGGER_ADDR) @@ -642,53 +639,45 @@ class ExynosDevice(): time.sleep(2) self.usb_read(0x200) # GiAs - # lr = self.cd.arch_dbg.state.LR - - - # self.cd.memwrite_region(0x020200dc, p32(hijacked_fun)) # Resore oginal boot flow - - # TODO patch verification - - - # self.cd.memwrite_region(0x0202010c - 52, p32(GADGET_RET0)) - - - # self.cd.memwrite_region(0x02024774, self.cd.arch_dbg.sc.mov_0_w0_ins + self.cd.arch_dbg.sc.ret_ins) # self.cd.arch_dbg.state.LR = DEBUGGER_ADDR # self.cd.arch_dbg.state.X0 = 0x020347f0 # self.cd.arch_dbg.state.X1 = 0 # self.cd.restore_stack_and_jump(0x02030464) self.cd.restore_stack_and_jump(lr) - time.sleep(2) - self.usb_read(0x200) # GiAs - self.cd.memwrite_region(0x02031008, b"ELH") + assert self.usb_read(0x200) == b"GiAs", "Failed to jump back to debugger" + # ====== PATCHES TO BL31 here! ====== + self.cd.memwrite_region(0x02031008, b"ELH") - - # Jump entry BL31 + # Jump into BL31 self.cd.restore_stack_and_jump(0x02024010) - - time.sleep(2) self.connect_device() - # WORKING assert self.usb_read(0x200) == b"GiAs", "Failed to jump back to debugger" + # print(self.cd.memdump_region(0x020200dc, 4)) self.cd.memwrite_region(0x020200dc, p32(hijacked_fun)) #Sets jump/X1 address at X0 0x2048000 -> Entry point of BL2 - self.cd.memwrite_region(0x02020, p32(DEBUGGER_ADDR)) # Restore original boot flow + # Boot mode? Not sure whether its important (related to boot type at function 02023800?) + # self.cd.memwrite_region(0x02020, p32(DEBUGGER_ADDR)) # Restore original boot flow - # Jump into BL2 + # Jump into USB download function + # self.cd.arch_dbg.state.LR = DEBUGGER_ADDR + + # WORKS self.cd.restore_stack_and_jump(hijacked_fun) - # END - - # self.usb_read(0x200) # GiAs - # self.cd.restore_stack_and_jump(hijacked_fun) + + # WORKING UNTIL HERE # ==== Stage 3 BL2 ==== - self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.3.bin", "rb").read()) + BL2_FUN = 0x2048000 + bl2 = open("../S7/g930f_latest/g930f_sboot.bin.3.bin", "rb").read() + # bl2 = bl2[:(0x02052bf4-0x02048000)] + b"00000000" + bl2[(0x02052bf4-0x02048000)+8:] + self.send_normal_stage(bl2) + + # self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.3.bin", "rb").read()) time.sleep(2) self.connect_device() diff --git a/source/exploit/modify_bin.py b/source/exploit/modify_bin.py deleted file mode 100644 index b7195f5..0000000 --- a/source/exploit/modify_bin.py +++ /dev/null @@ -1,8 +0,0 @@ -# Open a binary file and modify it -bl1 = open('../S7/bl1.bin', 'rb').read() - -# Modify the binary file at 1C10 -bl1 = bl1[:0x1C1C] + b'\x48' + bl1[0x1C1D:] - -# Write the modified binary file -open('../S7/bl1_mod.bin', 'wb').write(bl1) \ No newline at end of file