From 686e018bdc9c07b8fcf562549070be1cf8f04bfc Mon Sep 17 00:00:00 2001 From: "elias.bachaalany" Date: Tue, 27 Jul 2010 14:44:31 +0000 Subject: [PATCH] - updated debughook example - wrapped print_type - minor mods to idc.py - added idautils.GetIdbDir - added Names() - added Modules() - added idautils.peutils_t() - simplecustviewer_t.GetLineNo() now returns -1 on failure - idc.py / setregval: it was not possible to set register values > 0x7fffffff --- examples/debughook.py | 26 ++++++++++++++++- python/idautils.py | 67 +++++++++++++++++++++++++++++++++++++++++++ python/idc.py | 35 +++++++++++----------- swig/dbg.i | 2 +- swig/idp.i | 2 +- swig/kernwin.i | 4 +-- swig/typeinf.i | 27 +++++++++++++++++ 7 files changed, 142 insertions(+), 21 deletions(-) diff --git a/examples/debughook.py b/examples/debughook.py index 8ee74e8..5fc26e8 100644 --- a/examples/debughook.py +++ b/examples/debughook.py @@ -4,7 +4,10 @@ # This script start the executable and steps through the first five # instructions. Each instruction is disassembled after execution. # -# Author: Gergely Erdelyi +# Original Author: Gergely Erdelyi +# +# Maintained By: IDAPython Team +# #--------------------------------------------------------------------- from idaapi import * @@ -19,6 +22,10 @@ class MyDbgHook(DBG_Hooks): print "Process exited pid=%d tid=%d ea=0x%x code=%d" % (pid, tid, ea, code) return 0 + def dbg_library_unload(self, pid, tid, ea, info): + print "Library unloaded: pid=%d tid=%d ea=0x%x info=%s" % (pid, tid, ea, info) + return 0 + def dbg_library_load(self, pid, tid, ea, name, base, size): print "Library loaded: pid=%d tid=%d name=%s base=%x" % (pid, tid, name, base) @@ -31,6 +38,19 @@ class MyDbgHook(DBG_Hooks): # 1 - to always display a breakpoint warning dialog. return 0 + def dbg_suspend_process(self): + print "Process suspended" + + def dbg_exception(self, pid, tid, ea, exc_code, exc_can_cont, exc_ea, exc_info): + print "Exception: pid=%d tid=%d ea=0x%x exc_code=0x%x can_continue=%d exc_ea=0x%x exc_info=%s" % ( + pid, tid, ea, exc_code & idaapi.BADADDR, exc_can_cont, exc_ea, exc_info) + # return values: + # -1 - to display an exception warning dialog + # if the process is suspended. + # 0 - to never display an exception warning dialog. + # 1 - to always display an exception warning dialog. + return 0 + def dbg_trace(self, tid, ea): print tid, ea return 0 @@ -39,6 +59,10 @@ class MyDbgHook(DBG_Hooks): print "Step into" return self.dbg_step_over() +# def dbg_run_to(self, tid): +# print "Runto: tid=%d" % tid +# idaapi.continue_process() + def dbg_step_over(self): eip = GetRegValue("EIP") print "0x%x %s" % (eip, GetDisasm(eip)) diff --git a/python/idautils.py b/python/idautils.py index 8c49b12..ab31ee3 100644 --- a/python/idautils.py +++ b/python/idautils.py @@ -14,6 +14,7 @@ idautils.py - High level utility functions for IDA import idaapi import idc import types +import os def refs(ea, funcfirst, funcnext): """ @@ -240,6 +241,26 @@ def Chunks(start): yield (chunk.startEA, chunk.endEA) status = func_iter.next() +def Modules(): + """ + Returns a list of module objects with name,size,base and the rebase_to attributes + """ + mod = idaapi.module_info_t() + result = idaapi.get_first_module(mod) + while result: + yield idaapi.object_t(name=mod.name, size=mod.size, base=mod.base, rebase_to=mod.rebase_to) + result = idaapi.get_next_module(mod) + +def Names(): + """ + Returns a list of names + + @return: tuple(ea, name) + """ + for i in xrange(idaapi.get_nlist_size()): + ea = idaapi.get_nlist_ea(i) + name = idaapi.get_nlist_name(i) + yield (ea, name) def Segments(): """ @@ -424,14 +445,26 @@ class Strings(object): return Strings.StringItem(self._si) return None +# ----------------------------------------------------------------------- def GetRegisterList(): """Returns the register list""" return idaapi.ph_get_regnames() +# ----------------------------------------------------------------------- +def GetIdbDir(): + """ + Get IDB directory + + This function returns directory path of the current IDB database + """ + return os.path.dirname(idaapi.cvar.database_idb) + os.sep + +# ----------------------------------------------------------------------- def GetInstructionList(): """Returns the instruction list of the current processor module""" return [i[0] for i in idaapi.ph_get_instruc() if i[0]] +# ----------------------------------------------------------------------- def _Assemble(ea, line): """ Please refer to Assemble() - INTERNAL USE ONLY @@ -496,6 +529,7 @@ def _copy_obj(src, dest, skip_list = None): setattr(dest, x, t) return dest +# ----------------------------------------------------------------------- class _reg_dtyp_t(object): """ INTERNAL @@ -509,6 +543,7 @@ class _reg_dtyp_t(object): def __eq__(self, other): return (self.reg == other.reg) and (self.dtyp == other.dtyp) +# ----------------------------------------------------------------------- class _procregs(object): """Utility class allowing the users to identify registers in a decoded instruction""" def __getattr__(self, attr): @@ -522,6 +557,7 @@ class _procregs(object): def __setattr__(self, attr, value): raise AttributeError(attr) +# ----------------------------------------------------------------------- class _cpu(object): "Simple wrapper around GetRegValue/SetRegValue" def __getattr__(self, name): @@ -532,6 +568,37 @@ class _cpu(object): #print "cpu.set(%s)"%name return idc.SetRegValue(value, name) +# ----------------------------------------------------------------------- +class peutils_t(object): + """ + PE utility class. Retrieves PE information from the database. + + Constants from pe.h + """ + PE_NODE = "$ PE header" # netnode name for PE header + PE_ALT_DBG_FPOS = idaapi.BADADDR & -1 # altval() -> translated fpos of debuginfo + PE_ALT_IMAGEBASE = idaapi.BADADDR & -2 # altval() -> loading address (usually pe.imagebase) + PE_ALT_PEHDR_OFF = idaapi.BADADDR & -3 # altval() -> offset of PE header + PE_ALT_NEFLAGS = idaapi.BADADDR & -4 # altval() -> neflags + PE_ALT_TDS_LOADED = idaapi.BADADDR & -5 # altval() -> tds already loaded(1) or invalid(-1) + PE_ALT_PSXDLL = idaapi.BADADDR & -6 # altval() -> if POSIX(x86) imports from PSXDLL netnode + + def __init__(self): + self.__penode = idaapi.netnode() + self.__penode.create(peutils_t.PE_NODE) + + imagebase = property( + lambda self: self.__penode.altval(peutils_t.PE_ALT_IMAGEBASE) + ) + + header = property( + lambda self: self.__penode.altval(peutils_t.PE_ALT_PEHDR_OFF) + ) + + def __str__(self): + return "peutils_t(imagebase=%s, header=%s)" % (hex(self.imagebase), hex(self.header)) + +# ----------------------------------------------------------------------- cpu = _cpu() """This is a special class instance used to access the registers as if they were attributes of this object. For example to access the EAX register: diff --git a/python/idc.py b/python/idc.py index 99d64a7..a7a44d8 100644 --- a/python/idc.py +++ b/python/idc.py @@ -3817,7 +3817,7 @@ def writestr(handle, s): # F U N C T I O N S # ---------------------------------------------------------------------------- -def MakeFunction(start, end): +def MakeFunction(start, end = idaapi.BADADDR): """ Create a function @@ -7094,13 +7094,13 @@ def SetRegValue(value, name): A register name in the left side of an assignment will do too. """ rv = idaapi.regval_t() - if type(value)==types.StringType: - value = int(value) - elif type(value)!=types.IntType: + if type(value) == types.StringType: + value = int(value, 16) + elif type(value) != types.IntType and type(value) != types.LongType: print "SetRegValue: value must be integer!" return BADADDR - if value<0: + if value < 0: #ival_set cannot handle negative numbers value &= 0xFFFFFFFF @@ -7249,7 +7249,8 @@ def AddBptEx(ea, size, bpttype): return idaapi.add_bpt(ea, size, bpttype) -def AddBpt(ea): return AddBptEx(ea, 0, BPT_SOFT) +def AddBpt(ea): + return AddBptEx(ea, 0, BPT_SOFT) def DelBpt(ea): @@ -7499,17 +7500,17 @@ def WriteExe(filepath): return GenerateFile(OFILE_EXE, filepath, 0, BADADDR, 0) def AddConst(enum_id,name,value): return AddConstEx(enum_id,name,value,-1) -def AddStruc(index,name): return AddStrucEx(index,name,0) -def AddUnion(index,name): return AddStrucEx(index,name,1) -def OpStroff(ea,n,strid): return OpStroffEx(ea,n,strid,0) -def OpEnum(ea,n,enumid): return OpEnumEx(ea,n,enumid,0) -def DelConst(constid, v, mask): return DelConstEx(constid, v, 0, mask) -def GetConst(constid, v, mask): return GetConstEx(constid, v, 0, mask) -def AnalyseArea(sEA, eEA): return AnalyzeArea(sEA,eEA) +def AddStruc(index,name): return AddStrucEx(index,name,0) +def AddUnion(index,name): return AddStrucEx(index,name,1) +def OpStroff(ea,n,strid): return OpStroffEx(ea,n,strid,0) +def OpEnum(ea,n,enumid): return OpEnumEx(ea,n,enumid,0) +def DelConst(constid, v, mask): return DelConstEx(constid, v, 0, mask) +def GetConst(constid, v, mask): return GetConstEx(constid, v, 0, mask) +def AnalyseArea(sEA, eEA): return AnalyzeArea(sEA,eEA) -def MakeStruct(ea,name): return MakeStructEx(ea, -1, name) -def Name(ea): return NameEx(BADADDR, ea) -def GetTrueName(ea): return GetTrueNameEx(BADADDR, ea) +def MakeStruct(ea,name): return MakeStructEx(ea, -1, name) +def Name(ea): return NameEx(BADADDR, ea) +def GetTrueName(ea): return GetTrueNameEx(BADADDR, ea) def MakeName(ea, name): return MakeNameEx(ea,name,SN_CHECK) #def GetFrame(ea): return GetFunctionAttr(ea, FUNCATTR_FRAME) @@ -7533,6 +7534,8 @@ def SegDefReg(ea, reg, value): return SetSegDefReg(ea, reg, va def Comment(ea): return GetCommentEx(ea, 0) +"""Returns the non-repeatable comment or None""" + def RptCmt(ea): return GetCommentEx(ea, 1) def SetReg(ea, reg, value): return SetRegEx(ea, reg, value, SR_user) diff --git a/swig/dbg.i b/swig/dbg.i index ce7eb57..219f486 100644 --- a/swig/dbg.i +++ b/swig/dbg.i @@ -293,7 +293,7 @@ int idaapi DBG_Callback(void *ud, int notification_code, va_list va) } catch (Swig::DirectorException &) { - msg("Exception in IDP Hook function:\n"); + msg("Exception in DBG Hook function:\n"); if (PyErr_Occurred()) { PyErr_Print(); diff --git a/swig/idp.i b/swig/idp.i index 599cd9a..0310eb9 100644 --- a/swig/idp.i +++ b/swig/idp.i @@ -713,7 +713,7 @@ int idaapi IDB_Callback(void *ud, int notification_code, va_list va) } catch (Swig::DirectorException &) { - msg("Exception in IDP Hook function:\n"); + msg("Exception in IDB Hook function:\n"); if (PyErr_Occurred()) { PyErr_Print(); diff --git a/swig/kernwin.i b/swig/kernwin.i index 572fd71..f9e8188 100644 --- a/swig/kernwin.i +++ b/swig/kernwin.i @@ -2862,9 +2862,9 @@ class simplecustviewer_t(object): return _idaapi.pyscv_get_pos(self.__this, mouse) def GetLineNo(self, mouse = 0): - """Calls GetPos() and returns the current line number only or None on failure""" + """Calls GetPos() and returns the current line number or -1 on failure""" r = self.GetPos(mouse) - return None if not r else r[0] + return -1 if not r else r[0] def Jump(self, lineno, x=0, y=0): return _idaapi.pyscv_jumpto(self.__this, lineno, x, y) diff --git a/swig/typeinf.i b/swig/typeinf.i index 36d1557..358edae 100644 --- a/swig/typeinf.i +++ b/swig/typeinf.i @@ -116,6 +116,8 @@ %ignore apply_type_to_stkarg; %rename (apply_type_to_stkarg) py_apply_type_to_stkarg; +%ignore print_type; +%rename (print_type) py_print_type; %ignore use_regarg_type_cb; %ignore set_op_type_t; @@ -201,6 +203,31 @@ PyObject *py_get_type_size0(const til_t *ti, PyObject *tp) return PyInt_FromLong(sz); } +//------------------------------------------------------------------------- +/* +# +def print_type(ea, on_line): + """ + Returns the type of an item + @return: + - None on failure + - The type string with a semicolon. Can be used directly with idc.SetType() + """ + pass +# +*/ +static PyObject *py_print_type(ea_t ea, bool one_line) +{ + char buf[MAXSTR]; + if ( print_type(ea, buf, sizeof(buf), one_line) ) + { + qstrncat(buf, ";", sizeof(buf)); + return PyString_FromString(buf); + } + else + Py_RETURN_NONE; +} + //------------------------------------------------------------------------- /* #