seperated exynos device from exploit

This commit is contained in:
Eljakim Herrewijnen 2024-12-07 20:59:02 +01:00
parent f905c6d2d3
commit 6492aadd7c
3 changed files with 96 additions and 87 deletions

Binary file not shown.

View File

@ -1,23 +1,4 @@
import struct, sys, usb1, libusb1, ctypes, usb, argparse from exynos import *
from keystone import *
from capstone 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
import os, tqdm, datetime
def p32(x):
return struct.pack("<I", x)
def p8(x):
return struct.pack("<B", x)
def p16(x):
return struct.pack("<H", x)
def p64(x):
return struct.pack("<Q", x)
logger = setup_logger("") #Leave empty to get root logger logger = setup_logger("") #Leave empty to get root logger
logger.setLevel(logging.DEBUG) logger.setLevel(logging.DEBUG)
@ -52,57 +33,9 @@ ENDPOINT_BULK_OUT = 0x2
ks = Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN) ks = Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN)
cs = Cs(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN) cs = Cs(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN)
class ExynosDevice(): class S7Exploit(ExynosDevice):
"""
Class to exploit a Exynos device (8890/8895) using the USB stack.
"""
def __init__(self, idVendor=0x04e8, idProduct=0x1234): def __init__(self, idVendor=0x04e8, idProduct=0x1234):
"""Init with vendor/product IDs""" super().__init__(idVendor, idProduct)
self.idVendor = idVendor
self.idProduct = idProduct
self.target = "8890" # TODO auto detect device
self.connect_device()
def connect_device(self):
"""Setup proper connection, and ensure the connection is alive"""
self.context = usb1.USBContext()
while True:
self.handle = self.context.openByVendorIDAndProductID(
vendor_id=self.idVendor,
product_id=self.idProduct,
skip_on_error=False
)
if self.handle == None:
continue
break
try:
self.handle.getDevice().getSerialNumber()
except Exception as e:
if e.value == usb1.libusb1.LIBUSB_ERROR_TIMEOUT or e.value == usb1.libusb1.LIBUSB_ERROR_IO:
print("Device disconnected / not connected. Reconnect USB?")
sys.exit(1)
else:
raise e
# 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):
"""Write data to the device"""
transferred = ctypes.c_int()
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, data, len(data), ctypes.byref(transferred), 0)
assert(res == 0), "Could not perform bulk transfer"
return res
def send_empty_transfer(self): def send_empty_transfer(self):
"""Send an empty transfer (to not actually write data)""" """Send an empty transfer (to not actually write data)"""
@ -242,21 +175,6 @@ class ExynosDevice():
return return
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): def setup_concrete_device(self, concrete_device : ConcreteDevice):
@ -851,10 +769,11 @@ if __name__ == "__main__":
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)
arg.add_argument("--load_ga", action="store_true", help="Load Gupje debugger", default=False)
arg.add_argument("--MIB3", action="store_true", help="Whether boot is on a MIB3", default=False) arg.add_argument("--MIB3", action="store_true", help="Whether boot is on a MIB3", default=False)
args = arg.parse_args() args = arg.parse_args()
exynos = ExynosDevice() exynos = S7Exploit()
if args.debug: if args.debug:
shellcode = open("../dwc3_test/dwc3.bin", "rb").read() shellcode = open("../dwc3_test/dwc3.bin", "rb").read()
@ -863,7 +782,7 @@ if __name__ == "__main__":
# exynos.usb_debug() # exynos.usb_debug()
sys.exit(0) sys.exit(0)
if args.unsecure_boot: elif args.unsecure_boot:
exynos.unsecure_boot() exynos.unsecure_boot()
sys.exit(0) sys.exit(0)
@ -875,6 +794,9 @@ if __name__ == "__main__":
sys.exit(0) sys.exit(0)
exynos.setup_guppy_debugger() exynos.setup_guppy_debugger()
if args.load_ga:
info("Loaded gupje, exiting")
sys.exit(0)
exynos.dumb_interact() exynos.dumb_interact()
sys.exit(0) sys.exit(0)

87
source/exploit/exynos.py Normal file
View File

@ -0,0 +1,87 @@
import struct, sys, usb1, libusb1, ctypes, usb, argparse
from keystone import *
from capstone 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
import os, tqdm, datetime
def p32(x):
return struct.pack("<I", x)
def p8(x):
return struct.pack("<B", x)
def p16(x):
return struct.pack("<H", x)
def p64(x):
return struct.pack("<Q", x)
class ExynosDevice():
"""
Class to exploit a Exynos device (8890/8895) using the USB stack.
"""
def __init__(self, idVendor=0x04e8, idProduct=0x1234):
"""Init with vendor/product IDs"""
self.idVendor = idVendor
self.idProduct = idProduct
self.target = "8890" # TODO auto detect device
self.connect_device()
def connect_device(self):
"""Setup proper connection, and ensure the connection is alive"""
self.context = usb1.USBContext()
while True:
self.handle = self.context.openByVendorIDAndProductID(
vendor_id=self.idVendor,
product_id=self.idProduct,
skip_on_error=False
)
if self.handle == None:
continue
break
try:
self.handle.getDevice().getSerialNumber()
except Exception as e:
if e.value == usb1.libusb1.LIBUSB_ERROR_TIMEOUT or e.value == usb1.libusb1.LIBUSB_ERROR_IO:
print("Device disconnected / not connected. Reconnect USB?")
sys.exit(1)
else:
raise e
# 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):
"""Write data to the device"""
transferred = ctypes.c_int()
res = libusb1.libusb_bulk_transfer(self.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, data, len(data), ctypes.byref(transferred), 0)
assert(res == 0), "Could not perform bulk transfer"
return res
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]