def setup(): global qemu global avatar global fake_target arch = setup_ARCH() avatar = Avatar(arch=arch, output_directory=test_dir) qemu = QemuTarget( avatar, name='qemu_test', #firmware="./tests/binaries/qemu_arm_test", firmware='%s/firmware' % test_dir, ) fake_target = FakeTarget() dev1 = avatar.add_memory_range(0x101f2000, 0x1000, 'dev1', forwarded=True, forwarded_to=fake_target, qemu_name='avatar-rmemory') mem1 = avatar.add_memory_range( rom_addr, 0x1000, 'mem1', #file='%s/tests/binaries/qemu_arm_test' % # os.getcwd()) file='%s/firmware' % test_dir)
def setup(): global qemu global avatar avatar = Avatar() qemu = QemuTarget(avatar, name='qemu_test', firmware="./tests/binaries/qemu_arm_test", gdb_executable=GDB_EXECUTABLE, executable=QEMU_EXECUTABLE) fake_target = FakeTarget() dev1 = avatar.add_memory_range(0x101f2000, 0x1000, 'dev1', forwarded=True, forwarded_to=fake_target, qemu_name='avatar-rmemory') mem1 = avatar.add_memory_range(0x8000000, 0x1000, 'mem1', file='%s/tests/binaries/qemu_arm_test' % os.getcwd())
def setup(): global qemu global avatar global fake_target avatar = Avatar(output_directory='/tmp/testava') qemu = QemuTarget( avatar, name='qemu_test', firmware="./tests/binaries/qemu_arm_test", ) fake_target = FakeTarget() dev1 = avatar.add_memory_range(0x101f2000, 0x1000, 'dev1', forwarded=True, forwarded_to=fake_target, qemu_name='avatar-rmemory') mem1 = avatar.add_memory_range(0x8000000, 0x1000, 'mem1', file='%s/tests/binaries/qemu_arm_test' % os.getcwd())
avatar = Avatar(arch=ARMV7M, output_directory='/tmp/panda_rr') avatar.load_plugin('orchestrator') nucleo = avatar.add_target(OpenOCDTarget, openocd_script='nucleo-l152re.cfg', gdb_executable="arm-none-eabi-gdb", gdb_port=1234) panda = avatar.add_target(PandaTarget, executable='panda/qemu-system-arm', gdb_executable="arm-none-eabi-gdb", gdb_port=1235) rom = avatar.add_memory_range(0x08000000, 0x1000000, 'rom', file='firmware.bin') ram = avatar.add_memory_range(0x20000000, 0x14000, 'ram') mmio = avatar.add_memory_range(0x40000000, 0x1000000, 'mmio', forwarded=True, forwarded_to=nucleo) avatar.init_targets() avatar.start_target = nucleo avatar.add_transition(0x8005104, nucleo, panda, synced_ranges=[ram], stop=True) avatar.start_orchestration()
class PSPEmulator(): custom_memory = bytearray(2**32) accessed_mem = {} verbose = True interactive = False ccp_cmd = {"process": False, "start": 0x0, "end": 0x0} qemu = None def __init__(self): self.avatar = None self.close = False self.trace_parse = None self.trace_file = None self.ignored_addresses = set() def init(self, entry_addr, qemu_bin, qemu_args, verbose=False, interactive=False): self.avatar = Avatar(output_directory=AVATAR_DIR) self.avatar.log.setLevel('DEBUG') PSPEmulator.verbose = verbose PSPEmulator.interactive = interactive PSPEmulator.qemu = self.avatar.add_target( QemuTarget, name='qemu1', executable=qemu_bin, gdb_executable="arm-eabi-gdb", additional_args=qemu_args) PSPEmulator.qemu.cpu_model = 'cortex-a8' self.avatar.watchmen.add_watchman('RemoteMemoryRead', 'before', self.before_remote_memory_access, is_async=False) self.avatar.watchmen.add_watchman('RemoteMemoryWrite', 'before', self.before_remote_memory_access, is_async=False) PSPEmulator.qemu.entry_address = entry_addr def load_file(self, address, mem_size, filename, offset, file_size): self.avatar.add_memory_range(address, mem_size, file=filename, file_offset=offset, file_bytes=file_size) def load_custom_mem(self, address, filename, offset=0, size=0): f = open(filename, 'rb') if offset != 0: f.seek(offset) if size != 0: data = f.read(size) else: data = f.read() self.custom_memory[address:address + len(data)] = data def add_memory_range(self, start, end, permissions='rw-'): if ((end - start) % 0x1000) != 0: print("[PSPEmulator] ERROR: memory ranges must be page aligned" "(0x%.8x)" % start) self.avatar.add_memory_range(start, end - start, permission=permissions) def set_memory_value(self, address, value, size=4): if size != 1 and size != 4: print("[PSPEmulator] ERROR: Only 1 or 4 bytes are supported") return if size == 1: PSPEmulator.custom_memory[address] = value elif size == 4: bval = (value).to_bytes(4, byteorder='big') PSPEmulator.custom_memory[address] = bval[0] PSPEmulator.custom_memory[address + 1] = bval[1] PSPEmulator.custom_memory[address + 2] = bval[2] PSPEmulator.custom_memory[address + 3] = bval[3] def qemu_init(self): PSPEmulator.qemu.init() def set_breakpoint(self, address): PSPEmulator.qemu.set_breakpoint(address) def watch_memory_range(self, start, end, permissions='rw-'): if ((end - start) % 0x1000) != 0: print("[PSPEmulator] ERROR: watched memory ranges must be page" "aligned (0x%.8x)" % start) return self.avatar.add_memory_range(start, end - start, emulate=CustomMemoryPeripheral, permission=permissions) def add_virtual_ccp(self, address): if not PSPEmulator.qemu: print("[PSPEmulator] ERROR: PSPEmulator not initialized yet. Call" "init() first") return self.avatar.add_memory_range(address, 0x1000, emulate=VirtualCCP, permission='rw-') # self.ignored_addresses.add(address) def add_misc_dev(self, address): if not PSPEmulator.qemu: print("[PSPEmulator] ERROR: PSPEmulator not initialized yet. Call" "init() first") return self.avatar.add_memory_range(address, 0x1000, emulate=VirtMisc, permission='rw-') def add_virtual_timer(self, address): if not PSPEmulator.qemu: print("[PSPEmulator] ERROR: PSPEmulator not initialized yet. Call" "init() first") return self.avatar.add_memory_range(address, 0x1000, name="VirtualTimer", emulate=VirtualTimer, permission='rw-') # self.ignored_addresses.add(address) def watch_memory(self, address=None, size=None): # TODO: Automatically configure "remaining", i.e. not yet configured # memory ranges to be backed by our CustomMemoryPeripheral print(self.avatar.memory_ranges) for interval in self.avatar.memory_ranges: print("0x%x 0x%x" % (interval.begin, interval.end)) def __del__(self): self.avatar.shutdown() if self.trace_file and self.trace_parse: command = 'python2.7 %s %s /tmp/trace > /tmp/parsed' % \ (self.trace_parse, self.trace_file) print("[PSPEmulator] Calling %s" % command) os.system(command) def exit(self): self.close = True self.__del__() def disconnect_gdb(self): PSPEmulator.qemu.gdb.remote_disconnect() def connect_gdb(self): PSPEmulator.qemu.gdb.remote_connect() def run(self): while not self.close: if PSPEmulator.qemu.state != TargetStates.EXITED: PSPEmulator.qemu.cont() PSPEmulator.qemu.wait(TargetStates.EXITED | TargetStates.STOPPED) if PSPEmulator.qemu.state == TargetStates.STOPPED: if PSPEmulator.ccp_cmd["process"] is True: print("[ccp_dev] Parsing new cmd at pc=0x%.8x" % PSPEmulator.qemu.read_register("pc")) self.print_ccp_cmds(PSPEmulator.ccp_cmd["start"], PSPEmulator.ccp_cmd["end"]) PSPEmulator.ccp_cmd["process"] = False else: embed(banner1="QEMU entered STOPPED state at pc=0x%.8x" % PSPEmulator.qemu.read_register("pc")) else: print("[PSPEmulator] Qemu exited with state: %s" % str(PSPEmulator.qemu.state)) self.exit() def print_ccp_cmds(self, start, end): cmds = (end - start) // 0x20 for e in range(0x0, cmds): dwords = [ PSPEmulator.qemu.read_memory(i, 0x4) for i in range(start + (e * 0x20), start + (e * 0x20) + 0x20, 0x4) ] print("\n[ccp_dev] Processing ccp cmd %d" % e) cmt, engine = ccp_parse.parse_dword0(dwords[0]) print("[ccp_dev]\t %s" % cmt) print("[ccp_dev]\t Length of src data 0x%x" % dwords[1]) print("[ccp_dev]\t Src ptr 0x%x" % dwords[2]) print("[ccp_dev]\t %s" % ccp_parse.parse_dword3(dwords[3])) print("[ccp_dev]\t %s" % ccp_parse.parse_dword4(engine, dwords[4])) print("[ccp_dev]\t %s" % ccp_parse.parse_dword5(engine, dwords[5])) print("[ccp_dev]\t Low 32bit key ptr: 0x%x" % dwords[6]) print("[ccp_dev]\t High 16bit key ptr + mem type: 0x%x" % dwords[7]) print() def swap32(i): return struct.unpack("<I", struct.pack(">I", i))[0] def enable_tracing(self, trace_parse, trace_file): self.trace_file = trace_file self.trace_parse = trace_parse PSPEmulator.qemu.qmp.execute_command('trace-event-set-state', { 'name': 'exec_tb', 'enable': True }) PSPEmulator.qemu.qmp.execute_command('trace-event-set-state', { 'name': 'guest_mem_before_exec', 'enable': True }) def before_remote_memory_access(self, avatar, remote_memory_msg, **kwargs): address = remote_memory_msg.address pc = remote_memory_msg.pc # Ignore pages belonging to emulated devices if (address & 0xFFFFF000) in self.ignored_addresses: return read_or_write = '' if isinstance(remote_memory_msg, RemoteMemoryReadMessage): read_or_write = 'read' else: # if isinstance(remote_memory_msg, RemoteMemoryWriteMessage): read_or_write = 'write' # if not PSPEmulator.ccp_cmd["process"]: # print('[custom_memory] New %s at 0x%.8x from PC: 0x%.8x' % (read_or_write, address, pc)) if address not in PSPEmulator.accessed_mem: PSPEmulator.accessed_mem[address] = set() # print("BeforeMemaccess: pc 0x%.8x addr 0x%.8x" % (pc, address)) PSPEmulator.accessed_mem[address].add((pc, read_or_write)) def print_custom_memory(self): for i in PSPEmulator.accessed_mem: val = int.from_bytes(PSPEmulator.custom_memory[i:i + 4], 'little') print('\t0x%.8x: \t0x%.8x \taccessed_by: %s' % (i, val, repr([ v[1] + ':' + hex(v[0]) for v in PSPEmulator.accessed_mem[i] ])))
class QemuTargetTestCase(unittest.TestCase): def setUp(self): self.setup_env() def setup_env(self, gdb_unix_socket_path=None): self.rom_addr = None self.arch = None self.setup_arch() self.avatar = Avatar(arch=self.arch, output_directory=TEST_DIR, configure_logging=False) self.qemu = QemuTarget( self.avatar, name='qemu_test', #firmware="./tests/binaries/qemu_arm_test", firmware='%s/firmware' % TEST_DIR, gdb_unix_socket_path=gdb_unix_socket_path, ) self.fake_target = FakeTarget() dev1 = self.avatar.add_memory_range(0x101f2000, 0x1000, 'dev1', forwarded=True, forwarded_to=self.fake_target, qemu_name='avatar-rmemory') mem1 = self.avatar.add_memory_range( self.rom_addr, 0x1000, 'mem1', #file='%s/tests/binaries/qemu_arm_test' % # os.getcwd()) file='%s/firmware' % TEST_DIR) def setup_arch(self): ARCH = os.getenv('AVATAR2_ARCH') if ARCH == 'ARM': self.arch = ARM self.rom_addr = ARM_BASE_ADDR firmware = ARM_BIN elif ARCH == 'MIPS': self.arch = MIPS_24KF self.rom_addr = MIPS_BASE_ADDR firmware = MIPS_BIN else: self.assertTrue(False, 'Invalid Achitecture') if not os.path.exists(TEST_DIR): os.makedirs(TEST_DIR) with open('%s/firmware' % TEST_DIR, 'wb') as f: f.write(firmware) def tearDown(self): self.qemu.shutdown() def test_initilization(self): self.qemu.init() self.qemu.wait() self.assertEqual(self.qemu.state, TargetStates.STOPPED, self.qemu.state) def test_step(self): self.qemu.init() self.qemu.wait() self.qemu.regs.pc = self.rom_addr self.qemu.step() pc = self.qemu.regs.pc self.assertEqual(pc, self.rom_addr + 4, pc) def test_memory_read(self): self.qemu.init() self.qemu.wait() mem = self.qemu.read_memory(self.rom_addr, 4) if self.arch == ARM: self.assertEqual(mem, 0xe3a0101e, mem) elif self.arch == MIPS_24KF: #self.assertEqual(mem, 0x2409001e, mem) self.assertEqual(mem, 0x1e000924, mem) else: self.assertTrue(False, "Architecture not supported") def test_memory_write(self): self.qemu.init() self.qemu.wait() self.qemu.write_memory(self.rom_addr, 4, 0x41414141) mem = self.qemu.read_memory(self.rom_addr, 4) self.assertEqual(mem, 0x41414141, mem) def test_remote_memory_write(self): self.qemu.init() self.qemu.wait() remote_memory_write = self.qemu.write_memory(0x101f2000, 4, 0x41414141) self.assertEqual(remote_memory_write, True) addr = self.fake_target.fake_write_addr size = self.fake_target.fake_write_size val = self.fake_target.fake_write_val self.assertEqual(addr, 0x101f2000, addr) self.assertEqual(size, 4, size) self.assertEqual(val, 0x41414141, val) def test_remote_memory_read(self): self.qemu.init() self.qemu.wait() self.assertEqual(self.qemu.state, TargetStates.STOPPED, self.qemu.state) remote_memory_read = self.qemu.read_memory(0x101f2000, 4) self.assertEqual(remote_memory_read, 0xdeadbeef, remote_memory_read)