Example #1
0
def name(ea, string=None):
    '''Returns the name at the specified address. (local than global)'''
    if string is not None:
        SN_NOCHECK = 0x00
        SN_NOLIST = 0x80
        SN_LOCAL = 0x200
        SN_PUBLIC = 0x02

        n = name(ea)
        
        flags = SN_NOCHECK
        try:
            function.top(ea)
            flags |= SN_LOCAL
        except ValueError:
            flags |= 0

        idc.MakeNameEx(ea, string, flags)
        tag(ea, '__name__', string)
        return n

    try:
        return tag(ea, '__name__')
    except KeyError:
        pass
    return None
Example #2
0
def analyze_vtables():
    vtables = set(locate_vtables())
    fns = set(idautils.Functions())

    for vt in vtables:
        # create a new class
        sname = "class_%x" % (vt)
        sid = idc.AddStruc(-1, sname)
        if sid == idc.BADADDR:
            sid = idc.GetStrucIdByName(sname)

        # create a struc for the vtable
        vname = "vtable_%x" % (vt)
        vid = idc.AddStruc(-1, vname)
        vfuncs = set()

        if vid == idc.BADADDR:
            vid = idc.GetStrucIdByName(vname)

        for i in range(0xffffff):
            target = idc.Dword(vt + (4 * i))

            if target not in fns:
                break

            if i > 0:
                # if there is a data ref, then it's probably the start of a new vtable
                xrefs = set(idautils.DataRefsTo(vt + (4 * i)))
                if len(xrefs) > 0:
                    continue

            idc.AddStrucMember(vid, 'vfunc_%x' % (i), -1, idc.FF_DWRD, -1, 4)

            # setup the target function
            function.tag(target, 'virtual table', hex(vt))
            vfuncs.add(target)

        # add a vtable to the new class
        idc.AddStrucMember(sid, 'vtable', 0, idc.FF_DWRD, -1, 4)

        # tag functions that reference the vtable as either a constructor or destructor
        # in order to do decide which, take advantage of a C++ thing, destructors will be
        # virtual, and constructors will not
        xrefs = idautils.DataRefsTo(vt)
        for r in xrefs:
            try:
                if xrefs in vfuncs:
                    function.tag(function.top(r), 'destructor', 'guessed from vtable (%x) analysis' % (vt))
                else:
                    function.tag(function.top(r), 'constructor', 'guessed from vtable (%x) analysis' % (vt))
            except:
                pass
Example #3
0
def checkmarks():
    '''Output all functions (sys.stdout) containing more than 1 mark.'''
    res = []
    for a,m in database.marks():
        try:
            res.append((function.top(a), a, m))
        except ValueError:
            pass
        continue

    d = list(res)
    d.sort( lambda a,b: cmp(a[0], b[0]) )

    flookup = {}
    for fn,a,m in d:
        try:
            flookup[fn].append((a,m))
        except:
            flookup[fn] = [(a,m)]
        continue

    functions = [ (k,v) for k,v in flookup.items() if len(v) > 1 ]
    if not functions:
        logging.warning('There are no functions available containing multiple marks.')
        return

    for k,v in functions:
        print >>sys.stdout, '%x : in function %s'% (k,function.name(function.byAddress(k)))
        print >>sys.stdout, '\n'.join( ('- %x : %s'%(a,m) for a,m in sorted(v)) )
    return
Example #4
0
def checkmarks():
    """Emit all functions that contain more than 1 mark within them.

    As an example, if marks are used to keep track of backtraces then
    this tool will emit where those backtraces intersect.
    """
    res = []
    for a, m in database.marks():
        try:
            res.append((func.top(a), a, m))
        except internal.exceptions.FunctionNotFoundError:
            pass
        continue

    d = list(res)
    d.sort( lambda a, b: cmp(a[0], b[0]) )

    flookup = {}
    for fn, a, m in d:
        try:
            flookup[fn].append((a, m))
        except:
            flookup[fn] = [(a, m)]
        continue

    functions = [ (k, v) for k, v in flookup.items() if len(v) > 1 ]
    if not functions:
        logging.warning('There are no functions available containing multiple marks.')
        return

    for k, v in functions:
        print >>sys.stdout, "{:#x} : in function {:s}".format(k, func.name(func.byAddress(k)))
        print >>sys.stdout, '\n'.join( ("- {:#x} : {:s}".format(a, m) for a, m in sorted(v)) )
    return
