aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominik Maier <domenukk@gmail.com>2021-07-15 12:38:15 +0200
committerDominik Maier <domenukk@gmail.com>2021-07-15 12:38:15 +0200
commitc279750689a0e49e722d24a352dd0af28a60e986 (patch)
treea56c4454f9d34409e444caae67ab38135fe79ff9
parent7fb2d90c49b7836582420d5738cbaeaa5213f338 (diff)
downloadafl++-c279750689a0e49e722d24a352dd0af28a60e986.tar.gz
formatting
-rw-r--r--unicorn_mode/helper_scripts/unicorn_loader.py638
1 files changed, 381 insertions, 257 deletions
diff --git a/unicorn_mode/helper_scripts/unicorn_loader.py b/unicorn_mode/helper_scripts/unicorn_loader.py
index 4f82d0a3..c48a7572 100644
--- a/unicorn_mode/helper_scripts/unicorn_loader.py
+++ b/unicorn_mode/helper_scripts/unicorn_loader.py
@@ -29,6 +29,7 @@ from unicornafl.mips_const import *
# If Capstone libraries are availible (only check once)
try:
from capstone import *
+
CAPSTONE_EXISTS = 1
except:
CAPSTONE_EXISTS = 0
@@ -44,29 +45,38 @@ MAX_ALLOWABLE_SEG_SIZE = 1024 * 1024 * 1024
# Alignment functions to align all memory segments to Unicorn page boundaries (4KB pages only)
ALIGN_PAGE_DOWN = lambda x: x & ~(UNICORN_PAGE_SIZE - 1)
-ALIGN_PAGE_UP = lambda x: (x + UNICORN_PAGE_SIZE - 1) & ~(UNICORN_PAGE_SIZE-1)
+ALIGN_PAGE_UP = lambda x: (x + UNICORN_PAGE_SIZE - 1) & ~(UNICORN_PAGE_SIZE - 1)
+
+# ---------------------------------------
+# ---- Unicorn-based heap implementation
-#---------------------------------------
-#---- Unicorn-based heap implementation
class UnicornSimpleHeap(object):
- """ Use this class to provide a simple heap implementation. This should
- be used if malloc/free calls break things during emulation. This heap also
- implements basic guard-page capabilities which enable immediate notice of
- heap overflow and underflows.
+ """Use this class to provide a simple heap implementation. This should
+ be used if malloc/free calls break things during emulation. This heap also
+ implements basic guard-page capabilities which enable immediate notice of
+ heap overflow and underflows.
"""
# Helper data-container used to track chunks
class HeapChunk(object):
def __init__(self, actual_addr, total_size, data_size):
- self.total_size = total_size # Total size of the chunk (including padding and guard page)
- self.actual_addr = actual_addr # Actual start address of the chunk
- self.data_size = data_size # Size requested by the caller of actual malloc call
- self.data_addr = actual_addr + UNICORN_PAGE_SIZE # Address where data actually starts
+ self.total_size = (
+ total_size # Total size of the chunk (including padding and guard page)
+ )
+ self.actual_addr = actual_addr # Actual start address of the chunk
+ self.data_size = (
+ data_size # Size requested by the caller of actual malloc call
+ )
+ self.data_addr = (
+ actual_addr + UNICORN_PAGE_SIZE
+ ) # Address where data actually starts
# Returns true if the specified buffer is completely within the chunk, else false
def is_buffer_in_chunk(self, addr, size):
- if addr >= self.data_addr and ((addr + size) <= (self.data_addr + self.data_size)):
+ if addr >= self.data_addr and (
+ (addr + size) <= (self.data_addr + self.data_size)
+ ):
return True
else:
return False
@@ -75,9 +85,9 @@ class UnicornSimpleHeap(object):
HEAP_MIN_ADDR = 0x00002000
HEAP_MAX_ADDR = 0xFFFFFFFF
- _uc = None # Unicorn engine instance to interact with
- _chunks = [] # List of all known chunks
- _debug_print = False # True to print debug information
+ _uc = None # Unicorn engine instance to interact with
+ _chunks = [] # List of all known chunks
+ _debug_print = False # True to print debug information
def __init__(self, uc, debug_print=False):
self._uc = uc
@@ -98,7 +108,11 @@ class UnicornSimpleHeap(object):
self._uc.mem_map(addr, total_chunk_size, UC_PROT_READ | UC_PROT_WRITE)
chunk = self.HeapChunk(addr, total_chunk_size, size)
if self._debug_print:
- print("Allocating 0x{0:x}-byte chunk @ 0x{1:016x}".format(chunk.data_size, chunk.data_addr))
+ print(
+ "Allocating 0x{0:x}-byte chunk @ 0x{1:016x}".format(
+ chunk.data_size, chunk.data_addr
+ )
+ )
break
except UcError as e:
continue
@@ -110,19 +124,26 @@ class UnicornSimpleHeap(object):
def calloc(self, size, count):
# Simple wrapper around malloc with calloc() args
- return self.malloc(size*count)
+ return self.malloc(size * count)
def realloc(self, ptr, new_size):
# Wrapper around malloc(new_size) / memcpy(new, old, old_size) / free(old)
if self._debug_print:
- print("Reallocating chunk @ 0x{0:016x} to be 0x{1:x} bytes".format(ptr, new_size))
+ print(
+ "Reallocating chunk @ 0x{0:016x} to be 0x{1:x} bytes".format(
+ ptr, new_size
+ )
+ )
old_chunk = None
for chunk in self._chunks:
if chunk.data_addr == ptr:
old_chunk = chunk
new_chunk_addr = self.malloc(new_size)
if old_chunk != None:
- self._uc.mem_write(new_chunk_addr, str(self._uc.mem_read(old_chunk.data_addr, old_chunk.data_size)))
+ self._uc.mem_write(
+ new_chunk_addr,
+ str(self._uc.mem_read(old_chunk.data_addr, old_chunk.data_size)),
+ )
self.free(old_chunk.data_addr)
return new_chunk_addr
@@ -130,7 +151,11 @@ class UnicornSimpleHeap(object):
for chunk in self._chunks:
if chunk.is_buffer_in_chunk(addr, 1):
if self._debug_print:
- print("Freeing 0x{0:x}-byte chunk @ 0x{0:016x}".format(chunk.req_size, chunk.data_addr))
+ print(
+ "Freeing 0x{0:x}-byte chunk @ 0x{0:016x}".format(
+ chunk.req_size, chunk.data_addr
+ )
+ )
self._uc.mem_unmap(chunk.actual_addr, chunk.total_size)
self._chunks.remove(chunk)
return True
@@ -139,19 +164,27 @@ class UnicornSimpleHeap(object):
# Implements basic guard-page functionality
def __check_mem_access(self, uc, access, address, size, value, user_data):
for chunk in self._chunks:
- if address >= chunk.actual_addr and ((address + size) <= (chunk.actual_addr + chunk.total_size)):
+ if address >= chunk.actual_addr and (
+ (address + size) <= (chunk.actual_addr + chunk.total_size)
+ ):
if chunk.is_buffer_in_chunk(address, size) == False:
if self._debug_print:
- print("Heap over/underflow attempting to {0} 0x{1:x} bytes @ {2:016x}".format( \
- "write" if access == UC_MEM_WRITE else "read", size, address))
+ print(
+ "Heap over/underflow attempting to {0} 0x{1:x} bytes @ {2:016x}".format(
+ "write" if access == UC_MEM_WRITE else "read",
+ size,
+ address,
+ )
+ )
# Force a memory-based crash
uc.force_crash(UcError(UC_ERR_READ_PROT))
-#---------------------------
-#---- Loading function
-class AflUnicornEngine(Uc):
+# ---------------------------
+# ---- Loading function
+
+class AflUnicornEngine(Uc):
def __init__(self, context_directory, enable_trace=False, debug_print=False):
"""
Initializes an AflUnicornEngine instance, which extends standard the UnicornEngine
@@ -166,51 +199,56 @@ class AflUnicornEngine(Uc):
# Make sure the index file exists and load it
index_file_path = os.path.join(context_directory, INDEX_FILE_NAME)
if not os.path.isfile(index_file_path):
- raise Exception("Index file not found. Expected it to be at {}".format(index_file_path))
+ raise Exception(
+ "Index file not found. Expected it to be at {}".format(index_file_path)
+ )
# Load the process context from the index file
if debug_print:
print("Loading process context index from {}".format(index_file_path))
- index_file = open(index_file_path, 'r')
+ index_file = open(index_file_path, "r")
context = json.load(index_file)
index_file.close()
# Check the context to make sure we have the basic essential components
- if 'arch' not in context:
+ if "arch" not in context:
raise Exception("Couldn't find architecture information in index file")
- if 'regs' not in context:
+ if "regs" not in context:
raise Exception("Couldn't find register information in index file")
- if 'segments' not in context:
+ if "segments" not in context:
raise Exception("Couldn't find segment/memory information in index file")
# Set the UnicornEngine instance's architecture and mode
- self._arch_str = context['arch']['arch']
+ self._arch_str = context["arch"]["arch"]
arch, mode = self.__get_arch_and_mode(self._arch_str)
Uc.__init__(self, arch, mode)
# Load the registers
- regs = context['regs']
+ regs = context["regs"]
reg_map = self.__get_register_map(self._arch_str)
self.__load_registers(regs, reg_map, debug_print)
# If we have extra FLOATING POINT regs, load them in!
- if 'regs_extended' in context:
- if context['regs_extended']:
- regs_extended = context['regs_extended']
+ if "regs_extended" in context:
+ if context["regs_extended"]:
+ regs_extended = context["regs_extended"]
reg_map = self.__get_registers_extended(self._arch_str)
self.__load_registers(regs_extended, reg_map, debug_print)
# For ARM, sometimes the stack pointer is erased ??? (I think I fixed this (issue with ordering of dumper.py, I'll keep the write anyways)
if self.__get_arch_and_mode(self.get_arch_str())[0] == UC_ARCH_ARM:
- self.reg_write(UC_ARM_REG_SP, regs['sp'])
+ self.reg_write(UC_ARM_REG_SP, regs["sp"])
# Setup the memory map and load memory content
- self.__map_segments(context['segments'], context_directory, debug_print)
+ self.__map_segments(context["segments"], context_directory, debug_print)
if enable_trace:
self.hook_add(UC_HOOK_BLOCK, self.__trace_block)
self.hook_add(UC_HOOK_CODE, self.__trace_instruction)
self.hook_add(UC_HOOK_MEM_WRITE | UC_HOOK_MEM_READ, self.__trace_mem_access)
- self.hook_add(UC_HOOK_MEM_WRITE_UNMAPPED | UC_HOOK_MEM_READ_INVALID, self.__trace_mem_invalid_access)
+ self.hook_add(
+ UC_HOOK_MEM_WRITE_UNMAPPED | UC_HOOK_MEM_READ_INVALID,
+ self.__trace_mem_invalid_access,
+ )
if debug_print:
print("Done loading context.")
@@ -225,13 +263,19 @@ class AflUnicornEngine(Uc):
return self._arch_str
def force_crash(self, uc_error):
- """ This function should be called to indicate to AFL that a crash occurred during emulation.
- You can pass the exception received from Uc.emu_start
+ """This function should be called to indicate to AFL that a crash occurred during emulation.
+ You can pass the exception received from Uc.emu_start
"""
mem_errors = [
- UC_ERR_READ_UNMAPPED, UC_ERR_READ_PROT, UC_ERR_READ_UNALIGNED,
- UC_ERR_WRITE_UNMAPPED, UC_ERR_WRITE_PROT, UC_ERR_WRITE_UNALIGNED,
- UC_ERR_FETCH_UNMAPPED, UC_ERR_FETCH_PROT, UC_ERR_FETCH_UNALIGNED,
+ UC_ERR_READ_UNMAPPED,
+ UC_ERR_READ_PROT,
+ UC_ERR_READ_UNALIGNED,
+ UC_ERR_WRITE_UNMAPPED,
+ UC_ERR_WRITE_PROT,
+ UC_ERR_WRITE_UNALIGNED,
+ UC_ERR_FETCH_UNMAPPED,
+ UC_ERR_FETCH_PROT,
+ UC_ERR_FETCH_UNALIGNED,
]
if uc_error.errno in mem_errors:
# Memory error - throw SIGSEGV
@@ -245,13 +289,18 @@ class AflUnicornEngine(Uc):
def dump_regs(self):
""" Dumps the contents of all the registers to STDOUT """
- for reg in sorted(self.__get_register_map(self._arch_str).items(), key=lambda reg: reg[0]):
+ for reg in sorted(
+ self.__get_register_map(self._arch_str).items(), key=lambda reg: reg[0]
+ ):
print(">>> {0:>4}: 0x{1:016x}".format(reg[0], self.reg_read(reg[1])))
def dump_regs_extended(self):
""" Dumps the contents of all the registers to STDOUT """
try:
- for reg in sorted(self.__get_registers_extended(self._arch_str).items(), key=lambda reg: reg[0]):
+ for reg in sorted(
+ self.__get_registers_extended(self._arch_str).items(),
+ key=lambda reg: reg[0],
+ ):
print(">>> {0:>4}: 0x{1:016x}".format(reg[0], self.reg_read(reg[1])))
except Exception as e:
print("ERROR: Are extended registers loaded?")
@@ -290,8 +339,8 @@ class AflUnicornEngine(Uc):
struct.unpack('<Q', self.mem_read(addr, 8))[0]))
"""
- #-----------------------------
- #---- Loader Helper Functions
+ # -----------------------------
+ # ---- Loader Helper Functions
def __load_registers(self, regs, reg_map, debug_print):
for register, value in regs.items():
@@ -307,7 +356,11 @@ class AflUnicornEngine(Uc):
reg_write_retry = False
except Exception as e:
if debug_print:
- print("ERROR writing register: {}, value: {} -- {}".format(register, value, repr(e)))
+ print(
+ "ERROR writing register: {}, value: {} -- {}".format(
+ register, value, repr(e)
+ )
+ )
if reg_write_retry:
if debug_print:
@@ -316,7 +369,11 @@ class AflUnicornEngine(Uc):
self.reg_write(reg_map[register.lower()], int(value, 16))
except Exception as e:
if debug_print:
- print("ERROR writing hex string register: {}, value: {} -- {}".format(register, value, repr(e)))
+ print(
+ "ERROR writing hex string register: {}, value: {} -- {}".format(
+ register, value, repr(e)
+ )
+ )
def __map_segment(self, name, address, size, perms, debug_print=False):
# - size is unsigned and must be != 0
@@ -330,24 +387,30 @@ class AflUnicornEngine(Uc):
if mem_start_aligned != mem_start or mem_end_aligned != mem_end:
print("Aligning segment to page boundary:")
print(" name: {}".format(name))
- print(" start: {0:016x} -> {1:016x}".format(mem_start, mem_start_aligned))
+ print(
+ " start: {0:016x} -> {1:016x}".format(mem_start, mem_start_aligned)
+ )
print(" end: {0:016x} -> {1:016x}".format(mem_end, mem_end_aligned))
- print("Mapping segment from {0:016x} - {1:016x} with perm={2}: {3}".format(mem_start_aligned, mem_end_aligned, perms, name))
- if(mem_start_aligned < mem_end_aligned):
+ print(
+ "Mapping segment from {0:016x} - {1:016x} with perm={2}: {3}".format(
+ mem_start_aligned, mem_end_aligned, perms, name
+ )
+ )
+ if mem_start_aligned < mem_end_aligned:
self.mem_map(mem_start_aligned, mem_end_aligned - mem_start_aligned, perms)
-
def __map_segments(self, segment_list, context_directory, debug_print=False):
for segment in segment_list:
# Get the segment information from the index
- name = segment['name']
- seg_start = segment['start']
- seg_end = segment['end']
- perms = \
- (UC_PROT_READ if segment['permissions']['r'] == True else 0) | \
- (UC_PROT_WRITE if segment['permissions']['w'] == True else 0) | \
- (UC_PROT_EXEC if segment['permissions']['x'] == True else 0)
+ name = segment["name"]
+ seg_start = segment["start"]
+ seg_end = segment["end"]
+ perms = (
+ (UC_PROT_READ if segment["permissions"]["r"] == True else 0)
+ | (UC_PROT_WRITE if segment["permissions"]["w"] == True else 0)
+ | (UC_PROT_EXEC if segment["permissions"]["x"] == True else 0)
+ )
if debug_print:
print("Handling segment {}".format(name))
@@ -376,48 +439,86 @@ class AflUnicornEngine(Uc):
# Map memory into the address space if it is of an acceptable size.
if (seg_end - seg_start) > MAX_ALLOWABLE_SEG_SIZE:
if debug_print:
- print("Skipping segment (LARGER THAN {0}) from {1:016x} - {2:016x} with perm={3}: {4}".format(MAX_ALLOWABLE_SEG_SIZE, seg_start, seg_end, perms, name))
+ print(
+ "Skipping segment (LARGER THAN {0}) from {1:016x} - {2:016x} with perm={3}: {4}".format(
+ MAX_ALLOWABLE_SEG_SIZE, seg_start, seg_end, perms, name
+ )
+ )
continue
- elif not found: # Make sure it's not already mapped
- if overlap_start: # Partial overlap (start)
+ elif not found: # Make sure it's not already mapped
+ if overlap_start: # Partial overlap (start)
self.__map_segment(name, tmp, seg_end - tmp, perms, debug_print)
- elif overlap_end: # Patrial overlap (end)
- self.__map_segment(name, seg_start, tmp - seg_start, perms, debug_print)
- else: # Not found
- self.__map_segment(name, seg_start, seg_end - seg_start, perms, debug_print)
+ elif overlap_end: # Patrial overlap (end)
+ self.__map_segment(
+ name, seg_start, tmp - seg_start, perms, debug_print
+ )
+ else: # Not found
+ self.__map_segment(
+ name, seg_start, seg_end - seg_start, perms, debug_print
+ )
else:
if debug_print:
print("Segment {} already mapped. Moving on.".format(name))
# Load the content (if available)
- if 'content_file' in segment and len(segment['content_file']) > 0:
- content_file_path = os.path.join(context_directory, segment['content_file'])
+ if "content_file" in segment and len(segment["content_file"]) > 0:
+ content_file_path = os.path.join(
+ context_directory, segment["content_file"]
+ )
if not os.path.isfile(content_file_path):
- raise Exception("Unable to find segment content file. Expected it to be at {}".format(content_file_path))
- #if debug_print:
+ raise Exception(
+ "Unable to find segment content file. Expected it to be at {}".format(
+ content_file_path
+ )
+ )
+ # if debug_print:
# print("Loading content for segment {} from {}".format(name, segment['content_file']))
- content_file = open(content_file_path, 'rb')
+ content_file = open(content_file_path, "rb")
compressed_content = content_file.read()
content_file.close()
self.mem_write(seg_start, zlib.decompress(compressed_content))
else:
if debug_print:
- print("No content found for segment {0} @ {1:016x}".format(name, seg_start))
- self.mem_write(seg_start, b'\x00' * (seg_end - seg_start))
+ print(
+ "No content found for segment {0} @ {1:016x}".format(
+ name, seg_start
+ )
+ )
+ self.mem_write(seg_start, b"\x00" * (seg_end - seg_start))
def __get_arch_and_mode(self, arch_str):
arch_map = {
- "x64" : [ UC_X86_REG_RIP, UC_ARCH_X86, UC_MODE_64 ],
- "x86" : [ UC_X86_REG_EIP, UC_ARCH_X86, UC_MODE_32 ],
- "arm64be" : [ UC_ARM64_REG_PC, UC_ARCH_ARM64, UC_MODE_ARM | UC_MODE_BIG_ENDIAN ],
- "arm64le" : [ UC_ARM64_REG_PC, UC_ARCH_ARM64, UC_MODE_ARM | UC_MODE_LITTLE_ENDIAN ],
- "armbe" : [ UC_ARM_REG_PC, UC_ARCH_ARM, UC_MODE_ARM | UC_MODE_BIG_ENDIAN ],
- "armle" : [ UC_ARM_REG_PC, UC_ARCH_ARM, UC_MODE_ARM | UC_MODE_LITTLE_ENDIAN ],
- "armbethumb": [ UC_ARM_REG_PC, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_BIG_ENDIAN ],
- "armlethumb": [ UC_ARM_REG_PC, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_LITTLE_ENDIAN ],
- "mips" : [ UC_MIPS_REG_PC, UC_ARCH_MIPS, UC_MODE_MIPS32 | UC_MODE_BIG_ENDIAN ],
- "mipsel" : [ UC_MIPS_REG_PC, UC_ARCH_MIPS, UC_MODE_MIPS32 | UC_MODE_LITTLE_ENDIAN ],
+ "x64": [UC_X86_REG_RIP, UC_ARCH_X86, UC_MODE_64],
+ "x86": [UC_X86_REG_EIP, UC_ARCH_X86, UC_MODE_32],
+ "arm64be": [
+ UC_ARM64_REG_PC,
+ UC_ARCH_ARM64,
+ UC_MODE_ARM | UC_MODE_BIG_ENDIAN,
+ ],
+ "arm64le": [
+ UC_ARM64_REG_PC,
+ UC_ARCH_ARM64,
+ UC_MODE_ARM | UC_MODE_LITTLE_ENDIAN,
+ ],
+ "armbe": [UC_ARM_REG_PC, UC_ARCH_ARM, UC_MODE_ARM | UC_MODE_BIG_ENDIAN],
+ "armle": [UC_ARM_REG_PC, UC_ARCH_ARM, UC_MODE_ARM | UC_MODE_LITTLE_ENDIAN],
+ "armbethumb": [
+ UC_ARM_REG_PC,
+ UC_ARCH_ARM,
+ UC_MODE_THUMB | UC_MODE_BIG_ENDIAN,
+ ],
+ "armlethumb": [
+ UC_ARM_REG_PC,
+ UC_ARCH_ARM,
+ UC_MODE_THUMB | UC_MODE_LITTLE_ENDIAN,
+ ],
+ "mips": [UC_MIPS_REG_PC, UC_ARCH_MIPS, UC_MODE_MIPS32 | UC_MODE_BIG_ENDIAN],
+ "mipsel": [
+ UC_MIPS_REG_PC,
+ UC_ARCH_MIPS,
+ UC_MODE_MIPS32 | UC_MODE_LITTLE_ENDIAN,
+ ],
}
return (arch_map[arch_str][1], arch_map[arch_str][2])
@@ -430,140 +531,140 @@ class AflUnicornEngine(Uc):
arch = "mips"
registers = {
- "x64" : {
- "rax": UC_X86_REG_RAX,
- "rbx": UC_X86_REG_RBX,
- "rcx": UC_X86_REG_RCX,
- "rdx": UC_X86_REG_RDX,
- "rsi": UC_X86_REG_RSI,
- "rdi": UC_X86_REG_RDI,
- "rbp": UC_X86_REG_RBP,
- "rsp": UC_X86_REG_RSP,
- "r8": UC_X86_REG_R8,
- "r9": UC_X86_REG_R9,
- "r10": UC_X86_REG_R10,
- "r11": UC_X86_REG_R11,
- "r12": UC_X86_REG_R12,
- "r13": UC_X86_REG_R13,
- "r14": UC_X86_REG_R14,
- "r15": UC_X86_REG_R15,
- "rip": UC_X86_REG_RIP,
- "efl": UC_X86_REG_EFLAGS,
- "cs": UC_X86_REG_CS,
- "ds": UC_X86_REG_DS,
- "es": UC_X86_REG_ES,
- "fs": UC_X86_REG_FS,
- "gs": UC_X86_REG_GS,
- "ss": UC_X86_REG_SS,
+ "x64": {
+ "rax": UC_X86_REG_RAX,
+ "rbx": UC_X86_REG_RBX,
+ "rcx": UC_X86_REG_RCX,
+ "rdx": UC_X86_REG_RDX,
+ "rsi": UC_X86_REG_RSI,
+ "rdi": UC_X86_REG_RDI,
+ "rbp": UC_X86_REG_RBP,
+ "rsp": UC_X86_REG_RSP,
+ "r8": UC_X86_REG_R8,
+ "r9": UC_X86_REG_R9,
+ "r10": UC_X86_REG_R10,
+ "r11": UC_X86_REG_R11,
+ "r12": UC_X86_REG_R12,
+ "r13": UC_X86_REG_R13,
+ "r14": UC_X86_REG_R14,
+ "r15": UC_X86_REG_R15,
+ "rip": UC_X86_REG_RIP,
+ "efl": UC_X86_REG_EFLAGS,
+ "cs": UC_X86_REG_CS,
+ "ds": UC_X86_REG_DS,
+ "es": UC_X86_REG_ES,
+ "fs": UC_X86_REG_FS,
+ "gs": UC_X86_REG_GS,
+ "ss": UC_X86_REG_SS,
},
- "x86" : {
- "eax": UC_X86_REG_EAX,
- "ebx": UC_X86_REG_EBX,
- "ecx": UC_X86_REG_ECX,
- "edx": UC_X86_REG_EDX,
- "esi": UC_X86_REG_ESI,
- "edi": UC_X86_REG_EDI,
- "ebp": UC_X86_REG_EBP,
- "eip": UC_X86_REG_EIP,
- "esp": UC_X86_REG_ESP,
- "efl": UC_X86_REG_EFLAGS,
+ "x86": {
+ "eax": UC_X86_REG_EAX,
+ "ebx": UC_X86_REG_EBX,
+ "ecx": UC_X86_REG_ECX,
+ "edx": UC_X86_REG_EDX,
+ "esi": UC_X86_REG_ESI,
+ "edi": UC_X86_REG_EDI,
+ "ebp": UC_X86_REG_EBP,
+ "eip": UC_X86_REG_EIP,
+ "esp": UC_X86_REG_ESP,
+ "efl": UC_X86_REG_EFLAGS,
# Segment registers removed...
# They caused segfaults (from unicorn?) when they were here
},
- "arm" : {
- "r0": UC_ARM_REG_R0,
- "r1": UC_ARM_REG_R1,
- "r2": UC_ARM_REG_R2,
- "r3": UC_ARM_REG_R3,
- "r4": UC_ARM_REG_R4,
- "r5": UC_ARM_REG_R5,
- "r6": UC_ARM_REG_R6,
- "r7": UC_ARM_REG_R7,
- "r8": UC_ARM_REG_R8,
- "r9": UC_ARM_REG_R9,
- "r10": UC_ARM_REG_R10,
- "r11": UC_ARM_REG_R11,
- "r12": UC_ARM_REG_R12,
- "pc": UC_ARM_REG_PC,
- "sp": UC_ARM_REG_SP,
- "lr": UC_ARM_REG_LR,
- "cpsr": UC_ARM_REG_CPSR
+ "arm": {
+ "r0": UC_ARM_REG_R0,
+ "r1": UC_ARM_REG_R1,
+ "r2": UC_ARM_REG_R2,
+ "r3": UC_ARM_REG_R3,
+ "r4": UC_ARM_REG_R4,
+ "r5": UC_ARM_REG_R5,
+ "r6": UC_ARM_REG_R6,
+ "r7": UC_ARM_REG_R7,
+ "r8": UC_ARM_REG_R8,
+ "r9": UC_ARM_REG_R9,
+ "r10": UC_ARM_REG_R10,
+ "r11": UC_ARM_REG_R11,
+ "r12": UC_ARM_REG_R12,
+ "pc": UC_ARM_REG_PC,
+ "sp": UC_ARM_REG_SP,
+ "lr": UC_ARM_REG_LR,
+ "cpsr": UC_ARM_REG_CPSR,
},
- "arm64" : {
- "x0": UC_ARM64_REG_X0,
- "x1": UC_ARM64_REG_X1,
- "x2": UC_ARM64_REG_X2,
- "x3": UC_ARM64_REG_X3,
- "x4": UC_ARM64_REG_X4,
- "x5": UC_ARM64_REG_X5,
- "x6": UC_ARM64_REG_X6,
- "x7": UC_ARM64_REG_X7,
- "x8": UC_ARM64_REG_X8,
- "x9": UC_ARM64_REG_X9,
- "x10": UC_ARM64_REG_X10,
- "x11": UC_ARM64_REG_X11,
- "x12": UC_ARM64_REG_X12,
- "x13": UC_ARM64_REG_X13,
- "x14": UC_ARM64_REG_X14,
- "x15": UC_ARM64_REG_X15,
- "x16": UC_ARM64_REG_X16,
- "x17": UC_ARM64_REG_X17,
- "x18": UC_ARM64_REG_X18,
- "x19": UC_ARM64_REG_X19,
- "x20": UC_ARM64_REG_X20,
- "x21": UC_ARM64_REG_X21,
- "x22": UC_ARM64_REG_X22,
- "x23": UC_ARM64_REG_X23,
- "x24": UC_ARM64_REG_X24,
- "x25": UC_ARM64_REG_X25,
- "x26": UC_ARM64_REG_X26,
- "x27": UC_ARM64_REG_X27,
- "x28": UC_ARM64_REG_X28,
- "pc": UC_ARM64_REG_PC,
- "sp": UC_ARM64_REG_SP,
- "fp": UC_ARM64_REG_FP,
- "lr": UC_ARM64_REG_LR,
- "nzcv": UC_ARM64_REG_NZCV,
+ "arm64": {
+ "x0": UC_ARM64_REG_X0,
+ "x1": UC_ARM64_REG_X1,
+ "x2": UC_ARM64_REG_X2,
+ "x3": UC_ARM64_REG_X3,
+ "x4": UC_ARM64_REG_X4,
+ "x5": UC_ARM64_REG_X5,
+ "x6": UC_ARM64_REG_X6,
+ "x7": UC_ARM64_REG_X7,
+ "x8": UC_ARM64_REG_X8,
+ "x9": UC_ARM64_REG_X9,
+ "x10": UC_ARM64_REG_X10,
+ "x11": UC_ARM64_REG_X11,
+ "x12": UC_ARM64_REG_X12,
+ "x13": UC_ARM64_REG_X13,
+ "x14": UC_ARM64_REG_X14,
+ "x15": UC_ARM64_REG_X15,
+ "x16": UC_ARM64_REG_X16,
+ "x17": UC_ARM64_REG_X17,
+ "x18": UC_ARM64_REG_X18,
+ "x19": UC_ARM64_REG_X19,
+ "x20": UC_ARM64_REG_X20,
+ "x21": UC_ARM64_REG_X21,
+ "x22": UC_ARM64_REG_X22,
+ "x23": UC_ARM64_REG_X23,
+ "x24": UC_ARM64_REG_X24,
+ "x25": UC_ARM64_REG_X25,
+ "x26": UC_ARM64_REG_X26,
+ "x27": UC_ARM64_REG_X27,
+ "x28": UC_ARM64_REG_X28,
+ "pc": UC_ARM64_REG_PC,
+ "sp": UC_ARM64_REG_SP,
+ "fp": UC_ARM64_REG_FP,
+ "lr": UC_ARM64_REG_LR,
+ "nzcv": UC_ARM64_REG_NZCV,
"cpsr": UC_ARM_REG_CPSR,
},
- "mips" : {
- "0" : UC_MIPS_REG_ZERO,
- "at": UC_MIPS_REG_AT,
- "v0": UC_MIPS_REG_V0,
- "v1": UC_MIPS_REG_V1,
- "a0": UC_MIPS_REG_A0,
- "a1": UC_MIPS_REG_A1,
- "a2": UC_MIPS_REG_A2,
- "a3": UC_MIPS_REG_A3,
- "t0": UC_MIPS_REG_T0,
- "t1": UC_MIPS_REG_T1,
- "t2": UC_MIPS_REG_T2,
- "t3": UC_MIPS_REG_T3,
- "t4": UC_MIPS_REG_T4,
- "t5": UC_MIPS_REG_T5,
- "t6": UC_MIPS_REG_T6,
- "t7": UC_MIPS_REG_T7,
- "t8": UC_MIPS_REG_T8,
- "t9": UC_MIPS_REG_T9,
- "s0": UC_MIPS_REG_S0,
- "s1": UC_MIPS_REG_S1,
- "s2": UC_MIPS_REG_S2,
- "s3": UC_MIPS_REG_S3,
- "s4": UC_MIPS_REG_S4,
- "s5": UC_MIPS_REG_S5,
- "s6": UC_MIPS_REG_S6,
- "s7": UC_MIPS_REG_S7,
- "s8": UC_MIPS_REG_S8,
- "k0": UC_MIPS_REG_K0,
- "k1": UC_MIPS_REG_K1,
- "gp": UC_MIPS_REG_GP,
- "pc": UC_MIPS_REG_PC,
- "sp": UC_MIPS_REG_SP,
- "fp": UC_MIPS_REG_FP,
- "ra": UC_MIPS_REG_RA,
- "hi": UC_MIPS_REG_HI,
- "lo": UC_MIPS_REG_LO
- }
+ "mips": {
+ "0": UC_MIPS_REG_ZERO,
+ "at": UC_MIPS_REG_AT,
+ "v0": UC_MIPS_REG_V0,
+ "v1": UC_MIPS_REG_V1,
+ "a0": UC_MIPS_REG_A0,
+ "a1": UC_MIPS_REG_A1,
+ "a2": UC_MIPS_REG_A2,
+ "a3": UC_MIPS_REG_A3,
+ "t0": UC_MIPS_REG_T0,
+ "t1": UC_MIPS_REG_T1,
+ "t2": UC_MIPS_REG_T2,
+ "t3": UC_MIPS_REG_T3,
+ "t4": UC_MIPS_REG_T4,
+ "t5": UC_MIPS_REG_T5,
+ "t6": UC_MIPS_REG_T6,
+ "t7": UC_MIPS_REG_T7,
+ "t8": UC_MIPS_REG_T8,
+ "t9": UC_MIPS_REG_T9,
+ "s0": UC_MIPS_REG_S0,
+ "s1": UC_MIPS_REG_S1,
+ "s2": UC_MIPS_REG_S2,
+ "s3": UC_MIPS_REG_S3,
+ "s4": UC_MIPS_REG_S4,
+ "s5": UC_MIPS_REG_S5,
+ "s6": UC_MIPS_REG_S6,
+ "s7": UC_MIPS_REG_S7,
+ "s8": UC_MIPS_REG_S8,
+ "k0": UC_MIPS_REG_K0,
+ "k1": UC_MIPS_REG_K1,
+ "gp": UC_MIPS_REG_GP,
+ "pc": UC_MIPS_REG_PC,
+ "sp": UC_MIPS_REG_SP,
+ "fp": UC_MIPS_REG_FP,
+ "ra": UC_MIPS_REG_RA,
+ "hi": UC_MIPS_REG_HI,
+ "lo": UC_MIPS_REG_LO,
+ },
}
return registers[arch]
@@ -577,51 +678,50 @@ class AflUnicornEngine(Uc):
arch = "mips"
registers = {
- "arm": {
- "d0": UC_ARM_REG_D0,
- "d1": UC_ARM_REG_D1,
- "d2": UC_ARM_REG_D2,
- "d3": UC_ARM_REG_D3,
- "d4": UC_ARM_REG_D4,
- "d5": UC_ARM_REG_D5,
- "d6": UC_ARM_REG_D6,
- "d7": UC_ARM_REG_D7,
- "d8": UC_ARM_REG_D8,
- "d9": UC_ARM_REG_D9,
- "d10": UC_ARM_REG_D10,
- "d11": UC_ARM_REG_D11,
- "d12": UC_ARM_REG_D12,
- "d13": UC_ARM_REG_D13,
- "d14": UC_ARM_REG_D14,
- "d15": UC_ARM_REG_D15,
- "d16": UC_ARM_REG_D16,
- "d17": UC_ARM_REG_D17,
- "d18": UC_ARM_REG_D18,
- "d19": UC_ARM_REG_D19,
- "d20": UC_ARM_REG_D20,
- "d21": UC_ARM_REG_D21,
- "d22": UC_ARM_REG_D22,
- "d23": UC_ARM_REG_D23,
- "d24": UC_ARM_REG_D24,
- "d25": UC_ARM_REG_D25,
- "d26": UC_ARM_REG_D26,
- "d27": UC_ARM_REG_D27,
- "d28": UC_ARM_REG_D28,
- "d29": UC_ARM_REG_D29,
- "d30": UC_ARM_REG_D30,
- "d31": UC_ARM_REG_D31,
- "fpscr": UC_ARM_REG_FPSCR
+ "arm": {
+ "d0": UC_ARM_REG_D0,
+ "d1": UC_ARM_REG_D1,
+ "d2": UC_ARM_REG_D2,
+ "d3": UC_ARM_REG_D3,
+ "d4": UC_ARM_REG_D4,
+ "d5": UC_ARM_REG_D5,
+ "d6": UC_ARM_REG_D6,
+ "d7": UC_ARM_REG_D7,
+ "d8": UC_ARM_REG_D8,
+ "d9": UC_ARM_REG_D9,
+ "d10": UC_ARM_REG_D10,
+ "d11": UC_ARM_REG_D11,
+ "d12": UC_ARM_REG_D12,
+ "d13": UC_ARM_REG_D13,
+ "d14": UC_ARM_REG_D14,
+ "d15": UC_ARM_REG_D15,
+ "d16": UC_ARM_REG_D16,
+ "d17": UC_ARM_REG_D17,
+ "d18": UC_ARM_REG_D18,
+ "d19": UC_ARM_REG_D19,
+ "d20": UC_ARM_REG_D20,
+ "d21": UC_ARM_REG_D21,
+ "d22": UC_ARM_REG_D22,
+ "d23": UC_ARM_REG_D23,
+ "d24": UC_ARM_REG_D24,
+ "d25": UC_ARM_REG_D25,
+ "d26": UC_ARM_REG_D26,
+ "d27": UC_ARM_REG_D27,
+ "d28": UC_ARM_REG_D28,
+ "d29": UC_ARM_REG_D29,
+ "d30": UC_ARM_REG_D30,
+ "d31": UC_ARM_REG_D31,
+ "fpscr": UC_ARM_REG_FPSCR,
}
}
- return registers[arch];
- #---------------------------
- # Callbacks for tracing
+ return registers[arch]
+ # ---------------------------
+ # Callbacks for tracing
# TODO: Extra mode for Capstone (i.e. Cs(cs_arch, cs_mode + cs_extra) not implemented
-
def __trace_instruction(self, uc, address, size, user_data):
if CAPSTONE_EXISTS == 1:
# If Capstone is installed then we'll dump disassembly, otherwise just dump the binary.
@@ -651,11 +751,23 @@ class AflUnicornEngine(Uc):
cs = Cs(cs_arch, cs_mode)
mem = uc.mem_read(address, size)
if bit_size == 4:
- for (cs_address, cs_size, cs_mnemonic, cs_opstr) in cs.disasm_lite(bytes(mem), size):
- print(" Instr: {:#08x}:\t{}\t{}".format(address, cs_mnemonic, cs_opstr))
+ for (cs_address, cs_size, cs_mnemonic, cs_opstr) in cs.disasm_lite(
+ bytes(mem), size
+ ):
+ print(
+ " Instr: {:#08x}:\t{}\t{}".format(
+ address, cs_mnemonic, cs_opstr
+ )
+ )
else:
- for (cs_address, cs_size, cs_mnemonic, cs_opstr) in cs.disasm_lite(bytes(mem), size):
- print(" Instr: {:#16x}:\t{}\t{}".format(address, cs_mnemonic, cs_opstr))
+ for (cs_address, cs_size, cs_mnemonic, cs_opstr) in cs.disasm_lite(
+ bytes(mem), size
+ ):
+ print(
+ " Instr: {:#16x}:\t{}\t{}".format(
+ address, cs_mnemonic, cs_opstr
+ )
+ )
else:
print(" Instr: addr=0x{0:016x}, size=0x{1:016x}".format(address, size))
@@ -664,15 +776,27 @@ class AflUnicornEngine(Uc):
def __trace_mem_access(self, uc, access, address, size, value, user_data):
if access == UC_MEM_WRITE:
- print(" >>> Write: addr=0x{0:016x} size={1} data=0x{2:016x}".format(address, size, value))
+ print(
+ " >>> Write: addr=0x{0:016x} size={1} data=0x{2:016x}".format(
+ address, size, value
+ )
+ )
else:
print(" >>> Read: addr=0x{0:016x} size={1}".format(address, size))
def __trace_mem_invalid_access(self, uc, access, address, size, value, user_data):
if access == UC_MEM_WRITE_UNMAPPED:
- print(" >>> INVALID Write: addr=0x{0:016x} size={1} data=0x{2:016x}".format(address, size, value))
+ print(
+ " >>> INVALID Write: addr=0x{0:016x} size={1} data=0x{2:016x}".format(
+ address, size, value
+ )
+ )
else:
- print(" >>> INVALID Read: addr=0x{0:016x} size={1}".format(address, size))
+ print(
+ " >>> INVALID Read: addr=0x{0:016x} size={1}".format(
+ address, size
+ )
+ )
def bit_size_arch(self):
arch = self.get_arch()