added hw device in the loop emulator
This commit is contained in:
parent
b10e3fc359
commit
a1ab8650bc
@ -6,6 +6,8 @@ from ghidra_assistant.utils.debugger.debugger_archs.ga_arm_thumb import GA_arm_t
|
|||||||
from exploit import *
|
from exploit import *
|
||||||
from keystone import *
|
from keystone import *
|
||||||
from t210 import *
|
from t210 import *
|
||||||
|
from hw_in_the_loop import *
|
||||||
|
from partial_emulation import *
|
||||||
|
|
||||||
ks_arm = Ks(KS_ARCH_ARM, KS_MODE_ARM)
|
ks_arm = Ks(KS_ARCH_ARM, KS_MODE_ARM)
|
||||||
ks_thumb = Ks(KS_ARCH_ARM, KS_MODE_THUMB)
|
ks_thumb = Ks(KS_ARCH_ARM, KS_MODE_THUMB)
|
||||||
@ -447,11 +449,32 @@ def hw_init(cd : "ConcreteDevice"):
|
|||||||
# coldboot()
|
# coldboot()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def relocate_debugger(cd : ConcreteDevice):
|
||||||
|
'''
|
||||||
|
Works, relocates the debugger to the end of IRAM
|
||||||
|
'''
|
||||||
|
reloc = open('/home/eljakim/Source/gupje/source/bin/nvidia_shield_t/debugger_reloc.bin', 'rb').read()
|
||||||
|
cd.memwrite_region(0x4003c000, reloc)
|
||||||
|
cd.restore_stack_and_jump(0x4003c000 | 1)
|
||||||
|
assert cd.read(0x100) == b"GiAs"
|
||||||
|
|
||||||
|
# And relocate the debugger
|
||||||
|
cd.relocate_debugger(0x40011000, 0x4003c000, 0x4003e000)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def device_main(cd : "ConcreteDevice", args):
|
def device_main(cd : "ConcreteDevice", args):
|
||||||
'''
|
'''
|
||||||
Main function that will do execution for the device.
|
Main function that will do execution for the device.
|
||||||
'''
|
'''
|
||||||
cd.test_connection()
|
cd.test_connection()
|
||||||
|
partial_emu = True
|
||||||
|
if partial_emu:
|
||||||
|
relocate_debugger(cd)
|
||||||
|
do_partial_emu(cd)
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
hw_in_the_loop()
|
||||||
hw_init(cd)
|
hw_init(cd)
|
||||||
attempt_boot_bct(cd)
|
attempt_boot_bct(cd)
|
||||||
test_arm_asm(cd)
|
test_arm_asm(cd)
|
||||||
|
BIN
__pycache__/hw_in_the_loop.cpython-310.pyc
Normal file
BIN
__pycache__/hw_in_the_loop.cpython-310.pyc
Normal file
Binary file not shown.
BIN
__pycache__/partial_emulation.cpython-310.pyc
Normal file
BIN
__pycache__/partial_emulation.cpython-310.pyc
Normal file
Binary file not shown.
37
blog/part2.md
Normal file
37
blog/part2.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
```
|
||||||
|
1073803520:b'Checking whether Onsemi FG present \n'
|
||||||
|
1073813020:b'%s(): error code 0x%08x %s\n'
|
||||||
|
1073811068:b'%s(): error code 0x%08x %s\n'
|
||||||
|
1073811120:b'NvTbootI2c: Read failed for slave 0x%02x, offset 0x%02x with error code 0x%08x\n'
|
||||||
|
1073799404:b'[TegraBoot] (version %s)\n'
|
||||||
|
1073799412:b'Processing in cold boot mode\n'
|
||||||
|
1073799416:b'Reset reason: %s\n'
|
||||||
|
1073847520:b'Battery Present\n'
|
||||||
|
1073813020:b'%s(): error code 0x%08x %s\n'
|
||||||
|
1073811068:b'%s(): error code 0x%08x %s\n'
|
||||||
|
1073811120:b'NvTbootI2c: Read failed for slave 0x%02x, offset 0x%02x with error code 0x%08x\n'
|
||||||
|
1073806920:b'Error MAX17048 vcell read failed.\n'
|
||||||
|
1073801444:b'Failed to determine battery voltage\n'
|
||||||
|
1073818392:b'Error getting nvdumper carve out address! Booting normally!\n'
|
||||||
|
1073818500:b'Sdram initialization is successful \n'
|
||||||
|
1073801672:b'PMU BoardId: %d\n'
|
||||||
|
1073843272:b'CPU power rail is up \n'
|
||||||
|
1073813604:b'Performing RAM repair\n'
|
||||||
|
1073843308:b'CPU clock init successful \n'
|
||||||
|
1073863832:b'%s with error 0x%x in %s func at %d line \n'
|
||||||
|
1073863916:b'Command complete wait failed with error 0x%x Interrupt 0x%x\n'
|
||||||
|
1073866976:b'Number of retries left %d\n'
|
||||||
|
1073863832:b'%s with error 0x%x in %s func at %d line \n'
|
||||||
|
1073863916:b'Command complete wait failed with error 0x%x Interrupt 0x%x\n'
|
||||||
|
1073866976:b'Number of retries left %d\n'
|
||||||
|
1073863832:b'%s with error 0x%x in %s func at %d line \n'
|
||||||
|
1073863916:b'Command complete wait failed with error 0x%x Interrupt 0x%x\n'
|
||||||
|
1073866976:b'Number of retries left %d\n'
|
||||||
|
1073867180:b'Send command failed with 0x%x\n'
|
||||||
|
1073870972:b'%s with error 0x%x in %s func at %d line \n'
|
||||||
|
1073870844:b'Identify card failed with 0x%x\n'
|
||||||
|
1073862468:b'%s with error 0x%x in %s func at %d line \n'
|
||||||
|
1073862636:b'Sdmmc Init failed with 0x%x error\n'
|
||||||
|
1073844216:b'Error in %s: 0x%x !\n'
|
||||||
|
1073799640:b'Error is %x \n'
|
||||||
|
```
|
19
hw_in_the_loop.py
Normal file
19
hw_in_the_loop.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import typing
|
||||||
|
|
||||||
|
if typing.TYPE_CHECKING:
|
||||||
|
from GA_debugger import *
|
||||||
|
|
||||||
|
class HWDevice():
|
||||||
|
def __init__(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
class CryptoEngine(HWDevice):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# NvBootSeAesCmacGenerateSubkey
|
||||||
|
# NvBootSeAesEncrypt
|
||||||
|
|
||||||
|
def hw_in_the_loop():
|
||||||
|
|
||||||
|
pass
|
203
partial_emulation.py
Normal file
203
partial_emulation.py
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
import typing, pathlib, struct
|
||||||
|
from ghidra_assistant.utils.archs.arm.arm_emulator import *
|
||||||
|
from ghidra_assistant.ghidra_assistant import GhidraAssistant
|
||||||
|
from ghidra_assistant.concrete_device import ConcreteDevice
|
||||||
|
|
||||||
|
if typing.TYPE_CHECKING:
|
||||||
|
from GA_debugger import *
|
||||||
|
|
||||||
|
acces_str = {
|
||||||
|
UC_MEM_READ : "UC_MEM_READ",
|
||||||
|
UC_MEM_WRITE : "UC_MEM_WRITE",
|
||||||
|
UC_MEM_FETCH : "UC_MEM_FETCH",
|
||||||
|
UC_MEM_READ_UNMAPPED : "UC_MEM_READ_UNMAPPED",
|
||||||
|
UC_MEM_WRITE_UNMAPPED : "UC_MEM_WRITE_UNMAPPED",
|
||||||
|
UC_MEM_FETCH_UNMAPPED : "UC_MEM_FETCH_UNMAPPED",
|
||||||
|
UC_MEM_WRITE_PROT : "UC_MEM_WRITE_PROT",
|
||||||
|
UC_MEM_READ_PROT : "UC_MEM_READ_PROT",
|
||||||
|
UC_MEM_FETCH_PROT : "UC_MEM_FETCH_PROT",
|
||||||
|
UC_MEM_READ_AFTER : "UC_MEM_READ_AFTER",
|
||||||
|
}
|
||||||
|
|
||||||
|
def p8(value):
|
||||||
|
return struct.pack("<B", value)
|
||||||
|
|
||||||
|
class PartialEmu(ARM_Emulator):
|
||||||
|
def __init__(self, init_uc=True) -> None:
|
||||||
|
super().__init__(init_uc)
|
||||||
|
self.log_hw_access = True
|
||||||
|
self.saved_blocks = {}
|
||||||
|
try:
|
||||||
|
self.ghidra = GhidraAssistant()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
self.setup_memory()
|
||||||
|
self.setup_registers()
|
||||||
|
self.setup_hooks()
|
||||||
|
self.apply_patches()
|
||||||
|
|
||||||
|
|
||||||
|
def install_debugger(self, debugger : ConcreteDevice):
|
||||||
|
self.debugger = debugger
|
||||||
|
|
||||||
|
def setup_memory(self):
|
||||||
|
self.bootrom_path = pathlib.Path("bootrom_t124.bin")
|
||||||
|
self.bootrom = self.bootrom_path.read_bytes()
|
||||||
|
self.uc.mem_map(0x100000, page_align_top(len(self.bootrom)), UC_PROT_EXEC | UC_PROT_READ)
|
||||||
|
self.uc.mem_write(0x100000, self.bootrom)
|
||||||
|
|
||||||
|
# map IMEM
|
||||||
|
self.imem_path = pathlib.Path("imem3_bct")
|
||||||
|
self.imem = self.imem_path.read_bytes()
|
||||||
|
self.uc.mem_map(0x40000000, 0x40000, UC_PROT_EXEC | UC_PROT_READ | UC_PROT_WRITE)
|
||||||
|
self.uc.mem_write(0x40000000, self.imem)
|
||||||
|
|
||||||
|
# DRAM
|
||||||
|
DRAM_BASE = 0x80000000
|
||||||
|
DRAM_SIZE = 2 * GB
|
||||||
|
self.uc.mem_map(DRAM_BASE, DRAM_SIZE, UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC)
|
||||||
|
|
||||||
|
def setup_registers(self):
|
||||||
|
self.sp = 0x4000d000
|
||||||
|
self.pc = 0x4000e000
|
||||||
|
self.is_thumb = False
|
||||||
|
|
||||||
|
def hook_unmapped(self, uc, access, address, size, value, user_data):
|
||||||
|
print(f"Unmapped memory access at 0x{address:x} with size {size} and access {acces_str[access]}")
|
||||||
|
pass
|
||||||
|
|
||||||
|
def hook_hw_access(self, uc, access, address, size, value, user_data):
|
||||||
|
if self.log_hw_access:
|
||||||
|
p_info(f"{hex(self.pc)} HW access at 0x{address:x} with size {size} and access {acces_str[access]}")
|
||||||
|
# All unmapped memory is send to the debugger
|
||||||
|
try:
|
||||||
|
if access == UC_MEM_WRITE:
|
||||||
|
if size == 4:
|
||||||
|
self.debugger.memwrite_region(address, p32(value))
|
||||||
|
self.uc.mem_write(address, p32(value))
|
||||||
|
# self.uc.mem_write(address, self.debugger.memdump_region(address, size))
|
||||||
|
elif size == 1:
|
||||||
|
self.debugger.memwrite_region(address, p8(value))
|
||||||
|
self.uc.mem_write(address, p8(value))
|
||||||
|
# self.uc.mem_write(address, self.debugger.memdump_region(address, size))
|
||||||
|
else:
|
||||||
|
raise Exception("Unhandled write!")
|
||||||
|
elif access == UC_MEM_READ:
|
||||||
|
uc.mem_write(address, self.debugger.memdump_region(address, size))
|
||||||
|
else:
|
||||||
|
raise Exception("Not handled!")
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
return True
|
||||||
|
|
||||||
|
def setup_hooks(self):
|
||||||
|
# hook unmapped
|
||||||
|
self.uc.hook_add(UC_HOOK_MEM_WRITE_UNMAPPED | UC_HOOK_MEM_FETCH_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED | UC_HOOK_MEM_UNMAPPED, self.hook_unmapped)
|
||||||
|
|
||||||
|
# 0x6000f000
|
||||||
|
self.uc.mem_map(0x60000000, 0x10000, UC_PROT_READ | UC_PROT_WRITE)
|
||||||
|
self.uc.hook_add(UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE, self.hook_hw_access, begin=0x60000000, end=0x60000000 + 0x10000)
|
||||||
|
|
||||||
|
self.uc.mem_map(0x70000000, 0x100000, UC_PROT_READ | UC_PROT_WRITE)
|
||||||
|
self.uc.hook_add(UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE, self.hook_hw_access, begin=0x70000000, end=0x70000000 + 0x100000)
|
||||||
|
|
||||||
|
self.setup_log_hook()
|
||||||
|
self.setup_hook_blocks()
|
||||||
|
# self.setup_hook_EmmcValidateResponse()
|
||||||
|
|
||||||
|
def apply_patches(self):
|
||||||
|
# Nop out 400101f0 to 0x40010220, maybe this is restricting access to IMEM and ROM?
|
||||||
|
self.sc.mov_0_r0 = self.ks.asm("mov r0, #0", as_bytes=True)[0]
|
||||||
|
# self.uc.mem_write(0x400101e4, self.sc.mov_0_r0 * ((0x40010220 - 0x400101e4) // 4))
|
||||||
|
|
||||||
|
# Patch EMMCVerifyResponse
|
||||||
|
self.sc.bx_lr = self.ks.asm("bx lr", as_bytes=True)[0]
|
||||||
|
# self.uc.mem_write(0x4001dfb0, self.sc.mov_0_r0 + self.sc.bx_lr)
|
||||||
|
pass
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
self.uc.emu_start(self.pc, 0)
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
self.print_ctx(print)
|
||||||
|
pass
|
||||||
|
|
||||||
|
def setup_log_hook(self):
|
||||||
|
UART_LOG_HOOK = 0x4001cadc
|
||||||
|
def hook_log(uc, address, size, user_data):
|
||||||
|
msg = self.read_string(self.R0)
|
||||||
|
try:
|
||||||
|
args = msg.count(b"%")
|
||||||
|
arg_types = []
|
||||||
|
offset = 0
|
||||||
|
for i in range(args):
|
||||||
|
c_offset = msg[offset:].find(b"%")
|
||||||
|
mtype = msg[c_offset:offset + 2]
|
||||||
|
offset += c_offset + 2
|
||||||
|
arg_types.append(mtype)
|
||||||
|
|
||||||
|
def read_msg_var(mtype, addr):
|
||||||
|
if mtype == b"%s":
|
||||||
|
return self.read_string(addr)
|
||||||
|
elif mtype == b"%d":
|
||||||
|
return eval('b"'+ str(addr) +'"')# As int
|
||||||
|
else:
|
||||||
|
return eval('b"'+ hex(addr)[2:] +'"')# As hex
|
||||||
|
|
||||||
|
arg_str = []
|
||||||
|
for i in range(args):
|
||||||
|
if i == 0:
|
||||||
|
arg_str.append(read_msg_var(arg_types[i], self.R1))
|
||||||
|
elif i == 1:
|
||||||
|
arg_str.append(read_msg_var(arg_types[i], self.R2))
|
||||||
|
elif i == 2:
|
||||||
|
arg_str.append(read_msg_var(arg_types[i], self.R3))
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
for i in range(len(arg_str)):
|
||||||
|
offset = msg.find(b"%")
|
||||||
|
msg = msg[:offset] + arg_str[i] + msg[offset + 2:]
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
print(f"{hex(self.LR)} : {msg}")
|
||||||
|
if(b"Sdmmc Read failed" in msg):
|
||||||
|
pass
|
||||||
|
return True
|
||||||
|
self.uc.hook_add(UC_HOOK_CODE, hook_log, begin=UART_LOG_HOOK, end=UART_LOG_HOOK + 1)
|
||||||
|
|
||||||
|
# And patch function to just return
|
||||||
|
self.uc.mem_write(UART_LOG_HOOK, self.ks.asm("bx lr", as_bytes=True)[0])
|
||||||
|
|
||||||
|
def setup_hook_blocks(self):
|
||||||
|
def hook_block(uc, address, size, user_data):
|
||||||
|
# print(f"Block at {hex(self.LR)}")
|
||||||
|
self.saved_blocks[self.LR] = self.get_registers()
|
||||||
|
return True
|
||||||
|
self.uc.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||||
|
|
||||||
|
def setup_interrupt_hook(self):
|
||||||
|
RAISE_INTERRUPT = 0x4001cab8
|
||||||
|
def hook_interrupt(uc, address, size, user_data):
|
||||||
|
print(f"Interrupt at {self.LR}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
self.uc.hook_add(UC_HOOK_CODE, hook_interrupt, begin=RAISE_INTERRUPT, end=RAISE_INTERRUPT + 1)
|
||||||
|
|
||||||
|
def setup_hook_EmmcValidateResponse(self):
|
||||||
|
self.saved_emmc_responses = {}
|
||||||
|
def hook_emmc(uc, address, size, user_data):
|
||||||
|
self.saved_emmc_responses[self.pc] = self.get_registers()
|
||||||
|
return True
|
||||||
|
|
||||||
|
self.uc.hook_add(UC_HOOK_CODE, hook_emmc, begin=0x4001dfb0, end=0x4001e160)
|
||||||
|
|
||||||
|
def do_partial_emu(debugger : ConcreteDevice):
|
||||||
|
emu = PartialEmu()
|
||||||
|
emu.install_debugger(debugger)
|
||||||
|
emu.setup()
|
||||||
|
emu.run()
|
@ -20,12 +20,14 @@ ghidra_assistant/utils/__pycache__/ga_server.cpython-310.pyc,,
|
|||||||
ghidra_assistant/utils/__pycache__/utils.cpython-310.pyc,,
|
ghidra_assistant/utils/__pycache__/utils.cpython-310.pyc,,
|
||||||
ghidra_assistant/utils/archs/__pycache__/asm_utils.cpython-310.pyc,,
|
ghidra_assistant/utils/archs/__pycache__/asm_utils.cpython-310.pyc,,
|
||||||
ghidra_assistant/utils/archs/arm/__pycache__/armT_processor_state.cpython-310.pyc,,
|
ghidra_assistant/utils/archs/arm/__pycache__/armT_processor_state.cpython-310.pyc,,
|
||||||
|
ghidra_assistant/utils/archs/arm/__pycache__/arm_emulator.cpython-310.pyc,,
|
||||||
ghidra_assistant/utils/archs/arm/armT_processor_state.py,sha256=ZdsI6Q9mLv-YZEmJSEwKUmsh7903--nfa-dlhfi8QtQ,9466
|
ghidra_assistant/utils/archs/arm/armT_processor_state.py,sha256=ZdsI6Q9mLv-YZEmJSEwKUmsh7903--nfa-dlhfi8QtQ,9466
|
||||||
|
ghidra_assistant/utils/archs/arm/arm_emulator.py,sha256=Wq7Tyiph3KYmvmMnRG8dl4TFKJEeNP8dtDrm_XpBLew,7798
|
||||||
ghidra_assistant/utils/archs/arm64/__pycache__/arm64_emulator.cpython-310.pyc,,
|
ghidra_assistant/utils/archs/arm64/__pycache__/arm64_emulator.cpython-310.pyc,,
|
||||||
ghidra_assistant/utils/archs/arm64/__pycache__/arm64_processor_state.cpython-310.pyc,,
|
ghidra_assistant/utils/archs/arm64/__pycache__/arm64_processor_state.cpython-310.pyc,,
|
||||||
ghidra_assistant/utils/archs/arm64/__pycache__/asm_arm64.cpython-310.pyc,,
|
ghidra_assistant/utils/archs/arm64/__pycache__/asm_arm64.cpython-310.pyc,,
|
||||||
ghidra_assistant/utils/archs/arm64/__pycache__/uc_emulator.cpython-310.pyc,,
|
ghidra_assistant/utils/archs/arm64/__pycache__/uc_emulator.cpython-310.pyc,,
|
||||||
ghidra_assistant/utils/archs/arm64/arm64_emulator.py,sha256=Ncn3KcxfLgBuhvO6L7S8mLurRZeETnO3uxoc_6XHQd0,17049
|
ghidra_assistant/utils/archs/arm64/arm64_emulator.py,sha256=MtAM0DjxagGJZfN5SQuzKJ2tf7kqcYs4r_9a07pZg9o,17044
|
||||||
ghidra_assistant/utils/archs/arm64/arm64_processor_state.py,sha256=GqKoqwbCDhznJEbIgefvlsTcn6ensMD-q70bQMWsgvo,17633
|
ghidra_assistant/utils/archs/arm64/arm64_processor_state.py,sha256=GqKoqwbCDhznJEbIgefvlsTcn6ensMD-q70bQMWsgvo,17633
|
||||||
ghidra_assistant/utils/archs/arm64/asm_arm64.py,sha256=k96Xp7hEhQWD6lbbmT2bAKuwJCz5VDRF6gx2koMuDW8,2562
|
ghidra_assistant/utils/archs/arm64/asm_arm64.py,sha256=k96Xp7hEhQWD6lbbmT2bAKuwJCz5VDRF6gx2koMuDW8,2562
|
||||||
ghidra_assistant/utils/archs/arm64/misc/MMU/__pycache__/arm64_mmu.cpython-310.pyc,,
|
ghidra_assistant/utils/archs/arm64/misc/MMU/__pycache__/arm64_mmu.cpython-310.pyc,,
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,291 @@
|
|||||||
|
from unicorn.arm_const import *
|
||||||
|
from unicorn import *
|
||||||
|
from capstone import *
|
||||||
|
from keystone import *
|
||||||
|
from ..asm_utils import ShellcodeCrafter
|
||||||
|
from ...utils import *
|
||||||
|
|
||||||
|
class ARM_Emulator:
|
||||||
|
'''
|
||||||
|
Class that will interact with the unicorn engine for emulating ARM code.
|
||||||
|
'''
|
||||||
|
def __init__(self, init_uc = True):
|
||||||
|
if init_uc:
|
||||||
|
self.uc = Uc(UC_ARCH_ARM, UC_MODE_ARM)
|
||||||
|
|
||||||
|
# Disassembler configuration
|
||||||
|
self.md = Cs(CS_ARCH_ARM, CS_MODE_ARM)
|
||||||
|
self.mdT = Cs(CS_ARCH_ARM, CS_MODE_THUMB)
|
||||||
|
self.cs = self.md
|
||||||
|
self.csT = self.mdT
|
||||||
|
self.ks = Ks(KS_ARCH_ARM, KS_MODE_ARM)
|
||||||
|
self.ksT = Ks(KS_ARCH_ARM, KS_MODE_THUMB)
|
||||||
|
self.md.detail = True
|
||||||
|
|
||||||
|
self.setup_shellcode()
|
||||||
|
|
||||||
|
def setup_shellcode(self):
|
||||||
|
self.sc = ShellcodeCrafter(self.ks, self.cs)
|
||||||
|
self.scT = ShellcodeCrafter(self.ksT, self.csT)
|
||||||
|
|
||||||
|
def get_mapping(self, address):
|
||||||
|
for mem in self.uc.mem_regions():
|
||||||
|
if address >= mem[0] and address < mem[1]:
|
||||||
|
return mem
|
||||||
|
return None
|
||||||
|
|
||||||
|
def is_mapped(self, address):
|
||||||
|
if self.get_mapping(address) != None:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def read_string(self, at):
|
||||||
|
if at == 0:
|
||||||
|
return b''
|
||||||
|
s = b''
|
||||||
|
while 1:
|
||||||
|
b = self.uc.mem_read(at, 1)
|
||||||
|
at += 1
|
||||||
|
if b == b'\0':
|
||||||
|
return s
|
||||||
|
s += b
|
||||||
|
return s
|
||||||
|
|
||||||
|
def write_ptr(self, at, ptr):
|
||||||
|
return self.uc.mem_write(at, p32(ptr))
|
||||||
|
|
||||||
|
def read_ptr(self, at):
|
||||||
|
return u32(self.uc.mem_read(at, 4))
|
||||||
|
|
||||||
|
def add_breakpoint(self, at, target_fun):
|
||||||
|
self.uc.hook_add(UC_HOOK_CODE, target_fun, None, at, at + 1)
|
||||||
|
|
||||||
|
def get_registers(self):
|
||||||
|
# X0 - X32
|
||||||
|
return [self.uc.reg_read(x) for x in [UC_ARM_REG_R0, UC_ARM_REG_R1, UC_ARM_REG_R2, UC_ARM_REG_R3, UC_ARM_REG_R4, UC_ARM_REG_R5, UC_ARM_REG_R6, UC_ARM_REG_R7, UC_ARM_REG_R8, UC_ARM_REG_R9, UC_ARM_REG_R10, UC_ARM_REG_R11, UC_ARM_REG_R12, UC_ARM_REG_R13, UC_ARM_REG_R14, UC_ARM_REG_R15, UC_ARM_REG_SP, UC_ARM_REG_LR, UC_ARM_REG_PC]]
|
||||||
|
|
||||||
|
def disasm(self, address = None, dlen=0x80):
|
||||||
|
if not address:
|
||||||
|
address = self.pc
|
||||||
|
instructions = []
|
||||||
|
for instruction in self.md.disasm(self.uc.mem_read(address, dlen), address):
|
||||||
|
instructions.append(instruction)
|
||||||
|
return instructions
|
||||||
|
|
||||||
|
def print_ctx(self, print_fn=p_info):
|
||||||
|
state = f"""
|
||||||
|
PC: 0x{self.PC:8x}\t LR: 0x{self.LR:8x}\t SP: 0x{self.SP:8x}\t FP: 0x{self.FP:8x}\t
|
||||||
|
R0: 0x{self.R0:8x}\t R1: 0x{self.R1:8x}\t R2: 0x{self.R2:8x}\t R3: 0x{self.R3:8x}\t
|
||||||
|
R4: 0x{self.R4:8x}\t R5: 0x{self.R5:8x}\t R6: 0x{self.R6:8x}\t R7: 0x{self.R7:8x}\t
|
||||||
|
R8: 0x{self.R8:8x}\t R9: 0x{self.R9:8x}\tR10: 0x{self.R10:8x}\tR11: 0x{self.R11:8x}\t
|
||||||
|
R12: 0x{self.R12:8x}\tR13: 0x{self.R13:8x}\tR14: 0x{self.R14:8x}\tR15: 0x{self.R15:8x}\t
|
||||||
|
"""
|
||||||
|
print_fn(state)
|
||||||
|
|
||||||
|
# ========= Registers =========
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pc(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_PC)
|
||||||
|
|
||||||
|
@pc.setter
|
||||||
|
def pc(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_PC, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def PC(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_PC)
|
||||||
|
|
||||||
|
@PC.setter
|
||||||
|
def PC(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_PC, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def SP(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_SP)
|
||||||
|
|
||||||
|
@SP.setter
|
||||||
|
def SP(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_SP, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def LR(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_LR)
|
||||||
|
|
||||||
|
@LR.setter
|
||||||
|
def LR(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_LR, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def FP(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_R11)
|
||||||
|
|
||||||
|
@FP.setter
|
||||||
|
def FP(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_R11, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def R0(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_R0)
|
||||||
|
|
||||||
|
@R0.setter
|
||||||
|
def R0(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_R0, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def R1(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_R1)
|
||||||
|
|
||||||
|
@R1.setter
|
||||||
|
def R1(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_R1, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def R2(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_R2)
|
||||||
|
|
||||||
|
@R2.setter
|
||||||
|
def R2(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_R2, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def R3(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_R3)
|
||||||
|
|
||||||
|
@R3.setter
|
||||||
|
def R3(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_R3, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def R4(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_R4)
|
||||||
|
|
||||||
|
@R4.setter
|
||||||
|
def R4(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_R4, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def R5(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_R5)
|
||||||
|
|
||||||
|
@R5.setter
|
||||||
|
def R5(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_R5, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def R6(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_R6)
|
||||||
|
|
||||||
|
@R6.setter
|
||||||
|
def R6(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_R6, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def R7(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_R7)
|
||||||
|
|
||||||
|
@R7.setter
|
||||||
|
def R7(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_R7, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def R8(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_R8)
|
||||||
|
|
||||||
|
@R8.setter
|
||||||
|
def R8(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_R8, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def R9(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_R9)
|
||||||
|
|
||||||
|
@R9.setter
|
||||||
|
def R9(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_R9, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def R10(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_R10)
|
||||||
|
|
||||||
|
@R10.setter
|
||||||
|
def R10(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_R10, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def R11(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_R11)
|
||||||
|
|
||||||
|
@R11.setter
|
||||||
|
def R11(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_R11, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def R12(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_R12)
|
||||||
|
|
||||||
|
@R12.setter
|
||||||
|
def R12(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_R12, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def R13(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_R13)
|
||||||
|
|
||||||
|
@R13.setter
|
||||||
|
def R13(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_R13, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def R14(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_R14)
|
||||||
|
|
||||||
|
@R14.setter
|
||||||
|
def R14(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_R14, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def R15(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_R15)
|
||||||
|
|
||||||
|
@R15.setter
|
||||||
|
def R15(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_R15, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cpsr(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_CPSR)
|
||||||
|
|
||||||
|
@cpsr.setter
|
||||||
|
def cpsr(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_CPSR, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def spsr(self):
|
||||||
|
return self.uc.reg_read(UC_ARM_REG_SPSR)
|
||||||
|
|
||||||
|
@spsr.setter
|
||||||
|
def spsr(self, value):
|
||||||
|
self.uc.reg_write(UC_ARM_REG_SPSR, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def zf(self):
|
||||||
|
return self.cpsr & 0x40000000
|
||||||
|
|
||||||
|
@zf.setter
|
||||||
|
def zf(self, value):
|
||||||
|
if value:
|
||||||
|
self.cpsr |= 0x40000000
|
||||||
|
else:
|
||||||
|
self.cpsr &= ~0x40000000
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_thumb(self):
|
||||||
|
return self.cpsr & 0x20
|
||||||
|
|
||||||
|
@is_thumb.setter
|
||||||
|
def is_thumb(self, value):
|
||||||
|
if value:
|
||||||
|
self.cpsr |= 0x20 # Set the thumb bit
|
||||||
|
else:
|
||||||
|
self.cpsr &= ~0x20 # Clear the thumb bit
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -40,7 +40,7 @@ class ARM64UC_Emulator():
|
|||||||
s = b''
|
s = b''
|
||||||
while 1:
|
while 1:
|
||||||
b = self.uc.mem_read(at, 1)
|
b = self.uc.mem_read(at, 1)
|
||||||
at += 12
|
at += 1
|
||||||
if b == b'\0':
|
if b == b'\0':
|
||||||
return s
|
return s
|
||||||
s += b
|
s += b
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user