started device implementation
This commit is contained in:
parent
a1ab8650bc
commit
59eaf299ad
8
.vscode/launch.json
vendored
8
.vscode/launch.json
vendored
@ -35,6 +35,14 @@
|
||||
"program": "GA_debugger.py",
|
||||
"console": "integratedTerminal",
|
||||
"justMyCode": false
|
||||
},
|
||||
{
|
||||
"name": "Emulate BootROM",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "partial_emulation.py",
|
||||
"console": "integratedTerminal",
|
||||
"justMyCode": false
|
||||
}
|
||||
]
|
||||
}
|
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
import typing, pathlib, struct
|
||||
import typing, pathlib, struct, argparse
|
||||
from ghidra_assistant.utils.archs.arm.arm_emulator import *
|
||||
from ghidra_assistant.ghidra_assistant import GhidraAssistant
|
||||
from ghidra_assistant.concrete_device import ConcreteDevice
|
||||
@ -22,19 +22,120 @@ acces_str = {
|
||||
def p8(value):
|
||||
return struct.pack("<B", value)
|
||||
|
||||
class PartialEmu(ARM_Emulator):
|
||||
def __init__(self, init_uc=True) -> None:
|
||||
class TegraDevice():
|
||||
BASE = 0x0
|
||||
SIZE = 0x1000
|
||||
NAME = "Generic Tegra Device"
|
||||
NV_ADDRESS_MAP_CLK_RST_BASE = 0x60006000
|
||||
CLK_RST_CONTROLLER_MISC_CLK_ENB_0 = NV_ADDRESS_MAP_CLK_RST_BASE + 0x48
|
||||
|
||||
def __init__(self, emulator : "TegraEmulator") -> None:
|
||||
self.emulator = emulator
|
||||
self.fuses_visible = 0
|
||||
|
||||
def read(self, address, size):
|
||||
if address == TegraDevice.CLK_RST_CONTROLLER_MISC_CLK_ENB_0:
|
||||
self.emulator.write_ptr(TegraDevice.CLK_RST_CONTROLLER_MISC_CLK_ENB_0, self.fuses_visible)
|
||||
return True
|
||||
raise NotImplemented
|
||||
|
||||
def write(self, address, data):
|
||||
if address == TegraDevice.CLK_RST_CONTROLLER_MISC_CLK_ENB_0:
|
||||
self.fuses_visible = data
|
||||
return True
|
||||
raise NotImplemented
|
||||
|
||||
class FuseDevice(TegraDevice):
|
||||
BASE = 0x7000F000
|
||||
SIZE = 0x1000
|
||||
NAME = "Fuse"
|
||||
FUSE_ODM_INFO_0 = BASE + 0x99c
|
||||
FUSE_FUSEADDR_0 = BASE + 0x804
|
||||
FUSE_FUSECTRL_0 = BASE + 0x800
|
||||
CMD_READ = 1
|
||||
CMD_IDLE = 0
|
||||
FUSE_DAT = BytesIO()
|
||||
def __init__(self, emulator: "TegraEmulator") -> None:
|
||||
super().__init__(emulator)
|
||||
self.fuse_ctr_cmd = 0xc0040000
|
||||
self.fuse_addr = 0x0
|
||||
|
||||
def read(self, address, size):
|
||||
if address == FuseDevice.FUSE_ODM_INFO_0:
|
||||
self.emulator.write_ptr(FuseDevice.FUSE_ODM_INFO_0, 2)
|
||||
elif address == FuseDevice.FUSE_FUSECTRL_0:
|
||||
# get last int from fuse_ctr_cmd
|
||||
cmd = self.fuse_ctr_cmd & 0xffffffff
|
||||
if cmd == FuseDevice.CMD_READ:
|
||||
# Handle read
|
||||
|
||||
# Set idle, set last byte of cmd to 0
|
||||
self.fuse_ctr_cmd = cmd & 0xffffff00
|
||||
self.emulator.write_ptr(FuseDevice.FUSE_FUSECTRL_0, self.fuse_ctr_cmd)
|
||||
|
||||
self.emulator.write_ptr(FuseDevice.FUSE_FUSECTRL_0, self.fuse_ctr_cmd)
|
||||
else:
|
||||
raise NotImplemented
|
||||
return True
|
||||
|
||||
def write(self, address, value):
|
||||
if address == FuseDevice.FUSE_FUSEADDR_0:
|
||||
self.fuse_addr = value
|
||||
elif address == FuseDevice.FUSE_FUSECTRL_0:
|
||||
self.emulator.write_ptr(FuseDevice.FUSE_FUSECTRL_0, value)
|
||||
self.fuse_ctr_cmd = value
|
||||
else:
|
||||
raise NotImplemented
|
||||
return True
|
||||
pass
|
||||
|
||||
class TimerDevice(TegraDevice):
|
||||
BASE = 0x60005000
|
||||
SIZE = 0x1000
|
||||
NAME = "Timer"
|
||||
READ_TIME_OFFSET = BASE + 0x10
|
||||
def __init__(self, emulator: "TegraEmulator") -> None:
|
||||
super().__init__(emulator)
|
||||
|
||||
def read(self, address, size):
|
||||
if address == TimerDevice.READ_TIME_OFFSET:
|
||||
val = int(time.clock_gettime_ns(0)/1000) & 0xffffffff
|
||||
self.emulator.write_ptr(TimerDevice.READ_TIME_OFFSET, val)
|
||||
return True
|
||||
|
||||
class EmmcDevice(TegraDevice):
|
||||
BASE = 0x700b0000
|
||||
SIZE = 0x1000
|
||||
NAME = "Emmc"
|
||||
def __init__(self, emulator: "TegraEmulator") -> None:
|
||||
super().__init__(emulator)
|
||||
|
||||
class CryptoDevice(TegraDevice):
|
||||
BASE = 0x70012000
|
||||
SIZE = 0x1000
|
||||
NAME = "Crypto"
|
||||
def __init__(self, emulator: "TegraEmulator") -> None:
|
||||
super().__init__(emulator)
|
||||
|
||||
|
||||
|
||||
class TegraEmulator(ARM_Emulator):
|
||||
def __init__(self, hw_itm=True, init_uc=True) -> None:
|
||||
super().__init__(init_uc)
|
||||
self.log_hw_access = True
|
||||
self.hw_itm = hw_itm
|
||||
self.saved_blocks = {}
|
||||
try:
|
||||
self.ghidra = GhidraAssistant()
|
||||
except:
|
||||
pass
|
||||
|
||||
def setup(self):
|
||||
def setup(self, target="bootrom"):
|
||||
self.target = target
|
||||
self.setup_memory()
|
||||
self.setup_registers()
|
||||
if not self.hw_itm:
|
||||
self.setup_devices()
|
||||
self.setup_hooks()
|
||||
self.apply_patches()
|
||||
|
||||
@ -49,9 +150,12 @@ class PartialEmu(ARM_Emulator):
|
||||
self.uc.mem_write(0x100000, self.bootrom)
|
||||
|
||||
# map IMEM
|
||||
self.uc.mem_map(0x40000000, 0x40000, UC_PROT_EXEC | UC_PROT_READ | UC_PROT_WRITE)
|
||||
if self.target == "bootrom":
|
||||
pass
|
||||
else:
|
||||
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
|
||||
@ -59,67 +163,186 @@ class PartialEmu(ARM_Emulator):
|
||||
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):
|
||||
def setup_registers(self, target="bootrom"):
|
||||
if self.target == "bootrom":
|
||||
self.pc = 0x100000 | 1
|
||||
self.sp = 0x4000d000
|
||||
self.is_thumb = True
|
||||
else:
|
||||
self.sp = 0x4000d000
|
||||
self.pc = 0x4000e000
|
||||
self.is_thumb = False
|
||||
|
||||
def setup_devices(self):
|
||||
self.devices = {}
|
||||
self.devices['fuse'] = FuseDevice(self)
|
||||
self.devices['timer'] = TimerDevice(self)
|
||||
self.devices['emmc'] = EmmcDevice(self)
|
||||
self.devices['crypto'] = CryptoDevice(self)
|
||||
self.devices['tegra'] = TegraDevice(self) # For all other devices
|
||||
|
||||
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]}")
|
||||
def hook_mem_access(self, uc, access, address, size, value, user_data):
|
||||
# Hook all memory accesses
|
||||
# if self.log_hw_access:
|
||||
# p_info(f"{hex(self.pc)} HW access at 0x{address:x} with size {size}, value={hex(value)} and access {acces_str[access]}")
|
||||
|
||||
# Try and keep memory in sync with target device
|
||||
|
||||
if access == UC_MEM_WRITE:
|
||||
self.debugger.memwrite_region(address, self.uc.mem_read(address, size))
|
||||
if access == UC_MEM_READ:
|
||||
self.uc.mem_write(address, self.debugger.memdump_region(address, size))
|
||||
|
||||
pass
|
||||
|
||||
def hw_itm_handle(self, access, address, size, value):
|
||||
# All unmapped memory is send to the debugger
|
||||
if self.log_hw_access:
|
||||
if access == UC_MEM_READ:
|
||||
val = self.debugger.memdump_region(address, size)
|
||||
if len(val) == 4:
|
||||
val = struct.unpack("<I", val)[0]
|
||||
elif len(val) == 1:
|
||||
val = struct.unpack("<B", val)[0]
|
||||
p_info(f"{hex(self.pc)} READ at 0x{address:x} with size {size} value={hex(val)} | {hex(address)} <- {hex(val)}")
|
||||
elif access == UC_MEM_WRITE:
|
||||
p_info(f"{hex(self.pc)} WRITE at 0x{address:x} with size {size} value={hex(value)} | {hex(address)} -> {hex(value)}")
|
||||
try:
|
||||
if address == 0x70012800:
|
||||
# self.ghidra.ghidra.set_background_color(self.saved_blocks)
|
||||
sys.exit(0)
|
||||
pass
|
||||
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, 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.debugger.memwrite_io(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))
|
||||
if size == 1:
|
||||
pass
|
||||
self.uc.mem_write(address, self.debugger.memdump_region(address, size))
|
||||
else:
|
||||
raise Exception("Not handled!")
|
||||
except Exception as e:
|
||||
print(e)
|
||||
sys.exit(0)
|
||||
pass
|
||||
return True
|
||||
|
||||
def get_device_at(self, address):
|
||||
for devname in self.devices:
|
||||
dev = self.devices[devname]
|
||||
if address >= dev.BASE and address < dev.BASE + dev.SIZE:
|
||||
return dev
|
||||
return self.devices['tegra']
|
||||
# raise Exception(f"No device found at address {hex(address)} pc={hex(sef.pc)}")
|
||||
|
||||
def hw_emulation_handle(self, access, address, size, value):
|
||||
dev = self.get_device_at(address)
|
||||
print(f"Device={dev.NAME} pc={hex(self.pc)} target=0x{address:x} size={size} access={acces_str[access]}")
|
||||
if access == UC_MEM_READ:
|
||||
dev.read(address, size)
|
||||
elif access == UC_MEM_WRITE:
|
||||
dev.write(address, value)
|
||||
return True
|
||||
|
||||
def hook_hw_access(self, uc, access, address, size, value, user_data):
|
||||
if self.hw_itm:
|
||||
return self.hw_itm_handle(access, address, size, value)
|
||||
|
||||
return self.hw_emulation_handle(access, address, size, value)
|
||||
|
||||
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.mem_map(0x60000000, 0x20000, 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)
|
||||
|
||||
|
||||
#ROM
|
||||
# self.uc.hook_add(UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE, self.hook_mem_access, self, 0x100000, 0x100000 + len(self.bootrom))
|
||||
#IMEM access
|
||||
# self.uc.hook_add(UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE, self.hook_mem_access, self, 0x40000000, 0x40000000 + 0x40000)
|
||||
# DRAM
|
||||
# self.uc.hook_add(UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE, self.hook_mem_access, self, 0x80000000, 0x80000000 + 2 * GB)
|
||||
if self.target == "bootrom":
|
||||
self.setup_warmboot_hook()
|
||||
self.setup_hook_blocks()
|
||||
self.setup_rcm_hooks()
|
||||
else:
|
||||
self.setup_log_hook()
|
||||
self.setup_hook_blocks()
|
||||
# self.setup_hook_EmmcValidateResponse()
|
||||
|
||||
def setup_coldboot_hook(self):
|
||||
def hook_coldboot(uc, address, size, user_data):
|
||||
logging.info(f"Reached coldboot target.")
|
||||
self.print_ctx()
|
||||
return True
|
||||
self.uc.hook_add(UC_HOOK_CODE, hook_coldboot, begin=0x0010145e, end=0x0010145e + 1)
|
||||
|
||||
def setup_rcm_hooks(self):
|
||||
def hook_rcm(uc, address, size, user_data):
|
||||
self.R0 = 0
|
||||
self.R1 = 0
|
||||
return True
|
||||
self.uc.hook_add(UC_HOOK_CODE, hook_rcm, begin=0x00101414, end=0x00101414 + 1)
|
||||
|
||||
def setup_warmboot_hook(self):
|
||||
def hook_warmboot(uc, address, size, user_data):
|
||||
logging.info(f"Hooking warmboot, forcing coldboot.")
|
||||
self.R0 = 0
|
||||
return True
|
||||
self.uc.hook_add(UC_HOOK_CODE, hook_warmboot, begin=0x00101f3a, end=0x00101f3a + 1)
|
||||
|
||||
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]
|
||||
|
||||
bx_lr_thumb = self.ksT.asm("bx lr", as_bytes=True)[0]
|
||||
movs_0_r0_thumb = self.ksT.asm("movs r0, #0", as_bytes=True)[0]
|
||||
# self.uc.mem_write(0x4001dfb0, self.sc.mov_0_r0 + self.sc.bx_lr)
|
||||
if self.target == "bootrom":
|
||||
#NvBootClocksIsPllStable, ret
|
||||
# self.uc.mem_write(0x00101730, bx_lr_thumb)
|
||||
# # NvBootClocksStartPll
|
||||
self.uc.mem_write(0x00101866, bx_lr_thumb)
|
||||
# NvBootClocksPllDivRstCtrl
|
||||
self.uc.mem_write(0x001016ce, bx_lr_thumb)
|
||||
|
||||
#usb init?
|
||||
self.uc.mem_write(0x00103bf4, bx_lr_thumb)
|
||||
|
||||
#SE engine always ready
|
||||
# self.uc.mem_write(0x00102b24, movs_0_r0_thumb)
|
||||
|
||||
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.uc.emu_start(self.pc, 0)
|
||||
pass
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
self.print_ctx(print)
|
||||
@ -173,12 +396,19 @@ class PartialEmu(ARM_Emulator):
|
||||
# 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 setup_hook_blocks(self, only_blocks=False):
|
||||
if only_blocks:
|
||||
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)
|
||||
else:
|
||||
def hook_all(uc, address, size, user_data):
|
||||
# print(f"Block at {hex(self.LR)}")
|
||||
self.saved_blocks[self.pc] = self.get_registers()
|
||||
return True
|
||||
self.uc.hook_add(UC_HOOK_CODE, hook_all, self)
|
||||
|
||||
def setup_interrupt_hook(self):
|
||||
RAISE_INTERRUPT = 0x4001cab8
|
||||
@ -196,8 +426,14 @@ class PartialEmu(ARM_Emulator):
|
||||
|
||||
self.uc.hook_add(UC_HOOK_CODE, hook_emmc, begin=0x4001dfb0, end=0x4001e160)
|
||||
|
||||
def do_partial_emu(debugger : ConcreteDevice):
|
||||
emu = PartialEmu()
|
||||
def do_partial_emu(debugger : ConcreteDevice, real_hw=True):
|
||||
if real_hw:
|
||||
emu = TegraEmulator()
|
||||
emu.install_debugger(debugger)
|
||||
emu.setup()
|
||||
else:
|
||||
emu = TegraEmulator(hw_itm=False)
|
||||
emu.setup(target="bootrom")
|
||||
emu.run()
|
||||
|
||||
if __name__ == "__main__":
|
||||
do_partial_emu(None, real_hw=False)
|
@ -9,8 +9,8 @@ ghidra_assistant/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
|
||||
ghidra_assistant/__pycache__/__init__.cpython-310.pyc,,
|
||||
ghidra_assistant/__pycache__/concrete_device.cpython-310.pyc,,
|
||||
ghidra_assistant/__pycache__/ghidra_assistant.cpython-310.pyc,,
|
||||
ghidra_assistant/concrete_device.py,sha256=llVfmejKwBl8lohEhcpTeKvepguJ0dhUKGlZQL2wV0Y,8228
|
||||
ghidra_assistant/ghidra_assistant.py,sha256=CYJw9zTDB6QdXes0oebg2HRjIDdEc_SwqVdBY7iJQpY,497
|
||||
ghidra_assistant/concrete_device.py,sha256=MF6X-DZpPN9UhZzmrXUyM_GbGdJKQVziNAJ9RjOzyLI,8418
|
||||
ghidra_assistant/ghidra_assistant.py,sha256=tlpbxh9-V29IVN_tBiE6hOc7nuWa9zZt-z1AwGZpRD8,728
|
||||
ghidra_assistant/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
ghidra_assistant/utils/__pycache__/__init__.cpython-310.pyc,,
|
||||
ghidra_assistant/utils/__pycache__/bit_helper.cpython-310.pyc,,
|
||||
@ -22,12 +22,12 @@ 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__/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/arm_emulator.py,sha256=Wq7Tyiph3KYmvmMnRG8dl4TFKJEeNP8dtDrm_XpBLew,7798
|
||||
ghidra_assistant/utils/archs/arm/arm_emulator.py,sha256=dL86jwUMYON5Ry_OcDPDjvEYp4LYCZcadW3yiiG26fk,7841
|
||||
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__/asm_arm64.cpython-310.pyc,,
|
||||
ghidra_assistant/utils/archs/arm64/__pycache__/uc_emulator.cpython-310.pyc,,
|
||||
ghidra_assistant/utils/archs/arm64/arm64_emulator.py,sha256=MtAM0DjxagGJZfN5SQuzKJ2tf7kqcYs4r_9a07pZg9o,17044
|
||||
ghidra_assistant/utils/archs/arm64/arm64_emulator.py,sha256=h19lNQvT9RSHeN4MrUagqq7coo0tbTHzlofsNtAFcmI,16964
|
||||
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/misc/MMU/__pycache__/arm64_mmu.cpython-310.pyc,,
|
||||
@ -60,13 +60,13 @@ ghidra_assistant/utils/debugger/debugger_archs/__pycache__/ga_arm_thumb.cpython-
|
||||
ghidra_assistant/utils/debugger/debugger_archs/base_arch.py,sha256=uzyYUm_xEekk3j8uHx8blaKDbK8VR_gMU-Br8RY0tCs,1244
|
||||
ghidra_assistant/utils/debugger/debugger_archs/ga_arm.py,sha256=lPecV5UyTBErJgIkfrAa1d3kiH3PN_gaD5zhA4uzU4A,2745
|
||||
ghidra_assistant/utils/debugger/debugger_archs/ga_arm64.py,sha256=_195wxctqIBidDfHjSn-bicrsAbOtnhQGta4LgfiOog,9363
|
||||
ghidra_assistant/utils/debugger/debugger_archs/ga_arm_thumb.py,sha256=tZsQk6hnduZBy6n7g6x7tBhutpTmDk4W1wrNSbSaSsE,4946
|
||||
ghidra_assistant/utils/debugger/debugger_archs/ga_arm_thumb.py,sha256=v8qwn7DsI2Hl38bzzybpfmwhYi82o5i_-8Pva5gtFDw,5339
|
||||
ghidra_assistant/utils/definitions.py,sha256=tsk4MkEz510JN9-T1ZZExq61uZ32MVPc-0JljHQSde0,3511
|
||||
ghidra_assistant/utils/ga_client.py,sha256=dQeJdxL8z48WOw0cHf7sNtqlCVS3ZJ9FSTiB5om-ojM,2065
|
||||
ghidra_assistant/utils/ga_server.py,sha256=gchzEPmEtT8kigVB3Jnnv35nsB2k3_dSrQ5_BD8UgUA,5067
|
||||
ghidra_assistant/utils/ghidra/__pycache__/ghidra_connect.cpython-310.pyc,,
|
||||
ghidra_assistant/utils/ghidra/__pycache__/pyhidra.cpython-310.pyc,,
|
||||
ghidra_assistant/utils/ghidra/ghidra_connect.py,sha256=UUBAzRq4WraqBewi-gH-bXyoAkydBUpVvuVYthNjoUU,13856
|
||||
ghidra_assistant/utils/ghidra/ghidra_connect.py,sha256=69JunNjWcNc4uBLw5u3S0KAzBY9yeF_QQjvnTdI2Fwg,15506
|
||||
ghidra_assistant/utils/ghidra/pyhidra.py,sha256=amdhJcj4Fw3INuAqtIl7DfXNTtTwzPmj2FnyM0sNOFY,412
|
||||
ghidra_assistant/utils/utils.py,sha256=Ij9FiQsuCWAA8iIWt_3aO46E5K4e5zqaA7DCeqB7sk0,7372
|
||||
ghidra_assistant/venv/bin/__pycache__/rst2html.cpython-310.pyc,,
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -112,6 +112,12 @@ class ConcreteDevice():
|
||||
'''
|
||||
raise NotImplemented
|
||||
|
||||
def memwrite_io(self, address, data):
|
||||
'''
|
||||
Write some data byte by byte
|
||||
'''
|
||||
raise NotImplemented
|
||||
|
||||
def memdump_region(self, offset, size):
|
||||
'''
|
||||
Dump a region from target device. Based on an offset/address and size:
|
||||
@ -194,6 +200,7 @@ class ConcreteDevice():
|
||||
self.read = self.arch_dbg.read
|
||||
self.write = self.arch_dbg.write
|
||||
self.memdump_region = self.arch_dbg.memdump_region
|
||||
self.memwrite_io = self.arch_dbg.memwrite_io
|
||||
# self.memdump_region_small = self.arch_dbg.memdump_region_small
|
||||
self.memwrite_region = self.arch_dbg.memwrite_region
|
||||
self.get_debugger_location = self.arch_dbg.get_debugger_location
|
||||
|
@ -17,6 +17,12 @@ def main():
|
||||
'''
|
||||
info("Running tests")
|
||||
ga = GhidraAssistant()
|
||||
|
||||
# Test colouring lines
|
||||
# Generate a list of fake PC values from 0x4001ed94 to 0x4001ed94 + 0x1000
|
||||
pc_values = [0x4001ed94 + i for i in range(0, 0x1000, 4)]
|
||||
ga.ghidra.set_background_color(pc_values, "red")
|
||||
|
||||
dat = ga.ghidra.get_ghidra_memory_maps()
|
||||
|
||||
# Test concrete device
|
||||
|
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.
@ -8,6 +8,7 @@ from ...utils import *
|
||||
class ARM_Emulator:
|
||||
'''
|
||||
Class that will interact with the unicorn engine for emulating ARM code.
|
||||
Supports both ARM and Thumb modes.
|
||||
'''
|
||||
def __init__(self, init_uc = True):
|
||||
if init_uc:
|
||||
|
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.
@ -11,6 +11,15 @@ class GA_arm_thumb_debugger(BaseArch_debugger):
|
||||
self.sc = ShellcodeCrafterARMThumb(self.ks, self.cs)
|
||||
self.state = ARMThumb_Concrete_State(storage_addr, self)
|
||||
|
||||
def memwrite_io(self, address, data):
|
||||
assert len(data) < (0x20 - 12), "Data length is too long for IO write"
|
||||
self.write("HWIO")
|
||||
packet = struct.pack('<III', address, 0, len(data)) + data
|
||||
# fill the block up to 0x20 bytes
|
||||
packet += b"\x00" * (0x20 - len(packet))
|
||||
self.write(packet)
|
||||
self.read(DEBUGGER_BLOCKSIZE_TRANSMISSION)
|
||||
|
||||
def memdump_region(self, offset, size):
|
||||
'''
|
||||
Dump a region from target device. Based on an offset/address and size:
|
||||
|
Binary file not shown.
Binary file not shown.
@ -110,13 +110,24 @@ class Ghidra:
|
||||
# The string that's fed to getAddress NEEDS to be hex for some godawful reason
|
||||
return self.address_factory.getAddress(hex(addr))
|
||||
|
||||
def set_background_color(self, addresses):
|
||||
def _jbytes(self, dat):
|
||||
return bytes(dat)
|
||||
|
||||
def startTransaction(self, name):
|
||||
self.stopTransaction()
|
||||
self.transaction = currentProgram.startTransaction(f"Coloring lines")
|
||||
|
||||
def stopTransaction(self):
|
||||
if hasattr(self, "transaction"):
|
||||
currentProgram.endTransaction(self.transaction, True)
|
||||
|
||||
def set_background_color(self, addresses, color="java.awt.Color.YELLOW"):
|
||||
'''
|
||||
Highlight a list of addresses
|
||||
'''
|
||||
tr = currentProgram.startTransaction(f"Coloring lines")
|
||||
d = self.bridge.remote_eval("[currentProgram.getAddressFactory().getAddress(addr) for addr in addresses]", addresses=[hex(addr) for addr in addresses])
|
||||
self.bridge.remote_eval("[setBackgroundColor(addr, java.awt.Color.YELLOW) for addr in d]", d=d)
|
||||
self.bridge.remote_eval(f"[setBackgroundColor(addr, {color}) for addr in d]", d=d)
|
||||
currentProgram.endTransaction(tr, True)
|
||||
|
||||
def clear_background_color(self):
|
||||
@ -265,6 +276,36 @@ class Ghidra:
|
||||
self.memory.setBytes(toAddr(start), bytes(data))
|
||||
currentProgram.endTransaction(tr, True)
|
||||
|
||||
def mmap_region(self, addr, name, size, read=True, write=True, execute=False):
|
||||
tr = currentProgram.startTransaction(f"Mapping memory region {name} at {hex(addr)}")
|
||||
self.memory.createInitializedBlock(name, toAddr(addr), size, 0, monitor, False)
|
||||
block = self.memory.getBlock(toAddr(hex(addr)))
|
||||
block.setPermissions(read, write, execute)
|
||||
currentProgram.endTransaction(tr, True)
|
||||
|
||||
def write_mem(self, addr, data):
|
||||
'''
|
||||
write data to memory, if region is available
|
||||
'''
|
||||
# check if address is in a block
|
||||
block = self.get_memory_block(addr)
|
||||
if block is None:
|
||||
warn(f"Address {hex(addr)} is not in a block")
|
||||
return
|
||||
# check if len(data) is too big
|
||||
if len(data) > block.getSize():
|
||||
warn(f"Data is too big for block {block.name}")
|
||||
return
|
||||
tr = currentProgram.startTransaction(f"Writing memory at {hex(addr)}")
|
||||
self.memory.setBytes(toAddr(addr), bytes(data))
|
||||
currentProgram.endTransaction(tr, True)
|
||||
|
||||
def get_memory_block(self, addr):
|
||||
for block in self.memory.getBlocks():
|
||||
if block.contains(toAddr(hex(addr))):
|
||||
return block
|
||||
return None
|
||||
|
||||
def get_function_decompiled_code(self, func):
|
||||
# decompile the function and print the pseudo C
|
||||
results = self.ifc.decompileFunction(func, 0, ghidra.util.task.ConsoleTaskMonitor())
|
||||
|
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