예제 #1
0
def set_sig(addr, name, sig):
    try:
        typeSig = CParserUtils.parseSignature(None, currentProgram, sig, False)
    except ghidra.app.util.cparser.C.ParseException:
        print("Warning: Unable to parse")
        print(sig)
        print("Attempting to modify...")
        # try to fix by renaming the parameters
        try:
            newSig = sig.replace(", ", "ext, ").replace("\)", "ext\)")
            typeSig = CParserUtils.parseSignature(None, currentProgram, newSig,
                                                  False)
        except:
            print("Warning: also unable to parse")
            print(newSig)
            print("Skipping.")
            return
    if typeSig is not None:
        try:
            typeSig.setName(name)
            ApplyFunctionSignatureCmd(addr, typeSig, USER_DEFINED, False,
                                      True).applyTo(currentProgram)
        except:
            print(
                "Warning: unable to set Signature. ApplyFunctionSignatureCmd() Failed."
            )
예제 #2
0
    def parse_scatterload_table(self):
        """
        Go through the scatterload table and identify the calls to unpack the init data and
        clear the bss section.
        """
        self.data_init_start = None
        self.data_size_packed = None
        self.data_size_unpacked = None
        self.ram_clear_start = None
        self.ram_clear_size = None

        if self.scatterload_table.getLength() % 0x10:
            yikes("Scatterload table size not a multiple of 0x10")

        scatterload_nentries = self.scatterload_table.getLength() / 0x10
        if scatterload_nentries < 2:
            yikes("Scatterload table too small to contain a decompress and clear entry")

        # Actually iterating might be unnecessary because the table layout is identical
        # in all targets I've seen so far, but what do I know.
        # The one assumption in here is that the unpack call comes _before_ the clear call.
        for entry in range(scatterload_nentries):
            addr = self.scatterload_table.getMinAddress().add(entry * 0x10)
            listing.clearCodeUnits(addr, addr.add(0x10), False)
            listing.createData(addr, self.table_entry_type)
            entry = read_uints(addr, 4)

            function_name = None
            is_rwdata_init_function = False
            if entry[1] == self.ram_block.getStart().getOffset():
                print("Init data call found:", entry)
                is_rwdata_init_function = True

                self.data_init_start = addr.getNewAddress(entry[0])
                self.data_size_unpacked = entry[2]

            elif self.data_init_start and entry[1] == self.ram_block.getStart().getOffset() + self.data_size_unpacked:
                print("Clear memory call found:", entry)
                function_name = "__scatterload_zeroinit"

                self.data_size_packed = entry[0] - self.data_init_start.getOffset()
                self.ram_clear_start = addr.getNewAddress(entry[1])
                self.ram_clear_size = entry[2]

            function_addr = addr.getNewAddress(entry[3])
            function = createFunction(function_addr, function_name)
            # Using commands for high-level operations is the "Ghidra Way" it seems:
            # https://github.com/NationalSecurityAgency/ghidra/issues/1126
            ApplyFunctionSignatureCmd(function_addr, self.function_type, SourceType.USER_DEFINED, True, False).applyTo(currentProgram)
            if is_rwdata_init_function:
                self.rwdata_init_function = function or getFunctionAt(function_addr)
예제 #3
0
def checkFixReturn(func, ret_varnode):
    hf = get_highfunction(func)

    func_proto = hf.getFunctionPrototype()
    #  Check return types
    for i in hf.getPcodeOps():
        if i.getOpcode() == PcodeOp.RETURN:
            if len(i.getInputs()) < 2:
                print(func, "has no return value, fixing type...",
                      i.getInputs()[0].getPCAddress())
                sig = func.getSignature()
                sig.setReturnType(
                    Undefined.getUndefinedDataType(ret_varnode.getSize()))
                ApplyFunctionSignatureCmd(
                    func.getEntryPoint(), sig,
                    SourceType.USER_DEFINED).applyTo(currentProgram)