Example #5
0
def tag(address, *args, **kwds):
    '''tag(address, key?, value?) -> fetches/stores a tag from specified address'''
    try:
        context = function.top(address)

    except ValueError:
        context = None

    if len(args) == 0 and len(kwds) == 0:
#        result = __datastore.content.select(context, query.address(address))
        result = datastore.address(context).select(query.address(address))
        try:
            result = result[address]
        except:
            result = {}
        return result

    elif len(args) == 1:
        key, = args
#        result = __datastore.content.select(context, query.address(address), query.attribute(key))
        result = datastore.address(context).select(query.address(address), query.attribute(key))
        try:
            result = result[address][key]
        except:
            raise KeyError( (hex(address),key) )
            result = None
        return result

    if len(args) > 0:
        key,value = args
        kwds.update({key:value})
    return datastore.address(context).address(address).set(**kwds)
Example #6
0
def collectcall(ea, sentinel=set()):
    """Collect all of the function calls starting at function `ea` and recurse until a terminating function is encountered.

    If the set `sentinel` is specified, then its addresses are used as
    sentinel functions and collection will terminate when one of those
    functions are reached.
    """
    if isinstance(sentinel, list):
        sentinel = set(sentinel)
    if not isinstance(sentinel, set):
        raise AssertionError("{:s}.collectcall({:#x}, {!r}) : Sentinel is not a set.".format(__name__, ea, sentinel))
    def _collectcall(addr, result):
        process = set()
        for f in func.down(addr):
            if any(f in coll for coll in (result, sentinel)):
                continue
            if not func.within(f):
                logging.warn("{:s}.collectcall({:#x}, {!r}) : Adding non-function address {:#x} ({:s}).".format(__name__, ea, sentinel, f, database.name(f)))
                result.add(f)
                continue
            process.add(f)
        for addr in process:
            result |= _collectcall(addr, result | process)
        return result
    addr = func.top(ea)
    return _collectcall(addr, set([addr]))
Example #7
0
def __select(q):
    for x in functions():
        x = function.top(x)
        if q.has(function.tag(x)):
            yield x
        continue
    return
Example #8
0
 def addEdge(self, src, dst):
     func_top = function.top(src)
     context = self.store.c(func_top)
     content = context.address(src)
     x = dst
     content.edge((x,x))
     self.commit()
     return True
Example #9
0
    def iterate(self, pc, options):
        if self.provider.segStart(pc) == 0xFFFFFFFF:
            raise ValueError('Fucking IDA')
        
        # if its a call, get the xrefs from it
        # XXX: removed ia32 from public release
        #if ia32.isCall(insn):

        proc = self.provider.getArch()

        if proc == "pc":
            call_mnem = "call"
        elif proc == "arm" or proc == "ppc":
            call_mnem = "bl"
        elif proc == "mips":
            call_mnem = "jalr"
        
        # XXX gotta add support for jmps that go outside a function
        if call_mnem in self.provider.getMnem(pc).lower():

            xrefs_from = database.cxdown(pc)  
            func_top = function.top(pc)
            for x in xrefs_from:
                if self.provider.isCode(self.provider.getFlags(x)):
                    xref_top = function.top(x)
                    context = options['database'].c(func_top)
                    content = context.address(pc)
                    content.edge((x, x))
    
        try:
            endEA = self.provider.funcEnd(pc)
        except:
            return

        if endEA == pc:
            return
         
        # removed as we aren't in private release 
        # hlt instruction 
        #if insn[1] == "\xf4":
        #    return

        return
