Skip to content

Commit 686e018

Browse files
author
elias.bachaalany
committed
- 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
1 parent 97a9805 commit 686e018

7 files changed

Lines changed: 143 additions & 22 deletions

File tree

examples/debughook.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
# This script start the executable and steps through the first five
55
# instructions. Each instruction is disassembled after execution.
66
#
7-
# Author: Gergely Erdelyi <[email protected]>
7+
# Original Author: Gergely Erdelyi <[email protected]>
8+
#
9+
# Maintained By: IDAPython Team
10+
#
811
#---------------------------------------------------------------------
912
from idaapi import *
1013

@@ -19,6 +22,10 @@ def dbg_process_exit(self, pid, tid, ea, code):
1922
print "Process exited pid=%d tid=%d ea=0x%x code=%d" % (pid, tid, ea, code)
2023
return 0
2124

25+
def dbg_library_unload(self, pid, tid, ea, info):
26+
print "Library unloaded: pid=%d tid=%d ea=0x%x info=%s" % (pid, tid, ea, info)
27+
return 0
28+
2229
def dbg_library_load(self, pid, tid, ea, name, base, size):
2330
print "Library loaded: pid=%d tid=%d name=%s base=%x" % (pid, tid, name, base)
2431

@@ -31,6 +38,19 @@ def dbg_bpt(self, tid, ea):
3138
# 1 - to always display a breakpoint warning dialog.
3239
return 0
3340

41+
def dbg_suspend_process(self):
42+
print "Process suspended"
43+
44+
def dbg_exception(self, pid, tid, ea, exc_code, exc_can_cont, exc_ea, exc_info):
45+
print "Exception: pid=%d tid=%d ea=0x%x exc_code=0x%x can_continue=%d exc_ea=0x%x exc_info=%s" % (
46+
pid, tid, ea, exc_code & idaapi.BADADDR, exc_can_cont, exc_ea, exc_info)
47+
# return values:
48+
# -1 - to display an exception warning dialog
49+
# if the process is suspended.
50+
# 0 - to never display an exception warning dialog.
51+
# 1 - to always display an exception warning dialog.
52+
return 0
53+
3454
def dbg_trace(self, tid, ea):
3555
print tid, ea
3656
return 0
@@ -39,6 +59,10 @@ def dbg_step_into(self):
3959
print "Step into"
4060
return self.dbg_step_over()
4161

62+
# def dbg_run_to(self, tid):
63+
# print "Runto: tid=%d" % tid
64+
# idaapi.continue_process()
65+
4266
def dbg_step_over(self):
4367
eip = GetRegValue("EIP")
4468
print "0x%x %s" % (eip, GetDisasm(eip))

python/idautils.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import idaapi
1515
import idc
1616
import types
17+
import os
1718

1819
def refs(ea, funcfirst, funcnext):
1920
"""
@@ -240,6 +241,26 @@ def Chunks(start):
240241
yield (chunk.startEA, chunk.endEA)
241242
status = func_iter.next()
242243

244+
def Modules():
245+
"""
246+
Returns a list of module objects with name,size,base and the rebase_to attributes
247+
"""
248+
mod = idaapi.module_info_t()
249+
result = idaapi.get_first_module(mod)
250+
while result:
251+
yield idaapi.object_t(name=mod.name, size=mod.size, base=mod.base, rebase_to=mod.rebase_to)
252+
result = idaapi.get_next_module(mod)
253+
254+
def Names():
255+
"""
256+
Returns a list of names
257+
258+
@return: tuple(ea, name)
259+
"""
260+
for i in xrange(idaapi.get_nlist_size()):
261+
ea = idaapi.get_nlist_ea(i)
262+
name = idaapi.get_nlist_name(i)
263+
yield (ea, name)
243264

244265
def Segments():
245266
"""
@@ -424,14 +445,26 @@ def __getitem__(self, index):
424445
return Strings.StringItem(self._si)
425446
return None
426447

448+
# -----------------------------------------------------------------------
427449
def GetRegisterList():
428450
"""Returns the register list"""
429451
return idaapi.ph_get_regnames()
430452

453+
# -----------------------------------------------------------------------
454+
def GetIdbDir():
455+
"""
456+
Get IDB directory
457+
458+
This function returns directory path of the current IDB database
459+
"""
460+
return os.path.dirname(idaapi.cvar.database_idb) + os.sep
461+
462+
# -----------------------------------------------------------------------
431463
def GetInstructionList():
432464
"""Returns the instruction list of the current processor module"""
433465
return [i[0] for i in idaapi.ph_get_instruc() if i[0]]
434466

467+
# -----------------------------------------------------------------------
435468
def _Assemble(ea, line):
436469
"""
437470
Please refer to Assemble() - INTERNAL USE ONLY
@@ -496,6 +529,7 @@ def _copy_obj(src, dest, skip_list = None):
496529
setattr(dest, x, t)
497530
return dest
498531

532+
# -----------------------------------------------------------------------
499533
class _reg_dtyp_t(object):
500534
"""
501535
INTERNAL
@@ -509,6 +543,7 @@ def __init__(self, reg, dtyp):
509543
def __eq__(self, other):
510544
return (self.reg == other.reg) and (self.dtyp == other.dtyp)
511545

