Random examples and snippets - arizvisa/ida-minsc Wiki

Ideally, you'd drop these in your $HOME/.idapythonrc.py file or $YOURIDBPATH/idapythonrc.py so that way you have access to them when you start things up.

Simple cfuncptr_t tools

def find_expr_addr(cfunc, cexpr):
    if cexpr.ea == idaapi.BADADDR:
        while True:
            cexpr = cfunc.body.find_parent_of(cexpr)
            if cexpr is None:
                ea = cfunc.entry_ea
                break
            if cexpr.ea != idaapi.BADADDR:
                ea = cexpr.ea
                break
            continue
        return ea
    return cexpr.ea

def find_addr(vu):
    citem = vu.item
    if citem.citype in {idaapi.VDI_EXPR}:
        return find_expr_addr(vu.cfunc, citem.e)
    elif citem.citype in {idaapi.VDI_TAIL}:
        return citem.loc.ea
    elif citem.citype in {idaapi.VDI_LVAR}:
        return citem.l.defea
    elif citem.citype in {idaapi.VDI_FUNC}:
        return citem.f.entry_ea
    raise NotImplementedError(citem.citype)

import internal
class lvars(object):
    @classmethod
    def __iterate__(cls, D):
        lvars = D.get_lvars()
        for index in range(lvars.size()):
            yield lvars[index]
        return

    __matcher__ = internal.utils.matcher()
    __matcher__.boolean('name', lambda name, item: name.lower() == item.lower(), fgetattr('name'))
    __matcher__.combinator('like', utils.fcompose(fnmatch.translate, utils.fpartial(re.compile, flags=re.IGNORECASE), operator.attrgetter('match')), fgetattr('name'))
    __matcher__.predicate('predicate'), __matcher__.predicate('pred')

    @internal.utils.multicase()
    @classmethod
    def iterate(cls, **type):
        return cls.iterate(None, **type)
    @internal.utils.multicase(name=str)
    @classmethod
    def iterate(cls, name, **type):
        return cls.iterate(name, None, **type)
    @internal.utils.multicase(name=str, D=(None.__class__, idaapi.cfuncptr_t))
    @classmethod
    def iterate(cls, name, D, **type):
        type.setdefault('like', name)
        return cls.iterate(D, **type)
    @internal.utils.multicase(D=(None.__class__, idaapi.cfuncptr_t))
    @classmethod
    def iterate(cls, D, **type):
        state = D if D else idaapi.decompile(func.address())
        iterable = cls.__iterate__(state)
        for key, value in (type or {'predicate': utils.fconstant(True)}).items():
            iterable = cls.__matcher__.match(key, value, iterable)
        for item in iterable: yield item

    @internal.utils.multicase()
    @classmethod
    def list(cls, **type):
        return cls.list(None, **type)
    @internal.utils.multicase(name=str)
    @classmethod
    def list(cls, name, **type):
        return cls.list(name, None, **type)
    @internal.utils.multicase(name=str, D=(None.__class__, idaapi.cfuncptr_t))
    @classmethod
    def list(cls, name, D, **type):
        type.setdefault('like', name)
        return cls.list(D, **type)
    @internal.utils.multicase(D=(None.__class__, idaapi.cfuncptr_t))
    @classmethod
    def list(cls, D, **type):
        state = D if D else idaapi.decompile(func.address())
        res = [item for item in cls.iterate(state, **type)]

        print_t = lambda item: idaapi.print_tinfo('', 0, 0, 0, item.type(), item.name, '')

        maxdisasm = max(map(fcompose(fgetattr('defea'), db.disasm, len), res))
        maxname = max(map(fcompose(print_t, len), res))

        for item in res:
            t_s = print_t(item)
            print("{:<{:d}s} // {:<{:d}s} : {!s}".format(db.disasm(item.defea), maxdisasm, t_s, maxname, cls.vdloc(state, item)))
        return

    @internal.utils.multicase()
    @classmethod
    def by(cls, **type):
        return cls.by(None, **type)
    @internal.utils.multicase(name=str)
    @classmethod
    def by(cls, name, **type):
        return cls.by(name, None, **type)
    @internal.utils.multicase(name=str, D=(None.__class__, idaapi.cfuncptr_t))
    @classmethod
    def by(cls, name, D, **type):
        type.setdefault('like', name)
        return cls.by(D, **type)
    @internal.utils.multicase(D=(None.__class__, idaapi.cfuncptr_t))
    @classmethod
    def by(cls, D, **type):
        state = D if D else idaapi.decompile(func.address())
        return next(item for item in cls.iterate(state, **type))

    @internal.utils.multicase()
    @classmethod
    def get(cls, **type):
        return cls.get(None, **type)
    @internal.utils.multicase(name=str)
    @classmethod
    def get(cls, name, **type):
        return cls.get(name, None, **type)
    @internal.utils.multicase(name=str, D=(None.__class__, idaapi.cfuncptr_t))
    @classmethod
    def get(cls, name, D, **type):
        type.setdefault('like', name)
        return cls.get(D, **type)
    @internal.utils.multicase(D=(None.__class__, idaapi.cfuncptr_t))
    @classmethod
    def get(cls, D, **type):
        state = D if D else idaapi.decompile(func.address())
        res = cls.by(state, **type)
        return cls.vdloc(state, res)

    @internal.utils.multicase()
    @classmethod
    def name(cls, **type):
        return cls.name(None, **type)
    @internal.utils.multicase(name=str)
    @classmethod
    def name(cls, name, **type):
        return cls.name(name, None, **type)
    @internal.utils.multicase(name=str, D=(None.__class__, idaapi.cfuncptr_t))
    @classmethod
    def name(cls, name, D, **type):
        type.setdefault('like', name)
        return cls.name(D, **type)
    @internal.utils.multicase(D=(None.__class__, idaapi.cfuncptr_t))
    @classmethod
    def name(cls, D, **type):
        state = D if D else idaapi.decompile(func.address())
        res = cls.by(state, **type)
        return res.name

    @classmethod
    def vdloc(cls, state, lv):
        loc = lv.location
        atype, vtype = loc.atype(), lv.type()
        if atype in {idaapi.ALOC_REG1}:
            regname = idaapi.print_vdloc(loc, vtype.get_size())
            return ins.arch.byname(regname)
        elif atype in {idaapi.ALOC_STACK}:
            fr = func.frame(lv.defea)
            delta = state.get_stkoff_delta()
            realoffset = loc.stkoff() - delta
            return fr.members.by_realoffset(realoffset) if 0 <= realoffset < fr.size else location_t(realoffset, vtype.get_size())
        raise NotImplementedError(atype)

    @classmethod
    def refs(cls, lv):
        raise NotImplementedError('python/examples/hexrays/vds12.py')

