Beispiel #1
0
def init_avatar_target(ucf: Unicorefuzz, avatar: Avatar) -> Target:
    """
        初始化probe wrapper使用的target
    Init the target used by the probe wrapper.
        probe_wrapper会设置断点,导向寄存器和内存
    The probe_wrapper will set the breakpoint and forward regs and mem using this target.

    :param ucf: Unicorefuzz instance, access config using ucf.config.
    :param avatar: Initialized Avatar to add target to.
        返回一个初始化后的target
    :return: An initialized target, added to Avatar.
    """
    from avatar2 import GDBTarget

    # 调用avatar的add_target方法
    target = avatar.add_target(
        GDBTarget,
        gdb_ip=ucf.config.GDB_HOST, # gdb ip
        gdb_port=ucf.config.GDB_PORT, # gdb 端口
        gdb_executable=ucf.config.GDB_PATH, # gdb执行路径
    )

    # 初始化
    target.init()

    # 返回
    return target
Beispiel #2
0
def get_qemu_target(name,
                    entry_addr,
                    firmware=None,
                    log_basic_blocks=False,
                    output_base_dir='',
                    gdb_port=1234):
    qemu_path = find_qemu()
    outdir = os.path.join(output_base_dir, 'tmp', name)
    hal_stats.set_filename(outdir + "/stats.yaml")
    avatar = Avatar(arch=ARM_CORTEX_M3, output_directory=outdir)
    print "GDB_PORT", gdb_port
    log.critical("Using qemu in %s" % qemu_path)
    qemu = avatar.add_target(QemuTarget,
                             gdb_executable="arm-none-eabi-gdb",
                             gdb_port=gdb_port,
                             qmp_port=gdb_port + 1,
                             firmware=firmware,
                             executable=qemu_path,
                             entry_address=entry_addr,
                             name=name)
    #qemu.log.setLevel(logging.DEBUG)

    if log_basic_blocks == 'irq':
        qemu.additional_args = [
            '-d', 'in_asm,exec,int,cpu,guest_errors,avatar,trace:nvic*', '-D',
            os.path.join(outdir, 'qemu_asm.log')
        ]
    elif log_basic_blocks:
        qemu.additional_args = [
            '-d', 'in_asm', '-D',
            os.path.join(outdir, 'qemu_asm.log')
        ]
    return avatar, qemu
Beispiel #3
0
def get_qemu_target(name,
                    config,
                    firmware=None,
                    log_basic_blocks=False,
                    gdb_port=1234):
    qemu_path = find_qemu()
    outdir = os.path.join('tmp', name)
    hal_stats.set_filename(outdir + "/stats.yaml")

    # Get info from config
    arch = ARCH_LUT[config.machine.arch]

    avatar = Avatar(arch=arch, output_directory=outdir)
    log.info("GDB_PORT: %s" % gdb_port)
    log.info("QEMU Path: %s" % qemu_path)

    qemu_target = QEMU_ARCH_LUT[config.machine.arch]
    qemu = avatar.add_target(qemu_target,
                             cpu_model=config.machine.cpu_model,
                             gdb_executable=config.machine.gdb_exe,
                             gdb_port=gdb_port,
                             qmp_port=gdb_port + 1,
                             firmware=firmware,
                             executable=qemu_path,
                             entry_address=config.machine.entry_addr,
                             name=name)

    if log_basic_blocks == 'irq':
        qemu.additional_args = [
            '-d', 'in_asm,exec,int,cpu,guest_errors,avatar,trace:nvic*', '-D',
            os.path.join(outdir, 'qemu_asm.log')
        ]
    elif log_basic_blocks == 'regs':
        qemu.additional_args = [
            '-d', 'in_asm,exec,cpu', '-D',
            os.path.join(outdir, 'qemu_asm.log')
        ]
    elif log_basic_blocks == 'exec':
        qemu.additional_args = [
            '-d', 'exec', '-D',
            os.path.join(outdir, 'qemu_asm.log')
        ]
    elif log_basic_blocks == 'trace-nochain':
        qemu.additional_args = [
            '-d', 'in_asm,exec,nochain', '-D',
            os.path.join(outdir, 'qemu_asm.log')
        ]
    elif log_basic_blocks == 'trace':
        qemu.additional_args = [
            '-d', 'in_asm,exec', '-D',
            os.path.join(outdir, 'qemu_asm.log')
        ]

    elif log_basic_blocks:
        qemu.additional_args = [
            '-d', 'in_asm', '-D',
            os.path.join(outdir, 'qemu_asm.log')
        ]
    return avatar, qemu
Beispiel #4
0
def init_avatar_target(ucf: Unicorefuzz, avatar: Avatar) -> Target:
    """
    Init the target used by the probe wrapper.
    The probe_wrapper will set the breakpoint and forward regs and mem using this target.
    :param ucf: Unicorefuzz instance, access config using ucf.config.
    :param avatar: Initialized Avatar to add target to.
    :return: An initialized target, added to Avatar.
    """
    from avatar2 import GDBTarget

    target = avatar.add_target(
        GDBTarget,
        gdb_ip=ucf.config.GDB_HOST,
        gdb_port=ucf.config.GDB_PORT,
        gdb_executable=ucf.config.GDB_PATH,
    )
    target.init()
    return target
