started device implementation

This commit is contained in:
Eljakim Herrewijnen 2024-06-17 20:15:08 +02:00
parent a1ab8650bc
commit 59eaf299ad
54 changed files with 360 additions and 52 deletions

8
.vscode/launch.json vendored
View File

@ -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
}
]
}

View File

@ -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)

View File

@ -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,,

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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())