(Dumb) windbg breakpoint generator for all the functions you've touched

masmformat = lambda item: "@{:s}".format(item.name) if isinstance(item, register_t) else "@rsp+8+{:#x}".format(item.offset)
for ea, tags in db.select('__typeinfo__'):
    if not func.within(ea): continue

    sizes = [ ti.get_size() for ti in func.type.args(ea) ]
    locs = func.type.args.registers(ea) + func.type.args.locations(ea)

    params = [ "({:s}) & {:#x}".format(masmformat(item), pow(2, 8 * size) - 1) for item, size in zip(locs, sizes)]
    formats = [ "%0{:d}x".format(2 * size) for size in sizes ]
    bpstr = ".printf \"{:s} -> {:s}({:s})\\n\"{:s}; gc".format(tags['__typeinfo__'], func.name(ea), ', '.join(formats), ", {:s}".format(', '.join(params)) if params else '')
    db.tag(ea, 'func.entry.breakpoint', bpstr)

    result = func.type.result(ea)
    loc = func.type.result.location(ea)
    bpstr = ".printf \"{:s} -> returned{:s}\\n\"{:s};gc".format(tags['__typeinfo__'], ' %p' if loc else '', ",@{:s}".format(loc.name) if isinstance(loc, register_t) else '')
    for ea in func.bottom(ea):
        db.tag(ea, 'func.exit.breakpoint', bpstr)
    continue

Then to actually generate them so you can load them with $>< or something similar.

for f, tags in db.selectcontents(Or=['func.entry.breakpoint', 'func.exit.breakpoint']):
    for ea, tags in func.select(f, Or=['func.entry.breakpoint', 'func.exit.breakpoint']):
        for k, v in tags.items():
            print("bp {:s}+{:#x} \"{:s}\"".format(db.module(), db.offset(ea), custom.windbg.escape(v, 1)))

the same as custom.tags.export()

savegame = {}
for ea, content in db.select():           # db.select queries the index which contains only "your" notations
    savegame[ea] = content

savegame2 = {}
for funcea in db.functions():             # use db.selectcontents(), if you only want functions you've touched
    f = {}
    for ea, content in func.select(ea):   # use func.iterate() if you just want __everything__
        f[ea] = content
    fr = {}
    for m, content in func.frame(ea).select():    # for just __all__ the members, just use func.frame(ea) w/o the .select()
        fr[m.offset] = content
    savegame2[funcea] = f, fr

# send them all to another process
import pickle
mysavegame = pickle.dumps((savegame, savegame2))
socket.send(mysavegame)

serializing and deserializing all your types in the database.

need to save a structure? just pickle it.

import pickle
st = struc.search('_IO_STACK*')
with open(db.config.path('somefilerelativetodatabase'), 'wb') as outfile:
    pickle.dump(st, outfile)

import it into another database with:

import pickle
with open('/path/to/somefilerelativetodatabase', 'rb') as infile:
    st = pickle.load(infile)

or do all of them.

a = [st for st in struc.iterate()]
pickle.dumps(a)

types are natively serializable so its not too big a deal, but if you don't want to generate a .h file you can just select them with

a = [(ti, name) for index, name, ti in db.types.iterate('_*')]
b = [(name, ti.serialize()) for ti in a]
with open('blah', 'wb') as outfile: pickle.dump(b, outfile)

then load them into another db.

with open('blah', 'rb') as infile: b = pickle.load(infile)
ordinal = db.types.count()
for name, serialized in b:
    ti = db.types.get(serialized)
    db.types.set(ordinal, name, ti)
    ordinal += 1