Beispiel #5
0
def main(workdir, module=None, breakoffset=None, breakaddress=None, reset_state=True, arch="x64", gdb_port=1234):
    request_path = os.path.join(workdir, REQUEST_FOLDER)
    output_path = os.path.join(workdir, STATE_FOLDER)

    if arch != "x64":
        raise("Unsupported arch")
    if reset_state:
        try:
            shutil.rmtree(output_path)
        except:
            pass
    try:
        os.makedirs(output_path, exist_ok=True)
    except:
        pass

    if module:
        if breakaddress is not None:
            raise("Breakaddress and module supplied. They are not compatible.")
        if breakoffset is None:
            raise("Module but no breakoffset specified. Don't know where to break.")

        mem_addr = os.popen("./get_mod_addr.sh " + module).readlines()
        try:
            mem_addr = int(mem_addr[0], 16)
        except ValueError as ex:
            print("Error decoding module addr. Either module {} has not been loaded or something went wrong with ssh ({})".format(module, ex))
            exit(-1)
        print("Module " + module + " is at memory address " + hex(mem_addr))
        breakaddress = hex(mem_addr + breakoffset)
    else:
        breakaddress = hex(breakaddress)

    avatar = Avatar(arch=get_arch(arch),
                    output_directory=os.path.join(workdir, "avatar"))
    target = avatar.add_target(
        GDBTarget, gdb_port=gdb_port, gdb_executable=GDB_PATH)
    target.init()

    target.set_breakpoint("*{}".format(breakaddress))
    print("[*] Breakpoint set at {}".format(breakaddress))
    print("[+] waiting for bp hit...")
    target.cont()
    target.wait()

    print("[+] hit! dumping registers and memory")

    # dump registers
    for reg in all_regs(get_arch(arch)):
        written = True
        reg_file = os.path.join(output_path, reg)
        with open(reg_file, "w") as f:
            try:
                val = target.read_register(reg)
                if isinstance(val, list):
                    # Avatar special registers (xmm, ...)
                    i32list = val
                    val = 0
                    for shift, i32 in enumerate(i32list):
                        val += (i32 << (shift * 32))
                f.write(str(val))
            except Exception as ex:
                #print("Ignoring {}: {}".format(reg, ex))
                written = False
        if not written:
            os.unlink(reg_file)

    try:
        os.mkdir(request_path)
    except:
        pass

    forward_requests(target, workdir, request_path, output_path)
    print("[*] Initial dump complete. Listening for requests from ./harness.py.")

    i = inotify.adapters.Inotify()
    # only readily written files
    i.add_watch(request_path, mask=inotify.constants.IN_CLOSE_WRITE)
    for event in i.event_gen(yield_nones=False):
        #print("Request: ", event)
        forward_requests(target, workdir, request_path, output_path)

    print("[*] Exiting probe_wrapper (keyboard interrupt)")
from time import sleep
from avatar2 import Avatar, ARMV7M, OpenOCDTarget, PandaTarget

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
Beispiel #7
0
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]
                   ])))
Beispiel #8
0
# /opt/SEGGER/JLink/JLinkGDBServer -endian little -localhostonly -device STM32F479NI -if SWD

if __name__ == '__main__':
    from argparse import ArgumentParser
    p = ArgumentParser()
    p.add_argument("-e", '--elf', required=True, help='Elf file to profile')
    p.add_argument("-f",
                   '--functions',
                   required=True,
                   help='YAML file listing functions')
    p.add_argument("-d", '--db', help='sqlite3 database filename')
    args = p.parse_args()

    avatar = Avatar(arch=ARM_CORTEX_M3, output_directory='/tmp/hal_profile')
    gdb = avatar.add_target(GDBTarget,
                            gdb_additional_args=[args.elf],
                            gdb_executable="arm-none-eabi-gdb",
                            gdb_port=2331)

    avatar.watchmen.add_watchman('BreakpointHit',
                                 'before',
                                 handle_bp,
                                 is_async=True)
    avatar.init_targets()

    memories = [(0x20000000, 0x50000)]
    if args.db == None:
        db = os.path.splitext(args.elf)[0] + ".sqlite"
    else:
        db = args.db

    Recorder = State_Recorder(db, gdb, memories, args.elf)
Beispiel #9
0
from avatar2 import Avatar, ARMV7M, OpenOCDTarget
from IPython import embed

main_addr = 0xD270

avatar = Avatar(output_directory='/tmp/harvey', arch=ARMV7M)
avatar.load_plugin('assembler')

t = avatar.add_target(OpenOCDTarget,
                      openocd_script='plc.cfg',
                      gdb_executable='arm-none-eabi-gdb')

t.init()

t.set_breakpoint(main_addr)
t.cont()
t.wait()

t.inject_asm('b 0x2000250E', addr=0x20001E2E)
t.inject_asm('mov r5,0xfffffffc\n b 0x20001E30', addr=0x2000250E)

t.inject_asm('b 0x20002514', addr=0x20002338)
t.inject_asm('mov r5,0xfffffffd\n mov r4, r5 \n mov r5, 0\nb 0x2000233E',
             addr=0x20002514)

t.cont()
embed()