mirror of
https://github.com/cemu-project/idapython.git
synced 2024-12-29 11:11:51 +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
2
build.py
2
build.py
@ -70,6 +70,8 @@ BINDIST_MANIFEST = [
|
|||||||
"examples/ex1_idautils.py",
|
"examples/ex1_idautils.py",
|
||||||
"examples/hotkey.py",
|
"examples/hotkey.py",
|
||||||
"examples/structure.py",
|
"examples/structure.py",
|
||||||
|
"examples/ex_gdl_qflow_chart.py",
|
||||||
|
"examples/ex_strings.py",
|
||||||
]
|
]
|
||||||
|
|
||||||
# List files for the source distribution (appended to binary list)
|
# List files for the source distribution (appended to binary list)
|
||||||
|
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))
|
@ -233,7 +233,7 @@ def Segments():
|
|||||||
|
|
||||||
@return: List of segment start addresses.
|
@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)
|
seg = idaapi.getnseg(n)
|
||||||
if seg:
|
if seg:
|
||||||
yield seg.startEA
|
yield seg.startEA
|
||||||
@ -298,7 +298,7 @@ def DecodeInstruction(ea):
|
|||||||
setattr(self, x, getattr(op, x))
|
setattr(self, x, getattr(op, x))
|
||||||
r = dup(insn)
|
r = dup(insn)
|
||||||
r.Operands = []
|
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)
|
t = idaapi.get_instruction_operand(insn, n)
|
||||||
if t.type == idaapi.o_void:
|
if t.type == idaapi.o_void:
|
||||||
break
|
break
|
||||||
@ -359,4 +359,72 @@ class _cpu:
|
|||||||
#print "cpu.set(%s)"%name
|
#print "cpu.set(%s)"%name
|
||||||
return idc.SetRegValue(value, 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()
|
cpu = _cpu()
|
||||||
|
@ -3741,7 +3741,7 @@ def LoadFile(filepath, pos, ea, size):
|
|||||||
else:
|
else:
|
||||||
return 0
|
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):
|
def SaveFile(filepath, pos, ea, size):
|
||||||
@ -3764,7 +3764,7 @@ def SaveFile(filepath, pos, ea, size):
|
|||||||
else:
|
else:
|
||||||
return 0
|
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):
|
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 OpEnum(ea,n,enumid): return OpEnumEx(ea,n,enumid,0)
|
||||||
def DelConst(constid, v, mask): return DelConstEx(constid, v, 0, mask)
|
def DelConst(constid, v, mask): return DelConstEx(constid, v, 0, mask)
|
||||||
def GetConst(constid, v, mask): return GetConstEx(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 MakeStruct(ea,name): return MakeStructEx(ea, -1, name)
|
||||||
def Name(ea): return NameEx(BADADDR, ea)
|
def Name(ea): return NameEx(BADADDR, ea)
|
||||||
def GetTrueName(ea): return GetTrueNameEx(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 GetFrame(ea): return GetFunctionAttr(ea, FUNCATTR_FRAME)
|
||||||
#def GetFrameLvarSize(ea): return GetFunctionAttr(ea, FUNCATTR_FRSIZE)
|
#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::intersect;
|
||||||
%ignore node_set_t::node_set_t;
|
%ignore node_set_t::node_set_t;
|
||||||
%ignore node_set_t::sub;
|
%ignore node_set_t::sub;
|
||||||
|
%ignore qflow_chart_t::blocks;
|
||||||
%ignore flow_chart_t;
|
%ignore flow_chart_t;
|
||||||
%ignore setup_graph_subsystem;
|
%ignore setup_graph_subsystem;
|
||||||
|
%ignore qbasic_block_t::succ;
|
||||||
|
%ignore qbasic_block_t::pred;
|
||||||
|
|
||||||
%include "gdl.hpp"
|
%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