546+
# -----------------------------------------------------------------------
512547
class _procregs(object):
513548
"""Utility class allowing the users to identify registers in a decoded instruction"""
514549
def __getattr__(self, attr):
@@ -522,6 +557,7 @@ def __getattr__(self, attr):
522557
def __setattr__(self, attr, value):
523558
raise AttributeError(attr)
524559

560+
# -----------------------------------------------------------------------
525561
class _cpu(object):
526562
"Simple wrapper around GetRegValue/SetRegValue"
527563
def __getattr__(self, name):
@@ -532,6 +568,37 @@ def __setattr__(self, name, value):
532568
#print "cpu.set(%s)"%name
533569
return idc.SetRegValue(value, name)
534570

571+
# -----------------------------------------------------------------------
572+
class peutils_t(object):
573+
"""
574+
PE utility class. Retrieves PE information from the database.
575+
576+
Constants from pe.h
577+
"""
578+
PE_NODE = "$ PE header" # netnode name for PE header
579+
PE_ALT_DBG_FPOS = idaapi.BADADDR & -1 # altval() -> translated fpos of debuginfo
580+
PE_ALT_IMAGEBASE = idaapi.BADADDR & -2 # altval() -> loading address (usually pe.imagebase)
581+
PE_ALT_PEHDR_OFF = idaapi.BADADDR & -3 # altval() -> offset of PE header
582+
PE_ALT_NEFLAGS = idaapi.BADADDR & -4 # altval() -> neflags
583+
PE_ALT_TDS_LOADED = idaapi.BADADDR & -5 # altval() -> tds already loaded(1) or invalid(-1)
584+
PE_ALT_PSXDLL = idaapi.BADADDR & -6 # altval() -> if POSIX(x86) imports from PSXDLL netnode
585+
586+
def __init__(self):
587+
self.__penode = idaapi.netnode()
588+
self.__penode.create(peutils_t.PE_NODE)
589+
590+
imagebase = property(
591+
lambda self: self.__penode.altval(peutils_t.PE_ALT_IMAGEBASE)
592+
)
593+
594+
header = property(
595+
lambda self: self.__penode.altval(peutils_t.PE_ALT_PEHDR_OFF)
596+
)
597+
598+
def __str__(self):
599+
return "peutils_t(imagebase=%s, header=%s)" % (hex(self.imagebase), hex(self.header))
600+
601+
# -----------------------------------------------------------------------
535602
cpu = _cpu()
536603
"""This is a special class instance used to access the registers as if they were attributes of this object.
537604
For example to access the EAX register:

python/idc.py

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3817,7 +3817,7 @@ def writestr(handle, s):
38173817
# F U N C T I O N S
38183818
# ----------------------------------------------------------------------------
38193819

3820-
def MakeFunction(start, end):
3820+
def MakeFunction(start, end = idaapi.BADADDR):
38213821
"""
38223822
Create a function
38233823
@@ -7094,13 +7094,13 @@ def SetRegValue(value, name):
70947094
A register name in the left side of an assignment will do too.
70957095
"""
70967096
rv = idaapi.regval_t()
7097-
if type(value)==types.StringType:
7098-
value = int(value)
7099-
elif type(value)!=types.IntType:
7097+
if type(value) == types.StringType:
7098+
value = int(value, 16)
7099+
elif type(value) != types.IntType and type(value) != types.LongType:
71007100
print "SetRegValue: value must be integer!"
71017101
return BADADDR
71027102

7103-
if value<0:
7103+
if value < 0:
71047104
#ival_set cannot handle negative numbers
71057105
value &= 0xFFFFFFFF
71067106

@@ -7249,7 +7249,8 @@ def AddBptEx(ea, size, bpttype):
72497249
return idaapi.add_bpt(ea, size, bpttype)
72507250

72517251

7252-
def AddBpt(ea): return AddBptEx(ea, 0, BPT_SOFT)
7252+
def AddBpt(ea):
7253+
return AddBptEx(ea, 0, BPT_SOFT)
72537254

72547255

72557256
def DelBpt(ea):
@@ -7499,17 +7500,17 @@ def WriteExe(filepath):
74997500
return GenerateFile(OFILE_EXE, filepath, 0, BADADDR, 0)
75007501

75017502
def AddConst(enum_id,name,value): return AddConstEx(enum_id,name,value,-1)
7502-
def AddStruc(index,name): return AddStrucEx(index,name,0)
7503-
def AddUnion(index,name): return AddStrucEx(index,name,1)
7504-
def OpStroff(ea,n,strid): return OpStroffEx(ea,n,strid,0)
7505-
def OpEnum(ea,n,enumid): return OpEnumEx(ea,n,enumid,0)
7506-
def DelConst(constid, v, mask): return DelConstEx(constid, v, 0, mask)
7507-
def GetConst(constid, v, mask): return GetConstEx(constid, v, 0, mask)
7508-
def AnalyseArea(sEA, eEA): return AnalyzeArea(sEA,eEA)
7509-
7510-
def MakeStruct(ea,name): return MakeStructEx(ea, -1, name)
7511-
def Name(ea): return NameEx(BADADDR, ea)
7512-
def GetTrueName(ea): return GetTrueNameEx(BADADDR, ea)
7503+
def AddStruc(index,name): return AddStrucEx(index,name,0)
7504+
def AddUnion(index,name): return AddStrucEx(index,name,1)
7505+
def OpStroff(ea,n,strid): return OpStroffEx(ea,n,strid,0)
7506+
def OpEnum(ea,n,enumid): return OpEnumEx(ea,n,enumid,0)
7507+
def DelConst(constid, v, mask): return DelConstEx(constid, v, 0, mask)
7508+
def GetConst(constid, v, mask): return GetConstEx(constid, v, 0, mask)
7509+
def AnalyseArea(sEA, eEA): return AnalyzeArea(sEA,eEA)
7510+
7511+
def MakeStruct(ea,name): return MakeStructEx(ea, -1, name)
7512+
def Name(ea): return NameEx(BADADDR, ea)
7513+
def GetTrueName(ea): return GetTrueNameEx(BADADDR, ea)
75137514
def MakeName(ea, name): return MakeNameEx(ea,name,SN_CHECK)
75147515

75157516
#def GetFrame(ea): return GetFunctionAttr(ea, FUNCATTR_FRAME)
@@ -7533,6 +7534,8 @@ def SegDefReg(ea, reg, value): return SetSegDefReg(ea, reg, va
75337534

75347535

75357536
def Comment(ea): return GetCommentEx(ea, 0)
7537+
"""Returns the non-repeatable comment or None"""
7538+
75367539
def RptCmt(ea): return GetCommentEx(ea, 1)
75377540

75387541
def SetReg(ea, reg, value): return SetRegEx(ea, reg, value, SR_user)

swig/dbg.i

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ int idaapi DBG_Callback(void *ud, int notification_code, va_list va)
293293
}
294294
catch (Swig::DirectorException &)
295295
{
296-
msg("Exception in IDP Hook function:\n");
296+
msg("Exception in DBG Hook function:\n");
297297
if (PyErr_Occurred())
298298
{
299299
PyErr_Print();

swig/idp.i

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
713713
}
714714
catch (Swig::DirectorException &)
715715
{
716-
msg("Exception in IDP Hook function:\n");
716+
msg("Exception in IDB Hook function:\n");
717717
if (PyErr_Occurred())
718718
{
719719
PyErr_Print();

swig/kernwin.i

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2862,9 +2862,9 @@ class simplecustviewer_t(object):
28622862
return _idaapi.pyscv_get_pos(self.__this, mouse)
28632863

28642864
def GetLineNo(self, mouse = 0):
2865-
"""Calls GetPos() and returns the current line number only or None on failure"""
2865+
"""Calls GetPos() and returns the current line number or -1 on failure"""
28662866
r = self.GetPos(mouse)
2867-
return None if not r else r[0]
2867+
return -1 if not r else r[0]
28682868

28692869
def Jump(self, lineno, x=0, y=0):
28702870
return _idaapi.pyscv_jumpto(self.__this, lineno, x, y)

swig/typeinf.i

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@
116116

117117
%ignore apply_type_to_stkarg;
118118
%rename (apply_type_to_stkarg) py_apply_type_to_stkarg;
119+
%ignore print_type;
120+
%rename (print_type) py_print_type;
119121

120122
%ignore use_regarg_type_cb;
121123
%ignore set_op_type_t;
@@ -201,6 +203,31 @@ PyObject *py_get_type_size0(const til_t *ti, PyObject *tp)
201203
return PyInt_FromLong(sz);
202204
}
203205

206+
//-------------------------------------------------------------------------
207+
/*
208+
#<pydoc>
209+
def print_type(ea, on_line):
210+
"""
211+
Returns the type of an item
212+
@return:
213+
- None on failure
214+
- The type string with a semicolon. Can be used directly with idc.SetType()
215+
"""
216+
pass
217+
#</pydoc>
218+
*/
219+
static PyObject *py_print_type(ea_t ea, bool one_line)
220+
{
221+
char buf[MAXSTR];
222+
if ( print_type(ea, buf, sizeof(buf), one_line) )
223+
{
224+
qstrncat(buf, ";", sizeof(buf));
225+
return PyString_FromString(buf);
226+
}
227+
else
228+
Py_RETURN_NONE;
229+
}
230+
204231
//-------------------------------------------------------------------------
205232
/*
206233
#<pydoc>

0 commit comments

Comments
 (0)