mirror of
https://github.com/cemu-project/idapython.git
synced 2024-11-27 19:44:18 +01:00
- IDA Pro 6.1 support
- Added AskUsingForm() with embedded forms support (check ex_askusingform.py example and formchooser.py in the SDK) - Added idautils.DecodePreviousInstruction() / DecodePrecedingInstruction() - Added idc.BeginTypeUpdating() / EndTypeUpdating() for fast batch type update operations - Added more IDP callbacks - Added UI_Hooks with a few notification events - Added idaapi.process_ui_action() / idc.ProcessUiAction() - Added netnode.index() to get netnode number - Better handling of ea_t values with bitwise negation - Execute statement hotkey (Ctrl-F3), script timeout, and other options are now configurable with Python.cfg - bugfix: idaapi.msg() / error() and warning() so they don't accept vararg - bugfix: processor_t.id constants were incorrect - bugfix: get_debug_names() was broken with IDA64 - Various bugfixes
This commit is contained in:
parent
63b22d00d5
commit
109158fabb
29
CHANGES.txt
29
CHANGES.txt
@ -1,20 +1,40 @@
|
||||
Please see http://code.google.com/p/idapython/source/list for a detailed list of changes.
|
||||
|
||||
|
||||
Changes from version 1.4.3 to 1.5.0
|
||||
------------------------------------
|
||||
- IDA Pro 6.1 support
|
||||
- Added AskUsingForm() with embedded forms support (check ex_askusingform.py example and formchooser.py in the SDK)
|
||||
- Added idautils.DecodePreviousInstruction() / DecodePrecedingInstruction()
|
||||
- Added idc.BeginTypeUpdating() / EndTypeUpdating() for fast batch type update operations
|
||||
- Added more IDP callbacks
|
||||
- Added UI_Hooks with a few notification events
|
||||
- Added idaapi.process_ui_action() / idc.ProcessUiAction()
|
||||
- Added netnode.index() to get netnode number
|
||||
- Better handling of ea_t values with bitwise negation
|
||||
- Execute statement hotkey (Ctrl-F3), script timeout, and other options are now configurable with Python.cfg
|
||||
- bugfix: idaapi.msg() / error() and warning() so they don't accept vararg
|
||||
- bugfix: processor_t.id constants were incorrect
|
||||
- bugfix: get_debug_names() was broken with IDA64
|
||||
- Various bugfixes
|
||||
|
||||
Changes from version 1.4.2 to 1.4.3
|
||||
------------------------------------
|
||||
- IDA 6.0 support
|
||||
- IDA Pro 6.0 support
|
||||
- Python CLI now prints expression evaluation result (no need to use print())
|
||||
- Changed Alt-8 to Ctrl-F3 (because it conflicts with window switching key Alt+n)
|
||||
- Added get_highlighted_identifier()
|
||||
- Added PluginForm class to allow UI development with either PyQt4 or PySide
|
||||
- Added idautils.Entries() to enum entrypoints
|
||||
|
||||
|
||||
Changes from version 1.4.1 to 1.4.2
|
||||
------------------------------------
|
||||
- Added command completion
|
||||
- Added necessary changes so it compiles with Python 2.7
|
||||
- Wrapped set_user_defined_prefix()
|
||||
|
||||
|
||||
Changes from version 1.4.0 to 1.4.1
|
||||
------------------------------------
|
||||
- Added cli_t
|
||||
@ -22,6 +42,7 @@ Changes from version 1.4.0 to 1.4.1
|
||||
- Changed the copyright string to IDAPython Team
|
||||
- Some platform dependant classes are present but useable only where applicable
|
||||
|
||||
|
||||
Changes from version 1.3.0 to 1.4.0
|
||||
------------------------------------
|
||||
- IDA Pro 5.7 support
|
||||
@ -35,9 +56,9 @@ Changes from version 1.3.0 to 1.4.0
|
||||
- Documented all manually wrapped functions (check 'pywraps' module in the docs)
|
||||
- Lots of cleanups and fixes
|
||||
|
||||
|
||||
Changes from version 1.2.0 to 1.3.0
|
||||
------------------------------------
|
||||
|
||||
- IDA Pro 5.6 support
|
||||
- Added Appcall mechanism
|
||||
- Added procregs to idautils.py (r254)
|
||||
@ -45,7 +66,6 @@ Changes from version 1.2.0 to 1.3.0
|
||||
|
||||
Changes from version 1.1.0 to 1.2.0
|
||||
------------------------------------
|
||||
|
||||
- 64-bit support (largely untested)
|
||||
- IDA Pro 5.5 support
|
||||
- Long running (or inifinitely looping) scripts can now be stopped
|
||||
@ -58,7 +78,6 @@ Changes from version 1.1.0 to 1.2.0
|
||||
|
||||
Changes from version 0.9.0 to 1.0.0
|
||||
-----------------------------------
|
||||
|
||||
- Upgraded IDA Pro base version to 5.1
|
||||
- Dropped Python 2.4 support
|
||||
- Mac OS X support
|
||||
@ -76,7 +95,6 @@ Changes from version 0.9.0 to 1.0.0
|
||||
|
||||
Changes from version 0.8.0 to 0.9.0
|
||||
-----------------------------------
|
||||
|
||||
- Upgraded base version to IDA Pro 5.0
|
||||
- Works with IDA Pro 5.1
|
||||
- Python 2.4 and 2.5 supported
|
||||
@ -92,7 +110,6 @@ Changes from version 0.8.0 to 0.9.0
|
||||
|
||||
Changes from version 0.7.0 to 0.8.0
|
||||
-----------------------------------
|
||||
|
||||
- Added support for IDA Pro 4.9
|
||||
- Dropped support for IDA Pro 4.7
|
||||
- NOTE: Windows version is linked against Python 2.4.
|
||||
|
@ -38,10 +38,10 @@ Mailing list for the project is hosted by Google Groups at
|
||||
INSTALLATION FROM BINARIES
|
||||
--------------------------
|
||||
|
||||
1. Install Python 2.5 or 2.6 from http://www.python.org/
|
||||
2. Copy the python and python64 directories to the IDA install directory
|
||||
3. Copy the plugins to the %IDADIR%\plugins\
|
||||
|
||||
1. Install 2.6 or 2.7 from http://www.python.org/
|
||||
2. Copy "python" directory to %IDADIR%
|
||||
3. Copy "plugins" directory to the %IDADIR%\plugins\
|
||||
4. Copy "python.cfg" to %IDADIR%\cfg
|
||||
|
||||
USAGE
|
||||
-----
|
||||
@ -88,3 +88,4 @@ or
|
||||
|
||||
The user init file is read and executed at the end of the init process.
|
||||
|
||||
Please note that IDAPython can be configured with "python.cfg" file.
|
||||
|
216
Scripts/AsmViewer.py
Normal file
216
Scripts/AsmViewer.py
Normal file
@ -0,0 +1,216 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# This is an example illustrating how to use customview in Python
|
||||
# The sample will allow you to open an assembly file and display it in color
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
import idaapi
|
||||
import idautils
|
||||
import idc
|
||||
import os
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
class asm_colorizer_t(object):
|
||||
def is_id(self, ch):
|
||||
return ch == '_' or ch.isalpha() or '0' <= ch <= '9'
|
||||
|
||||
def get_identifier(self, line, x, e):
|
||||
i = x
|
||||
is_digit = line[i].isdigit()
|
||||
while i < e:
|
||||
ch = line[i]
|
||||
if not self.is_id(ch):
|
||||
if ch != '.' or not is_digit:
|
||||
break
|
||||
i += 1
|
||||
return (i, line[x:i])
|
||||
|
||||
def get_quoted_string(self, line, x, e):
|
||||
quote = line[x]
|
||||
i = x + 1
|
||||
while i < e:
|
||||
ch = line[i]
|
||||
if ch == '\\' and line[i+1] == quote:
|
||||
i += 1
|
||||
elif ch == quote:
|
||||
i += 1 # also take the quote
|
||||
break
|
||||
i += 1
|
||||
return (i, line[x:i])
|
||||
|
||||
def colorize(self, lines):
|
||||
for line in lines:
|
||||
line = line.rstrip()
|
||||
if not line:
|
||||
self.add_line()
|
||||
continue
|
||||
x = 0
|
||||
e = len(line)
|
||||
s = ""
|
||||
while x < e:
|
||||
ch = line[x]
|
||||
# String?
|
||||
if ch == '"' or ch == "'":
|
||||
x, w = self.get_quoted_string(line, x, e)
|
||||
s += self.as_string(w)
|
||||
# Tab?
|
||||
elif ch == '\t':
|
||||
s += ' ' * 4
|
||||
x += 1
|
||||
# Comment?
|
||||
elif ch == ';':
|
||||
s += self.as_comment(line[x:])
|
||||
# Done with this line
|
||||
break
|
||||
elif ch == '.' and x + 1 < e:
|
||||
x, w = self.get_identifier(line, x + 1, e)
|
||||
s += self.as_directive(ch + w)
|
||||
# Identifiers?
|
||||
elif self.is_id(ch):
|
||||
x, w = self.get_identifier(line, x, e)
|
||||
# Number?
|
||||
if ch.isdigit():
|
||||
s += self.as_num(w)
|
||||
# Other identifier
|
||||
else:
|
||||
s += self.as_id(w)
|
||||
# Output as is
|
||||
else:
|
||||
s += ch
|
||||
x += 1
|
||||
self.add_line(s)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class asmview_t(idaapi.simplecustviewer_t, asm_colorizer_t):
|
||||
def Create(self, fn):
|
||||
# Create the customview
|
||||
if not idaapi.simplecustviewer_t.Create(self, "Viewing file - %s" % os.path.basename(fn)):
|
||||
return False
|
||||
|
||||
self.instruction_list = idautils.GetInstructionList()
|
||||
self.instruction_list.extend(["ret"])
|
||||
self.register_list = idautils.GetRegisterList()
|
||||
self.register_list.extend(["eax", "ebx", "ecx", "edx", "edi", "esi", "ebp", "esp"])
|
||||
|
||||
self.fn = fn
|
||||
if not self.reload_file():
|
||||
return False
|
||||
|
||||
self.id_refresh = self.AddPopupMenu("Refresh")
|
||||
self.id_close = self.AddPopupMenu("Close")
|
||||
|
||||
return True
|
||||
|
||||
def reload_file(self):
|
||||
if not self.colorize_file(self.fn):
|
||||
self.Close()
|
||||
return False
|
||||
return True
|
||||
|
||||
def colorize_file(self, fn):
|
||||
try:
|
||||
f = open(fn, "r")
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
self.ClearLines()
|
||||
self.colorize(lines)
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
def add_line(self, s=None):
|
||||
if not s:
|
||||
s = ""
|
||||
self.AddLine(s)
|
||||
|
||||
def as_comment(self, s):
|
||||
return idaapi.COLSTR(s, idaapi.SCOLOR_RPTCMT)
|
||||
|
||||
def as_id(self, s):
|
||||
t = s.lower()
|
||||
if t in self.register_list:
|
||||
return idaapi.COLSTR(s, idaapi.SCOLOR_REG)
|
||||
elif t in self.instruction_list:
|
||||
return idaapi.COLSTR(s, idaapi.SCOLOR_INSN)
|
||||
else:
|
||||
return s
|
||||
|
||||
def as_string(self, s):
|
||||
return idaapi.COLSTR(s, idaapi.SCOLOR_STRING)
|
||||
|
||||
def as_num(self, s):
|
||||
return idaapi.COLSTR(s, idaapi.SCOLOR_NUMBER)
|
||||
|
||||
def as_directive(self, s):
|
||||
return idaapi.COLSTR(s, idaapi.SCOLOR_KEYWORD)
|
||||
|
||||
def OnPopupMenu(self, menu_id):
|
||||
"""
|
||||
A context (or popup) menu item was executed.
|
||||
@param menu_id: ID previously registered with AddPopupMenu()
|
||||
@return: Boolean
|
||||
"""
|
||||
if self.id_refresh == menu_id:
|
||||
return self.reload_file()
|
||||
elif self.id_close == menu_id:
|
||||
self.Close()
|
||||
return True
|
||||
return False
|
||||
|
||||
def OnKeydown(self, vkey, shift):
|
||||
"""
|
||||
User pressed a key
|
||||
@param vkey: Virtual key code
|
||||
@param shift: Shift flag
|
||||
@return Boolean. True if you handled the event
|
||||
"""
|
||||
# ESCAPE
|
||||
if vkey == 27:
|
||||
self.Close()
|
||||
elif vkey == ord('H'):
|
||||
lineno = self.GetLineNo()
|
||||
if lineno is not None:
|
||||
line, fg, bg = self.GetLine(lineno)
|
||||
if line and line[0] != idaapi.SCOLOR_INV:
|
||||
s = idaapi.SCOLOR_INV + line + idaapi.SCOLOR_INV
|
||||
self.EditLine(lineno, s, fg, bg)
|
||||
self.Refresh()
|
||||
elif vkey == ord('C'):
|
||||
self.ClearLines()
|
||||
self.Refresh()
|
||||
elif vkey == ord('S'):
|
||||
print "Selection (x1, y1, x2, y2) = ", self.GetSelection()
|
||||
elif vkey == ord('I'):
|
||||
print "Position (line, x, y) = ", self.GetPos(mouse = 0)
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class asmviewplg(idaapi.plugin_t):
|
||||
flags = idaapi.PLUGIN_KEEP
|
||||
comment = "ASM viewer"
|
||||
help = "This is help"
|
||||
wanted_name = "ASM file viewer"
|
||||
wanted_hotkey = "Alt-F8"
|
||||
def __init__(self):
|
||||
self.view = None
|
||||
|
||||
def init(self):
|
||||
return idaapi.PLUGIN_KEEP
|
||||
def run(self, arg):
|
||||
if self.view:
|
||||
self.Close()
|
||||
fn = idc.AskFile(0, "*.asm", "Select ASM file to view")
|
||||
if not fn:
|
||||
return
|
||||
self.view = asmview_t()
|
||||
if not self.view.Create(fn):
|
||||
return
|
||||
self.view.Show()
|
||||
|
||||
def term(self):
|
||||
if self.view:
|
||||
self.view.Close()
|
||||
|
||||
def PLUGIN_ENTRY():
|
||||
return asmviewplg()
|
175
Scripts/CallStackWalk.py
Normal file
175
Scripts/CallStackWalk.py
Normal file
@ -0,0 +1,175 @@
|
||||
"""
|
||||
|
||||
A script that tries to determine the call stack
|
||||
|
||||
Run the application with the debugger, suspend the debugger, select a thread and finally run the script.
|
||||
|
||||
Copyright (c) 1990-2009 Hex-Rays
|
||||
ALL RIGHTS RESERVED.
|
||||
|
||||
|
||||
v1.0 - initial version
|
||||
v1.0.1 - added stack segment bitness detection, thus works with 64bit processes too
|
||||
"""
|
||||
import idaapi
|
||||
import idc
|
||||
import idautils
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# class to take a copy of a segment_t
|
||||
class Seg():
|
||||
def __init__(self, s):
|
||||
self.startEA = s.startEA
|
||||
self.endEA = s.endEA
|
||||
self.perm = s.perm
|
||||
self.bitness = s.bitness
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.startEA, other.startEA)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# each item described as:
|
||||
# [ delta, [ opcode(s) ] ]
|
||||
#FF10 call d,[eax]
|
||||
#FF5000 call d,[eax][0]
|
||||
#FF9044332211 call d,[eax][011223344]
|
||||
#FF1500000100 call d,[000010000]
|
||||
#FF9300000000 call d,[ebx][0]
|
||||
#FF10 call d,[eax]
|
||||
CallPattern = \
|
||||
[
|
||||
[-2, [0xFF] ],
|
||||
[-3, [0xFF] ],
|
||||
[-5, [0xE8] ],
|
||||
[-6, [0xFF] ],
|
||||
]
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def IsPrevInsnCall(ea):
|
||||
"""
|
||||
Given a return address, this function tries to check if previous instruction
|
||||
is a CALL instruction
|
||||
"""
|
||||
global CallPattern
|
||||
if ea == idaapi.BADADDR or ea < 10:
|
||||
return None
|
||||
|
||||
for delta, opcodes in CallPattern:
|
||||
# assume caller's ea
|
||||
caller = ea + delta
|
||||
# get the bytes
|
||||
bytes = [x for x in GetDataList(caller, len(opcodes), 1)]
|
||||
# do we have a match? is it a call instruction?
|
||||
if bytes == opcodes and idaapi.is_call_insn(caller):
|
||||
return caller
|
||||
return None
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def CallStackWalk(nn):
|
||||
class Result:
|
||||
"""
|
||||
Class holding the result of one call stack item
|
||||
Each call stack item instance has the following attributes:
|
||||
caller = ea of caller
|
||||
displ = display string
|
||||
sp = stack pointer
|
||||
"""
|
||||
def __init__(self, caller, sp):
|
||||
self.caller = caller
|
||||
self.sp = sp
|
||||
f = idaapi.get_func(caller)
|
||||
self.displ = "%08x: " % caller
|
||||
if f:
|
||||
self.displ += idc.GetFunctionName(caller)
|
||||
t = caller - f.startEA
|
||||
if t > 0: self.displ += "+" + hex(t)
|
||||
else:
|
||||
self.displ += hex(caller)
|
||||
self.displ += " [" + hex(sp) + "]"
|
||||
|
||||
def __str__(self):
|
||||
return self.displ
|
||||
|
||||
# get stack pointer
|
||||
sp = cpu.Esp
|
||||
seg = idaapi.getseg(sp)
|
||||
if not seg:
|
||||
return (False, "Could not locate stack segment!")
|
||||
|
||||
stack_seg = Seg(seg)
|
||||
word_size = 2 ** (seg.bitness + 1)
|
||||
callers = []
|
||||
sp = cpu.Esp - word_size
|
||||
while sp < stack_seg.endEA:
|
||||
sp += word_size
|
||||
ptr = idautils.GetDataList(sp, 1, word_size).next()
|
||||
seg = idaapi.getseg(ptr)
|
||||
# only accept executable segments
|
||||
if (not seg) or ((seg.perm & idaapi.SEGPERM_EXEC) == 0):
|
||||
continue
|
||||
# try to find caller
|
||||
caller = IsPrevInsnCall(ptr)
|
||||
# we have no recognized caller, skip!
|
||||
if caller is None:
|
||||
continue
|
||||
|
||||
# do we have a debug name that is near?
|
||||
if nn:
|
||||
ret = nn.find(caller)
|
||||
if ret:
|
||||
ea = ret[0]
|
||||
# function exists?
|
||||
f = idaapi.get_func(ea)
|
||||
if not f:
|
||||
# create function
|
||||
idc.MakeFunction(ea, idaapi.BADADDR)
|
||||
|
||||
# get the flags
|
||||
f = idc.GetFlags(caller)
|
||||
# no code there?
|
||||
if not isCode(f):
|
||||
MakeCode(caller)
|
||||
|
||||
callers.append(Result(caller, sp))
|
||||
#
|
||||
return (True, callers)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Chooser class
|
||||
class CallStackWalkChoose(Choose):
|
||||
def __init__(self, list, title):
|
||||
Choose.__init__(self, list, title)
|
||||
self.width = 250
|
||||
|
||||
def enter(self, n):
|
||||
o = self.list[n-1]
|
||||
idc.Jump(o.caller)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def main():
|
||||
if not idaapi.is_debugger_on():
|
||||
idc.Warning("Please run the process first!")
|
||||
return
|
||||
if idaapi.get_process_state() != -1:
|
||||
idc.Warning("Please suspend the debugger first!")
|
||||
return
|
||||
|
||||
# only avail from IdaPython r232
|
||||
if hasattr(idaapi, "NearestName"):
|
||||
# get all debug names
|
||||
dn = idaapi.get_debug_names(idaapi.cvar.inf.minEA, idaapi.cvar.inf.maxEA)
|
||||
# initiate a nearest name search (using debug names)
|
||||
nn = idaapi.NearestName(dn)
|
||||
else:
|
||||
nn = None
|
||||
|
||||
ret, callstack = CallStackWalk(nn)
|
||||
if ret:
|
||||
title = "Call stack walker (thread %X)" % (GetCurrentThreadId())
|
||||
idaapi.close_chooser(title)
|
||||
c = CallStackWalkChoose(callstack, title)
|
||||
c.choose()
|
||||
else:
|
||||
idc.Warning("Failed to walk the stack:" + callstack)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
main()
|
101
Scripts/DbgCmd.py
Normal file
101
Scripts/DbgCmd.py
Normal file
@ -0,0 +1,101 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# Debugger command prompt with CustomViewers
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
import idaapi
|
||||
import idc
|
||||
from idaapi import simplecustviewer_t
|
||||
|
||||
def SendDbgCommand(cmd):
|
||||
"""Sends a command to the debugger and returns the output string.
|
||||
An exception will be raised if the debugger is not running or the current debugger does not export
|
||||
the 'SendDbgCommand' IDC command.
|
||||
"""
|
||||
s = Eval('SendDbgCommand("%s");' % cmd)
|
||||
if s.startswith("IDC_FAILURE"):
|
||||
raise Exception, "Debugger command is available only when the debugger is active!"
|
||||
return s
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class dbgcmd_t(simplecustviewer_t):
|
||||
def Create(self):
|
||||
# Form the title
|
||||
title = "Debugger command window"
|
||||
# Create the customview
|
||||
if not simplecustviewer_t.Create(self, title):
|
||||
return False
|
||||
self.last_cmd = ""
|
||||
self.menu_clear = self.AddPopupMenu("Clear")
|
||||
self.menu_cmd = self.AddPopupMenu("New command")
|
||||
|
||||
self.ResetOutput()
|
||||
return True
|
||||
|
||||
def IssueCommand(self):
|
||||
s = idaapi.askstr(0, self.last_cmd, "Please enter a debugger command")
|
||||
if not s:
|
||||
return
|
||||
|
||||
# Save last command
|
||||
self.last_cmd = s
|
||||
|
||||
# Add it using a different color
|
||||
self.AddLine("debugger>" + idaapi.COLSTR(s, idaapi.SCOLOR_VOIDOP))
|
||||
|
||||
try:
|
||||
r = SendDbgCommand(s).split("\n")
|
||||
for s in r:
|
||||
self.AddLine(idaapi.COLSTR(s, idaapi.SCOLOR_LIBNAME))
|
||||
except:
|
||||
self.AddLine(idaapi.COLSTR("Debugger is not active or does not export SendDbgCommand()", idaapi.SCOLOR_ERROR))
|
||||
self.Refresh()
|
||||
|
||||
def ResetOutput(self):
|
||||
self.ClearLines()
|
||||
self.AddLine(idaapi.COLSTR("Please press INS to enter command; X to clear output", idaapi.SCOLOR_AUTOCMT))
|
||||
self.Refresh()
|
||||
|
||||
def OnKeydown(self, vkey, shift):
|
||||
# ESCAPE?
|
||||
if vkey == 27:
|
||||
self.Close()
|
||||
# VK_INSERT
|
||||
elif vkey == 45:
|
||||
self.IssueCommand()
|
||||
elif vkey == ord('X'):
|
||||
self.ResetOutput()
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
|
||||
def OnPopupMenu(self, menu_id):
|
||||
if menu_id == self.menu_clear:
|
||||
self.ResetOutput()
|
||||
elif menu_id == self.menu_cmd:
|
||||
self.IssueCommand()
|
||||
else:
|
||||
# Unhandled
|
||||
return False
|
||||
return True
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def show_win():
|
||||
x = dbgcmd_t()
|
||||
if not x.Create():
|
||||
print "Failed to create debugger command line!"
|
||||
return None
|
||||
x.Show()
|
||||
return x
|
||||
|
||||
try:
|
||||
# created already?
|
||||
dbgcmd
|
||||
dbgcmd.Close()
|
||||
del dbgcmd
|
||||
except:
|
||||
pass
|
||||
|
||||
dbgcmd = show_win()
|
||||
if not dbgcmd:
|
||||
del dbgcmd
|
||||
|
105
Scripts/DrvsDispatch.py
Normal file
105
Scripts/DrvsDispatch.py
Normal file
@ -0,0 +1,105 @@
|
||||
"""
|
||||
|
||||
A script to demonstrate how to send commands to the debugger and then parse and use the output in IDA
|
||||
|
||||
Copyright (c) 1990-2009 Hex-Rays
|
||||
ALL RIGHTS RESERVED.
|
||||
|
||||
"""
|
||||
|
||||
import re
|
||||
from idaapi import Choose
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def CmdDriverList():
|
||||
s = Eval('WinDbgCommand("lm o");')
|
||||
if "IDC_FAILURE" in s: return False
|
||||
return s
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def CmdDrvObj(drvname, flag=2):
|
||||
return Eval('WinDbgCommand("!drvobj %s %d");' % (drvname, flag))
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def CmdReloadForce():
|
||||
s = Eval('WinDbgCommand(".reload /f");')
|
||||
if "IDC_FAILURE" in s: return False
|
||||
return True
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# class to hold dispatch entry information
|
||||
class DispatchEntry:
|
||||
def __init__(self, addr, name):
|
||||
self.addr = addr
|
||||
self.name = name
|
||||
def __repr__(self):
|
||||
return "%08X: %s" % (self.addr, self.name)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def GetDriverDispatch():
|
||||
|
||||
# return a list of arrays of the form: [addr, name]
|
||||
ret_list = []
|
||||
|
||||
# build the RE for parsing output from the "lm o" command
|
||||
re_drv = re.compile('^[a-f0-9]+\s+[a-f0-9]+\s+(\S+)', re.I)
|
||||
|
||||
# build the RE for parsing output from the "!drvobj DRV_NAME 2" command
|
||||
re_tbl = re.compile('^\[\d{2}\]\s+IRP_MJ_(\S+)\s+([0-9a-f]+)', re.I)
|
||||
|
||||
# force reloading of module symbols
|
||||
if not CmdReloadForce():
|
||||
print "Could not communicate with WinDbg, make sure the debugger is running!"
|
||||
return None
|
||||
|
||||
# get driver list
|
||||
lm_out = CmdDriverList()
|
||||
if not lm_out:
|
||||
return "Failed to get driver list!"
|
||||
|
||||
# for each line
|
||||
for line in lm_out.split("\n"):
|
||||
# parse
|
||||
r = re_drv.match(line)
|
||||
if not r: continue
|
||||
|
||||
# extract driver name
|
||||
drvname = r.group(1).strip()
|
||||
|
||||
# execute "drvobj" command
|
||||
tbl_out = CmdDrvObj(drvname)
|
||||
|
||||
if not tbl_out:
|
||||
print "Failed to get driver object for", drvname
|
||||
continue
|
||||
|
||||
# for each line
|
||||
for line in tbl_out.split("\n"):
|
||||
# parse
|
||||
r = re_tbl.match(line)
|
||||
if not r: continue
|
||||
disp_addr = int(r.group(2), 16) # convert hex string to number
|
||||
disp_name = "Dispatch" + r.group(1)
|
||||
ret_list.append(DispatchEntry(disp_addr, drvname + "_" + disp_name))
|
||||
|
||||
return ret_list
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Chooser class
|
||||
class DispatchChoose(Choose):
|
||||
def __init__(self, list, title):
|
||||
Choose.__init__(self, list, title)
|
||||
self.width = 250
|
||||
|
||||
def enter(self, n):
|
||||
o = self.list[n-1]
|
||||
idc.Jump(o.addr)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# main
|
||||
r = GetDriverDispatch()
|
||||
if r:
|
||||
c = DispatchChoose(r, "Dispatch table browser")
|
||||
c.choose()
|
||||
else:
|
||||
print "Failed to retrieve dispatchers list!"
|
52
Scripts/ExchainDump.py
Normal file
52
Scripts/ExchainDump.py
Normal file
@ -0,0 +1,52 @@
|
||||
"""
|
||||
|
||||
This script shows how to send debugger commands and use the result in IDA
|
||||
|
||||
Copyright (c) 1990-2009 Hex-Rays
|
||||
ALL RIGHTS RESERVED.
|
||||
|
||||
"""
|
||||
|
||||
import idc
|
||||
import re
|
||||
|
||||
# class to store parsed results
|
||||
class exchain:
|
||||
def __init__(self, m):
|
||||
self.name = m.group(1)
|
||||
self.addr = int(m.group(2), 16)
|
||||
|
||||
def __str__(self):
|
||||
return "%x: %s" % (self.addr, self.name)
|
||||
|
||||
# Chooser class
|
||||
class MyChoose(Choose):
|
||||
def __init__(self, list, title):
|
||||
Choose.__init__(self, list, title)
|
||||
self.width = 250
|
||||
|
||||
def enter(self, n):
|
||||
o = self.list[n-1]
|
||||
idc.Jump(o.addr)
|
||||
|
||||
# main
|
||||
def main():
|
||||
s = idc.Eval('SendDbgCommand("!exchain")')
|
||||
if "IDC_FAILURE" in s:
|
||||
return (False, "Cannot execute the command")
|
||||
|
||||
matches = re.finditer(r'[^:]+: ([^\(]+) \(([^\)]+)\)\n', s)
|
||||
L = []
|
||||
for x in matches:
|
||||
L.append(exchain(x))
|
||||
if not L:
|
||||
return (False, "Nothing to display: Could parse the result!")
|
||||
|
||||
# Get a Choose instance
|
||||
chooser = MyChoose(L, "Exchain choose")
|
||||
# Run the chooser
|
||||
chooser.choose()
|
||||
return (True, "Success!")
|
||||
ok, r = main()
|
||||
if not ok:
|
||||
print r
|
139
Scripts/FindInstructions.py
Normal file
139
Scripts/FindInstructions.py
Normal file
@ -0,0 +1,139 @@
|
||||
"""
|
||||
FindInstructions.py: A script to help you find desired opcodes/instructions in a database
|
||||
|
||||
The script accepts opcodes and assembly statements (which will be assembled) separated by semicolon
|
||||
|
||||
The general syntax is:
|
||||
find(asm or opcodes, x=Bool, asm_where=ea)
|
||||
|
||||
* Example:
|
||||
find("asm_statement1;asm_statement2;de ea dc 0d e0;asm_statement3;xx yy zz;...")
|
||||
* To filter-out non-executable segments pass x=True
|
||||
find("jmp dword ptr [esp]", x=True)
|
||||
* To specify in which context the instructions should be assembled, pass asm_where=ea:
|
||||
find("jmp dword ptr [esp]", asm_where=here())
|
||||
|
||||
Copyright (c) 1990-2009 Hex-Rays
|
||||
ALL RIGHTS RESERVED.
|
||||
|
||||
v1.0 - initial version
|
||||
"""
|
||||
import idaapi
|
||||
import idautils
|
||||
import idc
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def FindInstructions(instr, asm_where=None):
|
||||
"""
|
||||
Finds instructions/opcodes
|
||||
@return: Returns a tuple(True, [ ea, ... ]) or a tuple(False, "error message")
|
||||
"""
|
||||
if not asm_where:
|
||||
# get first segment
|
||||
asm_where = FirstSeg()
|
||||
if asm_where == idaapi.BADADDR:
|
||||
return (False, "No segments defined")
|
||||
|
||||
# regular expression to distinguish between opcodes and instructions
|
||||
re_opcode = re.compile('^[0-9a-f]{2} *', re.I)
|
||||
|
||||
# split lines
|
||||
lines = instr.split(";")
|
||||
|
||||
# all the assembled buffers (for each instruction)
|
||||
bufs = []
|
||||
for line in lines:
|
||||
if re_opcode.match(line):
|
||||
# convert from hex string to a character list then join the list to form one string
|
||||
buf = ''.join([chr(int(x, 16)) for x in line.split()])
|
||||
else:
|
||||
# assemble the instruction
|
||||
ret, buf = Assemble(asm_where, line)
|
||||
if not ret:
|
||||
return (False, "Failed to assemble:"+line)
|
||||
# add the assembled buffer
|
||||
bufs.append(buf)
|
||||
|
||||
# join the buffer into one string
|
||||
buf = ''.join(bufs)
|
||||
|
||||
# take total assembled instructions length
|
||||
tlen = len(buf)
|
||||
|
||||
# convert from binary string to space separated hex string
|
||||
bin_str = ' '.join(["%02X" % ord(x) for x in buf])
|
||||
|
||||
# find all binary strings
|
||||
print "Searching for: [%s]" % bin_str
|
||||
ea = MinEA()
|
||||
ret = []
|
||||
while True:
|
||||
ea = FindBinary(ea, SEARCH_DOWN, bin_str)
|
||||
if ea == idaapi.BADADDR:
|
||||
break
|
||||
ret.append(ea)
|
||||
Message(".")
|
||||
ea += tlen
|
||||
if not ret:
|
||||
return (False, "Could not match [%s]" % bin_str)
|
||||
Message("\n")
|
||||
return (True, ret)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Chooser class
|
||||
class SearchResultChoose(Choose):
|
||||
def __init__(self, list, title):
|
||||
Choose.__init__(self, list, title)
|
||||
self.width = 250
|
||||
|
||||
def enter(self, n):
|
||||
o = self.list[n-1]
|
||||
Jump(o.ea)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# class to represent the results
|
||||
class SearchResult:
|
||||
def __init__(self, ea):
|
||||
self.ea = ea
|
||||
if not isCode(GetFlags(ea)):
|
||||
MakeCode(ea)
|
||||
t = idaapi.generate_disasm_line(ea)
|
||||
if t:
|
||||
line = idaapi.tag_remove(t)
|
||||
else:
|
||||
line = ""
|
||||
func = GetFunctionName(ea)
|
||||
self.display = hex(ea) + ": "
|
||||
if func:
|
||||
self.display += func + ": "
|
||||
else:
|
||||
n = SegName(ea)
|
||||
if n: self.display += n + ": "
|
||||
self.display += line
|
||||
|
||||
def __str__(self):
|
||||
return self.display
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def find(s=None, x=False, asm_where=None):
|
||||
b, ret = FindInstructions(s, asm_where)
|
||||
if b:
|
||||
# executable segs only?
|
||||
if x:
|
||||
results = []
|
||||
for ea in ret:
|
||||
seg = idaapi.getseg(ea)
|
||||
if (not seg) or (seg.perm & idaapi.SEGPERM_EXEC) == 0:
|
||||
continue
|
||||
results.append(SearchResult(ea))
|
||||
else:
|
||||
results = [SearchResult(ea) for ea in ret]
|
||||
title = "Search result for: [%s]" % s
|
||||
idaapi.close_chooser(title)
|
||||
c = SearchResultChoose(results, title)
|
||||
c.choose()
|
||||
else:
|
||||
print ret
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
print "Please use find('asm_stmt1;xx yy;...', x=Bool,asm_where=ea) to search for instructions or opcodes. Specify x=true to filter out non-executable segments"
|
69
Scripts/ImpRef.py
Normal file
69
Scripts/ImpRef.py
Normal file
@ -0,0 +1,69 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# This is an example illustrating how to enumerate all addresses
|
||||
# that refer to all imported functions in a given module
|
||||
#
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
|
||||
import idaapi
|
||||
import idc
|
||||
import idautils
|
||||
import re
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def find_imported_funcs(dllname):
|
||||
def imp_cb(ea, name, ord):
|
||||
if not name:
|
||||
name = ''
|
||||
imports.append([ea, name, ord])
|
||||
return True
|
||||
|
||||
imports = []
|
||||
nimps = idaapi.get_import_module_qty()
|
||||
for i in xrange(0, nimps):
|
||||
name = idaapi.get_import_module_name(i)
|
||||
if re.match(dllname, name, re.IGNORECASE) is None:
|
||||
continue
|
||||
idaapi.enum_import_names(i, imp_cb)
|
||||
|
||||
return imports
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def find_import_ref(dllname):
|
||||
imports = find_imported_funcs(dllname)
|
||||
R = dict()
|
||||
for i, (ea, name,_) in enumerate(imports):
|
||||
#print "%x -> %s" % (ea, name)
|
||||
for xref in idautils.XrefsTo(ea):
|
||||
# check if referrer is a thunk
|
||||
ea = xref.frm
|
||||
f = idaapi.get_func(ea)
|
||||
if f and (f.flags & idaapi.FUNC_THUNK) != 0:
|
||||
imports.append([f.startEA, idaapi.get_func_name(f.startEA), 0])
|
||||
#print "\t%x %s: from a thunk, parent added %x" % (ea, name, f.startEA)
|
||||
continue
|
||||
|
||||
# save results
|
||||
if not R.has_key(i):
|
||||
R[i] = []
|
||||
|
||||
R[i].append(ea)
|
||||
|
||||
return (imports, R)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def main():
|
||||
dllname = idc.AskStr('kernel32', "Enter module name")
|
||||
if not dllname:
|
||||
print("Cancelled")
|
||||
return
|
||||
|
||||
imports, R = find_import_ref(dllname)
|
||||
for k, v in R.items():
|
||||
print(imports[k][1])
|
||||
for ea in v:
|
||||
print("\t%x" % ea)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
main()
|
124
Scripts/ImportExportViewer.py
Normal file
124
Scripts/ImportExportViewer.py
Normal file
@ -0,0 +1,124 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# This is an example illustrating how to:
|
||||
# - enumerate imports
|
||||
# - enumerate entrypoints
|
||||
# - Use PluginForm class
|
||||
# - Use PySide with PluginForm to create a Python UI
|
||||
#
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
import idaapi
|
||||
import idautils
|
||||
from idaapi import PluginForm
|
||||
from PySide import QtGui, QtCore
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
class ImpExpForm_t(PluginForm):
|
||||
|
||||
def imports_names_cb(self, ea, name, ord):
|
||||
self.items.append((ea, '' if not name else name, ord))
|
||||
# True -> Continue enumeration
|
||||
return True
|
||||
|
||||
|
||||
def BuildImports(self):
|
||||
tree = {}
|
||||
nimps = idaapi.get_import_module_qty()
|
||||
|
||||
for i in xrange(0, nimps):
|
||||
name = idaapi.get_import_module_name(i)
|
||||
if not name:
|
||||
continue
|
||||
# Create a list for imported names
|
||||
self.items = []
|
||||
|
||||
# Enum imported entries in this module
|
||||
idaapi.enum_import_names(i, self.imports_names_cb)
|
||||
|
||||
if name not in tree:
|
||||
tree[name] = []
|
||||
tree[name].extend(self.items)
|
||||
|
||||
return tree
|
||||
|
||||
|
||||
def BuildExports(self):
|
||||
return list(idautils.Entries())
|
||||
|
||||
|
||||
def PopulateTree(self):
|
||||
# Clear previous items
|
||||
self.tree.clear()
|
||||
|
||||
# Build imports
|
||||
root = QtGui.QTreeWidgetItem(self.tree)
|
||||
root.setText(0, "Imports")
|
||||
|
||||
for dll_name, imp_entries in self.BuildImports().items():
|
||||
imp_dll = QtGui.QTreeWidgetItem(root)
|
||||
imp_dll.setText(0, dll_name)
|
||||
|
||||
for imp_ea, imp_name, imp_ord in imp_entries:
|
||||
item = QtGui.QTreeWidgetItem(imp_dll)
|
||||
item.setText(0, "%s [0x%08x]" %(imp_name, imp_ea))
|
||||
|
||||
|
||||
# Build exports
|
||||
root = QtGui.QTreeWidgetItem(self.tree)
|
||||
root.setText(0, "Exports")
|
||||
|
||||
for exp_i, exp_ord, exp_ea, exp_name in self.BuildExports():
|
||||
item = QtGui.QTreeWidgetItem(root)
|
||||
item.setText(0, "%s [#%d] [0x%08x]" % (exp_name, exp_ord, exp_ea))
|
||||
|
||||
|
||||
def OnCreate(self, form):
|
||||
"""
|
||||
Called when the plugin form is created
|
||||
"""
|
||||
|
||||
# Get parent widget
|
||||
self.parent = self.FormToPySideWidget(form)
|
||||
|
||||
# Create tree control
|
||||
self.tree = QtGui.QTreeWidget()
|
||||
self.tree.setHeaderLabels(("Names",))
|
||||
self.tree.setColumnWidth(0, 100)
|
||||
|
||||
# Create layout
|
||||
layout = QtGui.QVBoxLayout()
|
||||
layout.addWidget(self.tree)
|
||||
|
||||
self.PopulateTree()
|
||||
# Populate PluginForm
|
||||
self.parent.setLayout(layout)
|
||||
|
||||
|
||||
def OnClose(self, form):
|
||||
"""
|
||||
Called when the plugin form is closed
|
||||
"""
|
||||
global ImpExpForm
|
||||
del ImpExpForm
|
||||
print "Closed"
|
||||
|
||||
|
||||
def Show(self):
|
||||
"""Creates the form is not created or focuses it if it was"""
|
||||
return PluginForm.Show(self,
|
||||
"Imports / Exports viewer",
|
||||
options = PluginForm.FORM_PERSIST)
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
def main():
|
||||
global ImpExpForm
|
||||
|
||||
try:
|
||||
ImpExpForm
|
||||
except:
|
||||
ImpExpForm = ImpExpForm_t()
|
||||
|
||||
ImpExpForm.Show()
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
main()
|
85
Scripts/PteDump.py
Normal file
85
Scripts/PteDump.py
Normal file
@ -0,0 +1,85 @@
|
||||
import idaapi
|
||||
import idc
|
||||
from idaapi import Choose2
|
||||
|
||||
def parse_pte(str):
|
||||
try:
|
||||
parse_pte.re
|
||||
except:
|
||||
parse_pte.re = re.compile('PDE at ([0-9a-f]+)\s*PTE at ([0-9a-f]+)\ncontains ([0-9a-f]+)\s*contains ([0-9a-f]+)\npfn ([0-9]+)\s*([^ ]+)\s*pfn ([0-9a-f]+)\s*([^\r\n]+)', re.I | re.M)
|
||||
parse_pte.items = ('pde', 'pte', 'pdec', 'ptec', 'pdepfn', 'pdepfns', 'ptepfn', 'ptepfns')
|
||||
|
||||
m = parse_pte.re.search(s)
|
||||
r = {}
|
||||
for i in range(0, len(parse_pte.items)):
|
||||
r[parse_pte.items[i]] = m.group(i+1)
|
||||
return r
|
||||
|
||||
class MyChoose2(Choose2):
|
||||
|
||||
def __init__(self, title, ea1, ea2):
|
||||
Choose2.__init__(self, title, [ ["VA", 10], ["PTE attr", 30] ])
|
||||
self.ea1 = ea1
|
||||
self.ea2 = ea2
|
||||
self.n = 0
|
||||
self.icon = 5
|
||||
self.items = []
|
||||
self.Refresh()
|
||||
self.selcount = 0
|
||||
|
||||
def OnGetLine(self, n):
|
||||
print("getline %d" % n)
|
||||
return self.items[n]
|
||||
|
||||
def OnGetSize(self):
|
||||
n = len(self.items)
|
||||
self.Refresh()
|
||||
return n
|
||||
|
||||
def OnRefresh(self, n):
|
||||
print("refresh %d" % n)
|
||||
return n
|
||||
|
||||
def Refresh(self):
|
||||
items = []
|
||||
PG = 0x1000
|
||||
ea1 = self.ea1
|
||||
npages = (self.ea2 - ea1) / PG
|
||||
for i in range(npages):
|
||||
r = idc.SendDbgCommand("!pte %x" % ea1)
|
||||
if not r:
|
||||
return False
|
||||
r = parse_pte(r)
|
||||
items.append([hex(ea1), r['ptepfns']])
|
||||
ea1 += PG
|
||||
|
||||
self.items = items
|
||||
print(self.items)
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def Execute(ea1, ea2):
|
||||
c = MyChoose2("PTE Viewer [%x..%x]" % (ea1, ea2), ea1, ea2)
|
||||
return (c, c.Show())
|
||||
|
||||
|
||||
def DumpPTE(ea1, ea2):
|
||||
items = []
|
||||
PG = 0x1000
|
||||
npages = (ea2 - ea1) / PG
|
||||
for i in range(npages):
|
||||
r = idc.SendDbgCommand("!pte %x" % ea1)
|
||||
if not r:
|
||||
return False
|
||||
print r
|
||||
r = parse_pte(r)
|
||||
print("VA: %08X PTE: %s PDE: %s" % (ea1, r['ptepfns'], r['pdepfns']))
|
||||
ea1 += PG
|
||||
|
||||
def DumpSegPTE(ea):
|
||||
DumpPTE(idc.SegStart(ea), idc.SegEnd(ea))
|
||||
|
||||
DumpSegPTE(here())
|
||||
|
||||
#MyChoose2.Execute(0xF718F000, 0xF718F000+0x1000)
|
||||
|
149
Scripts/SEHGraph.py
Normal file
149
Scripts/SEHGraph.py
Normal file
@ -0,0 +1,149 @@
|
||||
"""
|
||||
|
||||
A script that graphs all the exception handlers in a given process
|
||||
|
||||
It will be easy to see what thread uses what handler and what handlers are commonly used between threads
|
||||
|
||||
Copyright (c) 1990-2009 Hex-Rays
|
||||
ALL RIGHTS RESERVED.
|
||||
|
||||
|
||||
v1.0 - initial version
|
||||
|
||||
"""
|
||||
|
||||
import idaapi
|
||||
import idautils
|
||||
import idc
|
||||
|
||||
from idaapi import GraphViewer
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Since Windbg debug module does not support get_thread_sreg_base()
|
||||
# we will call the debugger engine "dg" command and parse its output
|
||||
def WindbgGetRegBase(tid):
|
||||
s = idc.Eval('WinDbgCommand("dg %x")' % cpu.fs)
|
||||
if "IDC_FAILURE" in s:
|
||||
return 0
|
||||
m = re.compile("[0-9a-f]{4} ([0-9a-f]{8})")
|
||||
t = m.match(s.split('\n')[-2])
|
||||
if not t:
|
||||
return 0
|
||||
return int(t.group(1), 16)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def GetFsBase(tid):
|
||||
idc.SelectThread(tid)
|
||||
base = idaapi.dbg_get_thread_sreg_base(tid, cpu.fs)
|
||||
if base != 0:
|
||||
return base
|
||||
return WindbgGetRegBase(tid)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Walks the SEH chain and returns a list of handlers
|
||||
def GetExceptionChain(tid):
|
||||
fs_base = GetFsBase(tid)
|
||||
exc_rr = Dword(fs_base)
|
||||
result = []
|
||||
while exc_rr != 0xffffffff:
|
||||
prev = Dword(exc_rr)
|
||||
handler = Dword(exc_rr + 4)
|
||||
exc_rr = prev
|
||||
result.append(handler)
|
||||
return result
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class SEHGraph(GraphViewer):
|
||||
def __init__(self, title, result):
|
||||
GraphViewer.__init__(self, title)
|
||||
self.result = result
|
||||
self.names = {} # ea -> name
|
||||
|
||||
def OnRefresh(self):
|
||||
self.Clear()
|
||||
addr_id = {}
|
||||
|
||||
for (tid, chain) in self.result.items():
|
||||
# Each node data will contain a tuple of the form: (Boolean->Is_thread, Int->Value, String->Label)
|
||||
# For threads the is_thread will be true and the value will hold the thread id
|
||||
# For exception handlers, is_thread=False and Value=Handler address
|
||||
|
||||
# Add the thread node
|
||||
id_parent = self.AddNode( (True, tid, "Thread %X" % tid) )
|
||||
|
||||
# Add each handler
|
||||
for handler in chain:
|
||||
# Check if a function is created at the handler's address
|
||||
f = idaapi.get_func(handler)
|
||||
if not f:
|
||||
# create function
|
||||
idc.MakeFunction(handler, idaapi.BADADDR)
|
||||
|
||||
# Node label is function name or address
|
||||
s = GetFunctionName(handler)
|
||||
if not s:
|
||||
s = "%x" % handler
|
||||
|
||||
# cache name
|
||||
self.names[handler] = s
|
||||
|
||||
# Get the node id given the handler address
|
||||
# We use an addr -> id dictionary so that similar addresses get similar node id
|
||||
if not addr_id.has_key(handler):
|
||||
id = self.AddNode( (False, handler, s) )
|
||||
addr_id[handler] = id # add this ID
|
||||
else:
|
||||
id = addr_id[handler]
|
||||
|
||||
# Link handlers to each other
|
||||
self.AddEdge(id_parent, id)
|
||||
id_parent = id
|
||||
|
||||
return True
|
||||
|
||||
def OnGetText(self, node_id):
|
||||
is_thread, value, label = self[node_id]
|
||||
if is_thread:
|
||||
return (label, 0xff00f0)
|
||||
return label
|
||||
|
||||
def OnDblClick(self, node_id):
|
||||
is_thread, value, label = self[node_id]
|
||||
if is_thread:
|
||||
idc.SelectThread(value)
|
||||
self.Show()
|
||||
s = "SEH chain for " + hex(value)
|
||||
t = "-" * len(s)
|
||||
print t
|
||||
print s
|
||||
print t
|
||||
for handler in self.result[value]:
|
||||
print "%x: %s" % (handler, self.names[handler])
|
||||
print t
|
||||
else:
|
||||
idc.Jump(value)
|
||||
return True
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def main():
|
||||
if not idaapi.dbg_can_query():
|
||||
print "The debugger must be active and suspended before using this script!"
|
||||
return
|
||||
|
||||
# Save current thread id
|
||||
tid = GetCurrentThreadId()
|
||||
|
||||
# Iterate through all function instructions and take only call instructions
|
||||
result = {}
|
||||
for tid in idautils.Threads():
|
||||
result[tid] = GetExceptionChain(tid)
|
||||
|
||||
# Restore previously selected thread
|
||||
idc.SelectThread(tid)
|
||||
|
||||
# Build the graph
|
||||
g = SEHGraph("SEH graph", result)
|
||||
g.Show()
|
||||
|
||||
main()
|
70
Scripts/VaDump.py
Normal file
70
Scripts/VaDump.py
Normal file
@ -0,0 +1,70 @@
|
||||
"""
|
||||
|
||||
This script shows how to send debugger commands and use the result in IDA
|
||||
|
||||
Copyright (c) 1990-2009 Hex-Rays
|
||||
ALL RIGHTS RESERVED.
|
||||
|
||||
"""
|
||||
|
||||
import idc
|
||||
from idaapi import Choose
|
||||
|
||||
import re
|
||||
|
||||
# class to store parsed results
|
||||
class memva:
|
||||
def __init__(self, m):
|
||||
self.base = int(m.group(1), 16)
|
||||
self.regionsize = int(m.group(2), 16)
|
||||
self.state = int(m.group(3), 16)
|
||||
self.statestr = m.group(4).strip()
|
||||
self.protect = int(m.group(5), 16)
|
||||
self.protectstr = m.group(6).strip()
|
||||
if m.group(7):
|
||||
self.type = int(m.group(8), 16)
|
||||
self.typestr = m.group(9).strip()
|
||||
else:
|
||||
self.type = 0
|
||||
self.typestr = ""
|
||||
def __str__(self):
|
||||
return "(Base %08X; RegionSize: %08X; State: %08X/%10s; protect: %08X/%10s; type: %08X/%10s)" % (
|
||||
self.base, self.regionsize, self.state,
|
||||
self.statestr, self.protect,
|
||||
self.protectstr, self.type, self.typestr)
|
||||
|
||||
# Chooser class
|
||||
class MemChoose(Choose):
|
||||
def __init__(self, list, title):
|
||||
Choose.__init__(self, list, title)
|
||||
self.width = 250
|
||||
|
||||
def enter(self, n):
|
||||
o = self.list[n-1]
|
||||
idc.Jump(o.base)
|
||||
|
||||
# main
|
||||
def main():
|
||||
s = idc.Eval('SendDbgCommand("!vadump")')
|
||||
if "IDC_FAILURE" in s:
|
||||
return (False, "Cannot execute the command")
|
||||
|
||||
matches = re.finditer(r'BaseAddress:\s*?(\w+?)\n' \
|
||||
+'RegionSize:\s*?(\w*?)\n' \
|
||||
+'State:\s*?(\w*?)\s*?(\w*?)\n' \
|
||||
+'Protect:\s*?(\w*?)\s*?(\w*?)\n' \
|
||||
+'(Type:\s*?(\w*?)\s*?(\w*?)\n)*', s)
|
||||
L = []
|
||||
for x in matches:
|
||||
L.append(memva(x))
|
||||
if not L:
|
||||
return (False, "Nothing to display: Could not parse the result!")
|
||||
|
||||
# Get a Choose instance
|
||||
chooser = MemChoose(L, "Memory choose")
|
||||
# Run the chooser
|
||||
chooser.choose()
|
||||
return (True, "Success!")
|
||||
r = main()
|
||||
if not r[0]:
|
||||
print r[1]
|
68
Scripts/msdnapihelp.py
Normal file
68
Scripts/msdnapihelp.py
Normal file
@ -0,0 +1,68 @@
|
||||
"""
|
||||
User contributed script: MSDN API HELP plugin
|
||||
|
||||
This script fetches the API reference (from MSDN) of a given highlighted identifier
|
||||
and returns the results in a new web browser page.
|
||||
|
||||
This script depends on the feedparser package: http://code.google.com/p/feedparser/
|
||||
|
||||
10/05/2010
|
||||
- initial version
|
||||
|
||||
|
||||
"""
|
||||
|
||||
import idaapi
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class msdnapihelp_plugin_t(idaapi.plugin_t):
|
||||
flags = idaapi.PLUGIN_UNL
|
||||
comment = "Online MSDN API Help"
|
||||
help = "Help me"
|
||||
wanted_name = "MSDN API Help"
|
||||
wanted_hotkey = "F3"
|
||||
|
||||
def init(self):
|
||||
return idaapi.PLUGIN_OK
|
||||
|
||||
|
||||
@staticmethod
|
||||
def sanitize_name(name):
|
||||
t = idaapi.FUNC_IMPORT_PREFIX
|
||||
if name.startswith(t):
|
||||
return name[len(t):]
|
||||
return name
|
||||
|
||||
|
||||
def run(self, arg):
|
||||
# Get the highlighted identifier
|
||||
id = idaapi.get_highlighted_identifier()
|
||||
if not id:
|
||||
print "No identifier was highlighted"
|
||||
return
|
||||
|
||||
import webbrowser
|
||||
|
||||
try:
|
||||
import feedparser
|
||||
except:
|
||||
idaapi.warning('Feedparser package not installed')
|
||||
return
|
||||
|
||||
id = self.sanitize_name(id)
|
||||
print "Looking up '%s' in MSDN online" % id
|
||||
d = feedparser.parse("http://social.msdn.microsoft.com/Search/Feed.aspx?locale=en-us&format=RSS&Query=%s" % id)
|
||||
if len(d['entries']) > 0:
|
||||
url = d['entries'][0].link
|
||||
webbrowser.open_new_tab(url)
|
||||
else:
|
||||
print "API documentation not found for: %s" % id
|
||||
|
||||
|
||||
def term(self):
|
||||
pass
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def PLUGIN_ENTRY():
|
||||
return msdnapihelp_plugin_t()
|
16
build.py
16
build.py
@ -24,7 +24,7 @@ from distutils import sysconfig
|
||||
VERBOSE = True
|
||||
|
||||
IDA_MAJOR_VERSION = 6
|
||||
IDA_MINOR_VERSION = 0
|
||||
IDA_MINOR_VERSION = 1
|
||||
|
||||
if 'IDA' in os.environ:
|
||||
IDA_SDK = os.environ['IDA']
|
||||
@ -35,8 +35,8 @@ else:
|
||||
|
||||
# IDAPython version
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 4
|
||||
VERSION_PATCH = 3
|
||||
VERSION_MINOR = 5
|
||||
VERSION_PATCH = 0
|
||||
|
||||
# Determine Python version
|
||||
PYTHON_MAJOR_VERSION = int(platform.python_version()[0])
|
||||
@ -68,6 +68,7 @@ BINDIST_MANIFEST = [
|
||||
"CHANGES.txt",
|
||||
"AUTHORS.txt",
|
||||
"STATUS.txt",
|
||||
"python.cfg",
|
||||
"docs/notes.txt",
|
||||
"examples/chooser.py",
|
||||
"examples/colours.py",
|
||||
@ -91,6 +92,8 @@ BINDIST_MANIFEST = [
|
||||
"examples/ex_prefix_plugin.py",
|
||||
"examples/ex_pyside.py",
|
||||
"examples/ex_pyqt.py",
|
||||
"examples/ex_askusingform.py",
|
||||
"examples/ex_uihook.py",
|
||||
"examples/ex_imports.py"
|
||||
]
|
||||
|
||||
@ -100,6 +103,7 @@ SRCDIST_MANIFEST = [
|
||||
"python.cpp",
|
||||
"basetsd.h",
|
||||
"build.py",
|
||||
"python.cfg",
|
||||
"swig/allins.i",
|
||||
"swig/area.i",
|
||||
"swig/auto.i",
|
||||
@ -309,7 +313,7 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
|
||||
platform_macros = [ "__LINUX__" ]
|
||||
python_libpath = sysconfig.EXEC_PREFIX + os.sep + "lib"
|
||||
python_library = "-lpython%d.%d" % (PYTHON_MAJOR_VERSION, PYTHON_MINOR_VERSION)
|
||||
ida_libpath = os.path.join(idasdkdir, "lib", ea64 and "gcc64.lnx" or "gcc32.lnx")
|
||||
ida_libpath = os.path.join(idasdkdir, "lib", ea64 and "x86_linux_gcc_64" or "x86_linux_gcc_32")
|
||||
ida_lib = ""
|
||||
extra_link_parameters = ""
|
||||
# Platform-specific settings for the Windows build
|
||||
@ -318,7 +322,7 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
|
||||
platform_macros = [ "__NT__" ]
|
||||
python_libpath = sysconfig.EXEC_PREFIX + os.sep + "libs"
|
||||
python_library = "python%d%d.lib" % (PYTHON_MAJOR_VERSION, PYTHON_MINOR_VERSION)
|
||||
ida_libpath = os.path.join(idasdkdir, "lib", ea64 and "vc.w64" or "vc.w32")
|
||||
ida_libpath = os.path.join(idasdkdir, "lib", ea64 and "x86_win_vc_64" or "x86_win_vc_32")
|
||||
ida_lib = "ida.lib"
|
||||
SWIG_OPTIONS += " -D__NT__ "
|
||||
extra_link_parameters = ""
|
||||
@ -329,7 +333,7 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
|
||||
platform_macros = [ "__MAC__" ]
|
||||
python_libpath = "."
|
||||
python_library = "-framework Python"
|
||||
ida_libpath = os.path.join(idasdkdir, "lib", ea64 and "gcc64.mac64" or "gcc32.mac")
|
||||
ida_libpath = os.path.join(idasdkdir, "lib", ea64 and "x86_mac_gcc_64" or "x86_mac_gcc_32")
|
||||
ida_lib = ea64 and "-lida64" or "-lida"
|
||||
extra_link_parameters = ""
|
||||
|
||||
|
@ -7,16 +7,17 @@
|
||||
#
|
||||
from idaapi import *
|
||||
|
||||
# Get current ea
|
||||
ea = get_screen_ea()
|
||||
def main():
|
||||
# Get current ea
|
||||
ea = get_screen_ea()
|
||||
|
||||
# Get segment class
|
||||
seg = getseg(ea)
|
||||
# Get segment class
|
||||
seg = getseg(ea)
|
||||
|
||||
# Loop from segment start to end
|
||||
func = get_func(seg.startEA)
|
||||
|
||||
while func != None and func.startEA < seg.endEA:
|
||||
# Loop from segment start to end
|
||||
func = get_next_func(seg.startEA)
|
||||
seg_end = seg.endEA
|
||||
while func is not None and func.startEA < seg_end:
|
||||
funcea = func.startEA
|
||||
print "Function %s at 0x%x" % (GetFunctionName(funcea), funcea)
|
||||
|
||||
@ -27,3 +28,6 @@ while func != None and func.startEA < seg.endEA:
|
||||
ref = get_next_cref_to(funcea, ref)
|
||||
|
||||
func = get_next_func(funcea)
|
||||
|
||||
|
||||
main()
|
@ -7,14 +7,21 @@
|
||||
#
|
||||
from idautils import *
|
||||
|
||||
# Get current ea
|
||||
ea = ScreenEA()
|
||||
def main():
|
||||
# Get current ea
|
||||
ea = ScreenEA()
|
||||
if ea == idaapi.BADADDR:
|
||||
print("Could not get get_screen_ea()")
|
||||
return
|
||||
|
||||
# Loop from start to end in the current segment
|
||||
for funcea in Functions(SegStart(ea), SegEnd(ea)):
|
||||
print "Function %s at 0x%x" % (GetFunctionName(funcea), funcea)
|
||||
# Loop from start to end in the current segment
|
||||
for funcea in Functions(SegStart(ea), SegEnd(ea)):
|
||||
print("Function %s at 0x%x" % (GetFunctionName(funcea), funcea))
|
||||
|
||||
# Find all code references to funcea
|
||||
for ref in CodeRefsTo(funcea, 1):
|
||||
print " called from %s(0x%x)" % (GetFunctionName(ref), ref)
|
||||
print(" called from %s(0x%x)" % (GetFunctionName(ref), ref))
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
main()
|
@ -1,18 +1,18 @@
|
||||
import idaapi
|
||||
|
||||
def cb(*args):
|
||||
print "Callback called!"
|
||||
print("Callback called!")
|
||||
return 1
|
||||
|
||||
try:
|
||||
if ctx:
|
||||
ctx
|
||||
idaapi.del_menu_item(ctx)
|
||||
except:
|
||||
pass
|
||||
|
||||
ctx = idaapi.add_menu_item("Search/", "X", "", 0, cb, tuple("hello world"))
|
||||
if ctx is None:
|
||||
print "Failed to add menu!"
|
||||
print("Menu removed")
|
||||
del ctx
|
||||
else:
|
||||
print "Menu added successfully!"
|
||||
except:
|
||||
ctx = idaapi.add_menu_item("Search/", "X", "", 0, cb, tuple("hello world"))
|
||||
if ctx is None:
|
||||
print("Failed to add menu!")
|
||||
del ctx
|
||||
else:
|
||||
print("Menu added successfully. Run the script again to delete the menu")
|
221
examples/ex_askusingform.py
Normal file
221
examples/ex_askusingform.py
Normal file
@ -0,0 +1,221 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# This is an example illustrating how to use the Form class
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
from idaapi import Form
|
||||
|
||||
#<pycode(ex_askusingform)>
|
||||
# --------------------------------------------------------------------------
|
||||
class TestEmbeddedChooserClass(Choose2):
|
||||
"""
|
||||
A simple chooser to be used as an embedded chooser
|
||||
"""
|
||||
def __init__(self, title, nb = 5, flags=0):
|
||||
Choose2.__init__(self,
|
||||
title,
|
||||
[ ["Address", 10], ["Name", 30] ],
|
||||
embedded=True, width=30, height=20, flags=flags)
|
||||
self.n = 0
|
||||
self.items = [ self.make_item() for x in xrange(0, nb+1) ]
|
||||
self.icon = 5
|
||||
self.selcount = 0
|
||||
|
||||
def make_item(self):
|
||||
r = [str(self.n), "func_%04d" % self.n]
|
||||
self.n += 1
|
||||
return r
|
||||
|
||||
def OnClose(self):
|
||||
pass
|
||||
|
||||
def OnGetLine(self, n):
|
||||
print("getline %d" % n)
|
||||
return self.items[n]
|
||||
|
||||
def OnGetSize(self):
|
||||
n = len(self.items)
|
||||
print("getsize -> %d" % n)
|
||||
return n
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
class MyForm(Form):
|
||||
def __init__(self):
|
||||
self.invert = False
|
||||
self.EChooser = TestEmbeddedChooserClass("E1", flags=Choose2.CH_MULTI)
|
||||
Form.__init__(self, r"""STARTITEM {id:rNormal}
|
||||
BUTTON YES* Yeah
|
||||
BUTTON NO Nope
|
||||
BUTTON CANCEL Nevermind
|
||||
Form Test
|
||||
|
||||
{FormChangeCb}
|
||||
This is a string: +{cStr1}+
|
||||
This is an address: +{cAddr1}+
|
||||
|
||||
Escape\{control}
|
||||
This is a string: '{cStr2}'
|
||||
This is a number: {cVal1}
|
||||
|
||||
<#Hint1#Enter name:{iStr1}>
|
||||
<#Hint2#Select color:{iColor1}>
|
||||
Browse test
|
||||
<#Select a file to open#Browse to open:{iFileOpen}>
|
||||
<#Select a file to save#Browse to save:{iFileSave}>
|
||||
<#Select dir#Browse for dir:{iDir}>
|
||||
Type
|
||||
<#Select type#Write a type:{iType}>
|
||||
Numbers
|
||||
<##Enter a selector value:{iSegment}>
|
||||
<##Enter a raw hex:{iRawHex}>
|
||||
<##Enter a character:{iChar}>
|
||||
<##Enter an address:{iAddr}>
|
||||
Button test
|
||||
<##Button1:{iButton1}> <##Button2:{iButton2}>
|
||||
|
||||
Check boxes:
|
||||
<Error output:{rError}>
|
||||
<Normal output:{rNormal}>
|
||||
<Warnings:{rWarnings}>{cGroup1}>
|
||||
|
||||
Radio boxes:
|
||||
<Green:{rGreen}>
|
||||
<Red:{rRed}>
|
||||
<Blue:{rBlue}>{cGroup2}>
|
||||
<Embedded chooser:{cEChooser}>
|
||||
The end!
|
||||
""", {
|
||||
'cStr1': Form.StringLabel("Hello"),
|
||||
'cStr2': Form.StringLabel("StringTest"),
|
||||
'cAddr1': Form.NumericLabel(0x401000, Form.FT_ADDR),
|
||||
'cVal1' : Form.NumericLabel(99, Form.FT_HEX),
|
||||
'iStr1': Form.StringInput(),
|
||||
'iColor1': Form.ColorInput(),
|
||||
'iFileOpen': Form.FileInput(open=True),
|
||||
'iFileSave': Form.FileInput(save=True),
|
||||
'iDir': Form.DirInput(),
|
||||
'iType': Form.StringInput(tp=Form.FT_TYPE),
|
||||
'iSegment': Form.NumericInput(tp=Form.FT_SEG),
|
||||
'iRawHex': Form.NumericInput(tp=Form.FT_RAWHEX),
|
||||
'iAddr': Form.NumericInput(tp=Form.FT_ADDR),
|
||||
'iChar': Form.NumericInput(tp=Form.FT_CHAR),
|
||||
'iButton1': Form.ButtonInput(self.OnButton1),
|
||||
'iButton2': Form.ButtonInput(self.OnButton2),
|
||||
'cGroup1': Form.ChkGroupControl(("rNormal", "rError", "rWarnings")),
|
||||
'cGroup2': Form.RadGroupControl(("rRed", "rGreen", "rBlue")),
|
||||
'FormChangeCb': Form.FormChangeCb(self.OnFormChange),
|
||||
'cEChooser' : Form.EmbeddedChooserControl(self.EChooser)
|
||||
})
|
||||
|
||||
|
||||
def OnButton1(self, code=0):
|
||||
print("Button1 pressed")
|
||||
|
||||
|
||||
def OnButton2(self, code=0):
|
||||
print("Button2 pressed")
|
||||
|
||||
|
||||
def OnFormChange(self, fid):
|
||||
if fid == self.iButton1.id:
|
||||
print("Button1 fchg;inv=%s" % self.invert)
|
||||
self.SetFocusedField(self.rNormal.id)
|
||||
self.EnableField(self.rError.id, self.invert)
|
||||
self.invert = not self.invert
|
||||
elif fid == self.iButton2.id:
|
||||
g1 = self.GetControlValue(self.cGroup1)
|
||||
g2 = self.GetControlValue(self.cGroup2)
|
||||
d = self.GetControlValue(self.iDir)
|
||||
f = self.GetControlValue(self.iFileOpen)
|
||||
print("cGroup2:%x;Dir=%s;fopen=%s;cGroup1:%x" % (g1, d, f, g2))
|
||||
elif fid == self.cEChooser.id:
|
||||
l = self.GetControlValue(self.cEChooser)
|
||||
print("Chooser: %s" % l)
|
||||
else:
|
||||
print(">>fid:%d" % fid)
|
||||
return 1
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
def stdalone_main():
|
||||
f = MyForm()
|
||||
f, args = f.Compile()
|
||||
print args[0]
|
||||
print args[1:]
|
||||
f.rNormal.checked = True
|
||||
f.rWarnings.checked = True
|
||||
print hex(f.cGroup1.value)
|
||||
|
||||
f.rGreen.selected = True
|
||||
print f.cGroup2.value
|
||||
print "Title: '%s'" % f.title
|
||||
|
||||
f.Free()
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
def ida_main():
|
||||
# Create form
|
||||
global f
|
||||
f = MyForm()
|
||||
|
||||
# Compile (in order to populate the controls)
|
||||
f.Compile()
|
||||
|
||||
f.iColor1.value = 0x5bffff
|
||||
f.iDir.value = os.getcwd()
|
||||
f.rNormal.checked = True
|
||||
f.rWarnings.checked = True
|
||||
f.rGreen.selected = True
|
||||
f.iStr1.value = "Hello"
|
||||
|
||||
# Execute the form
|
||||
ok = f.Execute()
|
||||
print("r=%d" % ok)
|
||||
if ok == 1:
|
||||
print("f.str1=%s" % f.iStr1.value)
|
||||
print("f.color1=%x" % f.iColor1.value)
|
||||
print("f.openfile=%s" % f.iFileOpen.value)
|
||||
print("f.savefile=%s" % f.iFileSave.value)
|
||||
print("f.dir=%s" % f.iDir.value)
|
||||
print("f.type=%s" % f.iType.value)
|
||||
print("f.seg=%s" % f.iSegment.value)
|
||||
print("f.rawhex=%x" % f.iRawHex.value)
|
||||
print("f.char=%x" % f.iChar.value)
|
||||
print("f.addr=%x" % f.iAddr.value)
|
||||
print("f.cGroup1=%x" % f.cGroup1.value)
|
||||
print("f.cGroup2=%x" % f.cGroup2.value)
|
||||
|
||||
sel = f.EChooser.GetEmbSelection()
|
||||
if sel is None:
|
||||
print("No selection")
|
||||
else:
|
||||
print("Selection: %s" % sel)
|
||||
# Dispose the form
|
||||
f.Free()
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
def ida_main_legacy():
|
||||
# Here we simply show how to use the old style form format using Python
|
||||
|
||||
# Sample form from kernwin.hpp
|
||||
s = """Sample dialog box
|
||||
|
||||
|
||||
This is sample dialog box for %A
|
||||
using address %$
|
||||
|
||||
<~E~nter value:N:32:16::>
|
||||
"""
|
||||
|
||||
# Use either StringArgument or NumericArgument to pass values to the function
|
||||
num = Form.NumericArgument('N', value=123)
|
||||
ok = idaapi.AskUsingForm(s,
|
||||
Form.StringArgument("PyAskUsingForm").arg,
|
||||
Form.NumericArgument('$', 0x401000).arg,
|
||||
num.arg)
|
||||
if ok == 1:
|
||||
print("You entered: %x" % num.value)
|
||||
|
||||
#</pycode(ex_askusingform)>
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
ida_main()
|
@ -10,38 +10,39 @@ class MyChoose2(Choose2):
|
||||
self.icon = 5
|
||||
self.selcount = 0
|
||||
self.popup_names = ["Inzert", "Del leet", "Ehdeet", "Ree frech"]
|
||||
print "created", str(self)
|
||||
print("created %s" % str(self))
|
||||
|
||||
def OnClose(self):
|
||||
print "closed", str(self)
|
||||
|
||||
def OnEditLine(self, n):
|
||||
self.items[n][1] = self.items[n][1] + "*"
|
||||
print "editing", str(n)
|
||||
print("editing %d" % n)
|
||||
|
||||
def OnInsertLine(self):
|
||||
self.items.append(self.make_item())
|
||||
print "insert line"
|
||||
print("insert line")
|
||||
|
||||
def OnSelectLine(self, n):
|
||||
self.selcount += 1
|
||||
Warning("[%02d] selectline '%s'" % (self.selcount, n))
|
||||
|
||||
def OnGetLine(self, n):
|
||||
print "getline", str(n)
|
||||
print("getline %d" % n)
|
||||
return self.items[n]
|
||||
|
||||
def OnGetSize(self):
|
||||
print "getsize"
|
||||
return len(self.items)
|
||||
n = len(self.items)
|
||||
print("getsize -> %d" % n)
|
||||
return n
|
||||
|
||||
def OnDeleteLine(self, n):
|
||||
print "del ",str(n)
|
||||
print("del %d " % n)
|
||||
del self.items[n]
|
||||
return n
|
||||
|
||||
def OnRefresh(self, n):
|
||||
print "refresh", n
|
||||
print("refresh %d" % n)
|
||||
return n
|
||||
|
||||
def OnCommand(self, n, cmd_id):
|
||||
@ -73,7 +74,7 @@ class MyChoose2(Choose2):
|
||||
return r
|
||||
|
||||
def OnGetLineAttr(self, n):
|
||||
print "getlineattr", n
|
||||
print("getlineattr %d" % n)
|
||||
if n == 1:
|
||||
return [0xFF0000, 0]
|
||||
|
||||
@ -81,4 +82,3 @@ for i in xrange(1, 5+1):
|
||||
c = MyChoose2("choose2 - sample %d" % i, i*2)
|
||||
r = c.show()
|
||||
print r
|
||||
|
@ -1,6 +1,9 @@
|
||||
import idautils
|
||||
|
||||
s = Strings(False)
|
||||
s = idautils.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))
|
||||
for i, v in enumerate(s):
|
||||
if v is None:
|
||||
print("Failed to retrieve string index %d" % i)
|
||||
else:
|
||||
print("%x: len=%d type=%d index=%d-> '%s'" % (v.ea, v.length, v.type, i, str(v)))
|
||||
|
42
examples/ex_uihook.py
Normal file
42
examples/ex_uihook.py
Normal file
@ -0,0 +1,42 @@
|
||||
#---------------------------------------------------------------------
|
||||
# UI hook example
|
||||
#
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
# Maintained By: IDAPython Team
|
||||
#
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
import idaapi
|
||||
|
||||
class MyUiHook(idaapi.UI_Hooks):
|
||||
def __init__(self):
|
||||
idaapi.UI_Hooks.__init__(self)
|
||||
self.cmdname = "<no command>"
|
||||
|
||||
def preprocess(self, name):
|
||||
print("IDA preprocessing command: %s" % name)
|
||||
self.cmdname = name
|
||||
return 0
|
||||
|
||||
def postprocess(self):
|
||||
print("IDA finished processing command: %s" % self.cmdname)
|
||||
return 0
|
||||
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# Remove an existing hook on second run
|
||||
try:
|
||||
ui_hook_stat = "un"
|
||||
print("UI hook: checking for hook...")
|
||||
uihook
|
||||
print("UI hook: unhooking....")
|
||||
uihook.unhook()
|
||||
del uihook
|
||||
except:
|
||||
print("UI hook: not installed, installing now....")
|
||||
ui_hook_stat = ""
|
||||
uihook = MyUiHook()
|
||||
uihook.hook()
|
||||
|
||||
print("UI hook %sinstalled. Run the script again to %sinstall" % (ui_hook_stat, ui_hook_stat))
|
180
python.cpp
180
python.cpp
@ -49,10 +49,10 @@
|
||||
#define IDAPYTHON_DISABLE_EXTLANG 4
|
||||
#define PYTHON_DIR_NAME "python"
|
||||
#define S_IDAPYTHON "IDAPython"
|
||||
#define S_INIT_PY "init.py"
|
||||
static const char S_IDC_ARGS_VARNAME[] = "ARGV";
|
||||
static const char S_MAIN[] = "__main__";
|
||||
static const char S_IDC_RUNPYTHON_STATEMENT[] = "RunPythonStatement";
|
||||
static const char S_HOTKEY_RUNSTATEMENT[] = "Ctrl-F3";
|
||||
static const char S_IDAPYTHON_DATA_NODE[] = "IDAPython_Data";
|
||||
|
||||
#ifdef PLUGINFIX
|
||||
@ -79,6 +79,7 @@ static bool g_menu_installed = false;
|
||||
static int g_run_when = -1;
|
||||
static char g_run_script[QMAXPATH];
|
||||
static char g_idapython_dir[QMAXPATH];
|
||||
static char g_runstmt_hotkey[30] = "Ctrl-F3";
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Prototypes and forward declarations
|
||||
@ -124,6 +125,9 @@ static bool box_displayed; // has the wait box been displayed?
|
||||
static time_t start_time; // the start time of the execution
|
||||
static int script_timeout = 2;
|
||||
static bool g_ui_ready = false;
|
||||
static bool g_alert_auto_scripts = true;
|
||||
static bool g_remove_cwd_sys_path = false;
|
||||
|
||||
void end_execution();
|
||||
void begin_execution();
|
||||
|
||||
@ -133,14 +137,15 @@ static int break_check(PyObject *obj, _frame *frame, int what, PyObject *arg)
|
||||
{
|
||||
if ( wasBreak() )
|
||||
{
|
||||
/* User pressed Cancel in the waitbox; send KeyboardInterrupt exception */
|
||||
// User pressed Cancel in the waitbox; send KeyboardInterrupt exception
|
||||
PyErr_SetInterrupt();
|
||||
}
|
||||
else if ( !box_displayed && ++ninsns > 10 )
|
||||
{
|
||||
/* We check the timer once every 10 calls */
|
||||
// We check the timer once every 10 calls
|
||||
ninsns = 0;
|
||||
if ( script_timeout != 0 && (time(NULL) - start_time > script_timeout) ) /* Timeout elapsed? */
|
||||
// Timeout disabled or elapsed?
|
||||
if ( script_timeout != 0 && (time(NULL) - start_time > script_timeout) )
|
||||
{
|
||||
box_displayed = true;
|
||||
show_wait_box("Running Python script");
|
||||
@ -323,13 +328,13 @@ static void handle_python_error(char *errbuf, size_t errbufsize)
|
||||
static PyObject *GetMainGlobals()
|
||||
{
|
||||
PyObject *module = PyImport_AddModule(S_MAIN);
|
||||
if ( module == NULL )
|
||||
return NULL;
|
||||
return PyModule_GetDict(module);
|
||||
return module == NULL ? NULL : PyModule_GetDict(module);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static void PythonEvalOrExec(const char *str, const char *filename = "<string>")
|
||||
static void PythonEvalOrExec(
|
||||
const char *str,
|
||||
const char *filename = "<string>")
|
||||
{
|
||||
// Compile as an expression
|
||||
PyCompilerFlags cf = {0};
|
||||
@ -345,11 +350,12 @@ static void PythonEvalOrExec(const char *str, const char *filename = "<string>")
|
||||
}
|
||||
|
||||
PyObject *py_globals = GetMainGlobals();
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_result = PyEval_EvalCode(
|
||||
(PyCodeObject *) py_code,
|
||||
py_globals,
|
||||
py_globals);
|
||||
|
||||
PYW_GIL_RELEASE;
|
||||
Py_DECREF(py_code);
|
||||
|
||||
if ( py_result == NULL || PyErr_Occurred() )
|
||||
@ -379,7 +385,13 @@ static error_t idaapi idc_runpythonstatement(idc_value_t *argv, idc_value_t *res
|
||||
PyErr_Clear();
|
||||
|
||||
begin_execution();
|
||||
PyObject *result = PyRun_String(argv[0].c_str(), Py_file_input, globals, globals );
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *result = PyRun_String(
|
||||
argv[0].c_str(),
|
||||
Py_file_input,
|
||||
globals,
|
||||
globals);
|
||||
PYW_GIL_RELEASE;
|
||||
Py_XDECREF(result);
|
||||
end_execution();
|
||||
|
||||
@ -401,6 +413,45 @@ static error_t idaapi idc_runpythonstatement(idc_value_t *argv, idc_value_t *res
|
||||
return eOk;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
const char *idaapi set_python_options(
|
||||
const char *keyword,
|
||||
int value_type,
|
||||
const void *value)
|
||||
{
|
||||
do
|
||||
{
|
||||
if ( value_type == IDPOPT_STR )
|
||||
{
|
||||
if ( qstrcmp(keyword, "EXEC_STATEMENT_HOTKEY" ) == 0 )
|
||||
{
|
||||
qstrncpy(g_runstmt_hotkey, (const char *)value, sizeof(g_runstmt_hotkey));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ( value_type == IDPOPT_NUM )
|
||||
{
|
||||
if ( qstrcmp(keyword, "SCRIPT_TIMEOUT") == 0 )
|
||||
{
|
||||
script_timeout = int(*(uval_t *)value);
|
||||
break;
|
||||
}
|
||||
else if ( qstrcmp(keyword, "ALERT_AUTO_SCRIPTS") == 0 )
|
||||
{
|
||||
g_alert_auto_scripts = *(uval_t *)value != 0;
|
||||
break;
|
||||
}
|
||||
else if ( qstrcmp(keyword, "REMOVE_CWD_SYS_PATH") == 0 )
|
||||
{
|
||||
g_remove_cwd_sys_path = *(uval_t *)value != 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return IDPOPT_BADKEY;
|
||||
} while (false);
|
||||
return IDPOPT_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Check for the presence of a file in IDADIR/python and complain on error
|
||||
bool CheckScriptFiles()
|
||||
@ -408,7 +459,7 @@ bool CheckScriptFiles()
|
||||
static const char *const script_files[] =
|
||||
{
|
||||
S_IDC_MODNAME ".py",
|
||||
"init.py",
|
||||
S_INIT_PY,
|
||||
"idaapi.py",
|
||||
"idautils.py"
|
||||
};
|
||||
@ -439,9 +490,19 @@ static int PyRunFile(const char *FileName)
|
||||
return 0;
|
||||
}
|
||||
PyErr_Clear();
|
||||
PyObject *result = PyRun_File(PyFile_AsFile(PyFileObject), FileName, Py_file_input, globals, globals);
|
||||
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *result = PyRun_File(
|
||||
PyFile_AsFile(PyFileObject),
|
||||
FileName,
|
||||
Py_file_input,
|
||||
globals,
|
||||
globals);
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
Py_XDECREF(PyFileObject);
|
||||
Py_XDECREF(result);
|
||||
|
||||
return result != NULL && !PyErr_Occurred();
|
||||
}
|
||||
|
||||
@ -461,7 +522,7 @@ void IDAPython_RunStatement(void)
|
||||
if ( history.getblob(statement, &statement_size, 0, 'A') == NULL )
|
||||
statement[0] = '\0';
|
||||
|
||||
if ( asktext(sizeof(statement), statement, statement, "Enter Python expressions") != NULL )
|
||||
if ( asktext(sizeof(statement), statement, statement, "ACCEPT TABS\nEnter Python expressions") != NULL )
|
||||
{
|
||||
begin_execution();
|
||||
PyRun_SimpleString(statement);
|
||||
@ -489,7 +550,13 @@ static bool IDAPython_ExecFile(const char *FileName, char *errbuf, size_t errbuf
|
||||
strrpl(script, '\\', '//');
|
||||
|
||||
PyObject *py_script = PyString_FromString(script);
|
||||
PyObject *py_ret = PyObject_CallFunctionObjArgs(py_execscript, py_script, GetMainGlobals(), NULL);
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_ret = PyObject_CallFunctionObjArgs(
|
||||
py_execscript,
|
||||
py_script,
|
||||
GetMainGlobals(),
|
||||
NULL);
|
||||
PYW_GIL_RELEASE;
|
||||
Py_DECREF(py_script);
|
||||
Py_DECREF(py_execscript);
|
||||
|
||||
@ -516,7 +583,7 @@ static bool IDAPython_ExecFile(const char *FileName, char *errbuf, size_t errbuf
|
||||
}
|
||||
// Cannot be otherwise!
|
||||
else
|
||||
INTERR();
|
||||
INTERR(30154);
|
||||
|
||||
Py_XDECREF(py_ret);
|
||||
return ok;
|
||||
@ -527,10 +594,12 @@ static bool IDAPython_ExecFile(const char *FileName, char *errbuf, size_t errbuf
|
||||
static bool RunScript(const char *script)
|
||||
{
|
||||
begin_execution();
|
||||
|
||||
char errbuf[MAXSTR];
|
||||
bool ok = IDAPython_ExecFile(script, errbuf, sizeof(errbuf));
|
||||
if ( !ok )
|
||||
warning("IDAPython: error executing '%s':\n%s", script, errbuf);
|
||||
|
||||
end_execution();
|
||||
return ok;
|
||||
}
|
||||
@ -612,7 +681,6 @@ bool idaapi IDAPython_extlang_compile(
|
||||
size_t errbufsize)
|
||||
{
|
||||
PyObject *globals = GetMainGlobals();
|
||||
QASSERT(globals != NULL);
|
||||
|
||||
PyCodeObject *code = (PyCodeObject *)Py_CompileString(expr, "<string>", Py_eval_input);
|
||||
if ( code == NULL )
|
||||
@ -621,11 +689,11 @@ bool idaapi IDAPython_extlang_compile(
|
||||
return false;
|
||||
}
|
||||
|
||||
// set the desired function name
|
||||
// Set the desired function name
|
||||
Py_XDECREF(code->co_name);
|
||||
code->co_name = PyString_FromString(name);
|
||||
|
||||
// create a function out of code
|
||||
// Create a function out of code
|
||||
PyObject *func = PyFunction_New((PyObject *)code, globals);
|
||||
|
||||
if ( func == NULL )
|
||||
@ -672,16 +740,18 @@ bool idaapi IDAPython_extlang_run(
|
||||
|
||||
if ( imported_module )
|
||||
{
|
||||
PYW_GIL_ENSURE;
|
||||
module = PyImport_ImportModule(modname);
|
||||
PYW_GIL_RELEASE;
|
||||
}
|
||||
else
|
||||
{
|
||||
module = PyImport_AddModule(S_MAIN);
|
||||
QASSERT(module != NULL);
|
||||
QASSERT(30156, module != NULL);
|
||||
}
|
||||
|
||||
PyObject *globals = PyModule_GetDict(module);
|
||||
QASSERT(globals != NULL);
|
||||
QASSERT(30157, globals != NULL);
|
||||
|
||||
PyObject *func = PyDict_GetItemString(globals, funcname);
|
||||
if ( func == NULL )
|
||||
@ -692,12 +762,13 @@ bool idaapi IDAPython_extlang_run(
|
||||
}
|
||||
|
||||
PyCodeObject *code = (PyCodeObject *) PyFunction_GetCode(func);
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *pres = PyEval_EvalCodeEx(
|
||||
code,
|
||||
globals, NULL,
|
||||
&pargs[0], nargs,
|
||||
NULL, 0, NULL, 0, NULL);
|
||||
|
||||
PYW_GIL_RELEASE;
|
||||
ok = return_python_result(result, pres, errbuf, errbufsize);
|
||||
} while ( false );
|
||||
|
||||
@ -766,7 +837,9 @@ bool idaapi IDAPython_extlang_create_object(
|
||||
ok = false;
|
||||
|
||||
// Call the constructor
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_res = PyObject_CallObject(py_cls, pargs.empty() ? NULL : pargs[0]);
|
||||
PYW_GIL_RELEASE;
|
||||
ok = return_python_result(result, py_res, errbuf, errbufsize);
|
||||
} while ( false );
|
||||
|
||||
@ -944,7 +1017,9 @@ bool idaapi IDAPython_extlang_calcexpr(
|
||||
return false;
|
||||
|
||||
begin_execution();
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *result = PyRun_String(expr, Py_eval_input, globals, globals);
|
||||
PYW_GIL_RELEASE;
|
||||
end_execution();
|
||||
|
||||
return return_python_result(rv, result, errbuf, errbufsize);
|
||||
@ -998,7 +1073,9 @@ bool idaapi IDAPython_extlang_call_method(
|
||||
if ( !ok )
|
||||
break;
|
||||
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_res = PyObject_CallObject(py_method, pargs.empty() ? NULL : pargs[0]);
|
||||
PYW_GIL_RELEASE;
|
||||
ok = return_python_result(result, py_res, errbuf, errbufsize);
|
||||
} while ( false );
|
||||
|
||||
@ -1030,6 +1107,7 @@ extlang_t extlang_python =
|
||||
IDAPython_extlang_call_method
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void enable_extlang_python(bool enable)
|
||||
{
|
||||
if ( enable )
|
||||
@ -1042,7 +1120,7 @@ void enable_extlang_python(bool enable)
|
||||
// Execute a line in the Python CLI
|
||||
bool idaapi IDAPython_cli_execute_line(const char *line)
|
||||
{
|
||||
// do not process empty lines
|
||||
// Do not process empty lines
|
||||
if ( line[0] == '\0' )
|
||||
return true;
|
||||
|
||||
@ -1052,11 +1130,11 @@ bool idaapi IDAPython_cli_execute_line(const char *line)
|
||||
else
|
||||
last_line += 1;
|
||||
|
||||
// skip empty lines
|
||||
// Skip empty lines
|
||||
if ( last_line[0] != '\0' )
|
||||
{
|
||||
// line ends with ":" or begins with a space character?
|
||||
bool more = last_line[qstrlen(last_line)-1] == ':' || isspace(last_line[0]);
|
||||
// Line ends with ":" or begins with a space character?
|
||||
bool more = last_line[qstrlen(last_line)-1] == ':' || qisspace(last_line[0]);
|
||||
if ( more )
|
||||
return false;
|
||||
}
|
||||
@ -1080,7 +1158,9 @@ bool idaapi IDAPYthon_cli_complete_line(
|
||||
if ( py_complete == NULL )
|
||||
return false;
|
||||
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_ret = PyObject_CallFunction(py_complete, "sisi", prefix, n, line, x);
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
Py_DECREF(py_complete);
|
||||
|
||||
@ -1124,7 +1204,9 @@ void enable_python_cli(bool enable)
|
||||
// Prints the IDAPython copyright banner
|
||||
void py_print_banner()
|
||||
{
|
||||
PYW_GIL_ENSURE;
|
||||
PyRun_SimpleString("print_banner()");
|
||||
PYW_GIL_RELEASE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@ -1136,8 +1218,11 @@ static void install_python_menus()
|
||||
|
||||
// Add menu items for all the functions
|
||||
// Note: Different paths are used for the GUI version
|
||||
add_menu_item("File/IDC command...", "P~y~thon command...",
|
||||
S_HOTKEY_RUNSTATEMENT, SETMENU_APP,
|
||||
add_menu_item(
|
||||
"File/IDC command...",
|
||||
"P~y~thon command...",
|
||||
g_runstmt_hotkey,
|
||||
SETMENU_APP,
|
||||
IDAPython_Menu_Callback,
|
||||
(void *)IDAPYTHON_RUNSTATEMENT);
|
||||
|
||||
@ -1277,6 +1362,19 @@ bool IDAPython_Init(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Read configuration value
|
||||
read_user_config_file("python.cfg", set_python_options, NULL);
|
||||
if ( g_alert_auto_scripts )
|
||||
{
|
||||
const char *autofn = pywraps_check_autoscripts();
|
||||
if ( autofn != NULL
|
||||
&& askyn_c(0, "HIDECANCEL\nTITLE IDAPython\nThe script '%s' was found in the current directory and will be automatically executed by Python.\n\n"
|
||||
"Do you want to continue loading IDAPython?", autofn) == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Start the interpreter
|
||||
Py_Initialize();
|
||||
if ( !Py_IsInitialized() )
|
||||
@ -1285,16 +1383,22 @@ bool IDAPython_Init(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enable multi-threading support
|
||||
if ( !PyEval_ThreadsInitialized() )
|
||||
PyEval_InitThreads();
|
||||
|
||||
// Init the SWIG wrapper
|
||||
init_idaapi();
|
||||
|
||||
// Set IDAPYTHON_VERSION in Python
|
||||
qsnprintf(tmp, sizeof(tmp), "IDAPYTHON_VERSION=(%d, %d, %d, '%s', %d)", \
|
||||
qsnprintf(tmp, sizeof(tmp), "IDAPYTHON_VERSION=(%d, %d, %d, '%s', %d)\n"
|
||||
"IDAPYTHON_REMOVE_CWD_SYS_PATH = %s\n",
|
||||
VER_MAJOR,
|
||||
VER_MINOR,
|
||||
VER_PATCH,
|
||||
VER_STATUS,
|
||||
VER_SERIAL);
|
||||
VER_SERIAL,
|
||||
g_remove_cwd_sys_path ? "True" : "False");
|
||||
PyRun_SimpleString(tmp);
|
||||
|
||||
// Install extlang. Needs to be done before running init.py
|
||||
@ -1302,11 +1406,11 @@ bool IDAPython_Init(void)
|
||||
install_extlang(&extlang_python);
|
||||
|
||||
// Execute init.py (for Python side initialization)
|
||||
qmakepath(tmp, MAXSTR, g_idapython_dir, "init.py", NULL);
|
||||
qmakepath(tmp, MAXSTR, g_idapython_dir, S_INIT_PY, NULL);
|
||||
if ( !PyRunFile(tmp) )
|
||||
{
|
||||
handle_python_error(tmp, sizeof(tmp));
|
||||
warning("IDAPython: error executing init.py:\n%s", tmp);
|
||||
warning("IDAPython: error executing " S_INIT_PY ":\n%s", tmp);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1357,18 +1461,18 @@ void IDAPython_Term(void)
|
||||
del_menu_item("File/Python command...");
|
||||
g_menu_installed = false;
|
||||
|
||||
// Remove the CLI
|
||||
enable_python_cli(false);
|
||||
|
||||
// Remove the extlang
|
||||
remove_extlang(&extlang_python);
|
||||
|
||||
// Notify about IDA closing
|
||||
pywraps_nw_notify(NW_TERMIDA_SLOT);
|
||||
|
||||
// De-init notify_when
|
||||
pywraps_nw_term();
|
||||
|
||||
// Remove the CLI
|
||||
enable_python_cli(false);
|
||||
|
||||
// Remove the extlang
|
||||
remove_extlang(&extlang_python);
|
||||
|
||||
// De-init pywraps
|
||||
deinit_pywraps();
|
||||
|
||||
@ -1446,5 +1550,5 @@ plugin_t PLUGIN =
|
||||
// the preferred short name of the plugin
|
||||
S_IDAPYTHON,
|
||||
// the preferred hotkey to run the plugin
|
||||
S_HOTKEY_RUNSTATEMENT
|
||||
NULL
|
||||
};
|
||||
|
@ -310,6 +310,37 @@ def FuncItems(start):
|
||||
ok = fii.next_code()
|
||||
|
||||
|
||||
|
||||
def DecodePrecedingInstruction(ea):
|
||||
"""
|
||||
Decode preceding instruction in the execution flow.
|
||||
|
||||
@param ea: address to decode
|
||||
@return: (None or the decode instruction, farref)
|
||||
farref will contain 'true' if followed an xref, false otherwise
|
||||
"""
|
||||
prev_addr, farref = idaapi.decode_preceding_insn(ea)
|
||||
if prev_addr == idaapi.BADADDR:
|
||||
return (None, False)
|
||||
else:
|
||||
return (idaapi.cmd.copy(), farref)
|
||||
|
||||
|
||||
|
||||
def DecodePreviousInstruction(ea):
|
||||
"""
|
||||
Decodes the previous instruction and returns an insn_t like class
|
||||
|
||||
@param ea: address to decode
|
||||
@return: None or a new insn_t instance
|
||||
"""
|
||||
inslen = idaapi.decode_prev_insn(ea)
|
||||
if inslen == 0:
|
||||
return None
|
||||
|
||||
return idaapi.cmd.copy()
|
||||
|
||||
|
||||
def DecodeInstruction(ea):
|
||||
"""
|
||||
Decodes an instruction and returns an insn_t like class
|
||||
@ -434,6 +465,7 @@ class Strings(object):
|
||||
"""Clears the strings list cache"""
|
||||
self.refresh(0, 0) # when ea1=ea2 the kernel will clear the cache
|
||||
|
||||
|
||||
def __init__(self, default_setup = True):
|
||||
"""
|
||||
Initializes the Strings enumeration helper class
|
||||
@ -446,6 +478,7 @@ class Strings(object):
|
||||
|
||||
self._si = idaapi.string_info_t()
|
||||
|
||||
|
||||
def refresh(self, ea1=None, ea2=None):
|
||||
"""Refreshes the strings list"""
|
||||
if ea1 is None:
|
||||
@ -456,6 +489,7 @@ class Strings(object):
|
||||
idaapi.refresh_strlist(ea1, ea2)
|
||||
self.size = idaapi.get_strlist_qty()
|
||||
|
||||
|
||||
def setup(self,
|
||||
strtypes = STR_C,
|
||||
minlen = 5,
|
||||
@ -483,15 +517,24 @@ class Strings(object):
|
||||
# Automatically refreshes
|
||||
self.refresh()
|
||||
|
||||
|
||||
def _get_item(self, index):
|
||||
if not idaapi.get_strlist_item(index, self._si):
|
||||
return None
|
||||
else:
|
||||
return Strings.StringItem(self._si)
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
return (self._get_item(index) for index in xrange(0, self.size))
|
||||
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Returns a string item or None"""
|
||||
if index >= self.size:
|
||||
raise StopIteration
|
||||
|
||||
if idaapi.get_strlist_item(index, self._si):
|
||||
return Strings.StringItem(self._si)
|
||||
|
||||
return None
|
||||
raise KeyError
|
||||
else:
|
||||
return self._get_item(index)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def GetIdbDir():
|
||||
@ -646,6 +689,12 @@ class peutils_t(object):
|
||||
def __str__(self):
|
||||
return "peutils_t(imagebase=%s, header=%s)" % (hex(self.imagebase), hex(self.header))
|
||||
|
||||
def header(self):
|
||||
"""
|
||||
Returns the complete PE header as an instance of peheader_t (defined in the SDK).
|
||||
"""
|
||||
return self.__penode.valobj()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
cpu = _cpu()
|
||||
"""This is a special class instance used to access the registers as if they were attributes of this object.
|
||||
|
@ -702,7 +702,7 @@ def MakeStr(ea, endea):
|
||||
|
||||
@note: The type of an existing string is returned by GetStringType()
|
||||
"""
|
||||
return idaapi.make_ascii_string(ea, endea - ea, GetLongPrm(INF_STRTYPE))
|
||||
return idaapi.make_ascii_string(ea, 0 if endea == BADADDR else endea - ea, GetLongPrm(INF_STRTYPE))
|
||||
|
||||
|
||||
def MakeData(ea, flags, size, tid):
|
||||
@ -1710,7 +1710,7 @@ def Byte(ea):
|
||||
might have more 1's.
|
||||
To check if a byte has a value, use functions hasValue(GetFlags(ea))
|
||||
"""
|
||||
return idaapi.get_byte(ea)
|
||||
return idaapi.get_full_byte(ea)
|
||||
|
||||
|
||||
def __DbgValue(ea, len):
|
||||
@ -1781,7 +1781,7 @@ def Word(ea):
|
||||
If the current byte size is different from 8 bits, then the returned value
|
||||
might have more 1's.
|
||||
"""
|
||||
return idaapi.get_word(ea)
|
||||
return idaapi.get_full_word(ea)
|
||||
|
||||
|
||||
def Dword(ea):
|
||||
@ -1792,7 +1792,7 @@ def Dword(ea):
|
||||
|
||||
@return: the value of the double word. If failed returns -1
|
||||
"""
|
||||
return idaapi.get_long(ea)
|
||||
return idaapi.get_full_long(ea)
|
||||
|
||||
|
||||
def Qword(ea):
|
||||
@ -1802,10 +1802,8 @@ def Qword(ea):
|
||||
@param ea: linear address
|
||||
|
||||
@return: the value of the quadro word. If failed, returns -1
|
||||
|
||||
@note: this function is available only in the 64-bit version of IDA Pro
|
||||
"""
|
||||
raise NotImplementedError, "will be implemented in the 64-bit version"
|
||||
return idaapi.get_qword(ea)
|
||||
|
||||
|
||||
def GetFloat(ea):
|
||||
@ -1839,7 +1837,7 @@ def LocByName(name):
|
||||
@param name: name of program byte
|
||||
|
||||
@return: address of the name
|
||||
badaddr - no such name
|
||||
BADADDR - No such name
|
||||
"""
|
||||
return idaapi.get_name_ea(BADADDR, name)
|
||||
|
||||
@ -1964,7 +1962,7 @@ def PrevAddr(ea):
|
||||
return idaapi.prevaddr(ea)
|
||||
|
||||
|
||||
def NextHead(ea, maxea):
|
||||
def NextHead(ea, maxea=BADADDR):
|
||||
"""
|
||||
Get next defined item (instruction or data) in the program
|
||||
|
||||
@ -1977,7 +1975,7 @@ def NextHead(ea, maxea):
|
||||
return idaapi.next_head(ea, maxea)
|
||||
|
||||
|
||||
def PrevHead(ea, minea):
|
||||
def PrevHead(ea, minea=0):
|
||||
"""
|
||||
Get previous defined item (instruction or data) in the program
|
||||
|
||||
@ -2938,6 +2936,17 @@ def AskLong(defval, prompt):
|
||||
return idaapi.asklong(defval, prompt)
|
||||
|
||||
|
||||
def ProcessUiAction(name, flags=0):
|
||||
"""
|
||||
Invokes an IDA Pro UI action by name
|
||||
|
||||
@param name: Command name
|
||||
@param flags: Reserved. Must be zero
|
||||
@return: Boolean
|
||||
"""
|
||||
return idaapi.process_ui_action(name, flags)
|
||||
|
||||
|
||||
def AskSeg(defval, prompt):
|
||||
"""
|
||||
Ask the user to enter a segment value
|
||||
@ -3374,7 +3383,7 @@ def SegByName(segname):
|
||||
if not seg:
|
||||
return BADADDR
|
||||
|
||||
return seg.startEA
|
||||
return seg.sel
|
||||
|
||||
|
||||
def SetSegDefReg(ea, reg, value):
|
||||
@ -6258,14 +6267,14 @@ def ParseType(inputtype, flags):
|
||||
"""
|
||||
return idaapi.idc_parse_decl(idaapi.cvar.idati, inputtype, flags)
|
||||
|
||||
def ParseTypes(inputtype, flags):
|
||||
def ParseTypes(inputtype, flags = 0):
|
||||
"""
|
||||
Parse type declarations
|
||||
|
||||
@param inputtype: file name or C declarations (depending on the flags)
|
||||
@param flags: combination of PT_... constants or 0
|
||||
|
||||
@return: number of errors
|
||||
@return: number of parsing errors (0 no errors)
|
||||
"""
|
||||
return idaapi.idc_parse_types(inputtype, flags)
|
||||
|
||||
@ -6790,7 +6799,6 @@ def GetProcessState():
|
||||
"""
|
||||
return idaapi.get_process_state()
|
||||
|
||||
DSTATE_SUSP_FOR_EVENT = -2 # process is currently suspended to react to a debug event (not used)
|
||||
DSTATE_SUSP = -1 # process is suspended
|
||||
DSTATE_NOTASK = 0 # no process is currently debugged
|
||||
DSTATE_RUN = 1 # process is running
|
||||
@ -7109,7 +7117,7 @@ def GetRegValue(name):
|
||||
"""
|
||||
rv = idaapi.regval_t()
|
||||
res = idaapi.get_reg_val(name, rv)
|
||||
assert res, "get_reg_val() failed, bogus name perhaps?"
|
||||
assert res, "get_reg_val() failed, bogus register name ('%s') perhaps?" % name
|
||||
return rv.ival
|
||||
|
||||
|
||||
@ -7209,11 +7217,25 @@ BPTATTR_COUNT = 4
|
||||
BPTATTR_FLAGS = 5
|
||||
BPT_BRK = 0x01 # the debugger stops on this breakpoint
|
||||
BPT_TRACE = 0x02 # the debugger adds trace information when this breakpoint is reached
|
||||
BPT_UPDMEM = 0x04 # update memory contents before evaluating bpt condition
|
||||
BPT_UPDSEG = 0x08 # update memory config before evaluating bpt condition
|
||||
BPT_UPDMEM = 0x04 # refresh the memory layout and contents before evaluating bpt condition
|
||||
BPT_ENABLED = 0x08 # enabled?
|
||||
BPT_LOWCND = 0x10 # condition is calculated at low level (on the server side)
|
||||
|
||||
BPTATTR_COND = 6 # Breakpoint condition. NOTE: the return value is a string in this case
|
||||
|
||||
# Breakpoint location type:
|
||||
BPLT_ABS = 0 # Absolute address. Attributes:
|
||||
# - locinfo: absolute address
|
||||
|
||||
BPLT_REL = 1 # Module relative address. Attributes:
|
||||
# - locpath: the module path
|
||||
# - locinfo: offset from the module base address
|
||||
|
||||
BPLT_SYM = 2 # Symbolic name. The name will be resolved on DLL load/unload
|
||||
# events and on naming an address. Attributes:
|
||||
# - locpath: symbol name
|
||||
# - locinfo: offset from the symbol base address
|
||||
|
||||
|
||||
def SetBptAttr(address, bptattr, value):
|
||||
"""
|
||||
@ -7530,16 +7552,44 @@ def WriteTxt(filepath, ea1, ea2):
|
||||
def WriteExe(filepath):
|
||||
return GenerateFile(OFILE_EXE, filepath, 0, BADADDR, 0)
|
||||
|
||||
def AddConst(enum_id,name,value): return AddConstEx(enum_id,name,value, idaapi.BADADDR)
|
||||
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)
|
||||
|
||||
UTP_STRUCT = idaapi.UTP_STRUCT
|
||||
UTP_ENUM = idaapi.UTP_ENUM
|
||||
|
||||
|
||||
def BeginTypeUpdating(utp):
|
||||
"""
|
||||
Begin type updating. Use this function if you
|
||||
plan to call AddEnumConst or similar type modification functions
|
||||
many times or from inside a loop
|
||||
|
||||
@param utp: one of UTP_xxxx consts
|
||||
@return: None
|
||||
"""
|
||||
return idaapi.begin_type_updating(utp)
|
||||
|
||||
|
||||
def EndTypeUpdating(utp):
|
||||
"""
|
||||
End type updating. Refreshes the type system
|
||||
at the end of type modification operations
|
||||
|
||||
@param utp: one of idaapi.UTP_xxxx consts
|
||||
@return: None
|
||||
"""
|
||||
return idaapi.end_type_updating(utp)
|
||||
|
||||
|
||||
def AddConst(enum_id, name,value): return AddConstEx(enum_id, name, value, idaapi.BADADDR)
|
||||
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 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)
|
||||
|
@ -31,7 +31,7 @@ class IDAPythonStdOut:
|
||||
# Swap out the unprintable characters
|
||||
text = text.decode('ascii', 'replace').encode('ascii', 'replace')
|
||||
# Print to IDA message window
|
||||
_idaapi.msg(text.replace("%", "%%"))
|
||||
_idaapi.msg(text)
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
@ -61,9 +61,9 @@ def print_banner():
|
||||
]
|
||||
sepline = '-' * (max([len(s) for s in banner])+1)
|
||||
|
||||
print sepline
|
||||
print "\n".join(banner)
|
||||
print sepline
|
||||
print(sepline)
|
||||
print("\n".join(banner))
|
||||
print(sepline)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
@ -76,8 +76,19 @@ sys.argv = [""]
|
||||
# Have to make sure Python finds our modules
|
||||
sys.path.append(_idaapi.idadir("python"))
|
||||
|
||||
# Remove current directory from the top of the patch search
|
||||
if '' in sys.path: # On non Windows, the empty path is added
|
||||
sys.path.remove('')
|
||||
|
||||
if os.getcwd() in sys.path:
|
||||
sys.path.remove(os.getcwd())
|
||||
|
||||
# ...and add it to the end if needed
|
||||
if not IDAPYTHON_REMOVE_CWD_SYS_PATH:
|
||||
sys.path.append(os.getcwd())
|
||||
|
||||
# Import all the required modules
|
||||
from idaapi import Choose, get_user_idadir, cvar, Choose2, Appcall
|
||||
from idaapi import Choose, get_user_idadir, cvar, Choose2, Appcall, Form
|
||||
from idc import *
|
||||
from idautils import *
|
||||
import idaapi
|
||||
|
37
pywraps.hpp
37
pywraps.hpp
@ -5,6 +5,7 @@
|
||||
// Types
|
||||
#ifndef PYUL_DEFINED
|
||||
#define PYUL_DEFINED
|
||||
typedef unsigned PY_LONG_LONG PY_ULONG_LONG;
|
||||
#ifdef __EA64__
|
||||
typedef unsigned PY_LONG_LONG pyul_t;
|
||||
typedef PY_LONG_LONG pyl_t;
|
||||
@ -56,6 +57,31 @@ typedef qvector<PyObject *> ppyobject_vec_t;
|
||||
#define CIP_OK 1 // Success
|
||||
#define CIP_OK_NODECREF 2 // Success but do not decrement its reference
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
class CGilStateAuto
|
||||
{
|
||||
private:
|
||||
PyGILState_STATE state;
|
||||
public:
|
||||
CGilStateAuto()
|
||||
{
|
||||
state = PyGILState_Ensure();
|
||||
}
|
||||
|
||||
~CGilStateAuto()
|
||||
{
|
||||
PyGILState_Release(state);
|
||||
}
|
||||
};
|
||||
// Declare a variable to acquire/release the GIL
|
||||
#define PYW_GIL_AUTO_ENSURE CGilStateAuto GIL_STATE_AUTO
|
||||
|
||||
// Macros to acquire/release GIL in a given scope
|
||||
#define PYW_GIL_ENSURE_N(name) PyGILState_STATE gil_state##name = PyGILState_Ensure()
|
||||
#define PYW_GIL_RELEASE_N(name) PyGILState_Release(gil_state##name)
|
||||
|
||||
#define PYW_GIL_ENSURE PYW_GIL_ENSURE_N(_)
|
||||
#define PYW_GIL_RELEASE PYW_GIL_RELEASE_N(_)
|
||||
//------------------------------------------------------------------------
|
||||
// All the exported functions from PyWraps are forward declared here
|
||||
insn_t *insn_t_get_clink(PyObject *self);
|
||||
@ -86,7 +112,8 @@ bool PyW_IsSequenceType(PyObject *obj);
|
||||
bool PyW_GetError(qstring *out = NULL);
|
||||
|
||||
// If an error occured (it calls PyGetError) it displays it and return TRUE
|
||||
bool PyW_ShowErr(const char *cb_name);
|
||||
// This function is used when calling callbacks
|
||||
bool PyW_ShowCbErr(const char *cb_name);
|
||||
|
||||
// Utility function to create a class instance whose constructor takes zero arguments
|
||||
PyObject *create_idaapi_class_instance0(const char *clsname);
|
||||
@ -124,6 +151,12 @@ Py_ssize_t pyvar_walk_list(
|
||||
int (idaapi *cb)(PyObject *py_item, Py_ssize_t index, void *ud) = NULL,
|
||||
void *ud = NULL);
|
||||
|
||||
// Converts an intvec_t to a Python list object
|
||||
PyObject *PyW_IntVecToPyList(const intvec_t &intvec);
|
||||
|
||||
// Converts an Python list to an intvec
|
||||
void PyW_PyListToIntVec(PyObject *py_list, intvec_t &intvec);
|
||||
|
||||
// Returns a reference to a class
|
||||
PyObject *get_idaapi_attr(const char *attr);
|
||||
|
||||
@ -132,4 +165,6 @@ bool pywraps_nw_term();
|
||||
bool pywraps_nw_notify(int slot, ...);
|
||||
bool pywraps_nw_init();
|
||||
|
||||
const char *pywraps_check_autoscripts();
|
||||
|
||||
#endif
|
63
swig/bytes.i
63
swig/bytes.i
@ -101,7 +101,9 @@
|
||||
static bool idaapi py_testf_cb(flags_t flags, void *ud)
|
||||
{
|
||||
PyObject *py_flags = PyLong_FromUnsignedLong(flags);
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *result = PyObject_CallFunctionObjArgs((PyObject *) ud, py_flags, NULL);
|
||||
PYW_GIL_RELEASE;
|
||||
bool ret = result != NULL && PyObject_IsTrue(result);
|
||||
Py_XDECREF(result);
|
||||
Py_XDECREF(py_flags);
|
||||
@ -114,6 +116,7 @@ static ea_t py_npthat(ea_t ea, ea_t bound, PyObject *py_callable, bool next)
|
||||
{
|
||||
if ( !PyCallable_Check(py_callable) )
|
||||
return BADADDR;
|
||||
else
|
||||
return (next ? nextthat : prevthat)(ea, bound, py_testf_cb, py_callable);
|
||||
}
|
||||
|
||||
@ -134,8 +137,17 @@ class py_custom_data_type_t
|
||||
size_t nbytes) // size of the future item
|
||||
{
|
||||
py_custom_data_type_t *_this = (py_custom_data_type_t *)ud;
|
||||
PyObject *py_result = PyObject_CallMethod(_this->py_self, (char *)S_MAY_CREATE_AT, PY_FMT64 PY_FMT64, pyul_t(ea), pyul_t(nbytes));
|
||||
PyW_ShowErr(S_MAY_CREATE_AT);
|
||||
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_result = PyObject_CallMethod(
|
||||
_this->py_self,
|
||||
(char *)S_MAY_CREATE_AT,
|
||||
PY_FMT64 PY_FMT64,
|
||||
pyul_t(ea),
|
||||
pyul_t(nbytes));
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
PyW_ShowCbErr(S_MAY_CREATE_AT);
|
||||
bool ok = py_result != NULL && PyObject_IsTrue(py_result);
|
||||
Py_XDECREF(py_result);
|
||||
return ok;
|
||||
@ -152,9 +164,18 @@ class py_custom_data_type_t
|
||||
// Returns: 0-no such item can be created/displayed
|
||||
// this callback is required only for varsize datatypes
|
||||
py_custom_data_type_t *_this = (py_custom_data_type_t *)ud;
|
||||
PyObject *py_result = PyObject_CallMethod(_this->py_self, (char *)S_CALC_ITEM_SIZE, PY_FMT64 PY_FMT64, pyul_t(ea), pyul_t(maxsize));
|
||||
if ( PyW_ShowErr(S_CALC_ITEM_SIZE) || py_result == NULL )
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_result = PyObject_CallMethod(
|
||||
_this->py_self,
|
||||
(char *)S_CALC_ITEM_SIZE,
|
||||
PY_FMT64 PY_FMT64,
|
||||
pyul_t(ea),
|
||||
pyul_t(maxsize));
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
if ( PyW_ShowCbErr(S_CALC_ITEM_SIZE) || py_result == NULL )
|
||||
return 0;
|
||||
|
||||
uint64 num = 0;
|
||||
PyW_GetNumber(py_result, &num);
|
||||
Py_XDECREF(py_result);
|
||||
@ -189,6 +210,7 @@ public:
|
||||
// name
|
||||
if ( !PyW_GetStringAttr(py_obj, S_NAME, &dt_name) )
|
||||
break;
|
||||
|
||||
dt.name = dt_name.c_str();
|
||||
|
||||
// menu_name (optional)
|
||||
@ -293,11 +315,14 @@ private:
|
||||
int dtid) // custom data type id
|
||||
{
|
||||
// Build a string from the buffer
|
||||
PyObject *py_value = PyString_FromStringAndSize((const char *)value, Py_ssize_t(size));
|
||||
PyObject *py_value = PyString_FromStringAndSize(
|
||||
(const char *)value,
|
||||
Py_ssize_t(size));
|
||||
if ( py_value == NULL )
|
||||
return false;
|
||||
|
||||
py_custom_data_format_t *_this = (py_custom_data_format_t *) ud;
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_result = PyObject_CallMethod(
|
||||
_this->py_self,
|
||||
(char *)S_PRINTF,
|
||||
@ -306,11 +331,12 @@ private:
|
||||
pyul_t(current_ea),
|
||||
operand_num,
|
||||
dtid);
|
||||
PYW_GIL_RELEASE;
|
||||
// Done with the string
|
||||
Py_DECREF(py_value);
|
||||
|
||||
// Error while calling the function?
|
||||
if ( PyW_ShowErr(S_PRINTF) || py_result == NULL )
|
||||
if ( PyW_ShowCbErr(S_PRINTF) || py_result == NULL )
|
||||
return false;
|
||||
|
||||
bool ok = false;
|
||||
@ -338,6 +364,7 @@ private:
|
||||
qstring *errstr) // buffer for error message
|
||||
{
|
||||
py_custom_data_format_t *_this = (py_custom_data_format_t *) ud;
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_result = PyObject_CallMethod(
|
||||
_this->py_self,
|
||||
(char *)S_SCAN,
|
||||
@ -345,9 +372,10 @@ private:
|
||||
input,
|
||||
pyul_t(current_ea),
|
||||
operand_num);
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
// Error while calling the function?
|
||||
if ( PyW_ShowErr(S_SCAN) || py_result == NULL)
|
||||
if ( PyW_ShowCbErr(S_SCAN) || py_result == NULL)
|
||||
return false;
|
||||
|
||||
bool ok = false;
|
||||
@ -356,6 +384,7 @@ private:
|
||||
// We expect a tuple(bool, string|None)
|
||||
if ( !PyTuple_Check(py_result) || PyTuple_Size(py_result) != 2 )
|
||||
break;
|
||||
|
||||
// Borrow references
|
||||
PyObject *py_bool = PyTuple_GetItem(py_result, 0);
|
||||
PyObject *py_val = PyTuple_GetItem(py_result, 1);
|
||||
@ -404,8 +433,17 @@ private:
|
||||
// this callback may be missing.
|
||||
{
|
||||
py_custom_data_format_t *_this = (py_custom_data_format_t *) ud;
|
||||
PyObject *py_result = PyObject_CallMethod(_this->py_self, (char *)S_ANALYZE, PY_FMT64 "i", pyul_t(current_ea),operand_num);
|
||||
PyW_ShowErr(S_ANALYZE);
|
||||
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_result = PyObject_CallMethod(
|
||||
_this->py_self,
|
||||
(char *)S_ANALYZE,
|
||||
PY_FMT64 "i",
|
||||
pyul_t(current_ea),
|
||||
operand_num);
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
PyW_ShowCbErr(S_ANALYZE);
|
||||
Py_XDECREF(py_result);
|
||||
}
|
||||
public:
|
||||
@ -415,7 +453,10 @@ public:
|
||||
py_self = NULL;
|
||||
}
|
||||
|
||||
const char *get_name() const { return df_name.c_str(); }
|
||||
const char *get_name() const
|
||||
{
|
||||
return df_name.c_str();
|
||||
}
|
||||
|
||||
int register_df(int dtid, PyObject *py_obj)
|
||||
{
|
||||
@ -491,9 +532,11 @@ public:
|
||||
Py_INCREF(py_obj);
|
||||
py_self = py_obj;
|
||||
|
||||
// Update the format ID
|
||||
py_attr = PyInt_FromLong(dfid);
|
||||
PyObject_SetAttrString(py_obj, S_ID, py_attr);
|
||||
Py_DECREF(py_attr);
|
||||
|
||||
py_attr = NULL;
|
||||
} while ( false );
|
||||
|
||||
|
10
swig/dbg.i
10
swig/dbg.i
@ -10,8 +10,14 @@ typedef struct
|
||||
%ignore source_file_t;
|
||||
%ignore source_item_t;
|
||||
%ignore srcinfo_provider_t;
|
||||
%ignore bpt_location_t::print;
|
||||
%ignore bpt_t::set_cond;
|
||||
%ignore bpt_t::eval_cond;
|
||||
%ignore bpt_t::write;
|
||||
%ignore bpt_t::erase;
|
||||
%rename (get_manual_regions) py_get_manual_regions;
|
||||
%ignore set_manual_regions;
|
||||
%ignore inform_idc_about_debthread;
|
||||
%include "dbg.hpp"
|
||||
%ignore DBG_Callback;
|
||||
%feature("director") DBG_Hooks;
|
||||
@ -75,8 +81,12 @@ static PyObject *refresh_debugger_memory()
|
||||
{
|
||||
invalidate_dbgmem_config();
|
||||
invalidate_dbgmem_contents(BADADDR, 0);
|
||||
|
||||
// Ask the debugger to populate debug names
|
||||
if ( dbg != NULL && dbg->stopped_at_debug_event != NULL )
|
||||
dbg->stopped_at_debug_event(true);
|
||||
|
||||
// Invalidate the cache
|
||||
isEnabled(0);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
|
@ -49,7 +49,12 @@
|
||||
int idaapi py_enumerate_files_cb(const char *file, void *ud)
|
||||
{
|
||||
PyObject *py_file = PyString_FromString(file);
|
||||
PyObject *py_ret = PyObject_CallFunctionObjArgs((PyObject *)ud, py_file, NULL);
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_ret = PyObject_CallFunctionObjArgs(
|
||||
(PyObject *)ud,
|
||||
py_file,
|
||||
NULL);
|
||||
PYW_GIL_RELEASE;
|
||||
int r = (py_ret == NULL || !PyNumber_Check(py_ret)) ? 1 /* stop enumeration on failure */ : PyInt_AsLong(py_ret);
|
||||
Py_XDECREF(py_file);
|
||||
Py_XDECREF(py_ret);
|
||||
|
13
swig/expr.i
13
swig/expr.i
@ -35,15 +35,17 @@
|
||||
%ignore expr_printf;
|
||||
%ignore expr_sprintf;
|
||||
%ignore expr_printfer;
|
||||
%ignore idaapi init_idc;
|
||||
%ignore idaapi term_idc;
|
||||
%ignore del_idc_userfuncs;
|
||||
%ignore del_idc_userdefs;
|
||||
%ignore init_idc;
|
||||
%ignore term_idc;
|
||||
%ignore create_default_idc_classes;
|
||||
%ignore insn_to_idc;
|
||||
%ignore find_builtin_idc_func;
|
||||
%ignore idc_mutex;
|
||||
%ignore idc_lx;
|
||||
%ignore idc_vars;
|
||||
%ignore idc_resolve_label;
|
||||
%ignore idc_resolver_ea;
|
||||
%ignore setup_lowcnd_regfuncs;
|
||||
|
||||
%cstring_output_maxstr_none(char *errbuf, size_t errbufsize);
|
||||
|
||||
@ -83,12 +85,13 @@ bool calc_idc_expr_wrap(ea_t where,const char *line, idc_value_t *rv, char *errb
|
||||
%}
|
||||
|
||||
%ignore CompileLine(const char *line, char *errbuf, size_t errbufsize, uval_t (idaapi*_getname)(const char *name)=NULL);
|
||||
%ignore CompileLineEx;
|
||||
|
||||
%rename (CompileLine) CompileLine_wrap;
|
||||
%inline %{
|
||||
bool CompileLine_wrap(const char *line, char *errbuf, size_t errbufsize)
|
||||
{
|
||||
return !CompileLine(line, errbuf, errbufsize);
|
||||
return !CompileLineEx(line, errbuf, errbufsize);
|
||||
}
|
||||
%}
|
||||
|
||||
|
32
swig/funcs.i
32
swig/funcs.i
@ -27,6 +27,7 @@
|
||||
%ignore create_func_eas_array;
|
||||
%ignore auto_add_func_tails;
|
||||
%ignore read_tails;
|
||||
%rename (get_idasgn_desc) py_get_idasgn_desc;
|
||||
|
||||
%include "funcs.hpp"
|
||||
|
||||
@ -34,18 +35,47 @@
|
||||
%clear(char *optlibs);
|
||||
|
||||
%inline %{
|
||||
//-----------------------------------------------------------------------
|
||||
/*
|
||||
#<pydoc>
|
||||
def get_fchunk_referer(ea, idx):
|
||||
pass
|
||||
#</pydoc>
|
||||
*/
|
||||
ea_t get_fchunk_referer(ea_t ea, size_t idx)
|
||||
static ea_t get_fchunk_referer(ea_t ea, size_t idx)
|
||||
{
|
||||
func_t *pfn = get_fchunk(ea);
|
||||
func_parent_iterator_t dummy(pfn); // read referer info
|
||||
if (idx >= pfn->refqty || pfn->referers == NULL)
|
||||
return BADADDR;
|
||||
else
|
||||
return pfn->referers[idx];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/*
|
||||
#<pydoc>
|
||||
def get_idasgn_desc(n):
|
||||
"""
|
||||
Get information about a signature in the list.
|
||||
It returns both:
|
||||
signame - the name of the signature
|
||||
optlibs - the names of the optional libraries
|
||||
|
||||
@param n: number of signature in the list (0..get_idasgn_qty()-1)
|
||||
@return: None on failure or tuple(signame, optlibs)
|
||||
"""
|
||||
#</pydoc>
|
||||
*/
|
||||
static PyObject *ida_export py_get_idasgn_desc(int n)
|
||||
{
|
||||
char signame[MAXSTR];
|
||||
char optlibs[MAXSTR];
|
||||
|
||||
if ( get_idasgn_desc(n, signame, sizeof(signame), optlibs, sizeof(optlibs)) == -1 )
|
||||
Py_RETURN_NONE;
|
||||
else
|
||||
return Py_BuildValue("(ss)", signame, optlibs);
|
||||
}
|
||||
|
||||
%}
|
||||
|
12
swig/gdl.i
12
swig/gdl.i
@ -91,6 +91,14 @@ class FlowChart(object):
|
||||
self._q.refresh()
|
||||
|
||||
|
||||
def _getitem(self, index):
|
||||
return BasicBlock(index, self._q[index], self)
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
return (self._getitem(index) for index in xrange(0, self.size))
|
||||
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""
|
||||
Returns a basic block
|
||||
@ -98,9 +106,9 @@ class FlowChart(object):
|
||||
@return: BasicBlock
|
||||
"""
|
||||
if index >= self.size:
|
||||
raise StopIteration
|
||||
raise KeyError
|
||||
else:
|
||||
return BasicBlock(index, self._q[index], self)
|
||||
return self._getitem(index)
|
||||
|
||||
#</pycode(py_gdl)>
|
||||
%}
|
||||
|
130
swig/graph.i
130
swig/graph.i
@ -2,26 +2,6 @@
|
||||
%ignore graph_visitor_t;
|
||||
%ignore abstract_graph_t;
|
||||
|
||||
%{
|
||||
#ifdef __GNUC__
|
||||
// for some reason GCC insists on putting the vtable into the object file,
|
||||
// even though we only use mutable_graph_t by pointer
|
||||
// so we define these methods here to make the linker happy
|
||||
|
||||
edge_info_t *idaapi mutable_graph_t::get_edge(edge_t e) { INTERR(); };
|
||||
mutable_graph_t *idaapi mutable_graph_t::clone(void) const { INTERR(); };
|
||||
bool idaapi mutable_graph_t::redo_layout(void) { INTERR(); };
|
||||
void idaapi mutable_graph_t::resize(int n) { INTERR(); };
|
||||
int idaapi mutable_graph_t::add_node(const rect_t *r) { INTERR(); };
|
||||
ssize_t idaapi mutable_graph_t::del_node(int n) { INTERR(); };
|
||||
bool idaapi mutable_graph_t::add_edge(int i, int j, const edge_info_t *ei) { INTERR(); };
|
||||
bool idaapi mutable_graph_t::del_edge(int i, int j) { INTERR(); };
|
||||
bool idaapi mutable_graph_t::replace_edge(int i, int j, int x, int y) { INTERR(); };
|
||||
bool idaapi mutable_graph_t::refresh(void) { INTERR(); };
|
||||
bool idaapi mutable_graph_t::set_nrect(int n, const rect_t &r) { INTERR(); };
|
||||
#endif
|
||||
%}
|
||||
|
||||
%{
|
||||
//<code(py_graph)>
|
||||
class py_graph_t
|
||||
@ -46,6 +26,7 @@ private:
|
||||
nodetext_cache_t(const char *t, bgcolor_t c): text(t), bgcolor(c) { }
|
||||
nodetext_cache_t() { }
|
||||
};
|
||||
|
||||
class nodetext_cache_map_t: public std::map<int, nodetext_cache_t>
|
||||
{
|
||||
public:
|
||||
@ -75,6 +56,7 @@ private:
|
||||
(*this)[form] = py;
|
||||
}
|
||||
};
|
||||
|
||||
class cmdid_map_t: public std::map<Py_ssize_t, py_graph_t *>
|
||||
{
|
||||
private:
|
||||
@ -83,7 +65,8 @@ private:
|
||||
|
||||
cmdid_map_t()
|
||||
{
|
||||
uid = 1; // we start by one and keep zero for error id
|
||||
// We start by one and keep zero for error id
|
||||
uid = 1;
|
||||
}
|
||||
|
||||
void add(py_graph_t *pyg)
|
||||
@ -92,7 +75,10 @@ private:
|
||||
++uid;
|
||||
}
|
||||
|
||||
const Py_ssize_t id() const { return uid; }
|
||||
const Py_ssize_t id() const
|
||||
{
|
||||
return uid;
|
||||
}
|
||||
|
||||
void clear(py_graph_t *pyg)
|
||||
{
|
||||
@ -108,6 +94,7 @@ private:
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
py_graph_t *get(Py_ssize_t id)
|
||||
{
|
||||
iterator it = find(id);
|
||||
@ -136,13 +123,16 @@ private:
|
||||
py_graph_t *_this = cmdid_pyg.get(id);
|
||||
if ( _this != NULL )
|
||||
_this->on_command(id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void on_command(Py_ssize_t id)
|
||||
{
|
||||
// Check return value to OnRefresh() call
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *ret = PyObject_CallMethod(self, (char *)S_ON_COMMAND, "n", id);
|
||||
PYW_GIL_RELEASE;
|
||||
Py_XDECREF(ret);
|
||||
}
|
||||
|
||||
@ -155,7 +145,9 @@ private:
|
||||
return;
|
||||
|
||||
// Check return value to OnRefresh() call
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *ret = PyObject_CallMethod(self, (char *)S_ON_REFRESH, NULL);
|
||||
PYW_GIL_RELEASE;
|
||||
if ( ret == NULL || !PyObject_IsTrue(ret) )
|
||||
{
|
||||
Py_XDECREF(ret);
|
||||
@ -213,11 +205,14 @@ private:
|
||||
Py_DECREF(id);
|
||||
if ( v > max_nodes )
|
||||
break;
|
||||
|
||||
edge_ids[j] = v;
|
||||
}
|
||||
|
||||
// Incomplete?
|
||||
if ( j != qnumber(edge_ids) )
|
||||
break;
|
||||
|
||||
// Add the edge
|
||||
g->add_edge(edge_ids[0], edge_ids[1], NULL);
|
||||
}
|
||||
@ -240,7 +235,9 @@ private:
|
||||
}
|
||||
|
||||
// Not cached, call Python
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *result = PyObject_CallMethod(self, (char *)S_ON_GETTEXT, "i", node);
|
||||
PYW_GIL_RELEASE;
|
||||
if ( result == NULL )
|
||||
return false;
|
||||
|
||||
@ -276,6 +273,7 @@ private:
|
||||
*str = c->text.c_str();
|
||||
if ( bg_color != NULL )
|
||||
*bg_color = c->bgcolor;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -290,7 +288,9 @@ private:
|
||||
if ( mousenode == -1 )
|
||||
return 0;
|
||||
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *result = PyObject_CallMethod(self, (char *)S_ON_HINT, "i", mousenode);
|
||||
PYW_GIL_RELEASE;
|
||||
bool ok = result != NULL && PyString_Check(result);
|
||||
if ( !ok )
|
||||
{
|
||||
@ -307,24 +307,33 @@ private:
|
||||
{
|
||||
if ( self != NULL )
|
||||
{
|
||||
if ( cb_flags & GR_HAVE_CLOSE )
|
||||
if ( (cb_flags & GR_HAVE_CLOSE) != 0 )
|
||||
{
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *result = PyObject_CallMethod(self, (char *)S_ON_CLOSE, NULL);
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
Py_XDECREF(result);
|
||||
}
|
||||
unbind();
|
||||
}
|
||||
|
||||
// Remove the TForm from list
|
||||
if ( form != NULL )
|
||||
tform_pyg.erase(form);
|
||||
// remove all associated commands from the list
|
||||
|
||||
// Remove all associated commands from the list
|
||||
cmdid_pyg.clear(this);
|
||||
|
||||
// Delete this instance
|
||||
delete this;
|
||||
}
|
||||
|
||||
// graph is being clicked
|
||||
int on_clicked(graph_viewer_t * /*gv*/, selection_item_t * /*item1*/, graph_item_t *item2)
|
||||
int on_clicked(
|
||||
graph_viewer_t * /*gv*/,
|
||||
selection_item_t * /*item1*/,
|
||||
graph_item_t *item2)
|
||||
{
|
||||
// in: graph_viewer_t *gv
|
||||
// selection_item_t *current_item1
|
||||
@ -338,7 +347,14 @@ private:
|
||||
if ( item2->n == -1 )
|
||||
return 1;
|
||||
|
||||
PyObject *result = PyObject_CallMethod(self, (char *)S_ON_CLICK, "i", item2->n);
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *result = PyObject_CallMethod(
|
||||
self,
|
||||
(char *)S_ON_CLICK,
|
||||
"i",
|
||||
item2->n);
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
if ( result == NULL || !PyObject_IsTrue(result) )
|
||||
{
|
||||
Py_XDECREF(result);
|
||||
@ -360,7 +376,15 @@ private:
|
||||
//selection_item_t *s = va_arg(va, selection_item_t *);
|
||||
if ( item == NULL || !item->is_node )
|
||||
return 1;
|
||||
PyObject *result = PyObject_CallMethod(self, (char *)S_ON_DBL_CLICK, "i", item->node);
|
||||
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *result = PyObject_CallMethod(
|
||||
self,
|
||||
(char *)S_ON_DBL_CLICK,
|
||||
"i",
|
||||
item->node);
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
if ( result == NULL || !PyObject_IsTrue(result) )
|
||||
{
|
||||
Py_XDECREF(result);
|
||||
@ -373,14 +397,25 @@ private:
|
||||
// a graph viewer got focus
|
||||
void on_gotfocus(graph_viewer_t * /*gv*/)
|
||||
{
|
||||
PyObject *result = PyObject_CallMethod(self, (char *)S_ON_ACTIVATE, NULL);
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *result = PyObject_CallMethod(
|
||||
self,
|
||||
(char *)S_ON_ACTIVATE,
|
||||
NULL);
|
||||
PYW_GIL_RELEASE;
|
||||
Py_XDECREF(result);
|
||||
}
|
||||
|
||||
// a graph viewer lost focus
|
||||
void on_lostfocus(graph_viewer_t *gv)
|
||||
{
|
||||
PyObject *result = PyObject_CallMethod(self, (char *)S_ON_DEACTIVATE, NULL);
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *result = PyObject_CallMethod(
|
||||
self,
|
||||
(char *)S_ON_DEACTIVATE,
|
||||
NULL);
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
Py_XDECREF(result);
|
||||
}
|
||||
|
||||
@ -392,7 +427,15 @@ private:
|
||||
// out: 0-ok, 1-forbid to change the current node
|
||||
if ( curnode < 0 )
|
||||
return 0;
|
||||
PyObject *result = PyObject_CallMethod(self, (char *)S_ON_SELECT, "i", curnode);
|
||||
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *result = PyObject_CallMethod(
|
||||
self,
|
||||
(char *)S_ON_SELECT,
|
||||
"i",
|
||||
curnode);
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
bool allow = (result != NULL && PyObject_IsTrue(result));
|
||||
Py_XDECREF(result);
|
||||
return allow ? 0 : 1;
|
||||
@ -428,7 +471,10 @@ private:
|
||||
ret = on_clicked(gv, item, gitem);
|
||||
}
|
||||
else
|
||||
ret = 1; // ignore click
|
||||
{
|
||||
// Ignore the click
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
//
|
||||
case grcode_dblclicked:
|
||||
@ -445,17 +491,20 @@ private:
|
||||
case grcode_gotfocus:
|
||||
if ( cb_flags & GR_HAVE_GOTFOCUS )
|
||||
on_gotfocus(va_arg(va, graph_viewer_t *));
|
||||
|
||||
ret = 0;
|
||||
break;
|
||||
//
|
||||
case grcode_lostfocus:
|
||||
if ( cb_flags & GR_HAVE_LOSTFOCUS )
|
||||
on_lostfocus(va_arg(va, graph_viewer_t *));
|
||||
|
||||
ret = 0;
|
||||
break;
|
||||
//
|
||||
case grcode_user_refresh:
|
||||
on_user_refresh(va_arg(va, mutable_graph_t *));
|
||||
|
||||
ret = 1;
|
||||
break;
|
||||
//
|
||||
@ -617,7 +666,7 @@ private:
|
||||
netnode id;
|
||||
id.create();
|
||||
gv = create_graph_viewer(form, id, s_callback, this, 0);
|
||||
open_tform(form, FORM_MDI|FORM_TAB|FORM_MENU);
|
||||
open_tform(form, FORM_MDI | FORM_TAB | FORM_MENU);
|
||||
if ( gv != NULL )
|
||||
viewer_fit_window(gv);
|
||||
}
|
||||
@ -625,6 +674,7 @@ private:
|
||||
{
|
||||
show();
|
||||
}
|
||||
|
||||
viewer_fit_window(gv);
|
||||
return 0;
|
||||
}
|
||||
@ -655,6 +705,7 @@ private:
|
||||
py_graph_t *_this = extract_this(self);
|
||||
if ( _this == NULL || _this->form == NULL )
|
||||
return;
|
||||
|
||||
_this->jump_to_node(0);
|
||||
}
|
||||
|
||||
@ -663,6 +714,7 @@ private:
|
||||
py_graph_t *_this = extract_this(self);
|
||||
if ( _this == NULL || _this->form == NULL )
|
||||
return 0;
|
||||
|
||||
return _this->add_command(title, hotkey);
|
||||
}
|
||||
|
||||
@ -671,6 +723,7 @@ private:
|
||||
py_graph_t *_this = extract_this(self);
|
||||
if ( _this == NULL || _this->form == NULL )
|
||||
return;
|
||||
|
||||
close_tform(_this->form, 0);
|
||||
}
|
||||
|
||||
@ -679,6 +732,7 @@ private:
|
||||
py_graph_t *_this = extract_this(self);
|
||||
if ( _this == NULL )
|
||||
return;
|
||||
|
||||
_this->refresh();
|
||||
}
|
||||
|
||||
@ -763,7 +817,7 @@ bool pyg_show(PyObject *self);
|
||||
|
||||
%pythoncode %{
|
||||
#<pycode(py_graph)>
|
||||
class GraphViewer:
|
||||
class GraphViewer(object):
|
||||
"""This class wraps the user graphing facility provided by the graph.hpp file"""
|
||||
def __init__(self, title, close_open = False):
|
||||
"""
|
||||
@ -793,10 +847,16 @@ class GraphViewer:
|
||||
self._nodes = []
|
||||
self._edges = []
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
return (self._nodes[index] for index in xrange(0, len(self._nodes)))
|
||||
|
||||
|
||||
def __getitem__(self, idx):
|
||||
"""Returns a reference to the object associated with this node id"""
|
||||
if idx > len(self._nodes):
|
||||
raise StopIteration
|
||||
if idx >= len(self._nodes):
|
||||
raise KeyError
|
||||
else:
|
||||
return self._nodes[idx]
|
||||
|
||||
def Count(self):
|
||||
|
2505
swig/idaapi.i
2505
swig/idaapi.i
File diff suppressed because it is too large
Load Diff
19
swig/idd.i
19
swig/idd.i
@ -85,7 +85,9 @@ PyObject *py_appcall(
|
||||
// Set exception message
|
||||
if ( !ok )
|
||||
{
|
||||
PyErr_SetString(PyExc_ValueError, "PyAppCall: Failed to convert Python values to IDC values");
|
||||
PyErr_SetString(
|
||||
PyExc_ValueError,
|
||||
"PyAppCall: Failed to convert Python values to IDC values");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -93,6 +95,7 @@ PyObject *py_appcall(
|
||||
{
|
||||
msg("input variables:\n"
|
||||
"----------------\n");
|
||||
|
||||
qstring s;
|
||||
for ( Py_ssize_t i=0; i<nargs; i++ )
|
||||
{
|
||||
@ -101,6 +104,7 @@ PyObject *py_appcall(
|
||||
s.qclear();
|
||||
}
|
||||
}
|
||||
|
||||
// Do Appcall
|
||||
idc_value_t idc_result;
|
||||
error_t ret = appcall(
|
||||
@ -146,6 +150,7 @@ PyObject *py_appcall(
|
||||
s.qclear();
|
||||
}
|
||||
}
|
||||
|
||||
// Convert IDC values back to Python values
|
||||
for ( Py_ssize_t i=0; i<nargs; i++ )
|
||||
{
|
||||
@ -268,6 +273,7 @@ static PyObject *dbg_get_thread_sreg_base(PyObject *py_tid, PyObject *py_sreg_va
|
||||
int sreg_value = PyInt_AsLong(py_sreg_value);
|
||||
if ( dbg->thread_get_sreg_base(tid, sreg_value, &answer) != 1 )
|
||||
Py_RETURN_NONE;
|
||||
|
||||
return Py_BuildValue(PY_FMT64, pyul_t(answer));
|
||||
}
|
||||
|
||||
@ -620,6 +626,7 @@ class Appcall_callable__(object):
|
||||
fields = property(__get_fields)
|
||||
"""Returns the field names"""
|
||||
|
||||
|
||||
def retrieve(self, src=None, flags=0):
|
||||
"""
|
||||
Unpacks a typed object from the database if an ea is given or from a string if a string was passed
|
||||
@ -628,7 +635,7 @@ class Appcall_callable__(object):
|
||||
"""
|
||||
|
||||
# Nothing passed? Take the address and unpack from the database
|
||||
if not src:
|
||||
if src is None:
|
||||
src = self.ea
|
||||
|
||||
if type(src) == types.StringType:
|
||||
@ -740,11 +747,11 @@ class Appcall__(object):
|
||||
# resolve and raise exception on error
|
||||
ea = Appcall__.__name_or_ea(name_or_ea)
|
||||
# parse the type
|
||||
if not flags:
|
||||
if flags is None:
|
||||
flags = 1 | 2 | 4 # PT_SIL | PT_NDC | PT_TYP
|
||||
|
||||
result = _idaapi.idc_parse_decl(_idaapi.cvar.idati, prototype, flags)
|
||||
if not result:
|
||||
if result is None:
|
||||
raise ValueError, "Could not parse type: " + prototype
|
||||
|
||||
# Return the callable method with type info
|
||||
@ -797,7 +804,7 @@ class Appcall__(object):
|
||||
Creates a string buffer. The returned value (r) will be a byref object.
|
||||
Use r.value to get the contents and r.size to get the buffer's size
|
||||
"""
|
||||
if not str:
|
||||
if str is None:
|
||||
str = ""
|
||||
left = size - len(str)
|
||||
if left > 0:
|
||||
@ -834,7 +841,7 @@ class Appcall__(object):
|
||||
"""
|
||||
# parse the type
|
||||
result = _idaapi.idc_parse_decl(_idaapi.cvar.idati, typestr, 1 | 2 | 4) # PT_SIL | PT_NDC | PT_TYP
|
||||
if not result:
|
||||
if result is None:
|
||||
raise ValueError, "Could not parse type: " + typestr
|
||||
# Return the callable method with type info
|
||||
return Appcall_callable__(ea, result[1], result[2])
|
||||
|
600
swig/idp.i
600
swig/idp.i
@ -42,72 +42,6 @@
|
||||
%feature("director") IDB_Hooks;
|
||||
%feature("director") IDP_Hooks;
|
||||
%inline %{
|
||||
int idaapi IDB_Callback(void *ud, int notification_code, va_list va);
|
||||
class IDB_Hooks
|
||||
{
|
||||
public:
|
||||
virtual ~IDB_Hooks() {};
|
||||
|
||||
bool hook() { return hook_to_notification_point(HT_IDB, IDB_Callback, this); }
|
||||
bool unhook() { return unhook_from_notification_point(HT_IDB, IDB_Callback, this); }
|
||||
/* Hook functions to override in Python */
|
||||
virtual int byte_patched(ea_t ea) { return 0; };
|
||||
virtual int cmt_changed(ea_t, bool repeatable_cmt) { return 0; };
|
||||
virtual int ti_changed(ea_t ea, const type_t *type, const p_list *fnames) { msg("ti_changed hook not supported yet\n"); return 0; };
|
||||
virtual int op_ti_changed(ea_t ea, int n, const type_t *type, const p_list *fnames) { msg("op_ti_changed hook not supported yet\n"); return 0; };
|
||||
virtual int op_type_changed(ea_t ea, int n) { return 0; };
|
||||
virtual int enum_created(enum_t id) { return 0; };
|
||||
virtual int enum_deleted(enum_t id) { return 0; };
|
||||
virtual int enum_bf_changed(enum_t id) { return 0; };
|
||||
virtual int enum_renamed(enum_t id) { return 0; };
|
||||
virtual int enum_cmt_changed(enum_t id) { return 0; };
|
||||
virtual int enum_member_created(enum_t id, const_t cid) { return 0; };
|
||||
virtual int enum_member_deleted(enum_t id, const_t cid) { return 0; };
|
||||
virtual int struc_created(tid_t struc_id) { return 0; };
|
||||
virtual int struc_deleted(tid_t struc_id) { return 0; };
|
||||
virtual int struc_renamed(struc_t *sptr) { return 0; };
|
||||
virtual int struc_expanded(struc_t *sptr) { return 0; };
|
||||
virtual int struc_cmt_changed(tid_t struc_id) { return 0; };
|
||||
virtual int struc_member_created(struc_t *sptr, member_t *mptr) { return 0; };
|
||||
virtual int struc_member_deleted(struc_t *sptr, tid_t member_id) { return 0; };
|
||||
virtual int struc_member_renamed(struc_t *sptr, member_t *mptr) { return 0; };
|
||||
virtual int struc_member_changed(struc_t *sptr, member_t *mptr) { return 0; };
|
||||
virtual int thunk_func_created(func_t *pfn) { return 0; };
|
||||
virtual int func_tail_appended(func_t *pfn, func_t *tail) { return 0; };
|
||||
virtual int func_tail_removed(func_t *pfn, ea_t tail_ea) { return 0; };
|
||||
virtual int tail_owner_changed(func_t *tail, ea_t owner_func) { return 0; };
|
||||
virtual int func_noret_changed(func_t *pfn) { return 0; };
|
||||
virtual int segm_added(segment_t *s) { return 0; };
|
||||
virtual int segm_deleted(ea_t startEA) { return 0; };
|
||||
virtual int segm_start_changed(segment_t *s) { return 0; };
|
||||
virtual int segm_end_changed(segment_t *s) { return 0; };
|
||||
virtual int segm_moved(ea_t from, ea_t to, asize_t size) { return 0; };
|
||||
};
|
||||
|
||||
// Assemble an instruction into the database (display a warning if an error is found)
|
||||
// args:
|
||||
// ea_t ea - linear address of instruction
|
||||
// ea_t cs - cs of instruction
|
||||
// ea_t ip - ip of instruction
|
||||
// bool use32 - is 32bit segment?
|
||||
// const char *line - line to assemble
|
||||
// returns: 1: success, 0: failure
|
||||
inline const int assemble(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *line)
|
||||
{
|
||||
int inslen;
|
||||
char buf[MAXSTR];
|
||||
|
||||
if (ph.notify != NULL)
|
||||
{
|
||||
inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf);
|
||||
if (inslen > 0)
|
||||
{
|
||||
patch_many_bytes(ea, buf, inslen);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//<inline(py_idp)>
|
||||
//-------------------------------------------------------------------------
|
||||
@ -117,7 +51,7 @@ inline const int assemble(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *lin
|
||||
#<pydoc>
|
||||
def AssembleLine(ea, cs, ip, use32, line):
|
||||
"""
|
||||
Assemble an instruction to a buffer (display a warning if an error is found)
|
||||
Assemble an instruction to a string (display a warning if an error is found)
|
||||
|
||||
@param ea: linear address of instruction
|
||||
@param cs: cs of instruction
|
||||
@ -143,6 +77,39 @@ static PyObject *AssembleLine(ea_t ea, ea_t cs, ea_t ip, bool use32, const char
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/*
|
||||
#<pydoc>
|
||||
def assemble(ea, cs, ip, use32, line):
|
||||
"""
|
||||
Assemble an instruction into the database (display a warning if an error is found)
|
||||
@param ea: linear address of instruction
|
||||
@param cs: cs of instruction
|
||||
@param ip: ip of instruction
|
||||
@param use32: is 32bit segment?
|
||||
@param line: line to assemble
|
||||
|
||||
@return: Boolean. True on success.
|
||||
"""
|
||||
#</pydoc>
|
||||
*/
|
||||
bool assemble(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *line)
|
||||
{
|
||||
int inslen;
|
||||
char buf[MAXSTR];
|
||||
|
||||
if (ph.notify != NULL)
|
||||
{
|
||||
inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf);
|
||||
if (inslen > 0)
|
||||
{
|
||||
patch_many_bytes(ea, buf, inslen);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
#<pydoc>
|
||||
@ -408,6 +375,7 @@ static PyObject *ph_get_regnames()
|
||||
PyObject *py_result = PyList_New(ph.regsNum);
|
||||
for ( Py_ssize_t i=0; i<ph.regsNum; i++ )
|
||||
PyList_SetItem(py_result, i, PyString_FromString(ph.regNames[i]));
|
||||
|
||||
return py_result;
|
||||
}
|
||||
|
||||
@ -415,6 +383,21 @@ static PyObject *ph_get_regnames()
|
||||
/*
|
||||
#<pydoc>
|
||||
class IDP_Hooks(object):
|
||||
def hook(self):
|
||||
"""
|
||||
Creates an IDP hook
|
||||
|
||||
@return: Boolean true on success
|
||||
"""
|
||||
pass
|
||||
|
||||
def unhook(self):
|
||||
"""
|
||||
Removes the IDP hook
|
||||
@return: Boolean true on success
|
||||
"""
|
||||
pass
|
||||
|
||||
def custom_ana(self):
|
||||
"""
|
||||
Analyzes and decodes an instruction at idaapi.cmd.ea
|
||||
@ -480,9 +463,9 @@ class IDP_Hooks(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
def is_sane_insn(self, no_crefs):
|
||||
def may_be_func(self, no_crefs):
|
||||
"""
|
||||
can a function start here?
|
||||
Can a function start here?
|
||||
@param state: autoanalysis phase
|
||||
0: creating functions
|
||||
1: creating chunks
|
||||
@ -490,8 +473,124 @@ class IDP_Hooks(object):
|
||||
@return: integer (probability 0..100)
|
||||
"""
|
||||
pass
|
||||
|
||||
def closebase(self):
|
||||
"""
|
||||
The database will be closed now
|
||||
"""
|
||||
pass
|
||||
|
||||
def savebase(self):
|
||||
"""
|
||||
The database is being saved. Processor module should
|
||||
"""
|
||||
pass
|
||||
|
||||
def rename(self, ea, new_name):
|
||||
"""
|
||||
The kernel is going to rename a byte.
|
||||
|
||||
@param ea: Address
|
||||
@param new_name: The new name
|
||||
|
||||
@return:
|
||||
- If returns value <=0, then the kernel should
|
||||
not rename it. See also the 'renamed' event
|
||||
"""
|
||||
|
||||
def renamed(self, ea, new_name, local_name):
|
||||
"""
|
||||
The kernel has renamed a byte
|
||||
|
||||
@param ea: Address
|
||||
@param new_name: The new name
|
||||
@param local_name: Is local name
|
||||
|
||||
@return: Ignored
|
||||
"""
|
||||
|
||||
def undefine(self, ea):
|
||||
"""
|
||||
An item in the database (insn or data) is being deleted
|
||||
@param ea: Address
|
||||
@return:
|
||||
- returns: >0-ok, <=0-the kernel should stop
|
||||
- if the return value is positive:
|
||||
bit0 - ignored
|
||||
bit1 - do not delete srareas at the item end
|
||||
"""
|
||||
|
||||
def make_code(self, ea, size):
|
||||
"""
|
||||
An instruction is being created
|
||||
@param ea: Address
|
||||
@param size: Instruction size
|
||||
@return: 1-ok, <=0-the kernel should stop
|
||||
"""
|
||||
|
||||
def make_code(self, ea, size):
|
||||
"""
|
||||
An instruction is being created
|
||||
@param ea: Address
|
||||
@param size: Instruction size
|
||||
@return: 1-ok, <=0-the kernel should stop
|
||||
"""
|
||||
|
||||
def make_data(self, ea, flags, tid, len):
|
||||
"""
|
||||
A data item is being created
|
||||
@param ea: Address
|
||||
@param tid: type id
|
||||
@param flags: item flags
|
||||
@param len: data item size
|
||||
@return: 1-ok, <=0-the kernel should stop
|
||||
"""
|
||||
|
||||
def load_idasgn(self, short_sig_name):
|
||||
"""
|
||||
FLIRT signature have been loaded for normal processing
|
||||
(not for recognition of startup sequences)
|
||||
@param short_sig_name: signature name
|
||||
@return: Ignored
|
||||
"""
|
||||
|
||||
def add_func(self, func):
|
||||
"""
|
||||
The kernel has added a function
|
||||
@param func: the func_t instance
|
||||
@return: Ignored
|
||||
"""
|
||||
|
||||
def del_func(self, func):
|
||||
"""
|
||||
The kernel is about to delete a function
|
||||
@param func: the func_t instance
|
||||
@return: 1-ok,<=0-do not delete
|
||||
"""
|
||||
|
||||
def is_call_insn(self, ea, func_name):
|
||||
"""
|
||||
Is the instruction a "call"?
|
||||
|
||||
@param ea: instruction address
|
||||
@return: 1-unknown, 0-no, 2-yes
|
||||
"""
|
||||
|
||||
def is_ret_insn(self, ea, func_name):
|
||||
"""
|
||||
Is the instruction a "return"?
|
||||
|
||||
@param ea: instruction address
|
||||
@param strict: - True: report only ret instructions
|
||||
False: include instructions like "leave" which begins the function epilog
|
||||
@return: 1-unknown, 0-no, 2-yes
|
||||
"""
|
||||
|
||||
#</pydoc>
|
||||
*/
|
||||
//---------------------------------------------------------------------------
|
||||
// IDP hooks
|
||||
//---------------------------------------------------------------------------
|
||||
int idaapi IDP_Callback(void *ud, int notification_code, va_list va);
|
||||
class IDP_Hooks
|
||||
{
|
||||
@ -544,12 +643,287 @@ public:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int closebase()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void savebase()
|
||||
{
|
||||
}
|
||||
|
||||
virtual int rename(ea_t ea, const char *new_name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void renamed(ea_t ea, const char *new_name, bool local_name)
|
||||
{
|
||||
}
|
||||
|
||||
virtual int undefine(ea_t ea)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int make_code(ea_t ea, asize_t size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int make_data(ea_t ea, flags_t flags, tid_t tid, asize_t len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void load_idasgn(const char *short_sig_name)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void add_func(func_t *func)
|
||||
{
|
||||
}
|
||||
|
||||
virtual int del_func(func_t *func)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int is_call_insn(ea_t ea)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int is_ret_insn(ea_t ea, bool strict)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// IDB hooks
|
||||
//---------------------------------------------------------------------------
|
||||
int idaapi IDB_Callback(void *ud, int notification_code, va_list va);
|
||||
class IDB_Hooks
|
||||
{
|
||||
public:
|
||||
virtual ~IDB_Hooks() {};
|
||||
|
||||
bool hook()
|
||||
{
|
||||
return hook_to_notification_point(HT_IDB, IDB_Callback, this);
|
||||
}
|
||||
bool unhook()
|
||||
{
|
||||
return unhook_from_notification_point(HT_IDB, IDB_Callback, this);
|
||||
}
|
||||
// Hook functions to override in Python
|
||||
virtual int byte_patched(ea_t ea) { return 0; };
|
||||
virtual int cmt_changed(ea_t, bool repeatable_cmt) { return 0; };
|
||||
virtual int ti_changed(ea_t ea, const type_t *type, const p_list *fnames) { msg("ti_changed hook not supported yet\n"); return 0; };
|
||||
virtual int op_ti_changed(ea_t ea, int n, const type_t *type, const p_list *fnames) { msg("op_ti_changed hook not supported yet\n"); return 0; };
|
||||
virtual int op_type_changed(ea_t ea, int n) { return 0; };
|
||||
virtual int enum_created(enum_t id) { return 0; };
|
||||
virtual int enum_deleted(enum_t id) { return 0; };
|
||||
virtual int enum_bf_changed(enum_t id) { return 0; };
|
||||
virtual int enum_renamed(enum_t id) { return 0; };
|
||||
virtual int enum_cmt_changed(enum_t id) { return 0; };
|
||||
virtual int enum_member_created(enum_t id, const_t cid) { return 0; };
|
||||
virtual int enum_member_deleted(enum_t id, const_t cid) { return 0; };
|
||||
virtual int struc_created(tid_t struc_id) { return 0; };
|
||||
virtual int struc_deleted(tid_t struc_id) { return 0; };
|
||||
virtual int struc_renamed(struc_t *sptr) { return 0; };
|
||||
virtual int struc_expanded(struc_t *sptr) { return 0; };
|
||||
virtual int struc_cmt_changed(tid_t struc_id) { return 0; };
|
||||
virtual int struc_member_created(struc_t *sptr, member_t *mptr) { return 0; };
|
||||
virtual int struc_member_deleted(struc_t *sptr, tid_t member_id) { return 0; };
|
||||
virtual int struc_member_renamed(struc_t *sptr, member_t *mptr) { return 0; };
|
||||
virtual int struc_member_changed(struc_t *sptr, member_t *mptr) { return 0; };
|
||||
virtual int thunk_func_created(func_t *pfn) { return 0; };
|
||||
virtual int func_tail_appended(func_t *pfn, func_t *tail) { return 0; };
|
||||
virtual int func_tail_removed(func_t *pfn, ea_t tail_ea) { return 0; };
|
||||
virtual int tail_owner_changed(func_t *tail, ea_t owner_func) { return 0; };
|
||||
virtual int func_noret_changed(func_t *pfn) { return 0; };
|
||||
virtual int segm_added(segment_t *s) { return 0; };
|
||||
virtual int segm_deleted(ea_t startEA) { return 0; };
|
||||
virtual int segm_start_changed(segment_t *s) { return 0; };
|
||||
virtual int segm_end_changed(segment_t *s) { return 0; };
|
||||
virtual int segm_moved(ea_t from, ea_t to, asize_t size) { return 0; };
|
||||
};
|
||||
|
||||
//</inline(py_idp)>
|
||||
%}
|
||||
|
||||
%{
|
||||
//<code(py_idp)>
|
||||
//-------------------------------------------------------------------------
|
||||
int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
|
||||
{
|
||||
IDP_Hooks *proxy = (IDP_Hooks *)ud;
|
||||
int ret = 0;
|
||||
try
|
||||
{
|
||||
switch ( notification_code )
|
||||
{
|
||||
case processor_t::custom_ana:
|
||||
ret = proxy->custom_ana() ? 1 + cmd.size : 0;
|
||||
break;
|
||||
|
||||
case processor_t::custom_out:
|
||||
ret = proxy->custom_out() ? 2 : 0;
|
||||
break;
|
||||
|
||||
case processor_t::custom_emu:
|
||||
ret = proxy->custom_emu() ? 2 : 0;
|
||||
break;
|
||||
|
||||
case processor_t::custom_outop:
|
||||
{
|
||||
op_t *op = va_arg(va, op_t *);
|
||||
PyObject *py_obj = create_idaapi_linked_class_instance(S_PY_OP_T_CLSNAME, op);
|
||||
if ( py_obj == NULL )
|
||||
break;
|
||||
ret = proxy->custom_outop(py_obj) ? 2 : 0;
|
||||
Py_XDECREF(py_obj);
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::custom_mnem:
|
||||
{
|
||||
PyObject *py_ret = proxy->custom_mnem();
|
||||
if ( py_ret != NULL && PyString_Check(py_ret) )
|
||||
{
|
||||
char *outbuffer = va_arg(va, char *);
|
||||
size_t bufsize = va_arg(va, size_t);
|
||||
|
||||
qstrncpy(outbuffer, PyString_AS_STRING(py_ret), bufsize);
|
||||
ret = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
Py_XDECREF(py_ret);
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::is_sane_insn:
|
||||
{
|
||||
int no_crefs = va_arg(va, int);
|
||||
ret = proxy->is_sane_insn(no_crefs);
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::may_be_func:
|
||||
{
|
||||
int state = va_arg(va, int);
|
||||
ret = proxy->may_be_func(state);
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::closebase:
|
||||
{
|
||||
proxy->closebase();
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::savebase:
|
||||
{
|
||||
proxy->savebase();
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::rename:
|
||||
{
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
const char *new_name = va_arg(va, const char *);
|
||||
ret = proxy->rename(ea, new_name);
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::renamed:
|
||||
{
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
const char *new_name = va_arg(va, const char *);
|
||||
bool local_name = va_argi(va, bool);
|
||||
proxy->renamed(ea, new_name, local_name);
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::undefine:
|
||||
{
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
ret = proxy->undefine(ea);
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::make_code:
|
||||
{
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
asize_t size = va_arg(va, asize_t);
|
||||
ret = proxy->make_code(ea, size);
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::make_data:
|
||||
{
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
flags_t flags = va_arg(va, flags_t);
|
||||
tid_t tid = va_arg(va, tid_t);
|
||||
asize_t len = va_arg(va, asize_t);
|
||||
ret = proxy->make_data(ea, flags, tid, len);
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::load_idasgn:
|
||||
{
|
||||
const char *short_sig_name = va_arg(va, const char *);
|
||||
proxy->load_idasgn(short_sig_name);
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::add_func:
|
||||
{
|
||||
func_t *func = va_arg(va, func_t *);
|
||||
proxy->add_func(func);
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::del_func:
|
||||
{
|
||||
func_t *func = va_arg(va, func_t *);
|
||||
ret = proxy->del_func(func);
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::is_call_insn:
|
||||
{
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
ret = proxy->is_call_insn(ea);
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::is_ret_insn:
|
||||
{
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
bool strict = va_argi(va, bool);
|
||||
ret = proxy->is_ret_insn(ea, strict);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Swig::DirectorException &)
|
||||
{
|
||||
msg("Exception in IDP Hook function:\n");
|
||||
if ( PyErr_Occurred() )
|
||||
PyErr_Print();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
|
||||
{
|
||||
class IDB_Hooks *proxy = (class IDB_Hooks *)ud;
|
||||
@ -615,12 +989,20 @@ int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
|
||||
id = va_arg(va, enum_t);
|
||||
return proxy->enum_cmt_changed(id);
|
||||
|
||||
#ifdef NO_OBSOLETE_FUNCS
|
||||
case idb_event::enum_member_created:
|
||||
#else
|
||||
case idb_event::enum_const_created:
|
||||
#endif
|
||||
id = va_arg(va, enum_t);
|
||||
cid = va_arg(va, const_t);
|
||||
return proxy->enum_member_created(id, cid);
|
||||
|
||||
#ifdef NO_OBSOLETE_FUNCS
|
||||
case idb_event::enum_member_deleted:
|
||||
#else
|
||||
case idb_event::enum_const_deleted:
|
||||
#endif
|
||||
id = va_arg(va, enum_t);
|
||||
cid = va_arg(va, const_t);
|
||||
return proxy->enum_member_deleted(id, cid);
|
||||
@ -722,86 +1104,6 @@ int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//<code(py_idp)>
|
||||
//-------------------------------------------------------------------------
|
||||
int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
|
||||
{
|
||||
IDP_Hooks *proxy = (IDP_Hooks *)ud;
|
||||
int ret;
|
||||
try
|
||||
{
|
||||
switch ( notification_code )
|
||||
{
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case processor_t::custom_ana:
|
||||
ret = proxy->custom_ana() ? 1 + cmd.size : 0;
|
||||
break;
|
||||
|
||||
case processor_t::custom_out:
|
||||
ret = proxy->custom_out() ? 2 : 0;
|
||||
break;
|
||||
|
||||
case processor_t::custom_emu:
|
||||
ret = proxy->custom_emu() ? 2 : 0;
|
||||
break;
|
||||
|
||||
case processor_t::custom_outop:
|
||||
{
|
||||
op_t *op = va_arg(va, op_t *);
|
||||
PyObject *py_obj = create_idaapi_linked_class_instance(S_PY_OP_T_CLSNAME, op);
|
||||
if ( py_obj == NULL )
|
||||
break;
|
||||
ret = proxy->custom_outop(py_obj) ? 2 : 0;
|
||||
Py_XDECREF(py_obj);
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::custom_mnem:
|
||||
{
|
||||
PyObject *py_ret = proxy->custom_mnem();
|
||||
if ( py_ret != NULL && PyString_Check(py_ret) )
|
||||
{
|
||||
char *outbuffer = va_arg(va, char *);
|
||||
size_t bufsize = va_arg(va, size_t);
|
||||
|
||||
qstrncpy(outbuffer, PyString_AS_STRING(py_ret), bufsize);
|
||||
ret = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
Py_XDECREF(py_ret);
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::is_sane_insn:
|
||||
{
|
||||
int no_crefs = va_arg(va, int);
|
||||
ret = proxy->is_sane_insn(no_crefs);
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::may_be_func:
|
||||
{
|
||||
int state = va_arg(va, int);
|
||||
ret = proxy->may_be_func(state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Swig::DirectorException &)
|
||||
{
|
||||
msg("Exception in IDP Hook function:\n");
|
||||
if ( PyErr_Occurred() )
|
||||
PyErr_Print();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//</code(py_idp)>
|
||||
%}
|
3411
swig/kernwin.i
3411
swig/kernwin.i
File diff suppressed because it is too large
Load Diff
11
swig/lines.i
11
swig/lines.i
@ -78,7 +78,6 @@
|
||||
//<code(py_lines)>
|
||||
//------------------------------------------------------------------------
|
||||
static PyObject *py_get_user_defined_prefix = NULL;
|
||||
static qstring py_get_user_defined_prefix_err;
|
||||
static void idaapi s_py_get_user_defined_prefix(
|
||||
ea_t ea,
|
||||
int lnnum,
|
||||
@ -92,12 +91,9 @@ static void idaapi s_py_get_user_defined_prefix(
|
||||
PY_FMT64 "iis" PY_FMT64,
|
||||
ea, lnnum, indent, line, bufsize);
|
||||
|
||||
if ( PyW_GetError(&py_get_user_defined_prefix_err) || py_ret == NULL )
|
||||
{
|
||||
msg("py_get_user_defined_prefix() error: %s\n", py_get_user_defined_prefix_err.c_str());
|
||||
PyErr_Clear();
|
||||
}
|
||||
else
|
||||
// Error? Display it
|
||||
// No error? Copy the buffer
|
||||
if ( !PyW_ShowCbErr("py_get_user_defined_prefix") )
|
||||
{
|
||||
Py_ssize_t py_len;
|
||||
char *py_str;
|
||||
@ -192,6 +188,7 @@ PyObject *py_tag_remove(const char *instr)
|
||||
char *buf = new char[sz + 5];
|
||||
if ( buf == NULL )
|
||||
Py_RETURN_NONE;
|
||||
|
||||
ssize_t r = tag_remove(instr, buf, sz);
|
||||
PyObject *res;
|
||||
if ( r < 0 )
|
||||
|
@ -12,6 +12,7 @@
|
||||
// TODO: These could be wrapped if needed
|
||||
%ignore load_info_t;
|
||||
%ignore add_plugin_option;
|
||||
%ignore get_plugins_path;
|
||||
%ignore build_loaders_list;
|
||||
%ignore free_loaders_list;
|
||||
%ignore get_loader_name_from_dll;
|
||||
@ -147,6 +148,7 @@ static int py_mem2base(PyObject *py_mem, ea_t ea, long fpos = -1)
|
||||
char *buf;
|
||||
if ( PyString_AsStringAndSize(py_mem, &buf, &len) == -1 )
|
||||
return 0;
|
||||
|
||||
return mem2base((void *)buf, ea, ea+len, fpos);
|
||||
}
|
||||
|
||||
@ -168,6 +170,7 @@ static PyObject *py_load_plugin(const char *name)
|
||||
plugin_t *r = load_plugin(name);
|
||||
if ( r == NULL )
|
||||
Py_RETURN_NONE;
|
||||
|
||||
return PyCObject_FromVoidPtr(r, NULL);
|
||||
}
|
||||
|
||||
@ -187,6 +190,7 @@ static bool py_run_plugin(PyObject *plg, int arg)
|
||||
{
|
||||
if ( !PyCObject_Check(plg) )
|
||||
return false;
|
||||
|
||||
return run_plugin((plugin_t *)PyCObject_AsVoidPtr(plg), arg);
|
||||
}
|
||||
|
||||
|
23
swig/nalt.i
23
swig/nalt.i
@ -25,7 +25,11 @@ static int idaapi py_import_enum_cb(
|
||||
uval_t ord,
|
||||
void *param)
|
||||
{
|
||||
PyObject *py_ea = Py_BuildValue(PY_FMT64, pyul_t(ea));
|
||||
// If no name, try to get the name associated with the 'ea'. It may be coming from IDS
|
||||
char name_buf[MAXSTR];
|
||||
if ( name == NULL )
|
||||
name = get_true_name(BADADDR, ea, name_buf, sizeof(name_buf));
|
||||
|
||||
PyObject *py_name;
|
||||
if ( name == NULL )
|
||||
{
|
||||
@ -36,13 +40,25 @@ static int idaapi py_import_enum_cb(
|
||||
{
|
||||
py_name = PyString_FromString(name);
|
||||
}
|
||||
|
||||
PyObject *py_ord = Py_BuildValue(PY_FMT64, pyul_t(ord));
|
||||
PyObject *py_result = PyObject_CallFunctionObjArgs((PyObject *)param, py_ea, py_name, py_ord, NULL);
|
||||
PyObject *py_ea = Py_BuildValue(PY_FMT64, pyul_t(ea));
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_result = PyObject_CallFunctionObjArgs(
|
||||
(PyObject *)param,
|
||||
py_ea,
|
||||
py_name,
|
||||
py_ord,
|
||||
NULL);
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
int r = py_result != NULL && PyObject_IsTrue(py_result) ? 1 : 0;
|
||||
|
||||
Py_DECREF(py_ea);
|
||||
Py_DECREF(py_name);
|
||||
Py_DECREF(py_ord);
|
||||
Py_XDECREF(py_result);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -90,6 +106,7 @@ static PyObject *py_get_import_module_name(int mod_index)
|
||||
char buf[MAXSTR];
|
||||
if ( !get_import_module_name(mod_index, buf, sizeof(buf)) )
|
||||
Py_RETURN_NONE;
|
||||
|
||||
return PyString_FromString(buf);
|
||||
}
|
||||
|
||||
@ -234,6 +251,7 @@ static int py_enum_import_names(int mod_index, PyObject *py_cb)
|
||||
{
|
||||
if ( !PyCallable_Check(py_cb) )
|
||||
return -1;
|
||||
|
||||
return enum_import_names(mod_index, py_import_enum_cb, py_cb);
|
||||
}
|
||||
|
||||
@ -244,6 +262,7 @@ static PyObject *switch_info_ex_t_create()
|
||||
return PyCObject_FromVoidPtr(inst, NULL);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
static bool switch_info_ex_t_destroy(PyObject *py_obj)
|
||||
{
|
||||
if ( !PyCObject_Check(py_obj) )
|
||||
|
18
swig/name.i
18
swig/name.i
@ -45,7 +45,7 @@ PyObject *py_get_debug_names(ea_t ea1, ea_t ea2)
|
||||
for (ea_name_vec_t::iterator it=names.begin();it!=names.end();++it)
|
||||
{
|
||||
PyDict_SetItem(dict,
|
||||
PyInt_FromSize_t(it->ea),
|
||||
Py_BuildValue(PY_FMT64, it->ea),
|
||||
PyString_FromString(it->name.c_str()));
|
||||
}
|
||||
return dict;
|
||||
@ -63,12 +63,14 @@ class NearestName:
|
||||
def __init__(self, ea_names):
|
||||
self.update(ea_names)
|
||||
|
||||
|
||||
def update(self, ea_names):
|
||||
"""Updates the ea/names map"""
|
||||
self._names = ea_names
|
||||
self._addrs = ea_names.keys()
|
||||
self._addrs.sort()
|
||||
|
||||
|
||||
def find(self, ea):
|
||||
"""
|
||||
Returns a tupple (ea, name, pos) that is the nearest to the passed ea
|
||||
@ -85,13 +87,21 @@ class NearestName:
|
||||
return None
|
||||
return self[pos]
|
||||
|
||||
|
||||
def _get_item(self, index):
|
||||
ea = self._addrs[index]
|
||||
return (ea, self._names[ea], index)
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
return (self._get_item(index) for index in xrange(0, len(self._addrs)))
|
||||
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Returns the tupple (ea, name, index)"""
|
||||
if index > len(self._addrs):
|
||||
raise StopIteration
|
||||
ea = self._addrs[index]
|
||||
return (ea, self._names[ea], index)
|
||||
return self._get_item(index)
|
||||
|
||||
%}
|
||||
%include "name.hpp"
|
||||
|
||||
|
@ -89,3 +89,11 @@
|
||||
%rename (hashset_idx) netnode::hashset(const char *idx, nodeidx_t value, char tag=htag);
|
||||
|
||||
%include "netnode.hpp"
|
||||
|
||||
%extend netnode
|
||||
{
|
||||
nodeidx_t index()
|
||||
{
|
||||
return self->operator nodeidx_t();
|
||||
}
|
||||
}
|
14
swig/pro.i
14
swig/pro.i
@ -23,7 +23,14 @@
|
||||
%ignore qthread_join;
|
||||
%ignore qthread_kill;
|
||||
%ignore qthread_self;
|
||||
%ignore qthread_same;
|
||||
%ignore qthread_t;
|
||||
%ignore qhandle_t;
|
||||
%ignore qpipe_create;
|
||||
%ignore qpipe_read;
|
||||
%ignore qpipe_write;
|
||||
%ignore qpipe_close;
|
||||
%ignore qwait_for_handles;
|
||||
%ignore qstrlen;
|
||||
%ignore qstrcmp;
|
||||
%ignore qstrstr;
|
||||
@ -65,8 +72,11 @@
|
||||
%ignore swap_value;
|
||||
%ignore qalloc_or_throw;
|
||||
%ignore qrealloc_or_throw;
|
||||
%ignore launch_process_t;
|
||||
%ignore init_process;
|
||||
%ignore get_buffer_for_sysdir;
|
||||
%ignore get_buffer_for_winerr;
|
||||
%ignore call_atexits;
|
||||
%ignore launch_process_params_t;
|
||||
%ignore launch_process;
|
||||
%ignore term_process;
|
||||
%ignore get_process_exit_code;
|
||||
%ignore BELOW_NORMAL_PRIORITY_CLASS;
|
||||
|
@ -148,8 +148,20 @@
|
||||
// Check that the argument is a callable Python object
|
||||
%typemap(in) PyObject *pyfunc {
|
||||
if (!PyCallable_Check($input)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Expecting a callable object");
|
||||
PyErr_SetString(PyExc_TypeError, "Expected a callable object");
|
||||
return NULL;
|
||||
}
|
||||
$1 = $input;
|
||||
}
|
||||
|
||||
// Convert ea_t
|
||||
%typemap(in) ea_t
|
||||
{
|
||||
uint64 $1_temp;
|
||||
if ( !PyW_GetNumber($input, &$1_temp) )
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "Expected an ea_t type");
|
||||
return NULL;
|
||||
}
|
||||
$1 = ea_t($1_temp);
|
||||
}
|
||||
|
@ -62,6 +62,9 @@
|
||||
%ignore print_type;
|
||||
%ignore show_type;
|
||||
%ignore show_plist;
|
||||
%ignore skip_function_arg_names;
|
||||
%ignore perform_funcarg_conversion;
|
||||
%ignore get_argloc_info;
|
||||
|
||||
%ignore extract_pstr;
|
||||
%ignore extract_name;
|
||||
@ -167,6 +170,7 @@ PyObject *idc_parse_decl(til_t *ti, const char *decl, int flags)
|
||||
bool ok = parse_decl(ti, decl, &name, &type, &fields, flags);
|
||||
if ( !ok )
|
||||
Py_RETURN_NONE;
|
||||
|
||||
return Py_BuildValue("(sss)",
|
||||
name.c_str(),
|
||||
(char *)type.c_str(),
|
||||
@ -256,7 +260,14 @@ PyObject *py_unpack_object_from_idb(
|
||||
type_t *type = (type_t *) PyString_AsString(py_type);
|
||||
p_list *fields = (p_list *) PyString_AsString(py_fields);
|
||||
idc_value_t idc_obj;
|
||||
error_t err = unpack_object_from_idb(&idc_obj, ti, type, fields, ea, NULL, pio_flags);
|
||||
error_t err = unpack_object_from_idb(
|
||||
&idc_obj,
|
||||
ti,
|
||||
type,
|
||||
fields,
|
||||
ea,
|
||||
NULL,
|
||||
pio_flags);
|
||||
|
||||
// Unpacking failed?
|
||||
if ( err != eOk )
|
||||
@ -265,9 +276,11 @@ PyObject *py_unpack_object_from_idb(
|
||||
// Convert
|
||||
PyObject *py_ret(NULL);
|
||||
err = idcvar_to_pyvar(idc_obj, &py_ret);
|
||||
|
||||
// Conversion failed?
|
||||
if ( err != CIP_OK )
|
||||
return Py_BuildValue("(ii)", 0, err);
|
||||
|
||||
PyObject *py_result = Py_BuildValue("(iO)", 1, py_ret);
|
||||
Py_DECREF(py_ret);
|
||||
return py_result;
|
||||
@ -315,7 +328,13 @@ PyObject *py_unpack_object_from_bv(
|
||||
memcpy(bytes.begin(), PyString_AsString(py_bytes), bytes.size());
|
||||
|
||||
idc_value_t idc_obj;
|
||||
error_t err = unpack_object_from_bv(&idc_obj, ti, type, fields, bytes, pio_flags);
|
||||
error_t err = unpack_object_from_bv(
|
||||
&idc_obj,
|
||||
ti,
|
||||
type,
|
||||
fields,
|
||||
bytes,
|
||||
pio_flags);
|
||||
|
||||
// Unpacking failed?
|
||||
if ( err != eOk )
|
||||
@ -324,9 +343,11 @@ PyObject *py_unpack_object_from_bv(
|
||||
// Convert
|
||||
PyObject *py_ret(NULL);
|
||||
err = idcvar_to_pyvar(idc_obj, &py_ret);
|
||||
|
||||
// Conversion failed?
|
||||
if ( err != CIP_OK )
|
||||
return Py_BuildValue("(ii)", 0, err);
|
||||
|
||||
PyObject *py_result = Py_BuildValue("(iO)", 1, py_ret);
|
||||
Py_DECREF(py_ret);
|
||||
return py_result;
|
||||
|
14
swig/ua.i
14
swig/ua.i
@ -64,6 +64,7 @@ PyObject *py_init_output_buffer(size_t size = MAXSTR)
|
||||
PyObject *py_str = PyString_FromStringAndSize(NULL, size);
|
||||
if ( py_str == NULL )
|
||||
Py_RETURN_NONE;
|
||||
|
||||
init_output_buffer(PyString_AsString(py_str), size);
|
||||
return py_str;
|
||||
}
|
||||
@ -326,6 +327,7 @@ bool py_out_name_expr(
|
||||
off = adiff_t(v);
|
||||
else
|
||||
off = BADADDR;
|
||||
|
||||
return op == NULL ? false : out_name_expr(*op, ea, off);
|
||||
}
|
||||
|
||||
@ -449,6 +451,7 @@ static void insn_t_set_cs(PyObject *self, PyObject *value)
|
||||
insn_t *link = insn_t_get_clink(self);
|
||||
if ( link == NULL )
|
||||
return;
|
||||
|
||||
uint64 v(0);
|
||||
PyW_GetNumber(value, &v);
|
||||
link->cs = ea_t(v);
|
||||
@ -886,7 +889,7 @@ class op_t(py_clinked_object_t):
|
||||
|
||||
def is_reg(self, r):
|
||||
"""Checks if the register operand is the given processor register"""
|
||||
return self.type == idaapi.o_reg and self == r
|
||||
return self.type == _idaapi.o_reg and self == r
|
||||
|
||||
def has_reg(self, r):
|
||||
"""Checks if the operand accesses the given processor register"""
|
||||
@ -1000,14 +1003,23 @@ class insn_t(py_clinked_object_t):
|
||||
def _create_clink(self):
|
||||
return _idaapi.insn_t_create()
|
||||
|
||||
|
||||
def _del_clink(self, lnk):
|
||||
return _idaapi.insn_t_destroy(lnk)
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
return (self.Operands[idx] for idx in xrange(0, UA_MAXOP))
|
||||
|
||||
|
||||
def __getitem__(self, idx):
|
||||
"""
|
||||
Operands can be accessed directly as indexes
|
||||
@return op_t: Returns an operand of type op_t
|
||||
"""
|
||||
if idx >= UA_MAXOP:
|
||||
raise KeyError
|
||||
else:
|
||||
return self.Operands[idx]
|
||||
|
||||
def is_macro(self):
|
||||
|
Loading…
Reference in New Issue
Block a user