Esempio n. 1
0
def get_decompile_interface():  # type: () -> DecompInterface
    interface = DecompInterface()
    options = DecompileOptions()
    interface.setOptions(options)
    interface.openProgram(currentProgram)
    interface.setSimplificationStyle("decompile")
    return interface
Esempio n. 2
0
def decompile(func):
    global decompiler
    if decompiler is None:
        decompiler = DecompInterface()
        decompiler.openProgram(currentProgram)
    results = decompiler.decompileFunction(func, 10, TaskMonitor.DUMMY)
    return results
Esempio n. 3
0
def renameFunctionsBasedOnstringRefrencesUsingTheDecompiler():
    monitor.setMessage("Rename Functions Based on string refrences ")    
    function =  getFirstFunction()
    decompinterface = DecompInterface()
    decompinterface.openProgram(currentProgram)
    uniqueList = []
    while function is not None and not monitor.isCancelled():
        try:
            tokengrp   = decompinterface.decompileFunction(function, 0, ConsoleTaskMonitor())
            code       = tokengrp.getDecompiledFunction().getC()
            pattern1   = r"\"[a-zA-Z0-9 .,\-\*\/\[\]\{\}\!\@\#\$\%\^\&\(\)\=\~\:\"\'\\\+\?\>\<\`\_\;]+\""
            pattern2   = r'[ .,\-\*\/\[\]\{\}\!\@\#\$\%\^\&\(\)\=\~\:\"\'\\\+\?\>\<\`]+'
            stringList = re.findall(pattern1,code)
            if not stringList == []:
                for unique in stringList:  
                    if unique not in uniqueList: 
                        uniqueList.append(unique)
                name = re.sub(pattern2,"","_".join(uniqueList))
                if len(name) > 15:
                    name = name[:15]
                functionName = "rep_s_fun_" + str(function.getEntryPoint()) + "_" + name
                print functionName               
                function.setName(functionName,USER_DEFINED)
        except:
            pass
    function = getFunctionAfter(function)
    return 0
Esempio n. 4
0
 def get_hfunction(self):
     decomplib = DecompInterface()
     decomplib.openProgram(currentProgram)
     timeout = self.timeout
     dRes = decomplib.decompileFunction(self.function, timeout, getMonitor())
     hfunction = dRes.getHighFunction()
     return hfunction
Esempio n. 5
0
def get_high_function(func):
    options = DecompileOptions()
    monitor = ConsoleTaskMonitor()
    ifc = DecompInterface()
    ifc.setOptions(options)
    ifc.openProgram(getCurrentProgram())
    res = ifc.decompileFunction(func, 60, monitor)
    return res.getHighFunction()
Esempio n. 6
0
class Decompiler:
    '''decompile binary into psuedo c using Ghidra API.
    Usage:
        >>> decompiler = Decompiler()
        >>> psuedo_c = decompiler.decompile()
        >>> # then write to file
    '''

    def __init__(self, program=None, timeout=None):
        '''init Decompiler class.
        Args:
            program (ghidra.program.model.listing.Program): target program to decompile, 
                default is `currentProgram`.
            timeout (ghidra.util.task.TaskMonitor): timeout for DecompInterface::decompileFunction
        '''

        # initialize decompiler with current program
        self._decompiler = DecompInterface()
        self._decompiler.openProgram(program or ghidra_app.currentProgram)

        self._timeout = timeout
    
    def decompile_func(self, func):
        '''decompile one function.
        Args:
            func (ghidra.program.model.listing.Function): function to be decompiled
        Returns:
            string: decompiled psuedo C code
        '''

        # decompile
        dec_status = self._decompiler.decompileFunction(func, 0, self._timeout)
        # check if it's successfully decompiled
        if dec_status and dec_status.decompileCompleted():
            # get psuedo c code
            dec_ret = dec_status.getDecompiledFunction()
            if dec_ret:
                return dec_ret.getC()

    def decompile(self):
        '''decompile all function recognized by Ghidra.
        Returns:
            string: decompiled all function as psuedo C
        '''

        # all decompiled result will be joined
        psuedo_c = ''

        # enum all functions and decompile each function
        funcs = ghidra_app.currentProgram.getListing().getFunctions(True)
        for func in funcs:
            dec_func = self.decompile_func(func)
            if dec_func:
                psuedo_c += dec_func

        return psuedo_c
def get_high_function(current_program, current_address):
    decomplib = DecompInterface()
    decomplib.openProgram(current_program)

    current_function = getFunctionContaining(current_address)
    decompile_res = decomplib.decompileFunction(current_function, 30,
                                                getMonitor())

    high_function = decompile_res.getHighFunction()
    return high_function
def decompile_func(func):
    decompiler = DecompInterface()
    decompiler.openProgram(currentProgram)

    results = decompiler.decompileFunction(func, 0, monitor)
    if not results.decompileCompleted():
        raise RuntimeError('failed to decompile function: {}'.format(func))

    high_func = results.getHighFunction()
    return high_func
