mirror of
https://github.com/cemu-project/idapython.git
synced 2024-12-28 02:31:53 +01:00
idautils: added Strings class to enumerate strings (check ex_strings.py)
gdl.i: added FlowChart and BasicBlock classes (check examples / ex_gdl_qflow_chart) idc.py : fixed MakeName() and AnalyseArea() (they were not returning return values)
This commit is contained in:
parent
e51eb69e3a
commit
e27524cca5
32
build.py
32
build.py
@ -2,7 +2,7 @@
|
||||
#------------------------------------------------------------
|
||||
# IDAPython - Python plugin for Interactive Disassembler Pro
|
||||
#
|
||||
# Copyright (c) 2004-2009 Gergely Erdelyi <dyce@d-dome.net>
|
||||
# Copyright (c) 2004-2009 Gergely Erdelyi <dyce@d-dome.net>
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
@ -70,6 +70,8 @@ BINDIST_MANIFEST = [
|
||||
"examples/ex1_idautils.py",
|
||||
"examples/hotkey.py",
|
||||
"examples/structure.py",
|
||||
"examples/ex_gdl_qflow_chart.py",
|
||||
"examples/ex_strings.py",
|
||||
]
|
||||
|
||||
# List files for the source distribution (appended to binary list)
|
||||
@ -220,10 +222,10 @@ class MSVCBuilder(BuilderBase):
|
||||
self.linker = "link"
|
||||
self.source_extension = ".cpp"
|
||||
self.object_extension = ".obj"
|
||||
|
||||
|
||||
def compiler_in_string(self, filename):
|
||||
return "/c %s" % filename
|
||||
|
||||
|
||||
def compiler_out_string(self, filename):
|
||||
return "/Fo%s" % filename
|
||||
|
||||
@ -244,7 +246,7 @@ def build_distribution(manifest, distrootdir, ea64, nukeold):
|
||||
# Also make a ZIP archive of the build
|
||||
zippath = distrootdir + ".zip"
|
||||
zip = zipfile.ZipFile(zippath, nukeold and "w" or "a", zipfile.ZIP_DEFLATED)
|
||||
|
||||
|
||||
# Copy files, one by one
|
||||
for f in manifest:
|
||||
if type(f) == types.TupleType:
|
||||
@ -259,11 +261,11 @@ def build_distribution(manifest, distrootdir, ea64, nukeold):
|
||||
if srcdir == "":
|
||||
dstdir = distrootdir
|
||||
else:
|
||||
dstdir = distrootdir + os.sep + srcdir
|
||||
dstdir = distrootdir + os.sep + srcdir
|
||||
|
||||
if not os.path.exists(dstdir):
|
||||
os.makedirs(dstdir)
|
||||
|
||||
|
||||
dstfilepath = dstdir + os.sep + srcfilename
|
||||
shutil.copyfile(srcfilepath, dstfilepath)
|
||||
zip.write(dstfilepath)
|
||||
@ -348,7 +350,7 @@ def build_binary_package(ea64, nukeold):
|
||||
system = "Windows"
|
||||
platform_string = "win32"
|
||||
plugin_name = ea64 and "python.p64" or "python.plw"
|
||||
|
||||
|
||||
if system == "Linux":
|
||||
platform_string = "linux"
|
||||
plugin_name = ea64 and "python.plx64" or "python.plx"
|
||||
@ -357,10 +359,10 @@ def build_binary_package(ea64, nukeold):
|
||||
platform_string = "macosx"
|
||||
plugin_name = ea64 and "python.pmc64" or "python.pmc"
|
||||
|
||||
BINDISTDIR = "idapython-%d.%d.%d_ida%d.%d_py%d.%d_%s" % (VERSION_MAJOR,
|
||||
VERSION_MINOR,
|
||||
VERSION_PATCH,
|
||||
IDA_MAJOR_VERSION,
|
||||
BINDISTDIR = "idapython-%d.%d.%d_ida%d.%d_py%d.%d_%s" % (VERSION_MAJOR,
|
||||
VERSION_MINOR,
|
||||
VERSION_PATCH,
|
||||
IDA_MAJOR_VERSION,
|
||||
IDA_MINOR_VERSION,
|
||||
PYTHON_MAJOR_VERSION,
|
||||
PYTHON_MINOR_VERSION,
|
||||
@ -378,9 +380,9 @@ def build_binary_package(ea64, nukeold):
|
||||
|
||||
def build_source_package():
|
||||
""" Build a directory and a ZIP file with all the sources """
|
||||
SRCDISTDIR = "idapython-%d.%d.%d" % (VERSION_MAJOR,
|
||||
VERSION_MINOR,
|
||||
VERSION_PATCH)
|
||||
SRCDISTDIR = "idapython-%d.%d.%d" % (VERSION_MAJOR,
|
||||
VERSION_MINOR,
|
||||
VERSION_PATCH)
|
||||
# Build the source distribution
|
||||
srcmanifest = []
|
||||
srcmanifest.extend(BINDIST_MANIFEST)
|
||||
@ -391,7 +393,7 @@ def build_source_package():
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Do 64-bit build?
|
||||
ea64 = '--ea64' in sys.argv
|
||||
ea64 = '--ea64' in sys.argv
|
||||
build_binary_package(ea64=False, nukeold=True)
|
||||
if ea64:
|
||||
build_binary_package(ea64=True, nukeold=False)
|
||||
|
35
examples/ex_gdl_qflow_chart.py
Normal file
35
examples/ex_gdl_qflow_chart.py
Normal file
@ -0,0 +1,35 @@
|
||||
import idaapi
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Using raw IDAAPI
|
||||
def raw_main(p=True):
|
||||
global q
|
||||
f = idaapi.get_func(here())
|
||||
if not f:
|
||||
return
|
||||
q = idaapi.qflow_chart_t("The title", f, 0, 0, idaapi.FC_PREDS)
|
||||
for n in xrange(0, q.size()):
|
||||
b = q[n]
|
||||
if p: print "%x - %x [%d]:" % (b.startEA, b.endEA, n)
|
||||
for ns in xrange(0, q.nsucc(n)):
|
||||
if p: print " %d->%d" % (n, q.succ(n, ns))
|
||||
for ns in xrange(0, q.npred(n)):
|
||||
if p: print " %d->%d" % (n, q.pred(n, ns))
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Using the class
|
||||
def cls_main(p=True):
|
||||
global f
|
||||
f = idaapi.FlowChart(idaapi.get_func(here()))
|
||||
for block in f:
|
||||
if p: print "%x - %x [%d]:" % (block.startEA, block.endEA, block.id)
|
||||
for succ_block in block.succs():
|
||||
if p: print " %x - %x [%d]:" % (succ_block.startEA, succ_block.endEA, succ_block.id)
|
||||
for pred_block in block.preds():
|
||||
if p: print " %x - %x [%d]:" % (pred_block.startEA, pred_block.endEA, pred_block.id)
|
||||
|
||||
q = None
|
||||
f = None
|
||||
raw_main(False)
|
||||
cls_main(True)
|
||||
|
6
examples/ex_strings.py
Normal file
6
examples/ex_strings.py
Normal file
@ -0,0 +1,6 @@
|
||||
import idautils
|
||||
|
||||
s = Strings(False)
|
||||
s.setup(strtypes=Strings.STR_UNICODE | Strings.STR_C)
|
||||
for i in s:
|
||||
print "%x: len=%d type=%d -> '%s'" % (i.ea, i.length, i.type, str(i))
|
@ -1,7 +1,7 @@
|
||||
#------------------------------------------------------------
|
||||
# IDAPython - Python plugin for Interactive Disassembler Pro
|
||||
#
|
||||
# Copyright (c) 2004-2009 Gergely Erdelyi <dyce@d-dome.net>
|
||||
# Copyright (c) 2004-2009 Gergely Erdelyi <dyce@d-dome.net>
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
@ -40,9 +40,9 @@ def CodeRefsTo(ea, flow):
|
||||
print ref
|
||||
"""
|
||||
if flow == 1:
|
||||
return refs(ea, idaapi.get_first_cref_to, idaapi.get_next_cref_to)
|
||||
return refs(ea, idaapi.get_first_cref_to, idaapi.get_next_cref_to)
|
||||
else:
|
||||
return refs(ea, idaapi.get_first_fcref_to, idaapi.get_next_fcref_to)
|
||||
return refs(ea, idaapi.get_first_fcref_to, idaapi.get_next_fcref_to)
|
||||
|
||||
|
||||
def CodeRefsFrom(ea, flow):
|
||||
@ -61,9 +61,9 @@ def CodeRefsFrom(ea, flow):
|
||||
print ref
|
||||
"""
|
||||
if flow == 1:
|
||||
return refs(ea, idaapi.get_first_cref_from, idaapi.get_next_cref_from)
|
||||
return refs(ea, idaapi.get_first_cref_from, idaapi.get_next_cref_from)
|
||||
else:
|
||||
return refs(ea, idaapi.get_first_fcref_from, idaapi.get_next_fcref_from)
|
||||
return refs(ea, idaapi.get_first_fcref_from, idaapi.get_next_fcref_from)
|
||||
|
||||
|
||||
def DataRefsTo(ea):
|
||||
@ -79,7 +79,7 @@ def DataRefsTo(ea):
|
||||
for ref in DataRefsTo(ScreenEA(), 1):
|
||||
print ref
|
||||
"""
|
||||
return refs(ea, idaapi.get_first_dref_to, idaapi.get_next_dref_to)
|
||||
return refs(ea, idaapi.get_first_dref_to, idaapi.get_next_dref_to)
|
||||
|
||||
|
||||
def DataRefsFrom(ea):
|
||||
@ -95,7 +95,7 @@ def DataRefsFrom(ea):
|
||||
for ref in DataRefsFrom(ScreenEA(), 1):
|
||||
print ref
|
||||
"""
|
||||
return refs(ea, idaapi.get_first_dref_from, idaapi.get_next_dref_from)
|
||||
return refs(ea, idaapi.get_first_dref_from, idaapi.get_next_dref_from)
|
||||
|
||||
|
||||
def XrefTypeName(typecode):
|
||||
@ -104,9 +104,9 @@ def XrefTypeName(typecode):
|
||||
|
||||
@param typecode: cross-reference type code
|
||||
"""
|
||||
ref_types = {
|
||||
ref_types = {
|
||||
0 : 'Data_Unknown',
|
||||
1 : 'Data_Offset',
|
||||
1 : 'Data_Offset',
|
||||
2 : 'Data_Write',
|
||||
3 : 'Data_Read',
|
||||
4 : 'Data_Text',
|
||||
@ -233,7 +233,7 @@ def Segments():
|
||||
|
||||
@return: List of segment start addresses.
|
||||
"""
|
||||
for n in range(idaapi.get_segm_qty()):
|
||||
for n in xrange(idaapi.get_segm_qty()):
|
||||
seg = idaapi.getnseg(n)
|
||||
if seg:
|
||||
yield seg.startEA
|
||||
@ -298,7 +298,7 @@ def DecodeInstruction(ea):
|
||||
setattr(self, x, getattr(op, x))
|
||||
r = dup(insn)
|
||||
r.Operands = []
|
||||
for n in range(0, idaapi.UA_MAXOP):
|
||||
for n in xrange(0, idaapi.UA_MAXOP):
|
||||
t = idaapi.get_instruction_operand(insn, n)
|
||||
if t.type == idaapi.o_void:
|
||||
break
|
||||
@ -359,4 +359,72 @@ class _cpu:
|
||||
#print "cpu.set(%s)"%name
|
||||
return idc.SetRegValue(value, name)
|
||||
|
||||
class Strings:
|
||||
"""
|
||||
Returns the string list.
|
||||
|
||||
Example:
|
||||
s = Strings()
|
||||
|
||||
for i in s:
|
||||
print "%x: len=%d type=%d -> '%s'" % (i.ea, i.length, i.type, str(i))
|
||||
|
||||
"""
|
||||
class StringItem:
|
||||
"""
|
||||
Class representing each string item.
|
||||
The attributes are:
|
||||
ea - string ea
|
||||
type - string type (ASCSTR_xxxxx)
|
||||
str() - returns the actual string
|
||||
"""
|
||||
def __init__(self, si):
|
||||
self.ea = si.ea
|
||||
self.type = si.type
|
||||
self.length = si.length
|
||||
def __str__(self):
|
||||
return idc.GetString(self.ea, self.length, self.type)
|
||||
|
||||
STR_C = 0x0001 # C-style ASCII string
|
||||
STR_PASCAL = 0x0002 # Pascal-style ASCII string (length byte)
|
||||
STR_LEN2 = 0x0004 # Pascal-style, length is 2 bytes
|
||||
STR_UNICODE = 0x0008 # Unicode string
|
||||
STR_LEN4 = 0x0010 # Pascal-style, length is 4 bytes
|
||||
STR_ULEN2 = 0x0020 # Pascal-style Unicode, length is 2 bytes
|
||||
STR_ULEN4 = 0x0040 # Pascal-style Unicode, length is 4 bytes
|
||||
|
||||
def clear_cache():
|
||||
"""Clears the strings list cache"""
|
||||
self.refresh(0, 0) # when ea1=ea2 the kernel will clear the cache
|
||||
|
||||
def __init__(self, default_setup=True):
|
||||
if default_setup:
|
||||
self.setup()
|
||||
self._si = idaapi.string_info_t()
|
||||
|
||||
def refresh(self, ea1=idaapi.cvar.inf.minEA, ea2=idaapi.cvar.inf.maxEA):
|
||||
"""Refreshes the strings list"""
|
||||
idaapi.refresh_strlist(ea1, ea2)
|
||||
self.size = idaapi.get_strlist_qty()
|
||||
|
||||
def setup(self, strtypes=STR_C, minlen=5, only_7bit=True, ignore_instructions=False, ea1=idaapi.cvar.inf.minEA, ea2=idaapi.cvar.inf.maxEA, display_only_existing_strings=False):
|
||||
t = idaapi.strwinsetup_t()
|
||||
t.strtypes = strtypes
|
||||
t.minlen = minlen
|
||||
t.only_7bit = only_7bit
|
||||
t.ea1 = ea1
|
||||
t.ea2 = ea2
|
||||
t.display_only_existing_strings = display_only_existing_strings
|
||||
idaapi.set_strlist_options(t)
|
||||
# automatically refreshes
|
||||
self.refresh()
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Returns string items"""
|
||||
if index >= self.size:
|
||||
raise StopIteration
|
||||
if idaapi.get_strlist_item(index, self._si):
|
||||
return Strings.StringItem(self._si)
|
||||
return None
|
||||
|
||||
cpu = _cpu()
|
||||
|
@ -3741,7 +3741,7 @@ def LoadFile(filepath, pos, ea, size):
|
||||
else:
|
||||
return 0
|
||||
|
||||
def loadfile(filepath, pos, ea, size): LoadFile(filepath, pos, ea, size)
|
||||
def loadfile(filepath, pos, ea, size): return LoadFile(filepath, pos, ea, size)
|
||||
|
||||
|
||||
def SaveFile(filepath, pos, ea, size):
|
||||
@ -3764,7 +3764,7 @@ def SaveFile(filepath, pos, ea, size):
|
||||
else:
|
||||
return 0
|
||||
|
||||
def savefile(filepath, pos, ea, size): SaveFile(filepath, pos, ea, size)
|
||||
def savefile(filepath, pos, ea, size): return SaveFile(filepath, pos, ea, size)
|
||||
|
||||
|
||||
def fgetc(handle):
|
||||
@ -7460,12 +7460,12 @@ 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): AnalyzeArea(sEA,eEA)
|
||||
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 MakeName(ea, name): MakeNameEx(ea,name,SN_CHECK)
|
||||
def MakeName(ea, name): return MakeNameEx(ea,name,SN_CHECK)
|
||||
|
||||
#def GetFrame(ea): return GetFunctionAttr(ea, FUNCATTR_FRAME)
|
||||
#def GetFrameLvarSize(ea): return GetFunctionAttr(ea, FUNCATTR_FRSIZE)
|
||||
|
76
swig/gdl.i
76
swig/gdl.i
@ -18,8 +18,82 @@
|
||||
%ignore node_set_t::intersect;
|
||||
%ignore node_set_t::node_set_t;
|
||||
%ignore node_set_t::sub;
|
||||
|
||||
%ignore qflow_chart_t::blocks;
|
||||
%ignore flow_chart_t;
|
||||
%ignore setup_graph_subsystem;
|
||||
%ignore qbasic_block_t::succ;
|
||||
%ignore qbasic_block_t::pred;
|
||||
|
||||
%include "gdl.hpp"
|
||||
|
||||
%extend qflow_chart_t
|
||||
{
|
||||
qbasic_block_t *__getitem__(int n)
|
||||
{
|
||||
return &(self->blocks[n]);
|
||||
}
|
||||
}
|
||||
|
||||
%pythoncode %{
|
||||
# -----------------------------------------------------------------------
|
||||
class BasicBlock:
|
||||
def __init__(self, id, bb, f):
|
||||
self._f = f
|
||||
self.id = id
|
||||
"""Basic block ID"""
|
||||
self.startEA = bb.startEA
|
||||
"""startEA of basic block"""
|
||||
self.endEA = bb.endEA
|
||||
"""endEA of basic block"""
|
||||
self.type = self._f._q.calc_block_type(self.id)
|
||||
"""Block type (check fc_block_type_t enum)"""
|
||||
|
||||
def preds(self):
|
||||
"""
|
||||
Iteratres the predecessors list
|
||||
"""
|
||||
q = self._f._q
|
||||
for i in xrange(0, self._f._q.npred(self.id)):
|
||||
yield self._f[q.pred(self.id, i)]
|
||||
|
||||
def succs(self):
|
||||
"""
|
||||
Iteratres the successors list
|
||||
"""
|
||||
q = self._f._q
|
||||
for i in xrange(0, q.nsucc(self.id)):
|
||||
yield self._f[q.succ(self.id, i)]
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class FlowChart:
|
||||
"""
|
||||
Flowchart class used to determine basic blocks
|
||||
"""
|
||||
def __init__(self, f=None, bounds=None, flags=0):
|
||||
"""
|
||||
Constructor
|
||||
@param f: A func_t type, use get_func(ea) to get a reference
|
||||
@param bounds: A tuple of the form (start, end). Used if "f" is None
|
||||
@param flags: one of the FC_xxxx flags. One interesting flag is FC_PREDS
|
||||
"""
|
||||
if (not f) and (not bounds or type(bounds) != types.TupleType):
|
||||
raise Exception("Please specifiy either a function or start/end pair")
|
||||
if not bounds:
|
||||
bounds = (BADADDR, BADADDR)
|
||||
# create the flowchart
|
||||
self._q = qflow_chart_t("", f, bounds[0], bounds[1], flags)
|
||||
self.size = self._q.size()
|
||||
def refresh():
|
||||
self._q.refresh()
|
||||
self.size = self._q.size()
|
||||
def __getitem__(self, index):
|
||||
"""
|
||||
Returns a basic block
|
||||
@return: BasicBlock
|
||||
"""
|
||||
if index >= self.size:
|
||||
raise StopIteration
|
||||
return BasicBlock(index, self._q[index], self)
|
||||
|
||||
|
||||
%}
|
||||
|
Loading…
Reference in New Issue
Block a user