IDAPython Scripting Examples

By way of offering a compare and contrast between IDC and IDAPython, the following sections present the same example cases seen previously in the discussion of IDC. Wherever possible we endeavor to make maximum use of Python-specific features to demonstrate some of the efficiencies that can be gained by scripting in Python.

Enumerating Functions

One of the strengths of IDAPython is the way that it uses Python’s powerful datatypes to simplify access to collections of database objects. In Example 15-8, we reimplement the function enumeration script of Example 15-1 in Python. Recall that the purpose of this script is to iterate over every function in a database and print basic information about each function, including the start and end addresses of the function, the size of the function’s arguments, and the size of the function’s local variable space. All output is sent to the output window.

Example 15-8. Function enumeration using Python

funcs = Functions()
for f in funcs:
   name = Name(f)
   end = GetFunctionAttr(f, FUNCATTR_END)
   locals = GetFunctionAttr(f, FUNCATTR_FRSIZE)
   frame = GetFrame(f)     # retrieve a handle to the function's stack frame
   if frame is None: continue
   ret = GetMemberOffset(frame, " r")  # " r" is the name of the return address
   if ret == −1: continue
   firstArg = ret + 4
   args = GetStrucSize(frame) - firstArg
   Message("Function: %s, starts at %x, ends at %x
" % (name, f, end))
   Message("   Local variable area is %d bytes
" % locals)
   Message("   Arguments occupy %d bytes (%d args)
" % (args, args / 4))

For this particular script, the use of Python gains us little in the way of efficiency other than the use of the Functions list generator, which facilitates the for loop at .

Enumerating Instructions

Example 15-9 demonstrates how the instruction-counting script of Example 15-2 might be written in Python, taking advantage of the list generators available in the idautils module.

Example 15-9. Instruction enumeration in Python

from idaapi import *
func = get_func(here())  # here() is synonymous with ScreenEA()
if not func is None:
   fname = Name(func.startEA)
   count = 0
   for i in FuncItems(func.startEA): count = count + 1
   Warning("%s contains %d instructions
" % (fname,count))
else:
   Warning("No function found at location %x" % here())

Differences from the IDC version include the use of an SDK function (accessed via idaapi) to retrieve a reference to a function object (specifically a func_t) and the use of the FuncItems generator (from idautils) to provide easy iteration over all of the instructions within the function. Because we can’t use Python’s len function on a generator, we are still obligated to step through the generator list in order to count each instruction one at a time.

Enumerating Cross-References

The idautils module contains several generator functions that build cross-reference lists in a somewhat more intuitive way than we saw in IDC. Example 15-10 rewrites the function call enumeration script that we saw previously in Example 15-3.

Example 15-10. Enumerating function calls using Python

from idaapi import *
func = get_func(here())
if not func is None:
   fname = Name(func.startEA)
   items = FuncItems(func.startEA)
   for i in items:
      for xref in XrefsFrom(i, 0):
         if xref.type == fl_CN or xref.type == fl_CF:
            Message("%s calls %s from 0x%x
" % (fname, Name(xref.to), i))
else:
   Warning("No function found at location %x" % here())

New in this script is the use of the XrefsFrom generator (from idautils) to step through all cross-references from the current instruction. XrefsFrom returns a reference to an xrefblk_t object that contains detailed information about the current cross-reference.

Enumerating Exported Functions

Example 15-11 is the Python version of the .idt generator script from Example 15-5.

Example 15-11. A Python script to generate IDT files

file = AskFile(1, "*.idt", "Select IDT save file")
with open(file, 'w') as fd:
   fd.write("ALIGNMENT 4
")
   fd.write("0 Name=%s
" % GetInputFile())
   for i in range(GetEntryPointQty()):
      ord = GetEntryOrdinal(i)
      if ord == 0: continue
      addr = GetEntryPoint(ord)
      if ord == addr: continue   #entry point has no ordinal
      fd.write("%d Name=%s" % (ord, Name(addr)))
      purged = GetFunctionAttr(addr, FUNCATTR_ARGSIZE)
      if purged > 0:
         fd.write(" Pascal=%d" % purged)
      fd.write("
")

The two scripts look remarkably similar because IDAPython has no generator function for entry-point lists, so we are left to use the same set of functions that were used in Example 15-5. One difference worth noting is that IDAPython deprecates IDC’s file-handling functions in favor of Python’s built-in file-handling functions.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.146.35.72