Esempio n. 9
0
    def colorize_blocks(self):
        global FINAL_MATCH_DICT
        global TABLE_DIALOG

        decompInterface = DecompInterface()
        decompInterface.openProgram(currentProgram)

        cov_block_list = []
        for bb in self.basic_blocks.keys():
            start_addr = toAddr(bb + self.program_base)
            block_size = self.basic_blocks[bb] - 1
            function = getFunctionContaining(start_addr)
            self.set_basic_block_colors(start_addr, block_size)
            if function and not function in cov_block_list:
                cov_block_list.append(function)

        for function in cov_block_list:
            hfunction = decompInterface.decompileFunction(
                function, 30, TaskMonitor.DUMMY).getHighFunction()
            basic_blocks = hfunction.getBasicBlocks()
            basic_block_len = len(basic_blocks)
            total_block_size = 0
            function_size = 0
            total_cov_size = 0
            for block in basic_blocks:
                block_size = int(block.getStop().toString(), 16) - int(
                    block.getStart().toString(), 16)
                function_size += block_size
                bg_color = service.getBackgroundColor(block.getStart())
                if bg_color and bg_color.getRGB() == -16711764:
                    total_block_size += 1
                    total_cov_size += block_size

            block_hit = str(total_block_size) + "/" + str(basic_block_len)

            if total_cov_size > 0:
                total_cov_size = str(
                    int(100 * float(total_cov_size) /
                        float(function_size))) + "%"
            elif total_block_size == basic_block_len:
                total_cov_size = "100%"
            else:
                total_cov_size = "0%"

            FINAL_MATCH_DICT[function.getName()] = [
                function.getName(), total_cov_size, block_hit,
                function.getEntryPoint()
            ]

        for key in FINAL_MATCH_DICT.keys():
            init_obj = Initializer()
            init_obj.head = key
            init_obj.function_address = FINAL_MATCH_DICT[key][3]
            FINAL_MATCH_DICT[key].append(init_obj)
            TABLE_DIALOG.add(init_obj)
Esempio n. 10
0
def get_decompilation(calle_addr, func_name):
    program = getCurrentProgram()
    ifc = DecompInterface()
    ifc.openProgram(program)

    # here we assume there is only one function named `main`
    function = getGlobalFunctions(func_name)[0]

    # decompile the function and print the pseudo C
    results = ifc.decompileFunction(function, 0, ConsoleTaskMonitor())
    print(results.getDecompiledFunction().getC())
    return results.getDecompiledFunction().getC()
Esempio n. 11
0
def _decompile():
    decompiler = DecompInterface()
    decompiler.openProgram(currentProgram)

    de_c = ""
    funcs = currentProgram.getListing().getFunctions(True)
    for func in funcs:
        decompiled_func = _decompile_func(decompiler, func)
        if decompiled_func:
            de_c += decompiled_func

    return de_c
Esempio n. 12
0
def _decompiler():
    ifc = DecompInterface()
    DecOptions = DecompileOptions()
    service = state.getTool().getService(OptionsService)

    opt = service.getOptions("Decompiler")
    DecOptions.grabFromToolAndProgram(None, opt, currentProgram)
    ifc.setOptions(DecOptions)

    ifc.toggleCCode(True)
    ifc.toggleSyntaxTree(True)
    ifc.setSimplificationStyle("decompile")

    ifc.openProgram(currentProgram)
    return ifc
Esempio n. 13
0
def generate_decomp_interface():
    decompiler = DecompInterface()
    opts = DecompileOptions()
    opts.grabFromProgram(curr)
    decompiler.setOptions(opts)
    decompiler.toggleCCode(True)
    decompiler.toggleSyntaxTree(True)

    # - decompile -- The main decompiler action
    # - normalize -- Decompilation tuned for normalization
    # - jumptable -- Simplify just enough to recover a jump-table
    # - paramid   -- Simplify enough to recover function parameters
    # - register  -- Perform one analysis pass on registers, without stack variables
    # - firstpass -- Construct the initial raw syntax tree, with no simplification
    decompiler.setSimplificationStyle("decompile")
    decompiler.openProgram(curr)
    return decompiler
Esempio n. 14
0
        def stub(address):
            functionOffset = function.getEntryPoint().getOffset()
            while functionOffset not in function_arguments_cache and not monitor.isCancelled():
                # program = currentProgram
                # function = currentProgram.getFunctionManager().getFunctionContaining(currentAddress)
                decompinterface = DecompInterface()
                decompinterface.openProgram(program)
                result = decompinterface.decompileFunction(function, 0, monitor)
                highFunction = result.getHighFunction()
                if not result.isCancelled() and not result.isTimedOut():
                    function_arguments_cache[functionOffset] = highFunction
            assert(functionOffset in function_arguments_cache)
            highFunction = function_arguments_cache[functionOffset]

            symbolMap = highFunction.getLocalSymbolMap()
            args = []
            for parameter in [symbolMap.getParam(i) for i in range(symbolMap.getNumParams())]:
                emulator.logger.debug("Found parameter `%s` with size `%d` with type `%s`" % (parameter.getName(), parameter.getSize(), str(parameter.getDataType())))
                param = getParam(parameter, emulator, monitor)
                args.append(param)
            emulator.logger.debug(str(args))
            retval = func(*args)
            emulator.logger.debug('Finish execution of hook %s with return value %s' % (func.__name__, repr(retval)))
            pointerSize = emulator.program.getLanguage().getProgramCounter().getBitLength()//8
            
            if type(retval) == int or type(retval) == long:
                retval = long_to_bytes(retval, pointerSize)
                if not emulator.program.getLanguage().isBigEndian():
                    retval = retval[::-1]
            offset = 0
            for varnode in function.getReturn().getVariableStorage().getVarnodes():
                emulator.emulatorHelper.writeMemory(varnode.getAddress(), retval[offset:offset+varnode.getSize()])
                offset += varnode.getSize()
            emulator.logger.debug('Finish execution of hook %s we were at %s before' % (func.__name__, str(emulator.lastAddresses)))
            current = emulator.emulatorHelper.getExecutionAddress()
            for address in emulator.lastAddresses:                
                emulator.logger.debug('Checking if %s is different from %s' % (address, current))
                if str(address) != str(current):
                    nextAddress = emulator.flatapi.getInstructionAfter(address).getAddress()
                    emulator.logger.debug('I propose to go to %s now' % (str(nextAddress)))
                    emulator.emulatorHelper.getEmulator().setExecuteAddress(nextAddress.getOffset())
                    emulator.logger.debug('Can you believe that we are at %s now?' % (str(emulator.emulatorHelper.getExecutionAddress())))
                    break
            return True