Example #10
0
def addressToLocation(ea, chunks=None):
    """Convert the address `ea` to a `(function, id, offset)`.

    The fields `id` and `offset` represent the chunk index and the
    offset into the chunk for the function at `ea`. If the list
    `chunks` is specified as a parameter, then use it as a tuple
    of ranges in order to calculate the correct address.
    """
    F, chunks = func.by(ea), chunks or [ch for ch in func.chunks(ea)]
    cid, base = next((i, l) for i, (l, r) in enumerate(chunks) if l <= ea < r)
    return func.top(F), cid, ea - base
Example #11
0
    def enter(self, pc, options):
        options['database'].address(pc)['name'] = database.name(pc)
       
        xrefs_to = database.cxup(pc)    
        func_top = pc    
       
        for x in xrefs_to:
            xref_top = function.top(x)
            context = options['database'].c(xref_top) 
            context.address(x).edge((func_top, func_top)) 

        return
Example #12
0
    def getText(self, addy):
        #print "Fetching text for %08x" % addy
        color = idaapi.SCOLOR_STRING

        if addy == function.top(addy):
            name = idc.NameEx(addy, addy)
            try:
                name = idc.Demangle(name, idc.GetLongPrm(idc.INF_SHORT_DN))
            except:
                pass
        else:
            name = idc.NameEx(addy, addy)

        if name:
            return idaapi.COLSTR(" %s " % name, color)
        else:
            return idaapi.COLSTR(" 0x%08x " % addy, color)
Example #13
0
def colormarks(color=0x7f007f):
    '''Iterate through all database marks and tag+color their address'''
    # tag and color
    f = set()
    for ea,m in database.marks():
        database.tag(ea, 'mark', m)
        database.color(ea, color)
        try:
            f.add(function.top(ea))
        except ValueError:
            pass
        continue

    # tag the functions too
    for ea in list(f):
        m = function.marks(ea)
        function.tag(ea, 'marks', [ea for ea,_ in m])
    return
Example #14
0
def colormarks(color=0x7f007f):
    """Walk through the current list of marks whilst coloring them with the specified `color`.

    Each mark's address is tagged with its description, and if the
    address belongs to a function, the function is also tagged with the
    address of the marks that it contains.
    """
    # tag and color
    f = set()
    for ea, m in database.marks():
        database.tag(ea, 'mark', m)
        if database.color(ea) is None:
            database.color(ea, color)
        try:
            f.add(func.top(ea))
        except internal.exceptions.FunctionNotFoundError:
            pass
        continue

    # tag the functions too
    for ea in list(f):
        m = func.marks(ea)
        func.tag(ea, 'marks', [ea for ea, _ in m])
    return
