added normal boot mode

This commit is contained in:
Eljakim Herrewijnen 2024-08-16 10:11:18 +02:00
parent a8aed2e480
commit 27fd2b00fb
10 changed files with 201 additions and 44 deletions

View File

@ -1,9 +1,9 @@
#Ghidra Lock File
#Fri Aug 09 11:27:43 CEST 2024
#Thu Aug 15 13:43:49 CEST 2024
OS\ Name=Linux
OS\ Version=6.5.0-44-generic
Username=eljakim
Hostname=levith
<META>\ Supports\ File\ Channel\ Locking=Channel Lock
OS\ Architecture=amd64
Timestamp=8/9/24, 11\:27 AM
Timestamp=8/15/24, 1\:43 PM

View File

@ -1,13 +1,17 @@
VERSION=1
/
00000006:8890_bootrom.bin:7f0119bc3142241939494339
0000000a:8890_bootrom.bin.1:7f011a6853998629050259
00000002:8890_bootrom.bin.keep:7f011889d240069673442230
00000008:8890_bootrom_old_bl1:7f011822f30596451841878
/dump
00000009:reloc_debugger.elf:7f0119bd531451643843511
/mib3
00000000:full_boot:7f0118059140616855428589
/s7
00000007:fwbl1.bin:7f011a0d5252765509589854
00000003:sboot.bin.2.bin:7f011ab837995028720085
00000007:bl1.bin:7f011a0d5252765509589854
00000003:bl31.bin:7f011ab837995028720085
00000004:sboot.bin.3.bin:7f011872b8163836628792
00000005:sboot.bin.4.bin:7f011842b8231996037592
NEXT-ID:8
NEXT-ID:b
MD5:d41d8cd98f00b204e9800998ecf8427e

View File

@ -2,6 +2,10 @@ VERSION=1
/
00000006:8890_bootrom.bin:7f0119bc3142241939494339
00000002:8890_bootrom.bin.keep:7f011889d240069673442230
0000000a:8890_bootrom_bl31_loaded:7f011a6853998629050259
00000008:8890_bootrom_old_bl1:7f011822f30596451841878
/dump
00000009:reloc_debugger.elf:7f0119bd531451643843511
/mib3
00000000:full_boot:7f0118059140616855428589
/s7
@ -9,5 +13,5 @@ VERSION=1
00000003:bl31.bin:7f011ab837995028720085
00000004:sboot.bin.3.bin:7f011872b8163836628792
00000005:sboot.bin.4.bin:7f011842b8231996037592
NEXT-ID:8
NEXT-ID:b
MD5:d41d8cd98f00b204e9800998ecf8427e

View File

@ -4,6 +4,7 @@ VERSION=1
00000004:udf_7f011842b8231996037592:7f01190f112184430945139
00000003:udf_7f011872b8163836628792:7f011a9478217161533597
00000001:udf_7f0119bc3142241939494339:7f011abb7142807435236045
00000005:udf_7f011a0d5252765509589854:7f0118e15255467845445248
00000002:udf_7f011ab837995028720085:7f0118cdd8148515697603
NEXT-ID:5
NEXT-ID:6
MD5:d41d8cd98f00b204e9800998ecf8427e

View File

@ -4,7 +4,8 @@ VERSION=1
00000004:udf_7f011842b8231996037592:7f01190f112184430945139
00000003:udf_7f011872b8163836628792:7f011a9478217161533597
00000001:udf_7f0119bc3142241939494339:7f011abb7142807435236045
00000006:udf_7f0119bd531451643843511:7f011a1c131523520933550
00000005:udf_7f011a0d5252765509589854:7f0118e15255467845445248
00000002:udf_7f011ab837995028720085:7f0118cdd8148515697603
NEXT-ID:6
NEXT-ID:7
MD5:d41d8cd98f00b204e9800998ecf8427e

View File

@ -1,2 +1,2 @@
IADD:00000005:/udf_7f011a0d5252765509589854
IDSET:/udf_7f011a0d5252765509589854:7f0118e15255467845445248
IADD:00000006:/udf_7f0119bd531451643843511
IDSET:/udf_7f0119bd531451643843511:7f011a1c131523520933550

View File