Esempio n. 15
0
                        newTypeName = newTypeName[:newTypeName.find(
                            '<')].replace(
                                u'::',
                                u'/') + newTypeName[newTypeName.find('<'):]
                        newType = currentProgram.getDataTypeManager(
                        ).getDataType("boot.dol/Demangler/" + newTypeName)
                        print offset, newTypeName, newType
                        thisType.replaceAtOffset(offset.value, newType, 0,
                                                 None, None)
        inst = inst.next

options = DecompileOptions()
monitor = ConsoleTaskMonitor()
ifc = DecompInterface()
ifc.setOptions(options)
ifc.openProgram(currentFunction.program)
res = ifc.decompileFunction(currentFunction, 60, monitor)
high_func = res.getHighFunction()

inst = getInstructionAt(currentAddress)
while inst.address < currentFunction.body.maxAddress:
    callConstructor = None
    if inst.getFlowType().isCall() and \
       inst.getFlows()[0] == baseParamConstructor.entryPoint:
        callConstructor = inst
        print "Constructor is called at", callConstructor.address

    fieldOffset = None
    if callConstructor is not None:
        call = list(high_func.getPcodeOps(callConstructor.address))[0]
        thisDef = call.inputs[1].getDef().inputs[0].getDef()
Esempio n. 16
0
# Verify the '.text' section is loaded
assert ('.text' in [b.name for b in getMemoryBlocks()])

# Verify the entry point has been marked
entry = None
for f in currentProgram.getFunctionManager().getFunctions(True):
    if f.name == 'entry':
        entry = f
        break
assert (entry is not None)

# Attempt to decompile the entry point function
from ghidra.app.decompiler import DecompInterface
di = DecompInterface()
di.openProgram(currentProgram)
print(di.decompileFunction(entry, 0, None).getDecompiledFunction().getC())

# Ghidra silently swallows exceptions, so create a file at the end of the test
# to mark success
open('TEST_PASS', 'w').write('pass')
Esempio n. 17
0
#@category
#@keybinding
#@menupath Tools.Misc.Populate empty structs
#@toolbar

import re  #gex
from ghidra.util.task import ConsoleTaskMonitor
from ghidra.app.decompiler import DecompileOptions, DecompInterface
from ghidra.program.model.data import PointerDataType, Pointer
from ghidra.program.database.data import StructureDB

program = getCurrentProgram()
dataManager = program.getDataTypeManager()
# We use the decompiler to find accesses to fields.
ifc = DecompInterface()
ifc.openProgram(program)
fm = program.getFunctionManager()

# all_datatypes is just a way of skipping the paths from the DataTypeManager
all_datatypes = dict()
for d in dataManager.getAllDataTypes():
    all_datatypes[d.getName()] = d
all_datatypes["code"] = all_datatypes["void"]


def getAddress(offset):
    return program.getAddressFactory().getDefaultAddressSpace().getAddress(
        offset)


def strToDataType(s):
Esempio n. 18
0
        data = sock.recv(rem)
        rem = rem - len(data)
    return data


def wr(sock, data):
    sz = len(data)
    i = 0
    while i < sz:
        s = sock.send(data[i:])
        i = i + s


fm = currentProgram.getFunctionManager()
decompiler = DecompInterface()
decompiler.openProgram(currentProgram)

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(("localhost", 14444))
serversocket.listen(1)

while True:
    try:
        (sock, address) = serversocket.accept()
        while True:
            addr_req = rd(sock, 8)
            fixed_addr = struct.unpack("<Q", addr_req)[0]
            addr_obj = getAddress(fixed_addr)
            func = fm.getFunctionContaining(addr_obj)
            status = decompiler.decompileFunction(func, 0, None)
            if status != None and status.getDecompiledFunction():
