IDAPython for IDA 7.0 SP1

This commit is contained in:
Arnaud Diederen
2017-12-05 10:37:09 +01:00
parent d99a893697
commit a0be95b7cd
25 changed files with 601 additions and 371 deletions
+63 -33
View File
@@ -3,11 +3,14 @@
# 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
import ida_idaapi
import ida_kernwin
import ida_lines
import idautils
# ----------------------------------------------------------------------
class asm_colorizer_t(object):
def is_id(self, ch):
@@ -79,11 +82,38 @@ class asm_colorizer_t(object):
x += 1
self.add_line(s)
class base_asmview_ah_t(ida_kernwin.action_handler_t):
def __init__(self, obj):
ida_kernwin.action_handler_t.__init__(self)
self.obj = obj
def update(self, ctx):
if self.obj.view and self.obj.view.GetWidget() == ctx.widget:
return ida_kernwin.AST_ENABLE_FOR_WIDGET
else:
return ida_kernwin.AST_DISABLE_FOR_WIDGET
class refresh_ah_t(base_asmview_ah_t):
def activate(self, ctx):
self.obj.view.reload_file()
print("Reloaded")
class close_ah_t(base_asmview_ah_t):
def activate(self, ctx):
self.obj.view.Close()
print("Closed")
# -----------------------------------------------------------------------
class asmview_t(idaapi.simplecustviewer_t, asm_colorizer_t):
class asmview_t(ida_kernwin.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)):
if not ida_kernwin.simplecustviewer_t.Create(
self,
"Viewing file - %s" % os.path.basename(fn)):
return False
self.instruction_list = idautils.GetInstructionList()
@@ -95,9 +125,6 @@ class asmview_t(idaapi.simplecustviewer_t, asm_colorizer_t):
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):
@@ -123,38 +150,25 @@ class asmview_t(idaapi.simplecustviewer_t, asm_colorizer_t):
self.AddLine(s)
def as_comment(self, s):
return idaapi.COLSTR(s, idaapi.SCOLOR_RPTCMT)
return ida_lines.COLSTR(s, ida_lines.SCOLOR_RPTCMT)
def as_id(self, s):
t = s.lower()
if t in self.register_list:
return idaapi.COLSTR(s, idaapi.SCOLOR_REG)
return ida_lines.COLSTR(s, ida_lines.SCOLOR_REG)
elif t in self.instruction_list:
return idaapi.COLSTR(s, idaapi.SCOLOR_INSN)
return ida_lines.COLSTR(s, ida_lines.SCOLOR_INSN)
else:
return s
def as_string(self, s):
return idaapi.COLSTR(s, idaapi.SCOLOR_STRING)
return ida_lines.COLSTR(s, ida_lines.SCOLOR_STRING)
def as_num(self, s):
return idaapi.COLSTR(s, idaapi.SCOLOR_NUMBER)
return ida_lines.COLSTR(s, ida_lines.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
return ida_lines.COLSTR(s, ida_lines.SCOLOR_KEYWORD)
def OnKeydown(self, vkey, shift):
"""
@@ -170,8 +184,8 @@ class asmview_t(idaapi.simplecustviewer_t, asm_colorizer_t):
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
if line and line[0] != ida_lines.SCOLOR_INV:
s = ida_lines.SCOLOR_INV + line + ida_lines.SCOLOR_INV
self.EditLine(lineno, s, fg, bg)
self.Refresh()
elif vkey == ord('C'):
@@ -186,8 +200,11 @@ class asmview_t(idaapi.simplecustviewer_t, asm_colorizer_t):
return True
# -----------------------------------------------------------------------
class asmviewplg(idaapi.plugin_t):
flags = idaapi.PLUGIN_KEEP
ACTNAME_REFRESH = "asmview_t::refresh"
ACTNAME_CLOSE = "asmview_t::close"
class asmviewplg(ida_idaapi.plugin_t):
flags = ida_idaapi.PLUGIN_KEEP
comment = "ASM viewer"
help = "This is help"
wanted_name = "ASM file viewer"
@@ -196,17 +213,30 @@ class asmviewplg(idaapi.plugin_t):
self.view = None
def init(self):
return idaapi.PLUGIN_KEEP
# Register actions
ida_kernwin.register_action(
ida_kernwin.action_desc_t(
ACTNAME_REFRESH, "Refresh", refresh_ah_t(self)))
ida_kernwin.register_action(
ida_kernwin.action_desc_t(
ACTNAME_CLOSE, "Close", close_ah_t(self)))
return ida_idaapi.PLUGIN_KEEP
def run(self, arg):
if self.view:
self.Close()
fn = idaapi.ask_file(0, "*.asm", "Select ASM file to view")
fn = ida_kernwin.ask_file(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()
widget = self.view.GetWidget()
# Attach actions to this widget's popup menu
ida_kernwin.attach_action_to_popup(widget, None, ACTNAME_REFRESH)
ida_kernwin.attach_action_to_popup(widget, None, ACTNAME_CLOSE)
def term(self):
if self.view:
+53 -53
View File
@@ -4,17 +4,19 @@ 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
Copyright (c) 1990-2017 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 ida_ua
import ida_bytes
import ida_kernwin
import ida_funcs
import ida_name
import ida_ida
import ida_idp
import ida_segment
import ida_dbg
import idautils
from ida_kernwin import Choose
# -----------------------------------------------------------------------
# class to take a copy of a segment_t
@@ -24,6 +26,7 @@ class Seg():
self.end_ea = s.end_ea
self.perm = s.perm
self.bitness = s.bitness
def __cmp__(self, other):
return cmp(self.start_ea, other.start_ea)
@@ -51,18 +54,18 @@ def IsPrevInsnCall(ea):
is a CALL instruction
"""
global CallPattern
if ea == idaapi.BADADDR or ea < 10:
if ea == ida_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)]
bytes = [x for x in idautils.GetDataList(caller, len(opcodes), 1)]
# do we have a match? is it a call instruction?
if bytes == opcodes:
tmp = idaapi.insn_t()
if idaapi.decode_insn(tmp, caller) and idaapi.is_call_insn(tmp):
insn = ida_ua.insn_t()
if ida_ua.decode_insn(insn, caller) and ida_idp.is_call_insn(insn):
return caller
return None
@@ -79,32 +82,35 @@ def CallStackWalk(nn):
def __init__(self, caller, sp):
self.caller = caller
self.sp = sp
f = idaapi.get_func(caller)
self.displ = ""
f = ida_funcs.get_func(caller)
self.displ = "%08x: " % caller
if f:
self.displ += idc.get_func_name(caller)
self.displ += ida_funcs.get_func_name(caller)
t = caller - f.start_ea
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)
sp = idautils.cpu.Esp
seg = ida_segment.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
sp = idautils.cpu.Esp - word_size
while sp < stack_seg.end_ea:
sp += word_size
ptr = idautils.GetDataList(sp, 1, word_size).next()
seg = idaapi.getseg(ptr)
seg = ida_segment.getseg(ptr)
# only accept executable segments
if (not seg) or ((seg.perm & idaapi.SEGPERM_EXEC) == 0):
if (not seg) or ((seg.perm & ida_segment.SEGPERM_EXEC) == 0):
continue
# try to find caller
caller = IsPrevInsnCall(ptr)
@@ -118,16 +124,16 @@ def CallStackWalk(nn):
if ret:
ea = ret[0]
# function exists?
f = idaapi.get_func(ea)
f = ida_funcs.get_func(ea)
if not f:
# create function
idc.add_func(ea, idaapi.BADADDR)
ida_funcs.add_func(ea)
# get the flags
f = idc.get_flags(caller)
f = ida_bytes.get_flags(caller)
# no code there?
if not is_code(f):
create_insn(caller)
if not ida_bytes.is_code(f):
ida_ua.create_insn(caller)
callers.append(Result(caller, sp))
#
@@ -135,52 +141,46 @@ def CallStackWalk(nn):
# -----------------------------------------------------------------------
# Chooser class
class CallStackWalkChoose(Choose):
class CallStackWalkChoose(ida_kernwin.Choose):
def __init__(self, title, items):
Choose.__init__(self, title, [ ["Caller", 16], ["Display", 250] ])
ida_kernwin.Choose.__init__(
self,
title,
[["Location", 30]])
self.items = items
def OnGetLine(self, n):
o = self.items[n]
line = []
line.append("%X" % o.caller)
line.append("%s" % o.displ)
return line
self.modal = True
def OnGetSize(self):
return len(self.items)
def OnGetLine(self, n):
return [str(self.items[n])]
def OnSelectLine(self, n):
o = self.items[n]
jumpto(o.caller)
return (Choose.NOTHING_CHANGED, )
ida_kernwin.jumpto(self.items[n].caller)
# -----------------------------------------------------------------------
def main():
if not idaapi.is_debugger_on():
idc.warning("Please run the process first!")
if not ida_dbg.is_debugger_on():
ida_kernwin.warning("Please run the process first!")
return
if idaapi.get_process_state() != -1:
idc.warning("Please suspend the debugger first!")
if ida_dbg.get_process_state() != -1:
ida_kernwin.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.min_ea, idaapi.cvar.inf.max_ea)
# initiate a nearest name search (using debug names)
nn = idaapi.NearestName(dn)
else:
nn = None
# get all debug namesp
dn = ida_name.get_debug_names(ida_ida.cvar.inf.min_ea, ida_ida.cvar.inf.max_ea)
# initiate a nearest name search (using debug names)
nn = ida_name.NearestName(dn)
ret, callstack = CallStackWalk(nn)
if ret:
title = "Call stack walker (thread %X)" % (get_current_thread())
idaapi.close_chooser(title)
title = "Call stack walker (thread %X)" % (ida_dbg.get_current_thread())
ida_kernwin.close_chooser(title)
c = CallStackWalkChoose(title, callstack)
c.Show()
c.Show(True)
else:
idc.warning("Failed to walk the stack:" + callstack)
ida_kernwin.warning("Failed to walk the stack:" + callstack)
# -----------------------------------------------------------------------
main()
+70 -57
View File
@@ -2,37 +2,70 @@
# Debugger command prompt with CustomViewers
# (c) Hex-Rays
#
import idaapi
import idc
from idaapi import simplecustviewer_t
import ida_idaapi
import ida_kernwin
import ida_lines
import ida_expr
import ida_dbg
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 'send_dbg_command' IDC command.
"""
s = idc.eval('send_dbg_command("%s");' % cmd)
if s.startswith("IDC_FAILURE"):
raise Exception, "Debugger command is available only when the debugger is active!"
return s
# The viewer instance
dbgcmd = None
# -----------------------------------------------------------------------
class dbgcmd_t(simplecustviewer_t):
class base_dbgcmd_ah_t(ida_kernwin.action_handler_t):
def __init__(self):
ida_kernwin.action_handler_t.__init__(self)
def update(self, ctx):
if dbgcmd and ctx.widget == dbgcmd.GetWidget():
return ida_kernwin.AST_ENABLE_FOR_WIDGET
else:
return ida_kernwin.AST_DISABLE_FOR_WIDGET
# -----------------------------------------------------------------------
class clear_dbgcmd_ah_t(base_dbgcmd_ah_t):
def activate(self, ctx):
dbgcmd.ResetOutput()
# -----------------------------------------------------------------------
class newcmd_dbgcmd_ah_t(base_dbgcmd_ah_t):
def activate(self, ctx):
dbgcmd.IssueCommand()
# -----------------------------------------------------------------------
class close_dbgcmd_ah_t(base_dbgcmd_ah_t):
def activate(self, ctx):
dbgcmd.Close()
# -----------------------------------------------------------------------
# Register actions (if needed)
ACTNAME_CLEAR = "dbgcmd:clear"
ACTNAME_NEWCMD = "dbgcmd:newcmd"
ACTNAME_CLOSE = "dbgcmd:close"
ida_kernwin.register_action(
ida_kernwin.action_desc_t(
ACTNAME_CLEAR, "Clear", clear_dbgcmd_ah_t(), "x"))
ida_kernwin.register_action(
ida_kernwin.action_desc_t(
ACTNAME_NEWCMD, "New command", newcmd_dbgcmd_ah_t(), "Insert"))
ida_kernwin.register_action(
ida_kernwin.action_desc_t(
ACTNAME_CLOSE, "Close", close_dbgcmd_ah_t(), "Escape"))
# -----------------------------------------------------------------------
class dbgcmd_t(ida_kernwin.simplecustviewer_t):
def Create(self):
# Form the title
title = "Debugger command window"
# Create the customview
if not simplecustviewer_t.Create(self, title):
if not ida_kernwin.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.ask_str(self.last_cmd, 0, "Please enter a debugger command")
s = ida_kernwin.ask_str(self.last_cmd, 0, "Please enter a debugger command")
if not s:
return
@@ -40,43 +73,24 @@ class dbgcmd_t(simplecustviewer_t):
self.last_cmd = s
# Add it using a different color
self.AddLine("debugger>" + idaapi.COLSTR(s, idaapi.SCOLOR_VOIDOP))
self.AddLine("debugger>" + ida_lines.COLSTR(s, ida_lines.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 send_dbg_command()", idaapi.SCOLOR_ERROR))
ok, out = ida_dbg.send_dbg_command(s)
if ok:
for line in out.split("\n"):
self.AddLine(ida_lines.COLSTR(line, ida_lines.SCOLOR_LIBNAME))
else:
self.AddLine(
ida_lines.COLSTR(
"Debugger is not active or does not export ida_dbg.send_dbg_command() (%s)" % out,
ida_lines.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.AddLine(ida_lines.COLSTR("Please press INS to enter command; X to clear output", ida_lines.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():
@@ -85,17 +99,16 @@ def show_win():
print "Failed to create debugger command line!"
return None
x.Show()
# Attach actions to this widget's popup menu
widget = x.GetWidget()
ida_kernwin.attach_action_to_popup(widget, None, ACTNAME_CLEAR)
ida_kernwin.attach_action_to_popup(widget, None, ACTNAME_NEWCMD)
ida_kernwin.attach_action_to_popup(widget, None, ACTNAME_CLOSE)
return x
try:
# created already?
dbgcmd
if dbgcmd is not None:
dbgcmd.Close()
del dbgcmd
except:
pass
dbgcmd = None
dbgcmd = show_win()
if not dbgcmd:
del dbgcmd
+64 -59
View File
@@ -2,30 +2,34 @@
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
Copyright (c) 1990-2017 Hex-Rays
ALL RIGHTS RESERVED.
"""
import re
import idc
from ida_kernwin import Choose
import ida_idaapi
import ida_expr
import ida_kernwin
import ida_dbg
# -----------------------------------------------------------------------
def WinDbg_command(cmd):
ok, s = ida_dbg.send_dbg_command(cmd)
return s if ok else False
# -----------------------------------------------------------------------
def CmdDriverList():
s = idc.eval('send_dbg_command("lm o");')
if "IDC_FAILURE" in s: return False
return s
return WinDbg_command("lm o")
# -----------------------------------------------------------------------
def CmdDrvObj(drvname, flag=2):
return idc.eval('send_dbg_command("!drvobj %s %d");' % (drvname, flag))
return WinDbg_command("!drvobj %s %d" % (drvname, flag))
# -----------------------------------------------------------------------
def CmdReloadForce():
s = idc.eval('send_dbg_command(".reload /f");')
if "IDC_FAILURE" in s: return False
return True
return WinDbg_command(".reload /f")
# -----------------------------------------------------------------------
# class to hold dispatch entry information
@@ -33,82 +37,83 @@ 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)
# return a list of arrays of the form: [addr, name]
ret_list = []
# force reloading of module symbols
if not CmdReloadForce():
print "Could not communicate with WinDbg, make sure the debugger is running!"
return None
# 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)
# get driver list
lm_out = CmdDriverList()
if not lm_out:
return "Failed to get driver list!"
# 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)
# for each line
for line in lm_out.split("\n"):
# parse
r = re_drv.match(line)
if not r: continue
# force reloading of module symbols
if not CmdReloadForce():
print "Could not communicate with WinDbg, make sure the debugger is running!"
return None
# 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
# get driver list
lm_out = CmdDriverList()
if not lm_out:
return "Failed to get driver list!"
# for each line
for line in tbl_out.split("\n"):
for line in lm_out.split("\n"):
# parse
r = re_tbl.match(line)
r = re_drv.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
# 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):
class DispatchChoose(ida_kernwin.Choose):
def __init__(self, title, items):
Choose.__init__(self, title, [ ["Address", 16], ["Name", 250] ])
ida_kernwin.Choose.__init__(
self,
title,
[["Address", 30]],
width=250)
self.items = items
def OnGetLine(self, n):
o = self.items[n]
line = []
line.append("%08X" % o.addr)
line.append("%s" % o.name)
return line
def OnGetSize(self):
return len(self.items)
def OnGetLine(self, n):
return [str(self.items[n])]
def OnSelectLine(self, n):
o = self.items[n]
Jump(o.addr)
return (Choose.NOTHING_CHANGED, )
ida_kernwin.jumpto(self.items[n].addr)
# -----------------------------------------------------------------------
# main
r = GetDriverDispatch()
if r:
c = DispatchChoose("Dispatch table browser", r)
c.Show()
c.Show(True)
else:
print "Failed to retrieve dispatchers list!"
print "Failed to retrieve dispatchers list!"
+16 -24
View File
@@ -7,56 +7,48 @@ ALL RIGHTS RESERVED.
"""
import idc
import re
import ida_kernwin
from ida_kernwin import Choose
# class to store parsed results
class exchain:
def __init__(self, m):
self.name = m.group(1)
self.addr = int(m.group(2), 16)
self.name = m.group(1)
self.addr = int(m.group(2), 16)
# Chooser class
class MyChoose(Choose):
class MyChoose(ida_kernwin.Choose):
def __init__(self, title, items):
Choose.__init__(self, title, [ ["Address", 16], ["Name", 250] ])
ida_kernwin.Choose.__init__(self, title, [ ["Address", 16], ["Name", 250] ])
self.items = items
def OnGetLine(self, n):
o = self.items[n]
line = []
line.append("%08X" % o.addr)
line.append("%s" % o.name)
return line
return ["%08X" % o.addr, o.name]
def OnGetSize(self):
return len(self.items)
def OnSelectLine(self, n):
o = self.items[n]
Jump(o.addr)
return (Choose.NOTHING_CHANGED, )
ida_kernwin.jumpto(self.items[n].addr)
return (ida_kernwin.Choose.NOTHING_CHANGED, )
# main
def main():
s = idc.eval('send_dbg_command("!exchain")')
if "IDC_FAILURE" in s:
return (False, "Cannot execute the command")
ok, s = ida_dbg.send_dbg_command("!exchain")
if not ok:
return (False, "Cannot execute the command (%s)" % s)
matches = re.finditer(r'[^:]+: ([^\(]+) \(([^\)]+)\)\n', s)
L = []
for x in matches:
L.append(exchain(x))
if not L:
entries = [exchain(x) for x in matches]
if not entries:
return (False, "Nothing to display: Could parse the result!")
# Get a Choose instance
chooser = MyChoose("Exchain choose", L)
# Run the chooser
# Show a list of results, and let the user possibly jump to one of those
chooser = MyChoose("Exchain choose", entries)
chooser.Show()
return (True, "Success!")
ok, r = main()
if not ok:
print r
+57 -46
View File
@@ -1,5 +1,5 @@
"""
FindInstructions.py: A script to help you find desired opcodes/instructions in a database
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
@@ -13,15 +13,22 @@ The general syntax is:
* 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
Copyright (c) 1990-2017 Hex-Rays
ALL RIGHTS RESERVED.
v1.0 - initial version
"""
import idaapi
import re
import ida_idaapi
import ida_lines
import ida_segment
import ida_kernwin
import ida_bytes
import ida_ua
import ida_ida
import ida_search
import ida_funcs
import idautils
import idc
from ida_kernwin import Choose
# -----------------------------------------------------------------------
def FindInstructions(instr, asm_where=None):
@@ -31,8 +38,9 @@ def FindInstructions(instr, asm_where=None):
"""
if not asm_where:
# get first segment
asm_where = get_first_seg()
if asm_where == idaapi.BADADDR:
seg = ida_segment.get_first_seg()
asm_where = seg.start_ea if seg else ida_idaapi.BADADDR
if asm_where == ida_idaapi.BADADDR:
return (False, "No segments defined")
# regular expression to distinguish between opcodes and instructions
@@ -49,7 +57,7 @@ def FindInstructions(instr, asm_where=None):
buf = ''.join([chr(int(x, 16)) for x in line.split()])
else:
# assemble the instruction
ret, buf = Assemble(asm_where, line)
ret, buf = idautils.Assemble(asm_where, line)
if not ret:
return (False, "Failed to assemble:"+line)
# add the assembled buffer
@@ -66,63 +74,66 @@ def FindInstructions(instr, asm_where=None):
# find all binary strings
print "Searching for: [%s]" % bin_str
ea = get_inf_attr(INF_MIN_EA)
ea = ida_ida.cvar.inf.min_ea
ret = []
while True:
ea = find_binary(ea, SEARCH_DOWN, bin_str)
if ea == idaapi.BADADDR:
ea = ida_search.find_binary(ea, ida_idaapi.BADADDR, bin_str, 16, ida_search.SEARCH_DOWN)
if ea == ida_idaapi.BADADDR:
break
ret.append(ea)
msg(".")
ida_kernwin.msg(".")
ea += tlen
if not ret:
return (False, "Could not match [%s]" % bin_str)
msg("\n")
ida_kernwin.msg("\n")
return (True, ret)
# -----------------------------------------------------------------------
# Chooser class
class SearchResultChoose(Choose):
class SearchResultChoose(ida_kernwin.Choose):
def __init__(self, title, items):
Choose.__init__(self, title, [ ["Address", 16], ["Results", 250] ])
ida_kernwin.Choose.__init__(
self,
title,
[["Address", 30], ["Function (or segment)", 25], ["Instruction", 20]],
width=250)
self.items = items
def OnGetLine(self, n):
o = self.items[n]
line = []
line.append("%08X" % o.ea)
line.append("%s" % o.display)
return line
def OnGetSize(self):
return len(self.items)
def OnGetLine(self, n):
i = self.items[n]
ea = i.ea
return [
hex(i.ea),
i.funcname_or_segname,
i.text
]
def OnSelectLine(self, n):
o = self.items[n]
Jump(o.ea)
return (Choose.NOTHING_CHANGED, )
ida_kernwin.jumpto(self.items[n].ea)
# -----------------------------------------------------------------------
# class to represent the results
class SearchResult:
def __init__(self, ea):
self.ea = ea
if not is_code(get_flags(ea)):
create_insn(ea)
t = idaapi.generate_disasm_line(ea)
self.funcname_or_segname = ""
self.text = ""
if not ida_bytes.is_code(ida_bytes.get_flags(ea)):
ida_ua.create_insn(ea)
# text
t = ida_lines.generate_disasm_line(ea)
if t:
line = idaapi.tag_remove(t)
else:
line = ""
func = get_func_name(ea)
self.display = ""
if func:
self.display += func + ": "
else:
n = get_segm_name(ea)
if n:
self.display += n + ": "
self.display += line
self.text = ida_lines.tag_remove(t)
# funcname_or_segname
n = ida_funcs.get_func_name(ea) \
or ida_segment.get_segm_name(ida_segment.getseg(ea))
if n:
self.funcname_or_segname = n
# -----------------------------------------------------------------------
def find(s=None, x=False, asm_where=None):
@@ -132,16 +143,16 @@ def find(s=None, x=False, asm_where=None):
if x:
results = []
for ea in ret:
seg = idaapi.getseg(ea)
if (not seg) or (seg.perm & idaapi.SEGPERM_EXEC) == 0:
seg = ida_segment.getseg(ea)
if (not seg) or (seg.perm & ida_segment.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)
ida_kernwin.close_chooser(title)
c = SearchResultChoose(title, results)
c.Show()
c.Show(True)
else:
print ret
+13 -11
View File
@@ -4,12 +4,14 @@
#
# (c) Hex-Rays
#
import idaapi
import idc
import idautils
import re
import ida_kernwin
import ida_nalt
import ida_funcs
import idautils
# -----------------------------------------------------------------------
def find_imported_funcs(dllname):
def imp_cb(ea, name, ord):
@@ -19,12 +21,12 @@ def find_imported_funcs(dllname):
return True
imports = []
nimps = idaapi.get_import_module_qty()
nimps = ida_nalt.get_import_module_qty()
for i in xrange(0, nimps):
name = idaapi.get_import_module_name(i)
name = ida_nalt.get_import_module_name(i)
if re.match(dllname, name, re.IGNORECASE) is None:
continue
idaapi.enum_import_names(i, imp_cb)
ida_nalt.enum_import_names(i, imp_cb)
return imports
@@ -38,9 +40,9 @@ def find_import_ref(dllname):
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.start_ea, idaapi.get_func_name(f.start_ea), 0])
f = ida_funcs.get_func(ea)
if f and (f.flags & ida_funcs.FUNC_THUNK) != 0:
imports.append([f.start_ea, ida_funcs.get_func_name(f.start_ea), 0])
#print "\t%x %s: from a thunk, parent added %x" % (ea, name, f.start_ea)
continue
@@ -54,7 +56,7 @@ def find_import_ref(dllname):
# -----------------------------------------------------------------------
def main():
dllname = idaapi.ask_str('kernel32', 0, "Enter module name")
dllname = ida_kernwin.ask_str('kernel32', 0, "Enter module name")
if not dllname:
print("Cancelled")
return
+22 -20
View File
@@ -1,8 +1,9 @@
import idaapi
import idc
from ida_kernwin import Choose
def parse_pte(str):
import ida_kernwin
import ida_segment
import ida_dbg
def parse_pte(s):
try:
parse_pte.re
except:
@@ -10,15 +11,17 @@ def parse_pte(str):
parse_pte.items = ('pde', 'pte', 'pdec', 'ptec', 'pdepfn', 'pdepfns', 'ptepfn', 'ptepfns')
m = parse_pte.re.search(s)
if not m:
return None
r = {}
for i in range(0, len(parse_pte.items)):
r[parse_pte.items[i]] = m.group(i+1)
return r
class MyChoose(Choose):
class MyChoose(ida_kernwin.Choose):
def __init__(self, title, ea1, ea2):
Choose.__init__(self, title, [ ["VA", 10], ["PTE attr", 30] ])
ida_kernwin.Choose.__init__(self, title, [ ["VA", 10], ["PTE attr", 30] ])
self.ea1 = ea1
self.ea2 = ea2
self.icon = 5
@@ -26,17 +29,14 @@ class MyChoose(Choose):
self.Refresh()
def OnGetLine(self, n):
print("getline %d" % n)
return self.items[n]
def OnGetSize(self):
n = len(self.items)
self.Refresh()
return n
return len(self.items)
def OnRefresh(self, n):
print("refresh %d" % n)
return None # call standard refresh
self.Refresh()
return (ida_kernwin.Choose.ALL_CHANGED, )
def Refresh(self):
items = []
@@ -44,11 +44,12 @@ class MyChoose(Choose):
ea1 = self.ea1
npages = (self.ea2 - ea1) / PG
for i in range(npages):
r = idc.send_dbg_command("!pte %x" % ea1)
if not r:
ok, r = ida_dbg.send_dbg_command("!pte %x" % ea1)
if not ok:
return False
r = parse_pte(r)
items.append([hex(ea1), r['ptepfns']])
if r:
items.append([hex(ea1), r['ptepfns']])
ea1 += PG
self.items = items
@@ -66,16 +67,17 @@ def DumpPTE(ea1, ea2):
PG = 0x1000
npages = (ea2 - ea1) / PG
for i in range(npages):
r = idc.send_dbg_command("!pte %x" % ea1)
if not r:
ok, r = ida_dbg.send_dbg_command("!pte %x" % ea1)
if not ok:
return False
print r
r = parse_pte(r)
print("VA: %08X PTE: %s PDE: %s" % (ea1, r['ptepfns'], r['pdepfns']))
if r:
print("VA: %08X PTE: %s PDE: %s" % (ea1, r['ptepfns'], r['pdepfns']))
ea1 += PG
def DumpSegPTE(ea):
DumpPTE(idc.get_segm_start(ea), idc.get_segm_end(ea))
s = ida_segment.getseg(ea)
DumpPTE(s.start_ea, s.end_ea)
DumpSegPTE(here())
+23 -24
View File
@@ -4,26 +4,24 @@ 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
Copyright (c) 1990-2017 Hex-Rays
ALL RIGHTS RESERVED.
v1.0 - initial version
"""
import idaapi
import idautils
import idc
import ida_kernwin
import ida_graph
import ida_idd
import ida_dbg
import ida_funcs
from idaapi import GraphViewer
import idautils
# -----------------------------------------------------------------------
# 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('send_dbg_command("dg %x")' % cpu.fs)
if "IDC_FAILURE" in s:
ok, s = ida_dbg.send_dbg_command("dg %x" % idautils.cpu.fs)
if not ok:
return 0
m = re.compile("[0-9a-f]{4} ([0-9a-f]{8})")
t = m.match(s.split('\n')[-2])
@@ -33,8 +31,8 @@ def WindbgGetRegBase(tid):
# -----------------------------------------------------------------------
def GetFsBase(tid):
idc.select_thread(tid)
base = idaapi.dbg_get_thread_sreg_base(tid, cpu.fs)
ida_dbg.select_thread(tid)
base = ida_idd.dbg_get_thread_sreg_base(tid, idautils.cpu.fs)
if base != 0:
return base
return WindbgGetRegBase(tid)
@@ -43,7 +41,8 @@ def GetFsBase(tid):
# Walks the SEH chain and returns a list of handlers
def GetExceptionChain(tid):
fs_base = GetFsBase(tid)
exc_rr = get_wide_dword(fs_base)
print("FS_BASE for %s: %s (cpu.fs=%s)" % (repr(tid), repr(fs_base), repr(idautils.cpu.fs)))
exc_rr = ida_bytes.get_wide_dword(fs_base)
result = []
while exc_rr != 0xffffffff:
prev = get_wide_dword(exc_rr)
@@ -53,9 +52,9 @@ def GetExceptionChain(tid):
return result
# -----------------------------------------------------------------------
class SEHGraph(GraphViewer):
class SEHGraph(ida_graph.GraphViewer):
def __init__(self, title, result):
GraphViewer.__init__(self, title)
ida_graph.GraphViewer.__init__(self, title)
self.result = result
self.names = {} # ea -> name
@@ -74,13 +73,13 @@ class SEHGraph(GraphViewer):
# Add each handler
for handler in chain:
# Check if a function is created at the handler's address
f = idaapi.get_func(handler)
f = ida_funcs.get_func(handler)
if not f:
# create function
idc.add_func(handler, idaapi.BADADDR)
ida_funcs.add_func(handler)
# Node label is function name or address
s = get_func_name(handler)
s = ida_funcs.get_func_name(handler)
if not s:
s = "%x" % handler
@@ -110,7 +109,7 @@ class SEHGraph(GraphViewer):
def OnDblClick(self, node_id):
is_thread, value, label = self[node_id]
if is_thread:
idc.select_thread(value)
ida_dbg.select_thread(value)
self.Show()
s = "SEH chain for " + hex(value)
t = "-" * len(s)
@@ -121,18 +120,18 @@ class SEHGraph(GraphViewer):
print "%x: %s" % (handler, self.names[handler])
print t
else:
idc.jumpto(value)
ida_kernwin.jumpto(value)
return True
# -----------------------------------------------------------------------
def main():
if not idaapi.dbg_can_query():
if not ida_idd.dbg_can_query():
print "The debugger must be active and suspended before using this script!"
return
# Save current thread id
tid = get_current_thread()
tid = ida_dbg.get_current_thread()
# Iterate through all function instructions and take only call instructions
result = {}
@@ -140,7 +139,7 @@ def main():
result[tid] = GetExceptionChain(tid)
# Restore previously selected thread
idc.select_thread(tid)
ida_dbg.select_thread(tid)
# Build the graph
g = SEHGraph("SEH graph", result)
+8 -9
View File
@@ -7,11 +7,10 @@ ALL RIGHTS RESERVED.
"""
import idc
from ida_kernwin import Choose
import re
import ida_kernwin
# class to store parsed results
class memva:
def __init__(self, m):
@@ -29,7 +28,7 @@ class memva:
self.typestr = ""
# Chooser class
class MemChoose(Choose):
class MemChoose(ida_kernwin.Choose):
def __init__(self, title, items):
headers = []
headers.append(["Base", 10])
@@ -37,7 +36,7 @@ class MemChoose(Choose):
headers.append(["State", 20])
headers.append(["Protect", 20])
headers.append(["Type", 20])
Choose.__init__(self, title, headers)
ida_kernwin.Choose.__init__(self, title, headers)
self.items = items
def OnGetLine(self, n):
@@ -55,13 +54,13 @@ class MemChoose(Choose):
def OnSelectLine(self, n):
o = self.items[n]
idc.jumpto(o.base)
return (NOTHING_CHANGED, )
ida_kernwin.jumpto(o.base)
return (ida_kernwin.Choose.NOTHING_CHANGED, )
# main
def main():
s = idc.eval('send_dbg_command("!vadump")')
if "IDC_FAILURE" in s:
ok, s = ida_dbg.send_dbg_command("!vadump")
if not ok:
return (False, "Cannot execute the command")
matches = re.finditer(r'BaseAddress:\s*?(\w+?)\n' \
+26 -26
View File
@@ -5,30 +5,33 @@ This script fetches the API reference (from MSDN) of a given highlighted identif
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
# -----------------------------------------------------------------------
import ida_kernwin
import ida_name
import ida_idaapi
try:
import feedparser
except:
ida_kernwin.warning('Feedparser package not installed')
# -----------------------------------------------------------------------
class msdnapihelp_plugin_t(idaapi.plugin_t):
flags = idaapi.PLUGIN_UNL
class msdnapihelp_plugin_t(ida_idaapi.plugin_t):
flags = ida_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
return ida_idaapi.PLUGIN_OK
@staticmethod
def sanitize_name(name):
t = idaapi.FUNC_IMPORT_PREFIX
t = ida_name.FUNC_IMPORT_PREFIX
if name.startswith(t):
return name[len(t):]
return name
@@ -36,28 +39,25 @@ class msdnapihelp_plugin_t(idaapi.plugin_t):
def run(self, arg):
# Get the highlighted identifier
v = idaapi.get_current_viewer()
id = ida_kernwin.get_highlight(v)[0]
if not id:
v = ida_kernwin.get_current_viewer()
ident, ok = ida_kernwin.get_highlight(v)
if not ok:
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)
ident = self.sanitize_name(ident)
print "Looking up '%s' in MSDN online" % ident
qurl = "https://social.msdn.microsoft.com/search/en-US/feed?query=%s&format=RSS&theme=feed%%2fen-us"
d = feedparser.parse(qurl % ident)
if len(d['entries']) > 0:
url = d['entries'][0].link
webbrowser.open_new_tab(url)
if arg > 0:
print("URL: %s" % url)
else:
import webbrowser
webbrowser.open_new_tab(url)
else:
print "API documentation not found for: %s" % id
print "API documentation not found for: %s" % ident
def term(self):
Binary file not shown.
+8
View File
@@ -2611,6 +2611,7 @@ AF_FINAL = 0x80000000 # Final pass of analysis
INF_AF2 = 44 # uint32; Analysis flags 2
AF2_DOEH = 0x00000001 # Handle EH information
AF2_DORTTI = 0x00000002 # Handle RTTI information
INF_BASEADDR = 48 # uval_t; base paragraph of the program
INF_START_SS = 52 # int32; value of SS at the start
@@ -8338,6 +8339,13 @@ if sys.modules["__main__"].IDAPYTHON_COMPAT_695_API:
def MakeStr(ea, endea):
return create_strlit(ea, endea)
def GetProcessorName():
return ida_ida.cvar.inf.procname
def SegStart(ea): return get_segm_start(ea)
def SegEnd(ea): return get_segm_end(ea)
def SetSegmentType(ea, type): return set_segm_type(ea, type)
# Convenience functions:
def here(): return get_screen_ea()
def is_mapped(ea): return (prev_addr(ea+1)==ea)
+28
View File
@@ -1,5 +1,7 @@
#<pycode(py_dbg)>
import ida_idaapi
import ida_idd
import ida_expr
def get_tev_reg_val(tev, reg):
rv = ida_idd.regval_t()
@@ -27,6 +29,32 @@ def get_tev_reg_mem_ea(tev, idx):
if get_insn_tev_reg_mem(tev, mis):
if idx >= 0 and idx < mis.size():
return mis[idx].ea
def send_dbg_command(command):
"""
Send a direct command to the debugger backend, and
retrieve the result as a string.
Note: any double-quotes in 'command' must be backslash-escaped.
Note: this only works with some debugger backends: Bochs, WinDbg, GDB.
Returns: (True, <result string>) on success, or (False, <Error message string>) on failure
"""
rv = ida_expr.idc_value_t()
err = ida_expr.eval_idc_expr(rv, ida_idaapi.BADADDR, """send_dbg_command("%s");""" % command)
if err:
return False, "eval_idc_expr() failed: %s" % err
vtype = ord(rv.vtype)
if vtype == ida_expr.VT_STR:
s = rv.c_str()
if "IDC_FAILURE" in s:
return False, "eval_idc_expr() reported an error: %s" % s
return True, s
elif vtype == ida_expr.VT_LONG:
return True, str(rv.num)
else:
return False, "eval_idc_expr(): wrong return type: %d" % vtype
#</pycode(py_dbg)>
#<pycode_BC695(py_dbg)>
+7 -3
View File
@@ -236,11 +236,15 @@ static PyObject *dbg_get_thread_sreg_base(PyObject *py_tid, PyObject *py_sreg_va
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !dbg_can_query() || !PyInt_Check(py_tid) || !PyInt_Check(py_sreg_value) )
if ( !dbg_can_query()
|| (!PyInt_Check(py_tid) && !PyLong_Check(py_tid))
|| (!PyInt_Check(py_sreg_value) && !PyLong_Check(py_sreg_value)) )
{
Py_RETURN_NONE;
}
ea_t answer;
thid_t tid = PyInt_AsLong(py_tid);
int sreg_value = PyInt_AsLong(py_sreg_value);
thid_t tid = PyLong_AsLong(py_tid);
int sreg_value = PyLong_AsLong(py_sreg_value);
if ( internal_get_sreg_base(&answer, tid, sreg_value) != 1 )
Py_RETURN_NONE;
+5 -2
View File
@@ -224,11 +224,14 @@ class Appcall_callable__(object):
class Appcall_consts__(object):
"""Helper class used by Appcall.Consts attribute
It is used to retrieve constants via attribute access"""
def __init__(self, default=0):
def __init__(self, default=None):
self.__default = default
def __getattr__(self, attr):
return Appcall__.valueof(attr, self.__default)
v = Appcall__.valueof(attr, self.__default)
if v is None:
raise ValueError, "No constant with name " + attr
return v
# -----------------------------------------------------------------------
class Appcall__(object):
+4 -1
View File
@@ -91,7 +91,10 @@ chtype_segreg=chtype_srcp
close_tform=close_widget
find_tform=find_widget
get_current_tform=get_current_widget
get_highlighted_identifier=get_highlight
def get_highlighted_identifier():
thing = get_highlight(get_current_widget())
if thing and thing[1]:
return thing[0]
get_tform_title=get_widget_title
get_tform_type=get_widget_type
is_chooser_tform=is_chooser_widget
+15
View File
@@ -67,6 +67,21 @@
%ignore close_linput;
%rename (close_linput) py_close_linput;
%apply qstrvec_t *out { qstrvec_t *dirs };
%cstring_output_buf_and_size_returning_charptr(
1,
char *buf,
size_t bufsize,
const char *filename,
const char *subdir); // getsysfile
%cstring_output_buf_and_size_returning_charptr(
3,
linput_t *li,
int64 fpos,
char *buf,
size_t bufsize); // qlgetz
%include "diskio.hpp"
%{
+6
View File
@@ -63,6 +63,12 @@
%ignore compile_idc_text;
%rename (compile_idc_text) py_compile_idc_text;
%cstring_output_buf_and_size_returning_charptr(
1,
char *buf,
size_t bufsize,
const char *file); // get_idc_filename
%nonnul_argument_prototype(
bool py_compile_idc_file(const char *nonnul_line, qstring *errbuf),
const char *nonnul_line);
+11
View File
@@ -7,4 +7,15 @@
%ignore register_custom_fixup;
%ignore unregister_custom_fixup;
%cstring_output_qstring_returning_charptr(
1,
qstring *buf,
ea_t source); // fixup_data_t::get_desc
%cstring_output_qstring_returning_charptr(
1,
qstring *buf,
ea_t source,
const fixup_data_t &fd); // get_fixup_desc
%include "fixup.hpp"
+14
View File
@@ -80,6 +80,20 @@
static PyObject *AssembleLine(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *nonnul_line),
const char *nonnul_line);
#ifndef SWIGIMPORTED // let's not modify the wrappers for modules %import'ing us (e.g., typeinf.i, hexrays.i)
%cstring_output_buf_and_size_returning_charptr(
1,
char *buf,
size_t bufsize); // get_idp_name
#endif // SWIGIMPORTED
%cstring_output_qstring_returning_charptr(
1,
qstring *out,
const char *name,
uint32 disable_mask,
int demreq); // ev_demangle_name
%include "idp.hpp"
%include "config.hpp"
+18
View File
@@ -131,6 +131,9 @@ extern plugin_t PLUGIN;
%ignore place_t__serialize;
%ignore place_t::deserialize;
%ignore place_t__deserialize;
%ignore place_t::generate;
%ignore place_t__generate;
%rename (generate) py_generate;
%ignore register_place_class;
%ignore register_loc_converter;
@@ -297,6 +300,21 @@ static void _py_unregister_compiled_form(PyObject *py_form, bool shutdown);
static enumplace_t *as_enumplace_t(place_t *p) { return (enumplace_t *) p; }
static structplace_t *as_structplace_t(place_t *p) { return (structplace_t *) p; }
static simpleline_place_t *as_simpleline_place_t(place_t *p) { return (simpleline_place_t *) p; }
PyObject *py_generate(void *ud, int maxsize)
{
qstrvec_t lines;
int deflnnum = 0;
color_t pfx_color = 0;
bgcolor_t bgcolor = DEFCOLOR;
int generated = $self->generate(&lines, &deflnnum, &pfx_color, &bgcolor, ud, maxsize);
PyObject *tuple = PyTuple_New(4);
PyTuple_SetItem(tuple, 0, qstrvec2pylist(lines));
PyTuple_SetItem(tuple, 1, PyLong_FromLong(deflnnum));
PyTuple_SetItem(tuple, 2, PyLong_FromLong(uchar(pfx_color)));
PyTuple_SetItem(tuple, 3, PyLong_FromLong(bgcolor));
return tuple;
}
}
%extend twinpos_t {
+6
View File
@@ -255,6 +255,12 @@
%ignore remove_tinfo_pointer;
%rename (remove_tinfo_pointer) py_remove_tinfo_pointer;
%cstring_output_buf_and_size_returning_charptr(
2,
ea_t ea,
char *buf,
size_t bufsize); // idc_guess_type, idc_get_type
%include "typeinf.hpp"
// Custom wrappers
+60 -3
View File
@@ -468,6 +468,28 @@ static PyObject *type##_get_clink_ptr(PyObject *self)
}
%enddef
//-------------------------------------------------------------------------
// and a helper for overriding the 'argout' of some of those functions,
// that return the input char* as return code; those build on recent
// versions of Xcode (>= 9.0), and need special care
%define %cstring_output_buf_and_size_returning_charptr(BUFIDX, ...)
%typemap(argout) (__VA_ARGS__) {
// cstring_output_buf_and_size_returning_charptr's argout
Py_XDECREF(resultobj);
if (result != NULL)
{
resultobj = PyString_FromString($BUFIDX);
}
else
{
Py_INCREF(Py_None);
resultobj = Py_None;
}
qfree($BUFIDX);
}
%enddef
//---------------------------------------------------------------------
// IN/OUT qstring
//---------------------------------------------------------------------
@@ -491,8 +513,43 @@ static PyObject *type##_get_clink_ptr(PyObject *self)
// Nothing. We certainly don't want 'temp' to be deleted.
}
//---------------------------------------------------------------------
// md5/sha256 hash retrieval
//-------------------------------------------------------------------------
// see %cstring_output_buf_and_size_returning_charptr above
%define %cstring_output_qstring_returning_charptr(BUFIDX, ...)
%typemap(argout) (__VA_ARGS__) {
// cstring_output_qstring_returning_charptr's argout
Py_XDECREF(resultobj);
if (result != NULL)
{
resultobj = PyString_FromStringAndSize($BUFIDX->begin(), $BUFIDX->length());
}
else
{
Py_INCREF(Py_None);
resultobj = Py_None;
}
}
%enddef
//-------------------------------------------------------------------------
// OUT qstrvec_t
//-------------------------------------------------------------------------
%typemap(in,numinputs=0) qstrvec_t *out (qstrvec_t temp) {
$1 = &temp;
}
%typemap(argout) qstrvec_t *out
{
Py_XDECREF(resultobj);
resultobj = qstrvec2pylist(*($1));
}
%typemap(freearg) qstrvec_t* out
{
// Nothing. We certainly don't want 'temp' to be deleted.
}
//-------------------------------------------------------------------------
// md5/sha256 hash retrieval
//-------------------------------------------------------------------------
%typemap(in, numinputs=0) uchar hash[ANY] (uchar temp[$1_dim0])
{
$1 = temp;
@@ -771,7 +828,7 @@ struct wrapped_array_t {
%{
static PyObject *qstrvec2pylist(qstrvec_t &vec)
static PyObject *qstrvec2pylist(const qstrvec_t &vec)
{
size_t n = vec.size();
PyObject *py_list = PyList_New(n);
+4
View File
@@ -64,6 +64,10 @@ forbidden = [
"SaveBase",
"eval",
"MakeStr",
"GetProcessorName",
"SegStart",
"SegEnd",
"SetSegmentType",
]
symbols_modules = {