@ -0,0 +1,5 @@
# input file argument : sboot.bin - G930W8VLS6CSH1 - sha1sum: 9322ccb4e9b382b8cc67ff9ef989c459a763621f
dd if=$1 of=$1.1.bin skip=0 bs=512 count=16 # 0x2000 @ 0x0
dd if=$1 of=$1.2.bin skip=16 bs=512 count=288 # 0x24000 @ 0x2000
dd if=$1 of=$1.3.bin skip=155648 bs=1 count=158992 # 0x26d10 @ 0x26000
dd if=$1 of=$1.4.bin skip=776 bs=512 count=1672 # 0xD1000 @ 0x61000

View File

@ -21,6 +21,15 @@
"justMyCode": false,
"args": []
},
{
"name": "Run unsecure boot",
"type": "debugpy",
"request": "launch",
"program": "exploit.py",
"console": "integratedTerminal",
"justMyCode": false,
"args": ["--boot"]
},
{
"name": "Debug current file",
"type": "debugpy",

View File

@ -38,6 +38,14 @@ TARGET_OFFSETS = {
"8895": (0x02021800, 0x02020F18, 0x02070000)
}
def wait_for_device():
while usb.core.find(idVendor=0x04e8, idProduct=0x1234) is None:
pass
def wait_disconnect():
while usb.core.find(idVendor=0x04e8, idProduct=0x1234) is not None:
pass
ENDPOINT_BULK_IN = 0x81
ENDPOINT_BULK_OUT = 0x2
@ -82,6 +90,12 @@ class ExynosDevice():
# claim usb interface
self.handle.claimInterface(0)
print(f"Connected device! {hex(self.idVendor)} {hex(self.idProduct)}")
def disconnect(self):
"""Disconnect the device"""
self.handle.releaseInterface(0)
self.handle.close()
self.context.exit()
def write(self, data):
transferred = ctypes.c_int()
@ -128,15 +142,42 @@ class ExynosDevice():
sys.exit(0)
def send_normal(self, payload):
def send_normal_stage(self, payload):
'''
TODO not working
'''
# construct dl_data
payload = struct.pack("<II", 0, len(payload)) #+ (payload + b"\x00" * 2)
transferred = ctypes.c_int()
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, payload, len(payload), ctypes.byref(transferred), 0)
assert res == 0, "Error sending payload"
dpayload = struct.pack("<II", 0, len(payload) + 8 + 2)
dpayload = dpayload + payload + b"\x00" * 2 # add footer
transferred = ctypes.c_int()
for block in range(0, len(dpayload), BLOCK_SIZE):
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, dpayload[block:block + BLOCK_SIZE], len(dpayload[block:block + BLOCK_SIZE]), ctypes.byref(transferred), 0)
assert res == 0, "Error sending payload"
p_ok("Sended stage")
def unsecure_boot(self):
self.exploit(open("../../dump/exynos-usbdl/payloads/Exynos8890_unsecure_boot_usb.bin", "rb").read())
time.sleep(2)
self.connect_device()
# self.send_normal_stage("/home/eljakim/Source/Samsung_S7/source/S7/g930f_latest/g930f_sboot.bin.1.bin")
self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.1.bin", "rb").read())
# wait_disconnect()
time.sleep(2)
self.connect_device()
self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.2.bin", "rb").read())
# wait_disconnect()
time.sleep(2)
self.connect_device()
self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.3.bin", "rb").read())
# wait_disconnect()
time.sleep(2)
self.connect_device()
self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.4.bin", "rb").read())
# self.send_normal_stage(open("../S7/bl1.bin", "rb").read())
# self.send_normal_stage(open("../S7/bl31.bin", "rb").read())
# self.send_normal_stage(open("../S7/sboot.bin.3.bin", "rb").read())
# self.send_normal_stage(open("../S7/sboot.bin.4.bin", "rb").read())
pass
def exploit(self, payload: bytes):
@ -341,8 +382,16 @@ class ExynosDevice():
self.cd.restore_stack_and_jump(0x020c0000)
assert self.usb_read(0x200) == b"GiAs", "Failed to relocate debugger"
self.cd.relocate_debugger(0x020c7000, 0x020c0000, 0x020c4000)
def first_debugger():
debugger = open("/home/eljakim/Source/gupje/source/bin/samsung_s7/debugger.bin", "rb").read()
self.cd.memwrite_region(0x2069000, debugger)
self.cd.restore_stack_and_jump(0x2069000)
assert self.usb_read(0x200) == b"GiAs", "Failed to relocate debugger"
self.cd.relocate_debugger(0x206d000 + 0x1000, 0x2069000, 0x206d000)
relocate_debugger()
# relocate_debugger()
DEBUGGER_ADDR = 0x2069000 #0x020c0000
logger.debug('State after relocating debugger')
self.cd.arch_dbg.state.print_ctx()
@ -354,10 +403,75 @@ class ExynosDevice():
dumped += self.cd.memdump_region(block, 0x200)
return dumped
# dump1 = memdump_imem()
AUTH_BL1 = 0x00012848
def auth_bl1(lr=0x2069000):
# Load the firmware
self.cd.arch_dbg.state.X0 = 1
self.cd.arch_dbg.state.X1 = 1
self.cd.arch_dbg.state.LR = lr #jump back to debugger when finished
self.cd.restore_stack_and_jump(AUTH_BL1)
assert self.usb_read(0x200) == b"GiAs", "Failed to jump back to debugger"
assert self.cd.arch_dbg.state.X0 == 0, "auth_bl1 returned with error!"
BOOT_BL1 = 0x00019310
def boot_bl1(lr=0x2069000):
self.cd.arch_dbg.state.LR = lr
self.cd.restore_stack_and_jump(BOOT_BL1)
assert self.usb_read(0x200) == b"GiAs", "Failed to jump back to debugger"
JUMP_BL1 = 0x000002c0
def jump_bl1(lr):
self.cd.arch_dbg.state.LR = lr
self.cd.restore_stack_and_jump(JUMP_BL1)
# Always hijack rom_usb_download function:
rom_usb_download = self.cd.memdump_region(0x020200dc, 4)
self.cd.memwrite_region(0x020200dc, p32(0x2069000))
# Try loading bl1
bl1 = open("../S7/bl1.bin", "rb").read()
self.cd.memwrite_region(0x02021800, bl1)
self.usb_write(b"FLSH") # Flush cache
self.cd.test_connection()
auth_bl1(DEBUGGER_ADDR)
# boot_bl1(DEBUGGER_ADDR)
self.cd.memwrite_region(0x02022858, self.cd.arch_dbg.sc.branch_absolute(DEBUGGER_ADDR)) # jump to debugger on next stage download
self.cd.memwrite_region(0x020219cc, self.cd.arch_dbg.sc.branch_absolute(DEBUGGER_ADDR))
jump_bl1(DEBUGGER_ADDR)
# Returns on usb_download function
assert self.usb_read(0x200) == b"GiAs", "Failed to jump back to debugger"
self.cd.arch_dbg.state.print_ctx()
dl_ready, next_stage = struct.unpack("<II", self.cd.memdump_region(0x02021518, 8))
bl31 = open("../S7/bl31.bin", "rb").read()
self.cd.memwrite_region(0x02024000, bl31)
self.cd.memwrite_region(0x02021518, p32(1)) # Set dl_ready to 1
self.cd.memwrite_region(0x02021518 + 4 , p32(self.cd.arch_dbg.state.X0))
self.cd.arch_dbg.state.X0 = 0
self.cd.restore_stack_and_jump(0x020219c8)
pass
# assert len(bl31) % 0x200 == 0, "Size needs to be 512 bytes aligned"
# self.cd.memwrite_region(self.cd.arch_dbg.state.X0, p32(147456)) # Update amount of blocks
# self.cd.arch_dbg.state.LR = DEBUGGER_ADDR
# self.cd.restore_stack_and_jump(0x02022a08)
# Patches
# self.cd.memwrite_region(0x02022a08, self.cd.arch_dbg.sc.mov_0_w0_ins + self.cd.arch_dbg.sc.ret_ins) # Overwrite line register to jump back to debugger (see code flow at 0x02021800 +0x10, after the bl1 has been written to memory at this address)
# self.cd.memwrite_region(0x2022948 + 4, self.cd.arch_dbg.sc.branch_absolute(DEBUGGER_ADDR))
# Patch stupid error funciton
# self.usb_write(b"FLSH") # Flush cache
# Download next stage?
lr = self.cd.arch_dbg.state.LR
# self.cd.arch_dbg.state.LR = DEBUGGER_ADDR
pass
# Using keystone, look for each msr instruction (AARCH64, LE)
@ -365,18 +479,9 @@ class ExynosDevice():
# If wanting to modify the binary
# bl1 = bl1[:0x1C23] + b'\xaa' + bl1[0x1C24:]
self.cd.memwrite_region(0x02021800, bl1)
imem1 = memdump_imem()
AUTH_BL1 = 0x00012848
def auth_bl1(lr=0x2069000):
# Load the firmware
self.cd.arch_dbg.state.W0 = 1
self.cd.arch_dbg.state.X1 = 1
self.cd.arch_dbg.state.LR = lr #jump back to debugger when finished
self.cd.restore_stack_and_jump(AUTH_BL1)
assert self.usb_read(0x200) == b"GiAs", "Failed to jump back to debugger"
assert self.cd.arch_dbg.state.X0 == 0, "auth_bl1 returned with error!"
auth_bl1(0x020c0000)
@ -389,28 +494,50 @@ class ExynosDevice():
# Overwrite jump back to the debugger from functions encountered during jump_bl1
# self.cd.memwrite_region(0x02020108, p32(0x020c0000)) # Hijack some weird function, original 0x00005790
self.cd.memwrite_region(0x020200e8, p32(0x020c0000)) # Overwrite line register to jump back to debugger (see code flow at 0x02021800 +0x10, after the bl1 has been written to memory at this address)
self.cd.memwrite_region(0x020200dc, p32(0x020c0000))
def hijack_brom_weird():
print(f"LR = {hex(self.cd.arch_dbg.state.LR - 4)} X0 = {hex(self.cd.arch_dbg.state.X0)}")
print(f"From = {hex(self.cd.arch_dbg.state.LR - 4)} X0 = {hex(self.cd.arch_dbg.state.X0)}")
self.cd.restore_stack_and_jump(0x00000314)
BOOT_BL1 = 0x00019310
def jump_bl1(lr):
self.cd.arch_dbg.state.LR = lr
self.cd.restore_stack_and_jump(BOOT_BL1)
jump_bl1(0x020c0000)
while True:
try:
resp = self.usb_read(0x200)
logging.debug(f'Within jump_bl1. Response: {resp}.')
if self.cd.arch_dbg.state.LR == 0x02022948:
break # ROM will load next stage over USB
hijack_brom_weird()
except:
pass
def handle_weird_brom():
while True:
try:
resp = self.usb_read(0x200)
logging.debug(f'Within jump_bl1. Response: {resp}.')
if self.cd.arch_dbg.state.LR == 0x02022948:
break # ROM will load next stage over USB
hijack_brom_weird()
except Exception as e:
pass
handle_weird_brom()
# Parse pagetables
# self.cd.jump_to(0x2069000)
# assert self.usb_read(0x200) == b"GiAs", "Failed to jump back to debugger"
# self.cd.fetch_special_regs()
# Address to download to
self.cd.memwrite_region(0x02022a08, self.cd.arch_dbg.sc.mov_0_w0_ins + self.cd.arch_dbg.sc.ret_ins)
# testfun(0x2069000)
self.cd.arch_dbg.state.X0 = 1
self.cd.restore_stack_and_jump(self.cd.arch_dbg.state.LR)
self.usb_read(0x200) # GiAs
self.cd.arch_dbg.state.LR = 0x2069000
self.cd.restore_stack_and_jump(0x00000314)
pass
shellcode = f"""
ldr x0, debugger_addr
@ -426,11 +553,11 @@ class ExynosDevice():
# load bl31
bl31 = open("../S7/bl31.bin", "rb").read()
# bl31 = bl31[:0x14] + self.cd.arch_dbg.sc.branch_absolute(0x2069000) + bl31[0x24:] # Overwrite jump back to debugger
# # Write bl31 at 0x02021800 and authenticate
self.cd.memwrite_region(0x02021800, bl31)
auth_bl1(0x020c0000)
# Jump to bl31
@ -490,6 +617,7 @@ class ExynosDevice():
if __name__ == "__main__":
arg = argparse.ArgumentParser("Exynos exploit")
arg.add_argument("--debug", action="store_true", help="Debug USB stack", default=False)
arg.add_argument("--boot", action="store_true", help="Unsecure boot", default=False)
args = arg.parse_args()
exynos = ExynosDevice()
@ -500,6 +628,11 @@ if __name__ == "__main__":
exynos.dump_memory(write=True)
# exynos.usb_debug()
sys.exit(0)
if args.boot:
exynos.unsecure_boot()
sys.exit(0)
stage1 = open("stage1/stage1.bin", "rb").read()
exynos.exploit(stage1)

View File

@ -2,7 +2,7 @@ from ghidra_assistant.ghidra_assistant import GhidraAssistant
if __name__ == "__main__":
# rom = open("S7/rom.bin", 'rb').read()
imem = open("exynos_imem_0x02020000_0x2070000.bin", 'rb').read()
imem = open("/tmp/imem", 'rb').read()
ga = GhidraAssistant()
# ga.ghidra.add_memory(rom, 0x0, True, "ROM")