Esempio n. 19
0
def fixUndefinedDataTypes():
	monitor.setMessage("Fixing Undefined Data Types")	
	function =  getFirstFunction()
	decompinterface = DecompInterface()
	decompinterface.openProgram(currentProgram)

    # get var list from decompilation
	while function is not None:
		prt 	   = False
		varList    = []
		try:
			tokengrp   = decompinterface.decompileFunction(function, 0, ConsoleTaskMonitor())
			code       = tokengrp.getDecompiledFunction().getC()
			for line in code.split("\n"):
				if line == "  \r":
					break
				if prt:
					varList.append(filter(None,line.split(";")[0].split(" ")))
				if line.startswith("{"):
					prt = True   
		except:
			pass

		for var in function.getAllVariables():
			varMsg = str(var)
			dt  = str(var.getDataType())
			inx = 0
			if "undefined" in dt:
				for decVar in varList:
					if len(decVar) > 1:
						arr = False
						if len(decVar) == 3:
							arr = True
							inx = int(decVar[2].split("[")[1].split("]")[0])
						if decVar[1].replace("*","") == var.getName():		
							if not "undefined" in decVar[0]:
								if '*' in decVar[1]:
									dt = getDataType("/" + decVar[0] + " " + ('*' * decVar[1].count("*")),arr,inx)
								else:								
									dt = getDataType("/" + decVar[0],arr,inx)
							else:							
								if '*' in decVar[1]:
									dtlen = decVar[0].replace("undefined","")
									if dtlen == "":
										dtlen = "1"
									dt = getDataTypeWrap(dtlen + ('*' * decVar[1].count("*")),arr,inx)
								else:
									dt = getDataTypeWrap(decVar[0],arr,inx)

				if type(dt) == str:
					dt = str(var.getDataType())
					dt = dt.replace("undefined","")
					dt = getDataTypeWrap(dt)
				if dt:
					try:
						var.setDataType(dt,USER_DEFINED)
						print "[+] " + str(function.getName()) + ": " + varMsg + " -> " + str(dt)
					except:
						pass
		function = getFunctionAfter(function)
	return 0
from ghidra.program.model.symbol import SourceType
from ghidra.program.model.listing.Function import FunctionUpdateType
from ghidra.app.util.cparser.C import CParserUtils
from ghidra.program.model.listing import ReturnParameterImpl
from ghidra.program.model.listing import ParameterImpl

TL_APIS = {}
MAX_TL_API = 0xC2

DR_APIS = {}
MAX_DR_API = 0x3D

blockModel = BasicBlockModel(currentProgram)
functionManager = currentProgram.getFunctionManager()
decompInterface = DecompInterface()
decompInterface.openProgram(currentProgram)


def load_api_names_types():
    curdir = os.path.dirname(os.path.abspath(inspect.getsourcefile(lambda: 0)))

    with open(os.path.join(curdir, 'tl_apis.json'), 'r') as f:
        TL_APIS.update({i: (n, t) for i, n, t in json.loads(f.read())})
    print("[*] Loaded %s trustlets APIs names" % len(TL_APIS))

    global DR_APIS
    with open(os.path.join(curdir, 'dr_apis.json'), 'r') as f:
        DR_APIS.update({i: (n, t) for i, n, t in json.loads(f.read())})
    print("[*] Loaded %s drivers APIs names" % len(DR_APIS))

 def prepare(self):
     Decompiler = DecompInterface()
     Decompiler.openProgram(currentProgram)
     Decompiled_Func = Decompiler.decompileFunction(self.function, 30,
                                                    getMonitor())
     self.highfunction = Decompiled_Func.getHighFunction()
Esempio n. 22
0
from ghidra.app.decompiler import DecompInterface
from ghidra.util.task import ConsoleTaskMonitor

# get the current program
# here currentProgram is predefined

program = currentProgram
decompinterface = DecompInterface()
decompinterface.openProgram(program)
functions = program.getFunctionManager().getFunctions(True)
for function in list(functions):
    print(function)
    # decompile each function
    tokengrp = decompinterface.decompileFunction(function, 0,
                                                 ConsoleTaskMonitor())
    print(tokengrp.getDecompiledFunction().getC())
Esempio n. 23
0
def open_program():
    iface = DecompInterface()
    iface.openProgram(currentProgram)
    return iface
Esempio n. 24
0
import re
import os
# to decompile
from ghidra.app.decompiler import DecompileOptions
from ghidra.app.decompiler import DecompInterface
# to rename function
from ghidra.program.model.symbol import SourceType
# to trace basic blocks
from ghidra.program.model.block import BasicBlockModel
from ghidra.program.model.pcode import HighFunctionDBUtil

# logic to find and rename the main function
ifc = DecompInterface()
ifc.setOptions(DecompileOptions())
ifc.openProgram(currentProgram)
try:
    entryfunction = getGlobalFunctions("entry")[0]
except:
    # if binary has symbols
    if getGlobalFunctions("_start"):
        entryfunction = getGlobalFunctions("_start")[0]
    else:
        exit()
res = ifc.decompileFunction(entryfunction, 60, monitor)
m = re.search("__libc_start_main\((.+?),", res.getCCodeMarkup().toString())
if m.group(1)[0] != "main":
    getGlobalFunctions(m.group(1))[0].setName("main", SourceType.ANALYSIS)

# for static blocks
blockiterator = BasicBlockModel(currentProgram).getCodeBlocks(monitor)
fun_blocks = {}
Esempio n. 25
0
"""
Usage:

./analyzeHeadless [GHIDRA WORKING DIR] [PROJECT NAME] -import [BINARY] -overwrite \
-postscript decompile_func.py [FUNCTION] [OUTPUT DIR]

"""

