Beispiel #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
Beispiel #2
0
def function(ea):
    '''Iterate through all addresses in the function ``ea`` and it's tagcache with any found tags.'''
    try:
        fn.top(ea)
    except LookupError:
        return {}, {}
    f, addr, tags = fetch_function(ea)

    for k in set(tags.keys()):
        if k in ('__tags__', '__address__'):
            if f in addr:
                addr[f] -= 1
                if addr[f] == 0:
                    addr.pop(f)
            if k in tags:
                tags[k] -= 1
                if tags[k] == 0:
                    tags.pop(k)
        continue

    for k, v in tags.iteritems():
        internal.comment.contents.set_name(f, k, v)

    for k, v in addr.iteritems():
        if not fn.within(k):
            continue
        internal.comment.contents.set_address(k, v)

    return addr, tags
Beispiel #3
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

        res = idaapi.set_name(ea, string, flags)
        tag(ea, 'name', string)
        return n

    try:
        return tag(ea, 'name')
    except KeyError:
        pass
    return None
Beispiel #4
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))
Beispiel #5
0
def above(ea, includeSegment=False):
    '''Return all of the function names and their offset that calls 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.up(ea))
Beispiel #6
0
def below(ea, includeSegment=False):
    '''Display all the functions that the function at /ea/ can call'''
    tryhard = lambda ea: "{:s}+{:x}".format(database.name(function.top(
        ea)), ea - function.top(ea)) if function.within(
            ea) else "+{:x}".format(ea) if database.name(
                ea) is None else database.name(ea)
    return '\n'.join(
        ':'.join((segment.name(ea),
                  tryhard(ea)) if includeSegment else (tryhard(ea), ))
        for ea in function.down(ea))
Beispiel #7
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
Beispiel #8
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}".format(
            k, function.name(function.byAddress(k)))
        print >> sys.stdout, '\n'.join(
            ("- {:x} : {:s}".format(a, m) for a, m in sorted(v)))
    return
Beispiel #9
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)
Beispiel #10
0
def __select(q):
    for x in functions():
        x = function.top(x)
        if q.has(function.tag(x)):
            yield x
        continue
    return
Beispiel #11
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]))
Beispiel #12
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
Beispiel #13
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
Beispiel #14
0
 def __select(q):
     for x in functions():
         x = function.top(x)
         if q.has(function.tag(x)):
             yield x
         continue
     return
Beispiel #15
0
def apply_dyn_calls(dyn_calls, delete=False):
    hex = '{:x}'.format
    for dyn_call in dyn_calls:
        print(dyn_call)
        for i, p in enumerate(dyn_call.parents):
            print(i, hex(p))
            top = func.top(p)
            if 'dynamic_call' not in func.tag(top):
                fn.tag(top, 'dynamic_call', set())
            if delete:
                fn.tag(top, 'dynamic_call', None)
                continue
            curr_tag = fn.tag(top, 'dynamic_call')
            print(type(curr_tag), hex(top))
            try:
                curr_tag.add(dyn_call.parents[i + 1])
            except IndexError:
                curr_tag.add(dyn_call.call)
            fn.tag(top, 'dynamic_call', curr_tag)

        # Be sure to tag the actual function containing the dynamic call
        top = fn.top(dyn_call.call)
        if delete:
            if 'dynamic_call' in fn.tag(top):
                fn.tag(top, 'dynamic_call', None)
            if 'dynamic_call' in fn.tag(dyn_call.call):
                fn.tag(dyn_call.call, 'dynamic_call', None)
            continue

        if 'dynamic_call' not in fn.tag(top):
            fn.tag(top, 'dynamic_call', set())
        curr_tag = fn.tag(top, 'dynamic_call')
        curr_tag.add(dyn_call.call)
        fn.tag(top, 'dynamic_call', curr_tag)
        db.tag(dyn_call.call, 'dynamic_call', 'here')
Beispiel #16
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.
    """
    listable = []
    for a, m in database.marks():
        try:
            listable.append((func.top(a), a, m))
        except internal.exceptions.FunctionNotFoundError:
            pass
        continue

    d = listable[:]
    d.sort(key=lambda item: item[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:
        six.print_("{:#x} : in function {:s}".format(k, func.name(func.by_address(k))), file=sys.stdout)
        six.print_('\n'.join(("- {:#x} : {:s}".format(a, m) for a, m in sorted(v))), file=sys.stdout)
    return
Beispiel #17
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]))
Beispiel #18
0
    def tag(ea, *args, **kwds):
        '''tag(ea, key?, value?) -> fetches/stores a tag from specified address'''
        try:
            context = function.top(ea)

        except ValueError:
            context = None

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

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

        if len(args) > 0:
            key, value = args
            kwds.update({key: value})
        return datastore.address(context).address(ea).set(**kwds)
Beispiel #19
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
Beispiel #20
0
    def iterate(self, pc, options):
        if self.provider.segStart(pc) == 0xFFFFFFFF:
            raise ValueError('F*****g 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
Beispiel #21
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
Beispiel #22
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
Beispiel #23
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
Beispiel #24
0
def fetch_function(f):
    addr, tags = {}, {}

    for ea in fn.iterate(f):
        res = db.tag(ea)
        #res.pop('name', None)
        for k, v in res.iteritems():
            addr[ea] = addr.get(ea, 0) + 1
            tags[k] = tags.get(k, 0) + 1
        continue
    ea = f
    return fn.top(ea), addr, tags
Beispiel #25
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

    return None
Beispiel #26
0
def color_block(ea=None, color=0x55ff7f):
    """http://reverseengineering.stackexchange.com/questions/10662/change-block-node-color-with-idapython
    and WanderingGlitch for the tip of refresh_idaview_anyway()"""

    func_top = fn.top()

    f = idaapi.get_func(ea)
    g = idaapi.FlowChart(f, flags=idaapi.FC_PREDS)
    bb_id = get_bb_id(g, ea)

    p = idaapi.node_info_t()
    p.bg_color = color

    idaapi.set_node_info2(func_top, bb_id, p,
                          idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR)
    idaapi.refresh_idaview_anyway()
Beispiel #27
0
def dump_breaks(func=None, tagname='break', stdout=True):
    if func is None:
        for func, _ in db.selectcontents(tagname):
            dump_breaks(func, tagname=tagname)
        return
    Escape = lambda s: s.replace('"', '\\"')

    entry, exit = fn.top(func), fn.bottom(func)
    funcname = fn.name(func)

    #[(entry,{tagname:'.printf "Entering {:s} %x,%x\\n",poi(@esp),@esp'.format(funcname)})], [(x,{tagname:'.printf "Exiting {:s} %x,%x\\n",poi(@esp),@esp'.format(funcname)}) for x in exit],
    select = itertools.chain(fn.select(func, And=(tagname, ), Or=('', )))

    res = {}
    for ea, t in select:
        h = res.setdefault(ea, {})
        for k in t.keys():
            if k == tagname:
                h.setdefault(k, []).extend(t[k].split(';'))
            else:
                assert k not in h
                h[k] = t[k]
        continue

    output = []
    for ea, t in res.iteritems():
        ofs = db.offset(ea)

        commands = []
        label = Template('.printf "$label -- $note\\n"' if t.
                         has_key('') else '.printf "$label\\n"')
        commands.append(
            label.safe_substitute(label=eaToLabel(ea), note=t.get('', '')))
        commands.extend(t.get(tagname, ['g']))
        commands = map(windbgescape, commands)

        breakpoint = 'bp {:s} "{:s}"'.format(eaToReference(ea),
                                             Escape(';'.join(commands)))
        if stdout:
            print(breakpoint)

        output.append(breakpoint)

    if len(output) == 1:
        return output[0] + '\n'

    return '\n'.join(output)
Beispiel #28
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)
Beispiel #29
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)
Beispiel #30
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 (LookupError, ValueError):
            pass

    # tag the functions too
    for ea in list(f):
        m = function.marks(ea)
        function.tag(ea, 'marks', [ea for ea, _ in m])
    return
Beispiel #31
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
Beispiel #32
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
Beispiel #33
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
Beispiel #34
0
def top(ea=None):
    return function.top(ea is not None and ea or database.h())
Beispiel #35
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)))
Beispiel #36
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)))
Beispiel #37
0
def top():
    import function     # ida's usage of python sucks.
    return function.top(db.h())
Beispiel #38
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)))
Beispiel #39
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
Beispiel #40
0
 def nextstack(cls, ea, delta):
     fn, sp = function.top(ea), function.getSpDelta(ea)
     return cls.walk(ea, cls.next,
                     lambda n: abs(function.getSpDelta(n) - sp) < delta)
Beispiel #41
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))
Beispiel #42
0
def top():
    return function.top(database.h())
Beispiel #43
0
def top():
    return function.top(database.h())
Beispiel #44
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)))
Beispiel #45
0
def name(ea=None, *args, **kwds):
    """name(ea), name(ea, string)
    First syntax returns the name at the given address.
    Second syntax changes the name at the given address.
    """
    if len(args) > 1:
        raise TypeError, "{:s}() takes exactly {!r} arguments ({:d} given)".format(
            'name', (1, 2),
            len(args) + 1 + len(kwds))
    if kwds and tuple(kwds.keys()) != ('string', ):
        raise TypeError, "{:s}() got an unexpected keyword argument '{:s}'".format(
            'name',
            filter(lambda n: n != 'string', kwds.keys())[0])

    ea = ui.current.address() if ea is None else ea
    if len(args) == 1 or kwds.has_key('string'):
        string = kwds.get('string', args[0])
        assert idaapi.SN_NOCHECK == 0, '%s.name : idaapi.SN_NOCHECK != 0' % __name__
        SN_NOLIST = idaapi.SN_NOLIST
        SN_LOCAL = idaapi.SN_LOCAL
        SN_NON_PUBLIC = idaapi.SN_NON_PUBLIC

        if idaapi.has_any_name(idaapi.getFlags(ea)):
            pass

        flags = idaapi.SN_NON_AUTO
        flags |= 0 if idaapi.is_in_nlist(ea) else idaapi.SN_NOLIST
        flags |= idaapi.SN_WEAK if idaapi.is_weak_name(
            ea) else idaapi.SN_NON_WEAK
        flags |= idaapi.SN_PUBLIC if idaapi.is_public_name(
            ea) else idaapi.SN_NON_PUBLIC

        try:
            function.top(ea)
            flags |= idaapi.SN_LOCAL
        except Exception:
            flags &= ~idaapi.SN_LOCAL

        try:
            # check if we're a label of some kind
            f = idaapi.getFlags(ea)
            if idaapi.has_dummy_name(f) or idaapi.has_user_name(f):
                # that is referenced by an array with a correctly sized pointer inside it
                (r, sidata), = ((r, type.array(r)) for r in xref.data_up(ea))
                if config.bits() == sidata.itemsize * 8 and ea in sidata:
                    # which we check to see if it's a switch_info_t
                    si, = (idaapi.get_switch_info_ex(r)
                           for r in xref.data_up(r))
                    if si is not None:
                        # because it's name has it's local flag cleared
                        flags ^= idaapi.SN_LOCAL
        except:
            pass

        res, ok = name(ea), idaapi.set_name(ea, string or "", flags)
        tag(ea, 'name', string)
        assert ok, '%s.name : unable to call idaapi.set_name(%x, %r, %x)' % (
            __name__, ea, string, flags)
        return res

    try:
        return tag(ea, 'name')
    except KeyError:
        pass
    return None