mirror of
https://github.com/bkerler/mtkclient.git
synced 2024-12-03 12:46:56 -05:00
568 lines
19 KiB
Python
568 lines
19 KiB
Python
|
#!/usr/bin/env python3
|
||
|
# (c) B.Kerler 2021
|
||
|
|
||
|
import logging
|
||
|
|
||
|
logger = logging.getLogger(__name__)
|
||
|
# debuglevel=logging.DEBUG
|
||
|
debuglevel = logging.INFO
|
||
|
logging.basicConfig(format='%(funcName)20s:%(message)s', level=debuglevel)
|
||
|
|
||
|
from unicorn import *
|
||
|
from unicorn.arm_const import *
|
||
|
import os
|
||
|
from struct import pack, unpack
|
||
|
from binascii import hexlify
|
||
|
|
||
|
debug = False
|
||
|
|
||
|
|
||
|
import os
|
||
|
import logging
|
||
|
import sys
|
||
|
import argparse
|
||
|
from binascii import hexlify
|
||
|
from struct import pack, unpack
|
||
|
from Library.usblib import usb_class
|
||
|
from Library.utils import LogBase
|
||
|
from Library.utils import print_progress
|
||
|
|
||
|
class Stage2(metaclass=LogBase):
|
||
|
def __init__(self, args, loglevel=logging.INFO):
|
||
|
self.__logger = self.__logger
|
||
|
self.args = args
|
||
|
self.info = self.__logger.info
|
||
|
self.error = self.__logger.error
|
||
|
self.warning = self.__logger.warning
|
||
|
if loglevel == logging.DEBUG:
|
||
|
logfilename = os.path.join("logs", "log.txt")
|
||
|
if os.path.exists(logfilename):
|
||
|
os.remove(logfilename)
|
||
|
fh = logging.FileHandler(logfilename, encoding='utf-8')
|
||
|
self.__logger.addHandler(fh)
|
||
|
self.__logger.setLevel(logging.DEBUG)
|
||
|
else:
|
||
|
self.__logger.setLevel(logging.INFO)
|
||
|
portconfig = [[0x0E8D, 0x0003, -1],[0x0E8D, 0x2000, -1]]
|
||
|
self.cdc = usb_class(portconfig=portconfig, loglevel=loglevel, devclass=10)
|
||
|
|
||
|
def connect(self):
|
||
|
self.cdc.connected = self.cdc.connect()
|
||
|
return self.cdc.connected
|
||
|
|
||
|
def close(self):
|
||
|
if self.cdc.connected:
|
||
|
self.cdc.close()
|
||
|
|
||
|
def readflash(self, type: int, start, length, display=False, filename:str=None):
|
||
|
wf = None
|
||
|
buffer=bytearray()
|
||
|
if filename is not None:
|
||
|
wf=open(filename, "wb")
|
||
|
sectors=(length//0x200)+(1 if length%0x200 else 0)
|
||
|
startsector=(start // 0x200)
|
||
|
# emmc_switch(1)
|
||
|
self.cdc.usbwrite(pack(">I", 0xf00dd00d))
|
||
|
self.cdc.usbwrite(pack(">I", 0x1002))
|
||
|
self.cdc.usbwrite(pack(">I", type))
|
||
|
|
||
|
if display:
|
||
|
print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50)
|
||
|
|
||
|
# kick-wdt
|
||
|
# self.cdc.usbwrite(pack(">I", 0xf00dd00d))
|
||
|
# self.cdc.usbwrite(pack(">I", 0x3001))
|
||
|
|
||
|
bytestoread = sectors * 0x200
|
||
|
bytesread = 0
|
||
|
old = 0
|
||
|
# emmc_read(0)
|
||
|
for sector in range(startsector, sectors):
|
||
|
self.cdc.usbwrite(pack(">I", 0xf00dd00d))
|
||
|
self.cdc.usbwrite(pack(">I", 0x1000))
|
||
|
self.cdc.usbwrite(pack(">I", sector))
|
||
|
tmp = self.cdc.usbread(0x200)
|
||
|
if len(tmp) != 0x200:
|
||
|
self.error("Error on getting data")
|
||
|
return
|
||
|
if display:
|
||
|
prog = sector / sectors * 100
|
||
|
if round(prog, 1) > old:
|
||
|
print_progress(prog, 100, prefix='Progress:',
|
||
|
suffix='Complete, Sector:' + hex((sectors * 0x200) - bytestoread),
|
||
|
bar_length=50)
|
||
|
old = round(prog, 1)
|
||
|
bytesread += len(tmp)
|
||
|
size = min(bytestoread, len(tmp))
|
||
|
if wf is not None:
|
||
|
wf.write(tmp[:size])
|
||
|
else:
|
||
|
buffer.extend(tmp)
|
||
|
bytestoread -= size
|
||
|
if display:
|
||
|
print_progress(100, 100, prefix='Complete: ', suffix=filename, bar_length=50)
|
||
|
if wf is not None:
|
||
|
wf.close()
|
||
|
else:
|
||
|
return buffer[start%0x200:(start%0x200)+length]
|
||
|
|
||
|
def preloader(self, start, length, filename):
|
||
|
sectors=0
|
||
|
if start != 0:
|
||
|
start = (start // 0x200)
|
||
|
if length != 0:
|
||
|
sectors=(length//0x200)+(1 if length%0x200 else 0)
|
||
|
self.info("Reading preloader...")
|
||
|
if self.cdc.connected:
|
||
|
if sectors == 0:
|
||
|
buffer=self.readflash(type=1, start=0, length=0x1000, display=False)
|
||
|
if len(buffer)!=0x1000:
|
||
|
print("Error on reading boot1 area.")
|
||
|
return
|
||
|
if buffer[:9]==b'EMMC_BOOT':
|
||
|
startbrlyt=unpack("<I",buffer[0x10:0x14])[0]
|
||
|
if buffer[startbrlyt:startbrlyt+5]==b"BRLYT":
|
||
|
start=unpack("<I",buffer[startbrlyt+0xC:startbrlyt+0xC+4])[0]
|
||
|
if buffer[start:start+4]==b"MMM\x01":
|
||
|
length=unpack("<I",buffer[start+0x20:start+0x24])[0]
|
||
|
self.readflash(type=1, start=start, length=length, display=True, filename=filename)
|
||
|
print("Done")
|
||
|
return
|
||
|
print("Error on getting preloader info, aborting.")
|
||
|
else:
|
||
|
self.readflash(type=1,start=start,length=length,display=True,filename=filename)
|
||
|
print("Done")
|
||
|
|
||
|
def memread(self, start, length):
|
||
|
bytestoread=length
|
||
|
addr=start
|
||
|
data=b""
|
||
|
pos=0
|
||
|
while bytestoread>0:
|
||
|
size=min(bytestoread,0x200)
|
||
|
self.cdc.usbwrite(pack(">I", 0xf00dd00d))
|
||
|
self.cdc.usbwrite(pack(">I", 0x4000))
|
||
|
self.cdc.usbwrite(pack(">I", addr+pos))
|
||
|
self.cdc.usbwrite(pack(">I", size))
|
||
|
data+=self.cdc.usbread(size)
|
||
|
bytestoread-=size
|
||
|
pos+=size
|
||
|
return data
|
||
|
|
||
|
def memwrite(self, start, data):
|
||
|
if isinstance(data,str):
|
||
|
data=bytes.fromhex(data)
|
||
|
elif isinstance(data,int):
|
||
|
data=pack("<I",data)
|
||
|
bytestowrite=len(data)
|
||
|
addr=start
|
||
|
pos=0
|
||
|
while bytestowrite>0:
|
||
|
size=min(bytestowrite,0x200)
|
||
|
self.cdc.usbwrite(pack(">I", 0xf00dd00d))
|
||
|
self.cdc.usbwrite(pack(">I", 0x4002))
|
||
|
self.cdc.usbwrite(pack(">I", addr+pos))
|
||
|
self.cdc.usbwrite(pack(">I", size))
|
||
|
self.cdc.usbwrite(data[pos:pos+4])
|
||
|
bytestowrite-=size
|
||
|
pos+=size
|
||
|
ack=self.cdc.usbread(4)
|
||
|
if ack==b"\xD0\xD0\xD0\xD0":
|
||
|
return True
|
||
|
else:
|
||
|
return False
|
||
|
|
||
|
def rpmb(self, start, length, filename):
|
||
|
if start == 0:
|
||
|
start=0
|
||
|
else:
|
||
|
start = (start // 0x100)
|
||
|
if length == 0:
|
||
|
sectors=4*1024*1024//0x100
|
||
|
else:
|
||
|
sectors=(length//0x100)+(1 if length%0x100 else 0)
|
||
|
self.info("Reading rpmb...")
|
||
|
|
||
|
self.cdc.usbwrite(pack(">I", 0xf00dd00d))
|
||
|
self.cdc.usbwrite(pack(">I", 0x1002))
|
||
|
self.cdc.usbwrite(pack(">I", 0x1))
|
||
|
|
||
|
# kick-wdt
|
||
|
self.cdc.usbwrite(pack(">I", 0xf00dd00d))
|
||
|
self.cdc.usbwrite(pack(">I", 0x3001))
|
||
|
|
||
|
print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50)
|
||
|
bytesread=0
|
||
|
old=0
|
||
|
bytestoread=sectors*0x100
|
||
|
with open(filename, "wb") as wf:
|
||
|
for sector in range(start, sectors):
|
||
|
self.cdc.usbwrite(pack(">I", 0xf00dd00d))
|
||
|
self.cdc.usbwrite(pack(">I", 0x2000))
|
||
|
self.cdc.usbwrite(pack(">H", sector))
|
||
|
tmp = self.cdc.usbread(0x100)[::-1]
|
||
|
if len(tmp) != 0x100:
|
||
|
self.error("Error on getting data")
|
||
|
return
|
||
|
prog = sector / sectors * 100
|
||
|
if round(prog, 1) > old:
|
||
|
print_progress(prog, 100, prefix='Progress:',
|
||
|
suffix='Complete, Sector:' + hex((sectors * 0x200) - bytestoread),
|
||
|
bar_length=50)
|
||
|
old = round(prog, 1)
|
||
|
bytesread+=0x100
|
||
|
size=min(bytestoread,len(tmp))
|
||
|
wf.write(tmp[:size])
|
||
|
bytestoread -= size
|
||
|
print_progress(100, 100, prefix='Complete: ', suffix=filename, bar_length=50)
|
||
|
print("Done")
|
||
|
|
||
|
st2 = Stage2(None)
|
||
|
|
||
|
def getint(valuestr):
|
||
|
if valuestr=='':
|
||
|
return None
|
||
|
try:
|
||
|
return int(valuestr)
|
||
|
except:
|
||
|
try:
|
||
|
return int(valuestr, 16)
|
||
|
except Exception as err:
|
||
|
pass
|
||
|
return 0
|
||
|
|
||
|
class ARMRegisters(dict):
|
||
|
def __init__(self, mu):
|
||
|
super().__init__()
|
||
|
self.mu = mu
|
||
|
|
||
|
def __setitem__(self, key, value):
|
||
|
if isinstance(key, str):
|
||
|
key = key.casefold()
|
||
|
self.mu.reg_write(eval("UC_ARM_REG_" + key.upper()), value)
|
||
|
super().__setitem__(key, value)
|
||
|
|
||
|
def __getitem__(self, key):
|
||
|
if isinstance(key, str):
|
||
|
key = key.casefold()
|
||
|
value = self.mu.reg_read(eval("UC_ARM_REG_" + key.upper()))
|
||
|
super().__setitem__(key, value)
|
||
|
return super().__getitem__(key)
|
||
|
|
||
|
|
||
|
buffer = bytearray()
|
||
|
data = ""
|
||
|
|
||
|
timer=0
|
||
|
|
||
|
def hook_mem_read(uc, access, address, size, value, user_data):
|
||
|
global st2
|
||
|
global data
|
||
|
global timer
|
||
|
pc = uc.reg_read(UC_ARM_REG_PC)
|
||
|
if 0x10009000 > address > 0x10000000 and not (0x11050000 <= address <= 0x11060000):
|
||
|
value=st2.memread(address,size)
|
||
|
v=unpack("<I",value)[0]
|
||
|
#print("READ of 0x%x at 0x%X, data size = %u, value: 0x%x" % (address, pc, size, v))
|
||
|
uc.mem_write(address,value)
|
||
|
return True
|
||
|
elif 0x11300000 > address > 0x11200000:
|
||
|
value=st2.memread(address,size)
|
||
|
v=unpack("<I",value)[0]
|
||
|
print("READ of 0x%x at 0x%X, data size = %u, value: 0x%x" % (address, pc, size, v))
|
||
|
uc.mem_write(address,value)
|
||
|
return True
|
||
|
elif address > 0x10009000 and not (0x11050000 <= address <= 0x11060000):
|
||
|
value=st2.memread(address,size)
|
||
|
v=unpack("<I",value)[0]
|
||
|
#print("READ of 0x%x at 0x%X, data size = %u, value: 0x%x" % (address, pc, size, v))
|
||
|
uc.mem_write(address,value)
|
||
|
return True
|
||
|
elif address == 0x11002014:
|
||
|
#print("UART0: %08X" % pc)
|
||
|
uc.mem_write(0x11002014,pack("<I",0x20))
|
||
|
return True
|
||
|
elif address == 0x11020014:
|
||
|
#print("UART0: %08X" % pc)
|
||
|
uc.mem_write(0x11020014,pack("<I",0x20))
|
||
|
return True
|
||
|
elif address == 0x11002000:
|
||
|
uc.mem_write(0x11002014,pack("<I",0))
|
||
|
print("UART1 R")
|
||
|
return True
|
||
|
elif address == 0x11003014:
|
||
|
#print("UART0: %08X" % pc)
|
||
|
uc.mem_write(0x11003014,pack("<I",0x20))
|
||
|
return True
|
||
|
elif address == 0x11003000:
|
||
|
uc.mem_write(0x11003014,pack("<I",0))
|
||
|
print("UART1 R")
|
||
|
return True
|
||
|
elif address == 0x11005014:
|
||
|
#print("UART0: %08X" % pc)
|
||
|
uc.mem_write(0x11005014,pack("<I",0x20))
|
||
|
return True
|
||
|
elif address == 0x11005000:
|
||
|
uc.mem_write(0x11005014,pack("<I",0))
|
||
|
print("UART1 R")
|
||
|
return True
|
||
|
elif address == 0x11050014:
|
||
|
#print("UART0: %08X" % pc)
|
||
|
uc.mem_write(0x11050014,pack("<I",0x20))
|
||
|
return True
|
||
|
elif address == 0x11050000:
|
||
|
uc.mem_write(0x11050014,pack("<I",0))
|
||
|
print("UART1 R")
|
||
|
return True
|
||
|
|
||
|
def hook_mem_write(uc, access, address, size, value, user_data):
|
||
|
global buffer
|
||
|
global data
|
||
|
global st2
|
||
|
pc = uc.reg_read(UC_ARM_REG_PC)
|
||
|
if 0x11300000 > address > 0x11200000:
|
||
|
print("WRITE of 0x%x at 0x%X, data size = %u, value: 0x%x" % (address, pc, size, value))
|
||
|
st2.memwrite(address, value)
|
||
|
uc.mem_write(address, pack("<I", value))
|
||
|
return True
|
||
|
elif address > 0x10000000 and not (0x11050000 <= address <= 0x11060000):
|
||
|
#print("WRITE of 0x%x at 0x%X, data size = %u, value: 0x%x" % (address, pc, size, value))
|
||
|
st2.memwrite(address,value)
|
||
|
uc.mem_write(address,pack("<I",value))
|
||
|
return True
|
||
|
elif address == 0x11020000:
|
||
|
r0 = uc.reg_read(UC_ARM_REG_R0)
|
||
|
if r0==0xa:
|
||
|
print("UART: "+buffer.decode('utf-8'))
|
||
|
data+=buffer.decode('utf-8')
|
||
|
buffer=bytearray()
|
||
|
else:
|
||
|
buffer.append(r0)
|
||
|
return True
|
||
|
elif address == 0x11050000:
|
||
|
r0 = uc.reg_read(UC_ARM_REG_R0)
|
||
|
if r0==0xd:
|
||
|
print("UART: "+buffer.decode('utf-8'))
|
||
|
data+=buffer.decode('utf-8')
|
||
|
buffer=bytearray()
|
||
|
else:
|
||
|
buffer.append(r0)
|
||
|
return True
|
||
|
elif address == 0x11002000:
|
||
|
r0 = uc.reg_read(UC_ARM_REG_R0)
|
||
|
if r0==0xa:
|
||
|
print("UART: "+buffer.decode('utf-8'))
|
||
|
data+=buffer.decode('utf-8')
|
||
|
buffer=bytearray()
|
||
|
else:
|
||
|
buffer.append(r0)
|
||
|
return True
|
||
|
elif address == 0x11003000:
|
||
|
r0 = uc.reg_read(UC_ARM_REG_R0)
|
||
|
if r0==0xa:
|
||
|
print("UART: "+buffer.decode('utf-8'))
|
||
|
data+=buffer.decode('utf-8')
|
||
|
buffer=bytearray()
|
||
|
else:
|
||
|
buffer.append(r0)
|
||
|
return True
|
||
|
elif address == 0x11005000:
|
||
|
r0 = uc.reg_read(UC_ARM_REG_R0)
|
||
|
if r0==0xa:
|
||
|
print("UART: "+buffer.decode('utf-8'))
|
||
|
data+=buffer.decode('utf-8')
|
||
|
buffer=bytearray()
|
||
|
else:
|
||
|
buffer.append(r0)
|
||
|
return True
|
||
|
#else:
|
||
|
# print("Write : %08X - %08X" % (address, value))
|
||
|
return True
|
||
|
|
||
|
|
||
|
def hook_code(uc, access, address, size):
|
||
|
global debug
|
||
|
pc = uc.reg_read(UC_ARM_REG_PC)
|
||
|
#print("PC: + " + hex(pc))
|
||
|
if pc == 0x70095364:
|
||
|
keyslot0 = uc.mem_read(0x701953CC, 0x20)
|
||
|
keyslot1 = uc.mem_read(0x701953EC, 0x20)
|
||
|
keyslot2 = uc.mem_read(0x7019540C, 0x20)
|
||
|
print("Keyslot0: " + hexlify(keyslot0).decode('utf-8'))
|
||
|
print("Keyslot1: " + hexlify(keyslot1).decode('utf-8'))
|
||
|
print("Keyslot2: " + hexlify(keyslot2).decode('utf-8'))
|
||
|
elif pc == 0x70094A5C: # sha256_write
|
||
|
lr = uc.reg_read(UC_ARM_REG_LR)
|
||
|
r1 = uc.reg_read(UC_ARM_REG_R1)
|
||
|
r2 = uc.reg_read(UC_ARM_REG_R2)
|
||
|
s1 = uc.mem_read(r1, r2)
|
||
|
print("sha256_write")
|
||
|
print("lr: " + hex(lr))
|
||
|
print(f"r1: {hex(r1)} " + hexlify(s1).decode('utf-8'))
|
||
|
print("r2: " + hex(r2) + "\n")
|
||
|
elif pc == 0x70094E3C: # kdflib_get_huk
|
||
|
lr = uc.reg_read(UC_ARM_REG_LR)
|
||
|
r0 = uc.reg_read(UC_ARM_REG_R0)
|
||
|
print("kdflib_get_huk")
|
||
|
print("klr: " + hex(lr))
|
||
|
print("kr0: " + hex(r0))
|
||
|
elif pc == 0x70095240:
|
||
|
lr = uc.reg_read(UC_ARM_REG_LR)
|
||
|
r0 = uc.reg_read(UC_ARM_REG_R0)
|
||
|
r4 = uc.reg_read(UC_ARM_REG_R4)
|
||
|
print("hmac_sha256")
|
||
|
print("hlr: " + hex(lr))
|
||
|
print("hr0: " + hex(r0))
|
||
|
print("hr4: " + hex(r4))
|
||
|
elif pc == 0x70087430: # memcpy
|
||
|
lr = uc.reg_read(UC_ARM_REG_LR)
|
||
|
r0 = uc.reg_read(UC_ARM_REG_R0)
|
||
|
r1 = uc.reg_read(UC_ARM_REG_R0)
|
||
|
r2 = uc.reg_read(UC_ARM_REG_R0)
|
||
|
print("memcpy")
|
||
|
print("lr: " + hex(lr))
|
||
|
print("r0: " + hex(r0))
|
||
|
print("r1: " + hex(r1))
|
||
|
print("r2: " + hex(r2))
|
||
|
elif pc == 0x70095084:
|
||
|
lr = uc.reg_read(UC_ARM_REG_LR)
|
||
|
print("hmac_init")
|
||
|
print("lr: " + hex(lr))
|
||
|
elif pc == 0x70094CF8:
|
||
|
lr = uc.reg_read(UC_ARM_REG_LR)
|
||
|
r1 = uc.reg_read(UC_ARM_REG_R1)
|
||
|
debug = r1
|
||
|
print("sha_finish")
|
||
|
print("lr: " + hex(lr))
|
||
|
print("r1: " + hex(r1))
|
||
|
elif pc == 0x70094DB8:
|
||
|
lr = uc.reg_read(UC_ARM_REG_LR)
|
||
|
r1 = debug
|
||
|
s1 = uc.mem_read(r1, 0x20)
|
||
|
print("sha_finish2")
|
||
|
print("lr: " + hex(lr))
|
||
|
print("r1: " + hex(r1))
|
||
|
print("s1: " + hexlify(s1).decode('utf-8'))
|
||
|
|
||
|
# print("PC %08X" % pc)
|
||
|
return True
|
||
|
|
||
|
|
||
|
def hook_mem_invalid(uc, access, address, size, value, user_data):
|
||
|
pc = uc.reg_read(UC_ARM_REG_PC)
|
||
|
if access == UC_MEM_WRITE:
|
||
|
info = ("invalid WRITE of 0x%x at 0x%X, data size = %u, data value = 0x%x" % (address, pc, size, value))
|
||
|
if access == UC_MEM_READ:
|
||
|
info = ("invalid READ of 0x%x at 0x%X, data size = %u" % (address, pc, size))
|
||
|
if access == UC_MEM_FETCH:
|
||
|
info = ("UC_MEM_FETCH of 0x%x at 0x%X, data size = %u" % (address, pc, size))
|
||
|
if access == UC_MEM_READ_UNMAPPED:
|
||
|
info = ("UC_MEM_READ_UNMAPPED of 0x%x at 0x%X, data size = %u" % (address, pc, size))
|
||
|
if access == UC_MEM_WRITE_UNMAPPED:
|
||
|
info = ("UC_MEM_WRITE_UNMAPPED of 0x%x at 0x%X, data size = %u" % (address, pc, size))
|
||
|
if access == UC_MEM_FETCH_UNMAPPED:
|
||
|
info = ("UC_MEM_FETCH_UNMAPPED of 0x%x at 0x%X, data size = %u" % (address, pc, size))
|
||
|
if access == UC_MEM_WRITE_PROT:
|
||
|
info = ("UC_MEM_WRITE_PROT of 0x%x at 0x%X, data size = %u" % (address, pc, size))
|
||
|
if access == UC_MEM_FETCH_PROT:
|
||
|
info = ("UC_MEM_FETCH_PROT of 0x%x at 0x%X, data size = %u" % (address, pc, size))
|
||
|
if access == UC_MEM_FETCH_PROT:
|
||
|
info = ("UC_MEM_FETCH_PROT of 0x%x at 0x%X, data size = %u" % (address, pc, size))
|
||
|
if access == UC_MEM_READ_AFTER:
|
||
|
info = ("UC_MEM_READ_AFTER of 0x%x at 0x%X, data size = %u" % (address, pc, size))
|
||
|
print(info)
|
||
|
return False
|
||
|
|
||
|
|
||
|
def do_generic_emu_setup(mu, reg):
|
||
|
def replace_function(address, callback):
|
||
|
def hook_code(uc, address, size, user_data):
|
||
|
logger.debug(">>> Installed hook at 0x%x, instruction size = 0x%x" % (address, size))
|
||
|
ret = user_data(reg)
|
||
|
uc.reg_write(UC_ARM_REG_R0, ret)
|
||
|
uc.reg_write(UC_ARM_REG_PC, uc.reg_read(UC_ARM_REG_LR))
|
||
|
|
||
|
mu.hook_add(UC_HOOK_CODE, hook_code, user_data=callback, begin=address, end=address)
|
||
|
|
||
|
def monitor_function(address, callback):
|
||
|
def hook_code(uc, address, size, user_data):
|
||
|
logger.debug(">>> Installed monitor at 0x%x, instruction size = 0x%x" % (address, size))
|
||
|
user_data(reg)
|
||
|
|
||
|
mu.hook_add(UC_HOOK_CODE, hook_code, user_data=callback, begin=address, end=address)
|
||
|
|
||
|
def copy_from_user(regs):
|
||
|
pc = reg["LR"]
|
||
|
r0 = reg["R0"]
|
||
|
r1 = reg["R1"]
|
||
|
r2 = reg["R2"]
|
||
|
print("copy_from_user %08X" % pc)
|
||
|
print("r0: %08X" % r0)
|
||
|
print("r1: %08X" % r1)
|
||
|
print("r2: %08X" % r2)
|
||
|
mu.mem_write(r0, mu.mem_read(r1, r2))
|
||
|
return 0
|
||
|
|
||
|
def uthread_get_current(regs):
|
||
|
pc = reg["LR"]
|
||
|
print("uthread_get_current %08X" % pc)
|
||
|
mu.mem_write(0x7000005C + 0x64, pack("<I", 0x70000200))
|
||
|
mu.mem_write(0x70000200 + 0x10, pack("<I", 0x70000400))
|
||
|
return 0x7000005C
|
||
|
|
||
|
def printf(regs):
|
||
|
pc = reg["LR"]
|
||
|
r0 = reg["R0"]
|
||
|
r1 = reg["R1"]
|
||
|
strdat = mu.mem_read(r0)
|
||
|
print(strdat + str(r1))
|
||
|
return 0
|
||
|
|
||
|
# mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||
|
mu.hook_add(UC_HOOK_MEM_INVALID, hook_mem_invalid)
|
||
|
mu.hook_add(UC_HOOK_CODE, hook_code, begin=0, end=-1)
|
||
|
mu.hook_add(UC_HOOK_MEM_READ, hook_mem_read)
|
||
|
mu.hook_add(UC_HOOK_MEM_WRITE, hook_mem_write)
|
||
|
replace_function(0x70082318, uthread_get_current)
|
||
|
replace_function(0x70087E4C, copy_from_user)
|
||
|
replace_function(0x224CD9, printf)
|
||
|
# replace_function(brom_base+br[field][2]-1,usbdl_get_data)
|
||
|
|
||
|
|
||
|
|
||
|
def main():
|
||
|
pfilename = "preloader_k71v1_64_bsp.bin"
|
||
|
|
||
|
with open(pfilename, "rb") as rf:
|
||
|
rf.seek(0x1C)
|
||
|
addr = unpack("<I", rf.read(4))[0]
|
||
|
length = unpack("<I", rf.read(4))[0]
|
||
|
rf.seek(0)
|
||
|
payload = rf.read()
|
||
|
|
||
|
mu = Uc(UC_ARCH_ARM, UC_MODE_ARM)
|
||
|
reg = ARMRegisters(mu)
|
||
|
reg["SP"] = addr - 0x10 # Stack from start
|
||
|
reg["R0"] = 0
|
||
|
emustart = addr // 4096 * 4096
|
||
|
emulen = (length // 4096) * 4096 + (4 * 4096)
|
||
|
mu.mem_map(0x100000, 0x100000)
|
||
|
mu.mem_map(0x11050000, 0x1000)
|
||
|
mu.mem_map(0x11F30000, 0x1000)
|
||
|
mu.mem_map(0x11230000, 0x1000)
|
||
|
mu.mem_map(0x10000000, 0x20000)
|
||
|
mu.mem_map(emustart, emulen) # Map generic memory for payload
|
||
|
mu.mem_write(addr, payload)
|
||
|
|
||
|
if st2.connect():
|
||
|
do_generic_emu_setup(mu, reg)
|
||
|
try:
|
||
|
mu.emu_start(0x21E224 + 1, 0x21E26A, 0, 0)
|
||
|
except:
|
||
|
pass
|
||
|
logger.info("Emulation done.")
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main()
|