import os
from ghidra.app.decompiler import DecompInterface
from ghidra.util.task import ConsoleTaskMonitor

args = getScriptArgs()
print("[+] Decompiling '{}' now...".format(args[0]))

program = getCurrentProgram()
decompiface = DecompInterface()
decompiface.openProgram(program)

func = getGlobalFunctions(args[0])[0]
res = decompiface.decompileFunction(func, 0, ConsoleTaskMonitor())

if not os.path.exists(args[1]):
    os.makedirs(args[1])

fname = "{}/{}.c".format(args[1], args[0])
f = open(fname, 'w')
f.write(res.getDecompiledFunction().getC())
f.close()
Esempio n. 26
0
class Emulator(object):
    def __init__(self, plugin, state=None, logger_fname="ghidra_emulator.txt"):
        self.plugin = plugin
        self.monitor = self.plugin.getMonitor()
        if state is None:
            state = self.plugin.getGhidraState()
        program = state.getCurrentProgram()
        address = state.getCurrentAddress()

        self.byte_substitution = {}

        self.initLogger(logger_fname)
        self.initEmulator(program, address)
        self.initCmdHandlers()

        self.emulator_state = EmulatorState.WAITING_FOR_PARAM
        self.flatapi = FlatProgramAPI(program)

    def initLogger(self, fname):
        self.logger_fname = fname
        
        self.logger = logging.getLogger(str(random.random()).replace(".","_"))
        self.logger.setLevel(logging.INFO)
        
        h_stdout = logging.StreamHandler(sys.stdout)
        h_stdout.setLevel(logging.INFO)
        self.logger.addHandler(h_stdout)
        if self.logger_fname:
            h_file = logging.FileHandler(self.logger_fname)
            h_file.setLevel(logging.INFO)
            self.logger.addHandler(h_file)

    def initEmulator(self, program, address, clear_param_map=True):
        ''' Setup the emulator helper, symbol maps and fn related stuff '''
        self.program = program
        self.function = self.program.getFunctionManager().getFunctionContaining(address)
        if self.function is None:
            function_name = self.plugin.askString("You are not in a function, please enter an address or a function name", "address or symbol name")
            for f in self.plugin.state.currentProgram.getFunctionManager().getFunctions(True):
                if function == f.getName():
                    self.plugin.state.setCurrentAddress(function.getEntryPoint())
                    self.doStart()
                    return
            for f in self.plugin.state.currentProgram.getFunctionManager().getFunctions(True):
                if int(function, 16) == f.getEntryPoint().getOffset():
                    self.plugin.state.setCurrentAddress(function.getEntryPoint())
                    self.doStart()
                    return
        self.entrypoint = self.program.getListing().getInstructionAt(self.function.getEntryPoint())

        self.logger.info("Program: %s" % self.program)
        self.logger.info("Function: %s" % self.function)

        self.decompinterface = DecompInterface()
        self.decompinterface.openProgram(program)
        result = self.decompinterface.decompileFunction(self.function, 0, self.monitor)
        self.highFunction = result.getHighFunction()
        # self.logger.info(result)
        # self.logger.info(self.highFunction)

        self.decompiled = str(result.getCCodeMarkup())
        # self.logger.info("Decompiled: %s" % self.decompiled)

        self.symbolMap = self.highFunction.getLocalSymbolMap()
        # self.logger.info(self.symbolMap)
        if clear_param_map:
            self.parameterMap = {}
        # fuzz = 0

        self.emulatorHelper = EmulatorHelper(self.program)
        self.stackPointer = (((1 << (self.emulatorHelper.getStackPointerRegister().getBitLength() - 1)) - 1) ^ ((1 << (self.emulatorHelper.getStackPointerRegister().getBitLength()//2))-1))    
        self.returnAddressSize = program.getLanguage().getProgramCounter().getBitLength()

        NULL_PTR_RET = 0
        self.emulatorHelper.writeRegister(self.emulatorHelper.getStackPointerRegister(), self.stackPointer)
        self.emulatorHelper.setBreakpoint(self.getStackAddress(NULL_PTR_RET))
        self.emulatorHelper.enableMemoryWriteTracking(True)

        self.emulator_state = EmulatorState.WAITING_FOR_PARAM
        if not clear_param_map:
            self.emulator_state = EmulatorState.READY
        self.history = []        

        self.lastAddresses = []
        # self.emulatorHelper.getEmulator().executeInstruction = executeInstruction

        self.hookExternalFunctions()
        # def nopCallBack(BreakCallBack):
        #     def __init__(self):
        #         # BreakCallBack.__init__(self)
        #         pass
        #     def pcodeCallback(self, op):
        #         return True
        # help(nopCallBack)
        # emulatorHelper.registerCallOtherCallback('HintPreloadData', nopCallBack(BreakCallBack()))

    def hookExternalFunctions(self):
        for externalFunction in list(self.program.getFunctionManager().getExternalFunctions()):
            self.logger.debug('Found external function `%s`' % (externalFunction.getName()))
            for library in lib.exports:
                self.logger.debug('Found library `%s`' % (library.name))
                for function in library.exports:
                    self.logger.debug('Found function `%s`' % (function.__name__))
                    if externalFunction.getName() == function.__name__:
                        for address in externalFunction.getFunctionThunkAddresses():
                            self.logger.info('Hooked function `%s`@%s with implementation lib/%s/%s' % (externalFunction.getName(), str(address), library.name, function.__name__))
                            callback = DucktapeBreakCallback(function(self.program, self, self.program.getFunctionManager().getFunctionAt(address), self.monitor), lambda x: True)
                            # callback.addressCallback = function(self.program, self, self.program.getFunctionManager().getFunctionAt(address), self.monitor)
                            self.emulatorHelper.emulator.getBreakTable().registerAddressCallback(address, callback)
                            # self.emulatorHelper.setBreakpoint(address)
                        # break
        for thunkFunction in list(filter(lambda x: x.isThunk(), self.program.getFunctionManager().getFunctions(True))):
            for library in lib.exports:
                self.logger.debug('Found library `%s`' % (library.name))
                for function in library.exports:
                    self.logger.debug('Found function `%s`' % (function.__name__))
                    if thunkFunction.getName() == function.__name__:
                        address = thunkFunction.getEntryPoint() 
                        self.logger.info('Hooked function `%s` at %s with implementation lib/%s/%s' % (thunkFunction.getName(), str(address), library.name, function.__name__))
                        callback = DucktapeBreakCallback(function(self.program, self, self.program.getFunctionManager().getFunctionAt(address), self.monitor), lambda x: True)
                        # callback.addressCallback = function(self.program, self, self.program.getFunctionManager().getFunctionAt(address), self.monitor)
                        self.emulatorHelper.emulator.getBreakTable().registerAddressCallback(address, callback)
                            
        
    def initFunctionParameters(self, bytesValueBuffer=""):
        ''' Setup fn input parameters '''
        self.input_wildcards = []
        self.fnParametersAllBytesValue = ""
        for parameter in [self.symbolMap.getParam(i) for i in range(self.symbolMap.getNumParams())]:
            psize = self.parameterStorageSize(parameter)
            if len(bytesValueBuffer) < psize*2:
                bytesValueBuffer = self.plugin.askString('Setting Parameters for `{}` (size: {})'.format(parameter.name, psize), 'byte values')
            bytesValue = bytesValueBuffer[:psize*2]
            bytesValue = (bytesValue + "00"*psize)[:psize*2]
            assert(len(bytesValue) == psize*2)

            for i in range(0,len(bytesValue), 2):
                if bytesValue[i] in string.hexdigits and bytesValue[i+1] in string.hexdigits: continue
                self.input_wildcards.append(bytesValue[i:i+2])
            
            self.parameterMap[parameter.name] = bytesValue
            self.fnParametersAllBytesValue += bytesValue
            
            bytesValueBuffer = bytesValueBuffer[psize*2:]
        # self.logger.info(self.parameterMap)
        if self.input_wildcards:
            self.logger.info("Found %d wildcards: %s" % (len(self.input_wildcards), self.input_wildcards))
            self.logger.info("The next batch of cmds will be executed in fuzzing mode")
        
        for w in self.input_wildcards:
            self.byte_substitution[w] = "00"
        
        self.emulator_state = EmulatorState.READY

    # @staticmethod
    def parameterStorageSize(self, parameter):
        return sum(map(lambda x: x.getSize(), parameter.getStorage().getVarnodes()))

    def getAddress(self, offset):
        return self.program.getAddressFactory().getDefaultAddressSpace().getAddress(offset)

    def getStackAddress(self, offset):
        address = self.getAddress(self.emulatorHelper.readRegister(self.emulatorHelper.getStackPointerRegister()) + offset)
        orAddress = self.getAddress(self.stackPointer + offset)
        self.logger.debug('Stack address at {} or {}'.format(address, orAddress))
        return orAddress

    def writeStackValue(offset, size, value):
        bytesValue = long_to_bytes(value, size)
        if not self.emulatorHelper.getLanguage().isBigEndian():
            bytesValue = bytesValue[::-1]
        self.emulatorHelper.writeMemory(self.getStackAddress(offset), bytesValue)

    def applyByteSubstitution(self, bytesValue):
        for k,v in self.byte_substitution.items():
            bytesValue = bytesValue.replace(k, v)
        return bytesValue.decode('hex')

    def start(self, byte_substitution=None):
        ''' Write the fn inputs in memory (eventually applying the byte substitution) and 
            start the emulation, breaking at fn entry point'''
        assert(self.emulator_state == EmulatorState.READY)
        if byte_substitution is not None:
            self.byte_substitution = byte_substitution

        self.logger.info('Started with byte_sub: %r' % self.byte_substitution)
        
        for parameter in [self.symbolMap.getParam(i) for i in range(self.symbolMap.getNumParams())]:
            bytesValue = self.parameterMap[parameter.name]
            bytesValue = self.applyByteSubstitution(bytesValue)
            storage = parameter.getStorage()
            offset = 0
            for varnode in storage.getVarnodes():
                chunk = bytesValue[offset:offset+varnode.getSize()]
                if varnode.getAddress().isStackAddress():
                    self.emulatorHelper.writeMemory(self.getStackAddress(varnode.getAddress().getOffset()), chunk)
                else:
                    self.emulatorHelper.writeMemory(varnode.getAddress(), chunk)
                offset += varnode.getSize()

        self.emulatorHelper.setBreakpoint(self.function.getEntryPoint())
        self.emulatorHelper.run(self.function.getEntryPoint(), self.entrypoint, self.monitor)

        self.emulator_state = EmulatorState.EXECUTING

    def executeCmds(self, cmds):
        assert(self.emulator_state == EmulatorState.EXECUTING)
        cmds = cmds.strip().split(', ')
        for cmd_id, cmd in enumerate(cmds):
            cmd = cmd.strip().split()
            if cmd[0] not in self.cmd_handlers:
                self.logger.error("Unknown command %s (%r)" % (cmd[0], cmd))
                self.cmdHelp(cmd)
                break

            res = self.cmd_handlers[cmd[0]](cmd)
            if res: self.last_result = res
            self.updateUI()
        # self.printState()
        self.logger.info('Stopping execution for {} at {:x} with error {}'.format(self.emulatorHelper.getEmulateExecutionState(), self.emulatorHelper.readRegister(self.emulatorHelper.getPCRegister()), self.emulatorHelper.getLastError()))
    
    def printState(self):
        for symbol in self.program.getSymbolTable().getAllSymbols(True):
            symbolObject = symbol.getObject()
            try:
                dataType = symbolObject.getDataType()
                name = symbol.getName()
                if name in self.decompiled and symbol.getAddress():
                    self.logger.debug('Found symbol name={} type={} location={}'.format(name, dataType, symbol.getAddress()))
                    bytesValue = self.emulatorHelper.readMemory(symbol.getAddress(), dataType.getLength())
                    stringValue = bytesValue.tostring()
                    printValue = repr(stringValue) if isPrintable(stringValue) else stringValue.encode('hex')
                    self.logger.info('Variable {} has value `{}`'.format(name, printValue))
            except AttributeError as e:
                self.logger.debug(str(e))
            except Exception as e:
                self.logger.error(str(e))
        
        writeSet = self.emulatorHelper.getTrackedMemoryWriteSet()
        for parameter in self.highFunction.getLocalSymbolMap().getSymbols():
            if parameter.name not in self.decompiled:
                continue
            storage = parameter.getStorage()
            bytesValue = bytearray(0)
            for varnode in storage.getVarnodes():
                if varnode.getAddress().isStackAddress():
                    bytesValue.extend(self.emulatorHelper.readMemory(self.getStackAddress(varnode.getAddress().getOffset()), varnode.getSize()))
                elif writeSet.contains(varnode.getAddress()):
                    bytesValue.extend(self.emulatorHelper.readMemory(varnode.getAddress(), varnode.getSize()))
            stringValue = str(bytesValue)
            printValue = repr(stringValue) if isPrintable(stringValue) else stringValue.encode('hex')
            self.logger.info('Variable `{}` @ `{}` has value `{}`'.format(parameter.name, storage, printValue))
        
        for register in self.emulatorHelper.getLanguage().getRegisters():
            if register.isBaseRegister() and not register.isProcessorContext():
                self.logger.debug(str(register))
                self.logger.debug(str(self.emulatorHelper.readRegister(register)))

        self.logger.debug(str(self.emulatorHelper))
        self.logger.debug(str(self.emulatorHelper.getLanguage()))
        self.logger.debug(str(self.emulatorHelper.getLanguage().getRegisters()))
        self.logger.info(str(['{} = {}'.format(register, self.emulatorHelper.readRegister(register)) for register in self.emulatorHelper.getLanguage().getRegisters() if register.isBaseRegister() and not register.isProcessorContext()]))

        self.logger.info('Stopping execution at {:x}'.format(self.emulatorHelper.readRegister(self.emulatorHelper.getPCRegister())))
        self.logger.debug('Logged writes at {}'.format(self.emulatorHelper.getTrackedMemoryWriteSet()))
    
    def readMemory(self, from_, size):
        bytesValue = bytearray(0)
        bytesValue.extend(self.emulatorHelper.readMemory(self.getAddress(from_), size))
        stringValue = str(bytesValue)
        self.logger.info('Reading from {} (size: {}): {}\n\thex={}'.format(from_, size, repr(stringValue), stringValue.encode("hex")))
        return stringValue


    def readPointer(self, address):
        self.logger.debug('reading %d from address %s' % (self.program.getLanguage().getProgramCounter().getBitLength()//8, str(address)))
        packed = bytearray(0)
        packed.extend(self.emulatorHelper.readMemory(address, self.program.getLanguage().getProgramCounter().getBitLength()//8))
        self.logger.debug('reading `%s` from address' % repr(str(packed)))
        if not self.program.getLanguage().isBigEndian():
            packed = str(packed[::-1])
        self.logger.debug('got pointer at `%s`' % repr(str(packed)))        
        return int(packed.encode('hex'), 16)
    def writeMemory(self, from_, bytesValue):
        bytesValue = applyByteSubstitution(bytesValue)
        self.emulatorHelper.writeMemory(self.getAddress(from_), bytesValue)
    
    def updateUI(self):
        self.plugin.syncView(self.emulatorHelper.getExecutionAddress())

    def initCmdHandlers(self):
        self.cmd_handlers = {
            's': self.cmdStep,
            'c': self.cmdContinue,
            'n': self.cmdNext,
            'b': self.cmdBreakpointAdd,
            'd': self.cmdBreakpointRemove,
            'x': self.cmdSleep,
            'q': self.cmdQuit,
            'r': self.cmdReadMem,
            'w': self.cmdWriteMem,
            'p': self.cmdPrintState,
            'h': self.cmdHelp,
            'l': self.cmdLogHistory,
            'e': self.cmdEval,
            'hook': self.cmdHook,
            'list-hooks': self.cmdListHook,
        }

    
    @history
    def cmdHook(self, cmd):
        '''hook address module.function - replace a function with a python implementation
        e.g. hook 0x40000 libc6.puts
        '''
        address = self.getAddress(int(cmd[1], 16))
        library_name, function_name = cmd[2].split('.')
        thunkedFunction = self.program.getFunctionManager().getFunctionContaining(address)
        for library in lib.exports:
            if library_name == library_name:
                self.logger.debug('Found library `%s`' % (library.name))
                for function in library.exports:
                    self.logger.debug('Found function `%s`' % (function.__name__))
                    if function_name == function.__name__:
                        self.logger.info('Hooked function `%s` at %s with implementation lib/%s/%s' % (thunkedFunction.getName(), str(address), library.name, function.__name__))
                        callback = DucktapeBreakCallback(function(self.program, self, thunkedFunction, self.monitor), lambda x: True)
                        # callback.addressCallback = function(self.program, self, self.program.getFunctionManager().getFunctionAt(address), self.monitor)
                        self.emulatorHelper.emulator.getBreakTable().registerAddressCallback(address, callback)
                        break
    @history
    def cmdListHook(self, cmd):
        '''List available hooks
        '''
        for library in lib.exports:
            self.logger.debug('Found library `%s`' % (library.name))
            for function in library.exports:
                self.logger.debug('Found function `%s`' % (function.__name__))
                self.logger.info('%s.%s - %s' % (library.name, function.__name__, function.__doc__))

    @history
    def cmdStep(self, cmd):
        '''step'''
        self.emulatorHelper.step(self.monitor)
    def run(self, monitor):
        self.emulatorHelper.emulator.setHalt(False)
        while not self.emulatorHelper.emulator.getHalt():
            self.emulatorHelper.step(monitor)
            currentAddress = self.emulatorHelper.getExecutionAddress()
            if len(self.lastAddresses) == 0 or self.lastAddresses[0] != currentAddress:
                self.lastAddresses = [currentAddress] + self.lastAddresses[:1]

    @history
    def cmdContinue(self, cmd):
        '''continue'''
        self.run(self.monitor)
    
    @history
    def cmdNext(self, cmd):
        '''step over/next'''
        address = self.flatapi.getInstructionAfter(self.emulatorHelper.getExecutionAddress()).getAddress()
        self.emulatorHelper.setBreakpoint(address)
        self.run(self.monitor)
        self.emulatorHelper.clearBreakpoint(address)
        
    @history
    def cmdBreakpointAdd(self, cmd):
        '''add breakpoint (`hex_address`)'''
        address = self.getAddress(int(cmd[1], 16))
        self.emulatorHelper.setBreakpoint(address)

    @history
    def cmdBreakpointRemove(self, cmd):
        '''remove breakpoint (`hex_address`)'''
        address = self.getAddress(int(cmd[1], 16))
        self.emulatorHelper.clearBreakpoint(address)

    @history
    def cmdSleep(self, cmd):
        '''sleep (`time(=5)`)'''
        for i in range(10000):
            self.monitor.isCancelled()
        # time.sleep(5 if len(cmd) == 1 else int(cmd[1]))
    
    @history
    def cmdQuit(self, cmd):
        '''quit'''
        self.printState()
        self.updateUI()
        self.emulator_state = EmulatorState.DONE

    @history
    def cmdReadMem(self, cmd):
        '''read memory addr (either `hex_from:hex_to` or `hex_from size`)'''
        if len(cmd) == 3:
            from_ = cmd[1]
            size = int(cmd[2], 16 if "0x" in cmd[2].lower() else 10)
        else:
            from_, to_ = map(lambda x: int(x,16), cmd[1].split(":"))
            size = to_-from_
            from_ = hex(from_)
        return self.readMemory(from_.replace("0x",""), size)
    
    @history
    def cmdWriteMem(self, cmd):
        '''write memory addr (`hex_addr hex_bytes`)'''
        self.writeMemory(cmd[1], cmd[2])
    
    @history
    def cmdPrintState(self, cmd):
        '''print state'''
        self.printState()

    @history
    def cmdEval(self, cmd):
        '''executes your command'''
        exec(' '.join(cmd[1:]))

    def cmdHelp(self, cmd):
        '''help'''
        self.logger.info("Commands:")
        for k,v in self.cmd_handlers.items():
            self.logger.info("\t%s: %s" % (k, v.__doc__))

    def cmdLogHistory(self, cmd):
        '''prints a serialized version of this debugging session'''
        self.logger.debug(self.history)
        self.logger.info("`%s`" % (', '.join(self.history)))