예제 #4
0
def SetFunctionType(addr, sig):
	MakeFunction(addr)
	typeSig = CParserUtils.parseSignature(None, currentProgram, sig)
	ApplyFunctionSignatureCmd(toAddr(addr), typeSig, SourceType.USER_DEFINED, False, True).applyTo(currentProgram)
예제 #5
0
def fixLabel(data):
    name = getSymbolAt(data).getName()
    labelAddress = getSymbolAt(data).getAddress()
    #print labelAddress, name
    # ghidra refers to some functions as data, I've seen only one case
    if ("LAB_" not in name):
        currentProgram.getListing().clearCodeUnits(data, data.add(8), False)
        name = name.split("_")[1]
        ret = createFunction(labelAddress, "LAB_" + name)

    labelName = name.replace("LAB_", "FUN_")
    #print disassemble(labelAddress)
    if disassemble(labelAddress) == False:
        popup("This Label " + labelAddress + "cannot be disassembled !")
        return -1
    #print "labelName:",labelName
    ret = createFunction(labelAddress, labelName)
    func = getFunctionAt(labelAddress)
    if func == None:
        # Calling CreateFunction twice will force function creation
        # Don't ask me,ask NSA
        ret = createFunction(labelAddress, labelName)

    # why it sometimes returns None ? last chance
    func = getFunctionAt(labelAddress)
    if (func == None):
        listing = currentProgram.getListing()
        blockModelService = state.getTool().getService(BlockModelService)
        cbm = blockModelService.getActiveSubroutineModel()
        cbIter = cbm.getCodeBlocksContaining(labelAddress, monitor)
        l = labelAddress
        currentProgram.getListing().clearCodeUnits(l, l.add(8), True)
        createFunction(labelAddress, "FUN_" + name)

        #x = getFunctionAt(labelAddress)
        #print cbIter
        #x = CreateFunctionCmd(labelAddress,False)
        #print type(x)
        #funcBody =  x.getFunctionBody(currentProgram,labelAddress)
        #print funcBody
        #mgr = currentProgram.getFunctionManager()
        #mgr.createFunction("test",labelAddress,funcBody,SourceType.USER_DEFINED)
        #raise Exception("Unable to create a function 0x%s" %(labelAddress.toString()))
        #x = ApplyFunctionSignatureCmd(labelName)
        #print x

        #return

    func = getFunctionAt(labelAddress)
    assert (func != None)
    func.setCustomVariableStorage(False)
    #params = func.getParameters()
    df = FunctionDefinitionDataType(func, False)

    # TODO : remove the below line , no need to change calling convention
    #df.setGenericCallingConvention(GenericCallingConvention.thiscall)
    df.setReturnType(func.getReturnType())

    #df = FunctionDefinitionDataType(func,False)
    """
    func.replaceParameters(FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS,#CUSTOM_STORAGE,
            True,
            SourceType.USER_DEFINED,
            params)
    """
    x = ApplyFunctionSignatureCmd(func.getEntryPoint(), df,
                                  SourceType.USER_DEFINED)
    x.applyTo(func.getProgram())
dwordDef = ParameterDefinitionImpl(None, dword, "double word")

# list of functions to change signatures
functionsToChange = [
    "foo", "bar"
    #...
]

#function definitions
fooDef = FunctionDefinitionDataType("foo")
fooDef.setArguments([pointer32Def, dwordDef])
barDef = FunctionDefinitionDataType("bar")
barDef.setArguments([pointer32Def])
functionDefs = [fooDef, barDef]

func = getFirstFunction()

#loop though functions looking names that match our list
while func is not None:
    func_name = func.getName()
    if func_name in functionsToChange:
        for defi in functionDefs:
            if func_name == defi.getName():
                cmd = ApplyFunctionSignatureCmd(func.getEntryPoint(), defi,
                                                SourceType.USER_DEFINED)
                runCommand(cmd)
                if debug == True:
                    print "Address {} -> Name {}".format(
                        func.getEntryPoint(), defi.getName())
                    print cmd.getStatusMsg()
    func = getFunctionAfter(func)