Example #15
0
    def __init__(self, options, create=True, existing=None):

        self.provider = ida.IDA()

        if create:
            # create the DB
            print "[*] db.py: Creating a new DB file"

            db = store.sqlite3.connect(options['full_file_name'])
            #db.isolation_level =
            self.db_obj = db

            store.driver.sqlite.Deploy(db).create()

            # mutes the pesky sqlite messages
            tmp = sys.stderr 
            sys.stderr = StringIO()
            session = store.driver.sqlite.Session(db,0)
            my_store = store.Store(session)
            sys.stderr = tmp

            all_funcs = database.functions()
            opt = {}
            opt['database'] = my_store

            self.store = my_store

            proc = self.provider.getArch()

            if proc == "pc":
                # XXX: hackish way to fix a crap ton of stuff...
                start = self.provider.segByBase(self.provider.segByName(".text"))
                end = self.provider.segEnd(self.provider.segByBase(self.provider.segByName(".text")))

                succeeded = 0
                for instr in self.provider.iterInstructions(start, end):
                    disasm = self.provider.getDisasm(instr)
                    tokens = disasm.split(" ")

                    res = []
                    for t in tokens:
                        if len(t) != 0:
                            res.append(t)

                    prologues = [['mov', 'edi,', 'edi'], ['push', 'ebp'], ['push', 'rbp']]

                    if res in prologues and instr not in all_funcs:
                        try:
                            prev_ea = self.provider.prevItem(instr, instr-0x20)
                            if prev_ea not in all_funcs:
                                if options['verbosity'] > 2:
                                    print "[!] Attempting to create a function at 0x%08x" % instr
                                ret = self.provider.makeFunc(instr)
                            else:
                                continue

                            if ret:
                                if options['verbosity'] > 2:
                                    print "[*] Successfully made new function at 0x%08x" % instr
                                succeeded += 1

                        except Exception as detail:
                            print detail
                            pass

                    elif "dup(90h)" in disasm:
                        if options['verbosity'] > 2:
                            print "Found dup at 0x%08x" % instr
                        try:
                            next_ea = self.provider.nextItem(instr, instr+0x20)

                            if next_ea not in all_funcs:
                                ret = self.provider.nextItem(next_ea, 0xFFFFFFFF)
                            else:
                                continue

                            if not ret and (next_ea in database.functions()) :
                                if options['verbosity'] > 2:
                                    print "[*] Successfully made new function at 0x%08x" % next_ea
                                succeeded += 1
                        except:
                            pass
                   
                if succeeded != 0:
                    print "[*] Successfully created %d new functions" % succeeded

            print "[*] There are %d funtions to process" % len(all_funcs)

            failed = 0
            succeeded = 0

            for i in xrange(0, len(all_funcs)):
    
                i_actual = i+1
                ea = all_funcs[i]
                if ((i_actual % 250 == 0) or (i == len(all_funcs)-1)):
                    print "[*] db.py: Processing 0x%08x (%d of %d)" % (ea, i_actual, len(all_funcs))

                analyza = analyze_xrefs(opt)
                collecta = collector(analyza, opt)

                try:
                    collecta.go(ea)
                    succeeded += 1
                
                except ValueError as detail:
                    failed += 1
                    if options['verbosity'] > 2:
                        print "0x%08x - failed to process node, %s" % (ea, detail)
                    
                opt['database'].commit()
            
            print "[*] Failed to process %d functions" % failed
            print "[*] Successfully processed %d functions" % succeeded

            # now loop imports
            segs = list(self.provider.getSegments())

            if proc in ["arm", "ppc", "mips"]:
                idata = "extern"
            elif proc == "pc":
                idata = ".idata"

            for s in segs:
                if self.provider.segName(s) == idata:
                    start = s
                    end = self.provider.segEnd(s)

                    for head in self.provider.iterData(start, end):
                        opt['database'].address(head)['name'] = self.provider.getName(head)

                        xrefs_to = database.cxup(head)

                        for x in xrefs_to:
                            try:
                                xref_top = function.top(x)
                            except ValueError: 
                                continue
                            context = opt['database'].c(xref_top)
                            context.address(x).edge((head, head))
            self.commit()


        else:
            db = store.sqlite3.connect(options['full_file_name'])
            self.db_obj = db

            # mutes the pesky sqlite messages
            tmp = sys.stderr
            sys.stderr = StringIO()
            session = store.driver.sqlite.Session(db,0)
            sys.stderr = tmp

            my_store = store.Store(session)
            self.store = my_store
Example #16
0
def top():
    return function.top(database.h())
Example #17
0
def below(ea, includeSegment=False):
    '''Return all of the function names and their offset that are called by the function at `ea`.'''
    tryhard = lambda ea: "{:s}{:+x}".format(func.name(func.top(ea)), ea - func.top(ea)) if func.within(ea) else "{:+x}".format(ea) if func.name(ea) is None else func.name(ea)
    return '\n'.join(':'.join((segment.name(ea), tryhard(ea)) if includeSegment else (tryhard(ea),)) for ea in func.down(ea))
Example #18
0
def below(ea):
    '''Display all the functions that the function at /ea/ can call'''
    tryhard = lambda x: '%s+%x'%(database.name(function.top(x)),x-function.top(x)) if function.within(x) else hex(x) if database.name(x) is None else database.name(x)
    return '\n'.join(map(tryhard,function.down(ea)))
Example #19
0
def above(ea):
    '''Display all the callers of the function at /ea/'''
    tryhard = lambda x: '%s+%x'%(database.name(function.top(x)),x-function.top(x)) if function.within(x) else hex(x) if database.name(x) is None else database.name(x)
    return '\n'.join(map(tryhard,function.up(ea)))
Example #20
0
def top():
    import function     # ida's usage of python sucks.
    return function.top(db.h())