예제 #1
0
def makeSwitch(vw, vajmp, offarraybase, indiroffbase=None):
    '''
    Makes the changes to the Workspace for the given jmp location.  Handles 
    naming for all cases because naming wants to indicate larger context.

    (future)If indiroffbase is not None, the indirection "database" is analyzed for naming
    '''
    filename = vw.getMemoryMap(vajmp)[3]
    imagebase = vw.getFileMeta(filename, 'imagebase')
    # we have identified this is a switch case
    vw.verbprint("FOUND MS SWITCH CASE SPRAY at 0x%x" % vajmp)

    # roll through the offset array until imagebase+offset is not a valid pointer, points to non-op locations or splits instructions
    count = 0
    tracker = []
    ptr = offarraybase

    while True:
        off = vw.readMemValue(ptr + imagebase, 4)
        ova = imagebase + off

        tgtva = makeSwitchCase(vw, vajmp, ova)
        if not tgtva:
            break

        tracker.append((count, tgtva))
        count += 1
        ptr += 4

    # FIXME: this doesn't take into account two-level derefs (indiroffbase)
    naming = {}
    for idx, va in tracker:
        lst = naming.get(va)
        if lst == None:
            lst = []
            naming[va] = lst
        lst.append("%xh" % idx)

    #TODO: analyze indiroffbase to determine case information

    for va, opts in list(naming.items()):
        options = "_".join(opts)
        name = "switch_case_%s_%.8x" % (options, va)
        vw.makeName(va, name)

    #TODO: analyze which paths handle which cases, name accordingly
    #TODO: determine good hint for symbolik constraints
    funcva = vw.getFunction(vajmp)
    vw.makeName(vajmp, "jmp_switch_%.8x" % vajmp)
    vagc.analyzeFunction(vw, funcva)
    return tracker
예제 #2
0
def makeSwitch(vw, vajmp, offarraybase, indiroffbase=None):
    '''
    Makes the changes to the Workspace for the given jmp location.  Handles 
    naming for all cases because naming wants to indicate larger context.

    (future)If indiroffbase is not None, the indirection "database" is analyzed for naming
    '''
    filename = vw.getMemoryMap(vajmp)[3]
    imagebase = vw.getFileMeta(filename, 'imagebase')
    # we have identified this is a switch case
    vw.verbprint( "FOUND MS SWITCH CASE SPRAY at 0x%x" % vajmp)

    # roll through the offset array until imagebase+offset is not a valid pointer, points to non-op locations or splits instructions
    count = 0
    tracker = []
    ptr = offarraybase

    while True:
        off = vw.readMemValue(ptr+imagebase, 4)
        ova = imagebase + off

        tgtva = makeSwitchCase(vw, vajmp, ova)
        if not tgtva:
            break
        
        tracker.append((count, tgtva))
        count += 1
        ptr += 4
       
    # FIXME: this doesn't take into account two-level derefs (indiroffbase)
    naming = {}
    for idx,va in tracker:
        lst = naming.get(va)
        if lst == None:
            lst = []
            naming[va] = lst
        lst.append("%xh" % idx)

    #TODO: analyze indiroffbase to determine case information
    
    for va, opts in list(naming.items()):
        options = "_".join(opts)
        name = "switch_case_%s_%.8x" % (options, va)
        vw.makeName(va, name)

    #TODO: analyze which paths handle which cases, name accordingly
    #TODO: determine good hint for symbolik constraints
    funcva = vw.getFunction(vajmp)
    vw.makeName(vajmp, "jmp_switch_%.8x" % vajmp)
    vagc.analyzeFunction(vw, funcva)
    return tracker
예제 #3
0
def analyzeJmp(amod, emu, op, starteip):
    '''
    Top level logic
    '''
    vw = emu.vw
    ctx = getSwitchBase(vw, op, starteip, emu)
    if ctx is not None:
        tova, scale = ctx
        vw.makeJumpTable(op, tova, rebase=True, psize=scale)
        # so the codeblocks this jumptable points to aren't proper locations...yet.
        # let's fix that up and kick off codeblock analysis to make the codeblocks
        for xrfrom, xrto, xrtype, xrflags in vw.getXrefsFrom(
                op.va, rtype=v_const.REF_CODE):
            vw.makeCode(xrto)
        vagc.analyzeFunction(vw, vw.getFunction(starteip))
예제 #4
0
def analyzeFunction(vw, fva):
    #print("++ Arm EMU fmod: 0x%x" % fva)
    emu = vw.getEmulator()
    emumon = AnalysisMonitor(vw, fva)
    emu.setEmulationMonitor(emumon)

    loc = vw.getLocation(fva)
    if loc is not None:
        lva, lsz, lt, lti = loc
        if lt == LOC_OP:
            if (lti & envi.ARCH_MASK) != envi.ARCH_ARMV7:
                emu.setFlag(PSR_T_bit, 1)
    else:
        logger.warn("NO LOCATION at FVA: 0x%x", fva)

    emu.runFunction(fva, maxhit=1)

    # Do we already have API info in meta?
    # NOTE: do *not* use getFunctionApi here, it will make one!
    api = vw.getFunctionMeta(fva, 'api')
    if api is None:
        api = buildFunctionApi(vw, fva, emu, emumon)

    rettype, retname, callconv, callname, callargs = api

    argc = len(callargs)
    cc = emu.getCallingConvention(callconv)
    if cc is None:
        return

    stcount = cc.getNumStackArgs(emu, argc)
    stackidx = argc - stcount
    baseoff = cc.getStackArgOffset(emu, argc)

    # Register our stack args as function locals
    for i in range(stcount):

        vw.setFunctionLocal(fva, baseoff + (i * 4), LSYM_FARG, i + stackidx)

    emumon.addAnalysisResults(vw, emu)

    # handle infinite loops (actually, while 1;)

    # switch-cases may have updated codeflow.  reanalyze
    viv_cb.analyzeFunction(vw, fva)