IDAPython for IDA 9.1

This commit is contained in:
Arnaud Diederen
2025-03-13 16:17:53 +01:00
parent ae62cd4df5
commit af978e79e6
348 changed files with 62240 additions and 180466 deletions
+1
View File
@@ -0,0 +1 @@
from PySide6.QtCore import *
+1
View File
@@ -0,0 +1 @@
from PySide6.QtGui import *
+1
View File
@@ -0,0 +1 @@
from PySide6.QtWidgets import *
+17
View File
@@ -0,0 +1,17 @@
print("#" * 70)
print("""# Please note that IDA is now using Qt 6, and PyQt5
# support will be dropped eventually.
# It is recommended to port your scripts/plugins to PySide6
# as soon as possible.
# Essentially, that means rewriting statement such as:
#
# import PyQt5
# import PyQt5.QtWidgets
# from PyQt5.QtGui import QGuiApplication
#
# into:
#
# import PySide6
# import PySide6.QtWidgets
# from PySide6.QtGui import QGuiApplication""")
print("#" * 70)
+1
View File
@@ -0,0 +1 @@
# Placeholder
+1 -1
View File
@@ -15,7 +15,7 @@ Latest stable versions of IDAPython are available from
## Resources
The full function cross-reference is readable online at
https://www.hex-rays.com/products/ida/support/idapython_docs/
https://python.docs.hex-rays.com
Mailing list for the project is hosted by Google Groups at
https://groups.google.com/g/idapython
-5
View File
@@ -13,8 +13,3 @@ please run `idapyswitch` from the IDA directory. It will scan for Python
installs present in the system's standard locations and offer you to choose one.
It also supports optional command-line switches to handle non-standard installs.
Run `idapyswitch -h` to see them.
On Windows, you may need to run it as administrator
so it can patch sip.pyd (library required for PyQt bindings).
-2
View File
@@ -21,7 +21,6 @@ dbg.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
demangle.hpp - EXCLUDED
diskio.hpp - INCOMPLETE (no SWIGs, some unwrapped)
entry.hpp - COMPLETE
enum.hpp - COMPLETE
err.h - EXCLUDED
exehdr.h - EXCLUDED
expr.hpp - COMPLETE (necessary SWIGs)
@@ -57,7 +56,6 @@ segment.hpp - COMPLETE
sistack.hpp - EXCLUDED
segregs.hpp - INCOMPLETE (not wrapped at all)
strlist.hpp - COMPLETE
struct.hpp - COMPLETE
typeinf.hpp - INCOMPLETE (no SWIGs, lot of fixing to do)
ua.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
va.hpp - EXCLUDED
+2 -2
View File
@@ -4,7 +4,7 @@ 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-2024 Hex-Rays
Copyright (c) 1990-2025 Hex-Rays
ALL RIGHTS RESERVED.
"""
import ida_ua
@@ -169,7 +169,7 @@ def main():
return
# get all debug namesp
dn = ida_name.get_debug_names(ida_ida.cvar.inf.min_ea, ida_ida.cvar.inf.max_ea)
dn = ida_name.get_debug_names(ida_ida.inf_get_min_ea(), ida_ida.inf_get_max_ea())
# initiate a nearest name search (using debug names)
nn = ida_name.NearestName(dn)
+1 -1
View File
@@ -2,7 +2,7 @@
A script to demonstrate how to send commands to the debugger and then parse and use the output in IDA
Copyright (c) 1990-2024 Hex-Rays
Copyright (c) 1990-2025 Hex-Rays
ALL RIGHTS RESERVED.
"""
+1 -1
View File
@@ -2,7 +2,7 @@
This script shows how to send debugger commands and use the result in IDA
Copyright (c) 1990-2024 Hex-Rays
Copyright (c) 1990-2025 Hex-Rays
ALL RIGHTS RESERVED.
"""
+3 -4
View File
@@ -13,7 +13,7 @@ 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-2024 Hex-Rays
Copyright (c) 1990-2025 Hex-Rays
ALL RIGHTS RESERVED.
"""
from __future__ import print_function
@@ -27,7 +27,6 @@ import ida_kernwin
import ida_bytes
import ida_ua
import ida_ida
import ida_search
import ida_funcs
import idautils
@@ -76,10 +75,10 @@ def FindInstructions(instr, asm_where=None):
# find all binary strings
print("Searching for: [%s]" % bin_str)
ea = ida_ida.cvar.inf.min_ea
ea = ida_ida.inf_get_min_ea()
ret = []
while True:
ea = ida_search.find_binary(ea, ida_idaapi.BADADDR, bin_str, 16, ida_search.SEARCH_DOWN)
ea = ida_bytes.find_bytes(bin_str, ea, radix=16)
if ea == ida_idaapi.BADADDR:
break
ret.append(ea)
+1 -1
View File
@@ -4,7 +4,7 @@ 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-2024 Hex-Rays
Copyright (c) 1990-2025 Hex-Rays
ALL RIGHTS RESERVED.
"""
from __future__ import print_function
+1 -1
View File
@@ -2,7 +2,7 @@
This script shows how to send debugger commands and use the result in IDA
Copyright (c) 1990-2024 Hex-Rays
Copyright (c) 1990-2025 Hex-Rays
ALL RIGHTS RESERVED.
"""
+1 -1
View File
@@ -2,7 +2,7 @@ from __future__ import print_function
# -----------------------------------------------------------------------
# VirusTotal IDA Plugin
# By Elias Bachaalany <elias at hex-rays.com>
# (c) Hex-Rays 2011-2024
# (c) Hex-Rays 2011-2025
#
# Special thanks:
# - VirusTotal team
+72
View File
@@ -0,0 +1,72 @@
# API examples
This file contains the list of all the IDA python examples.
## func
* decompile_func_and_callees.py
* list_func_callees.py
* print_location_info.py
* sort_func_by_calls.py
## gdl
* colorize_graph_node.py
## hexrays
* hr_decompile_func_and_callees.py
## idb
* frame_event_listener.py
* lt_event_listener.py
## idp
* log_idp_events.py
## inf
* print_basic_info.py
* print_basic_info_plugin.py
## misc
* find_binary_pattern.py
## segm
* list_imports.py
## typeinf
* add_frame_member.py
* apply_callee_tinfo.py
* change_stkvar_name.py
* change_stkvar_type.py
* create_array.py
* create_bfstruct.py
* create_bmenum.py
* create_libssh2_til.py
* create_structs.py
* create_user_shared_data.py
* del_struct_members.py
* func_ti_changed_listener.py
* gap_size_align_snippet.py
* import_type_from_til.py
* insert_gap.py
* list_enum_member.py
* list_frame_info.py
* list_func_details.py
* list_stkvar_xrefs.py
* list_struct_accesses.py
* list_struct_member.py
* list_struct_xrefs.py
* list_union_member.py
* mark_func_spoiled.py
* operand_to_struct_member.py
* setpehdr.py
* visit_tinfo.py
+104
View File
@@ -0,0 +1,104 @@
import ida_idaapi
import ida_dbg
import ida_kernwin
import ida_name
import ida_idd
import ida_bytes
import ida_ida
import ida_ua
import idc
import os
ST_NONE = 0
ST_RUNTO = 1
ST_ADD_BPT = 2
ST_MONITOR = 3
func_name = 'kernelbase_CreateFileW'
class filemon_dbg_hook_t(ida_dbg.DBG_Hooks):
def __init__(self):
ida_dbg.DBG_Hooks.__init__(self)
self.func_entry_ea = ida_idaapi.BADADDR
ida_dbg.run_to(ida_ida.inf_get_start_ea())
self.stage = ST_RUNTO
def dbg_process_start(self, pid, tid, ea, path, base, size):
name = os.path.basename(path)
ida_kernwin.msg(f'Process started: {name}.\n\tLoad address: {base:x}\n\tPID: {pid:x}\n')
def dbg_run_to(self, pid, tid=0, ea=0):
if self.stage == ST_RUNTO:
ida_kernwin.msg(f'Run to: {ea:x}\n')
self.stage = ST_ADD_BPT
def dbg_suspend_process(self):
all_good = True
if self.stage == ST_ADD_BPT:
ida_dbg.refresh_debugger_memory()
self.func_entry_ea = ida_name.get_name_ea(ida_idaapi.BADADDR, func_name)
if self.func_entry_ea == ida_idaapi.BADADDR:
all_good = False
ida_kernwin.msg('Could not resolve \n')
else:
ida_kernwin.msg(f'{func_name} found @ {self.func_entry_ea:x}. Setting breakpoint.\n')
if ida_dbg.add_bpt(self.func_entry_ea):
ida_kernwin.msg('Breakpoint added\n')
else:
ida_kernwin.msg('Failed to add the breakpoint.\n')
if not all_good:
ida_dbg.request_exit_process()
ida_dbg.run_requests()
else:
ida_dbg.continue_process()
self.stage = ST_MONITOR
def dbg_bpt(self, tid, bpt_ea):
if self.stage == ST_MONITOR:
ida_kernwin.msg(f'In dbg_bpt {bpt_ea:x}.\n')
if bpt_ea == self.func_entry_ea:
ida_kernwin.msg('Trying to retreive RCX: ')
rcx_val = ida_idd.regval_t()
if not ida_dbg.get_reg_val('rcx', rcx_val):
ida_kernwin.msg('Could not get rcx register.\n')
return 0
fn_ea = rcx_val.ival
ida_kernwin.msg(f'{fn_ea:x}\n')
if not ida_bytes.is_mapped(fn_ea):
ida_dbg.invalidate_dbgmem_config()
ida_dbg.invalidate_dbgmem_contents(fn_ea, 1024)
len = ida_bytes.get_max_strlit_length(fn_ea, idc.STRTYPE_C_16)
ida_kernwin.msg(f'String length: {len}.\n')
if len:
raw = ida_bytes.get_strlit_contents(fn_ea, len, idc.STRTYPE_C_16)
ida_kernwin.msg(f' CreateFile -> {raw.decode('UTF-8')}\n')
ida_dbg.continue_process()
return 0
def dbg_process_exit(self, pid, tid, ea, code):
if not self.func_entry_ea == ida_idaapi.BADADDR:
ida_dbg.del_bpt(self.func_entry_ea)
self.func_entry_ea = ida_idaapi.BADADDR
self.stage = ST_NONE
try:
dbg_hook_stat = "un"
print("Filemon DBG hook: checking for hook...")
dbg_hook
print("Filemon DBG hook: unhooking....")
dbg_hook_stat2 = ""
dbg_hook.unhook()
del dbg_hook
except:
print("Filemon DBG hook: not installed, installing now....")
dbg_hook_stat = ""
dbg_hook_stat2 = "un"
dbg_hook = filemon_dbg_hook_t()
dbg_hook.hook()
+56
View File
@@ -0,0 +1,56 @@
"""
summary: This script shows an example of function clasification
using the dirtree API.
description:
In this example we calssify the functions of ntdll.dll into
three categories (there are more but three is enough for this
example):
* Runtime library (Rtl).
* System calls (Zw).
* Kernel internal (Ki)
For each category we create a corresponding folder in the functions
dirtreee. Then we iterates through all the functions and use the
folder name as filter: namely if a function name starts with 'Rtl'
it is moved to the Rtl folder and so on.
level: intermediate.
"""
import ida_funcs
import ida_dirtree
import idautils
lst = ['Rtl', 'Zw', 'Ki']
def main():
#
# Get the functions standard dirtree.
#
dt = ida_dirtree.get_std_dirtree(ida_dirtree.DIRTREE_FUNCS)
#
# Create the folders.
#
for folder in lst:
result = dt.mkdir(folder)
if result != ida_dirtree.DTE_OK and result != ida_dirtree.DTE_ALREADY_EXISTS:
print(f'Not able to create folder {folder} ({result:x})')
return
#
# For all the function in the base directory, check that the function name
# starts with the provided prefix. If it does we try to move it to the
# corresponding folder.
#
for func_ea in idautils.Functions():
name = ida_funcs.get_func_name(func_ea)
for func_prefix in lst:
if name and name.startswith(func_prefix):
if dt.isfile(name):
if dt.rename(name, f'{func_prefix}/{name}') != ida_dirtree.DTE_OK:
print(f'Not able to move {name} inside {func_prefix} folder')
else:
print(f'{name} moved in {func_prefix} folder')
if __name__ == '__main__':
main()
@@ -0,0 +1,76 @@
import idautils
import ida_kernwin
import ida_funcs
import ida_ua
import ida_allins
import ida_ida
import ida_hexrays
import ida_lines
import idc
def build_function_list(func):
func_list = []
items = ida_funcs.func_item_iterator_t(func)
for item in items:
is_jmp = False
insn = ida_ua.insn_t()
if not ida_ua.decode_insn(insn, item):
continue
if not insn.itype == ida_allins.NN_call and not insn.itype == ida_allins.NN_jmp:
continue
if insn.itype == ida_allins.NN_jmp:
is_jmp = True
for xref in idautils.CodeRefsFrom(item, 0):
callee = ida_funcs.get_func(xref)
if not callee:
print(f'Unable to retrieve function object for {xref:x}. Skipping.')
continue
if is_jmp and callee.start_ea == func.start_ea:
continue
if callee not in func_list:
func_list.append(callee)
return func_list
def print_pseudo_code(cfunc):
sv = cfunc.get_pseudocode()
for sline in sv:
print(ida_lines.tag_remove(sline.line))
print('')
def decompile_and_print(func):
func_list = build_function_list(func)
func_list = [func, *func_list]
for item in func_list:
cfunc = ida_hexrays.decompile(item)
if not cfunc:
print(f'Unable to decompile function {ida_funcs.get_func_name(item.start_ea)}')
return False
print_pseudo_code(cfunc)
def main():
if not ida_ida.inf_get_procname() == 'metapc':
return False
if not ida_hexrays.init_hexrays_plugin():
return False
func = ida_funcs.get_func(idc.here())
if not func:
print('Please put the cursor inside a function and retry.')
decompile_and_print(func)
ida_kernwin.msg_clear()
main()
+55
View File
@@ -0,0 +1,55 @@
"""
summary: List all the functions called by the one in which the
cursor is currently located.
description:
If the cursor is located inside a function:
* get the function object
* get the function name
* get a function item iterator
* iterate through the items, and for each one decode it
* if the item is a call get the address of the callee
- get its name
- display its name its address and address of the call.
* if no calle is found print a statement indicating this fact.
"""
import idautils
import ida_kernwin
import ida_funcs
import ida_ua
import ida_allins
import ida_ida
import idc
ida_kernwin.msg_clear()
if ida_ida.inf_get_procname() == 'metapc':
func = ida_funcs.get_func(idc.here())
if func:
has_callee = False
func_name = ida_funcs.get_func_name(func.start_ea)
if not func_name:
func_name = hex(func.start_ea)
print(f'Function {func_name} [{func.start_ea:x}] calls:')
items = ida_funcs.func_item_iterator_t(func)
for item in items:
insn = ida_ua.insn_t()
if not ida_ua.decode_insn(insn, item):
continue
if not insn.itype == ida_allins.NN_call:
continue
if not has_callee:
has_callee = True
for xref in idautils.CodeRefsFrom(item, 0):
print(f'\t- {ida_funcs.get_func_name(xref)} [{xref:x}] @{item:x}')
if not has_callee:
print('\t- no function.')
else:
print('Please place the cursor inside a function and retry.')
else:
print('This script will propely work for "metapc" procmod only.')
+50
View File
@@ -0,0 +1,50 @@
"""
summary: Print argument location information.
description:
In this script, we iterate through a function
arguments and display information about their
location and size. For this we:
* get the function type information
* iterate through the arguments
* for each of them we print its location (register or stack),
offset (if in stack) and size
"""
import ida_nalt
import ida_funcs
import ida_typeinf
import idc
import ida_kernwin
def print_argument_locations(func):
tif = ida_typeinf.tinfo_t()
if ida_nalt.get_tinfo(tif, func.start_ea):
fi = ida_typeinf.func_type_data_t()
if tif.get_func_details(fi):
if fi.size():
print('Argument location:')
for item in fi:
if item.name:
ida_kernwin.msg(f'\t{item.name}: ')
else:
ida_kernwin.msg(f'\t????: ')
location = ida_typeinf.print_argloc(item.argloc)
if location:
ida_kernwin.msg(f'{location}.')
elif item.argloc.in_stack:
ida_kernwin.msg(f'stack({item.argloc.stkoff():x}).')
print(f'{item.type.get_size()}')
else:
print('No arguments')
else:
print('Problems retrieving function details')
else:
print('Problem retrieving function type info.')
if __name__ == '__main__':
func = ida_funcs.get_func(idc.here())
if not func:
print('Place the cursor inside a function and retry.')
else:
print_argument_locations(func)
+38
View File
@@ -0,0 +1,38 @@
"""
summary: Print the list of the functions in the currently loaded
IDB sorted (descending) by the number of code reference to
each of them.
description:
In this script, we iterate through the list of function entry
points and fore each of them we:
* get its name
* get the number of code reference made to it
* put it in the map.
Once done we:
* sort the map in descending number of calls
* print it.
"""
import ida_kernwin
import ida_funcs
import idc
import idautils
ida_kernwin.msg_clear()
func_map = {}
for funcea in idautils.Functions():
func_name = ida_funcs.get_func_name(funcea)
if not func_name:
func_name = hex(funcea)
else:
func_name = idc.demangle_name(func_name, idc.get_inf_attr(idc.INF_LONG_DN))
call_count = 0
for xref in idautils.CodeRefsTo(funcea, 1):
call_count += 1
if call_count:
func_map[func_name] = call_count
func_map_by_calls = sorted(func_map.items(), key=lambda x:x[1], reverse=True)
for func, calls in func_map_by_calls:
print(f'{func} called {calls} time(s)')
+15
View File
@@ -0,0 +1,15 @@
import ida_graph
import ida_funcs
import ida_gdl
import ida_kernwin
import idc
func = ida_funcs.get_func(idc.here())
qflow = ida_gdl.qflow_chart_t("", func, 0, 0, 0)
for n in range(qflow.size()):
node = qflow[n]
print(f'Start ea : {node.start_ea:x}, end ea: {node.end_ea:x}, index: {n}')
ni = ida_graph.node_info_t()
ni.bg_color = 0xFF00
ida_graph.set_node_info(func.start_ea, n, ni, ida_graph.NIF_BG_COLOR)
ida_kernwin.refresh_idaview_anyway()
@@ -0,0 +1,74 @@
"""
summary: Python plugin that decompiles a function and its callees.
description:
This script does the same as decompile_func_and_callee but instead
of using the cross-references, uses a ctree visitor to build the
list of callees.
"""
import ida_hexrays
import ida_lines
import ida_funcs
import ida_kernwin
def find_calls(cfunc):
class finder_t(ida_hexrays.ctree_visitor_t):
def __init__(self):
ida_hexrays.ctree_visitor_t.__init__(self, ida_hexrays.CV_FAST | ida_hexrays.CV_INSNS)
self.results = []
return
def visit_insn(self, inst):
if inst.op == ida_hexrays.cit_expr and inst.cexpr.op == ida_hexrays.cot_call:
self.results.append(inst.cexpr.x.obj_ea)
return 0
finder = finder_t()
finder.apply_to(cfunc.body, None)
return finder.results
def print_pseudo_code(cfunc):
sv = cfunc.get_pseudocode();
for sline in sv:
print(ida_lines.tag_remove(sline.line))
def main():
if not ida_hexrays.init_hexrays_plugin():
return False
print("Hex-rays version %s has been detected" % ida_hexrays.get_hexrays_version())
f = ida_funcs.get_func(ida_kernwin.get_screen_ea())
if f is None:
print("Please position the cursor within a function")
return True
cfunc = ida_hexrays.decompile(f);
if cfunc is None:
print("Failed to decompile!")
return True
print_pseudo_code(cfunc)
lst = find_calls(cfunc)
lst = list(set(lst))
already = []
for ea in lst:
f = ida_funcs.get_func(ea)
if f is None:
continue
cfunc = ida_hexrays.decompile(f);
if cfunc is None:
print("Failed to decompile!")
return True
print_pseudo_code(cfunc)
return True
if __name__ == '__main__':
main()
+65
View File
@@ -0,0 +1,65 @@
"""
summary: log various frame events.
description:
hooks to be notified about frame IDP events, and
dump their information to the "Output" window.
"""
import inspect
import ida_idp
import ida_ua
class frame_logger_hooks_t(ida_idp.IDB_Hooks):
def __init__(self):
ida_idp.IDB_Hooks.__init__(self)
self.inhibit_log = 0
def _format_value(self, v):
return str(v)
def _log(self, msg=None):
if self.inhibit_log <= 0:
if msg:
print(f'>>> frame_logger_hooks_f: {msg}')
else:
stack = inspect.stack()
frame, _, _, _, _, _ = stack[1]
args, _, _, values = inspect.getargvalues(frame)
method_name = inspect.getframeinfo(frame)[2]
argstrs = []
for arg in args[1:]:
argstrs.append("%s=%s" % (arg, self._format_value(values[arg])))
print(f'>>> frame_logger_hooks_t.{method_name}: {", ".join(args)}')
return 0
def frame_udm_created(self, func_ea, udm):
return self._log()
def frame_udm_deleted(self, func_ea, udm_tid, udm):
return self._log()
def frame_udm_renamed(self, func_ea, udm, oldname):
return self._log()
def frame_udm_changed(self, func_ea, udm_tid, udmold, udmnew):
return self._log()
# Remove an existing hook on second run
try:
frame_idp_hook_stat = "un"
print("Frame IDP hook: checking for hook...")
framehook
print("Frame IDP hook: unhooking....")
frame_idp_hook_stat2 = ""
framehook.unhook()
del framehook
except:
print("Frame IDP hook: not installed, installing now....")
frame_idp_hook_stat = ""
frame_idp_hook_stat2 = "un"
framehook = frame_logger_hooks_t()
framehook.hook()
print(f'Frame IDB hook {frame_idp_hook_stat}installed. Run the script again to {frame_idp_hook_stat2}install')
+68
View File
@@ -0,0 +1,68 @@
"""
summary: log various local type events.
description:
hooks to be notified about local type IDP events,
and dump their information to the "Output" window
"""
import inspect
import ida_idp
import ida_ua
class lt_logger_hooks_t(ida_idp.IDB_Hooks):
def __init__(self):
ida_idp.IDB_Hooks.__init__(self)
self.inhibit_log = 0
def _format_value(self, v):
return str(v)
def _log(self, msg=None):
if self.inhibit_log <= 0:
if msg:
print(f'>>> lt_logger_hooks_f: {msg}')
else:
stack = inspect.stack()
frame, _, _, _, _, _ = stack[1]
args, _, _, values = inspect.getargvalues(frame)
method_name = inspect.getframeinfo(frame)[2]
argstrs = []
for arg in args[1:]:
argstrs.append("%s=%s" % (arg, self._format_value(values[arg])))
print(f'>>> lt_logger_hooks_t.{method_name}: {", ".join(args)}')
return 0
def lt_udm_created(self, udtname, udm):
msg = f'UDM {udm.name} has been created in UDT {udtname}'
return self._log(msg)
def lt_udm_deleted(self, udtname, udm_tid):
msg = f'UDM tid {udm_tid:x} has been deleted from {udtname}'
return self._log(msg)
def lt_udm_renamed(self, udtname, udm, oldname):
msg = f'UDM {oldname} from UDT {udtname} has been renamed to {udm.name}'
return self._log(msg)
def lt_udm_changed(self, udtname, udm_tid, udmold, udmnew):
return self._log()
# Remove an existing hook on second run
try:
idp_hook_stat = "un"
print("Local type IDB hook: checking for hook...")
lthook
print("Local type IDB hook: unhooking....")
idp_hook_stat2 = ""
lthook.unhook()
del lthook
except:
print("local type IDB hook: not installed, installing now....")
idp_hook_stat = ""
idp_hook_stat2 = "un"
lthook = lt_logger_hooks_t()
lthook.hook()
print(f'Local type IDB hook {idp_hook_stat}installed. Run the script again to {idp_hook_stat2}install')
+677
View File
@@ -0,0 +1,677 @@
"""
summary: being notified, and logging some IDP events
description:
hooks to be notified about certain IDP events, and
dump their information to the "Output" window
See enum event_t in idp.hpp for additional.
"""
import inspect
import ida_idp
import ida_ua
class idp_logger_hooks_t(ida_idp.IDP_Hooks):
def __init__(self):
ida_idp.IDP_Hooks.__init__(self)
self.inhibit_log = 0
def _format_value(self, v):
return str(v)
def _log(self, msg=None):
if self.inhibit_log <= 0:
if msg:
print(f'>>> idp_logger_hooks_f: {msg}')
else:
stack = inspect.stack()
frame, _, _, _, _, _ = stack[1]
args, _, _, values = inspect.getargvalues(frame)
method_name = inspect.getframeinfo(frame)[2]
argstrs = []
for arg in args[1:]:
argstrs.append("%s=%s" % (arg, self._format_value(values[arg])))
print(f'>>> idp_logger_hooks_t.{method_name}: {", ".join(args)}')
return 0
def ev_init(self, idp_modname):
"""
The IDP module is just loaded.
idp_modname - processor module name
Returns: <0 on failure
"""
return self._log(f'idp_logger_hooks_t.ev_init(self, {idp_modname})')
def ev_term(self):
"""
The IDP module is being unloaded
"""
return self._log()
def ev_newprc(self, nproc, keep_cfg):
"""
Before changing proccesor type
nproc - processor number in the array of processor names
Returns: >=0-ok,<0-prohibit
"""
return self._log()
def ev_newasm(self, asmnum):
"""
Before setting a new assembler.
"""
return self._log()
def ev_newfile(self, fname):
"""
A new file has been loaded.
"""
return self._log()
def ev_oldfile(self, filename):
"""
An old file has been loaded.
"""
return self._log()
def ev_newbinary(self, filename, fileoff, basepara, binoff, nbytes):
"""
Before loading a binary file
"""
return self._log()
def ev_endbinary(self, ok):
"""
After loading a binary file
Returns: >=0-ok
"""
return self._log()
def ev_set_idp_options(self, keyword, value_type, value, idb_loaded):
"""
Set IDP-specific option
Returns: 1-ok, 0-not implemented, -1-error
"""
#msg = f'KEY: {keyword}, TYPE: {value_type}, value: {value}, loaded: {idb_loaded}'
return self._log()
def ev_set_proc_options(self, options, confidence):
"""
Called if the user specified an option string in the command line:
Returns: <0-bad option string
"""
return self._log()
def ev_ana_insn(self, insn):
"""
Decodes an instruction into insn
Returns: insn.size (=the size of the decoded instruction) or zero
"""
self._log()
return insn.size
def ev_emu_insn(self, insn):
"""
Emulate instruction, create cross-references, plan to analyze
subsequent instructions, modify flags etc. Upon entrance to this function
all information about the instruction is in 'insn' structure.
Returns: -1, the kernel will delete the instruction.
"""
return self._log()
def ev_out_header(self, ctx):
"""
Function to produce start of disassembled text
"""
self._log()
def ev_out_footer(self, ctx):
"""
Function to produce end of disassembled text
"""
self._log()
def ev_out_segstart(self, ctx, segment):
"""
Function to produce start of segment
Returns: 1-ok, 0-not implemented
"""
return self._log()
def ev_out_insn(self, ctx):
"""
Generate text representation of an instruction in 'ctx.insn' structure.
This function shouldn't change the database, flags or anything else.
All these actions should be performed only by u_emu() function.
Returns: nothing
"""
self._log()
def ev_out_segstart(self, ctx, segment):
"""
Function to produce start of segment
Returns: 1-ok, 0-not implemented
"""
return self._log()
def ev_out_segend(self, ctx, segment):
"""
Function to produce end of segment
Returns: 1-ok, 0-not implemented
"""
return self._log()
def ev_out_assumes(self, ctx):
"""
Function to produce assume directives
Returns: 1-ok, 0-not implemented
"""
return self._log()
def ev_out_mnem(self, ctx):
"""
Generate text representation of an instruction in 'ctx.insn'
Returns: 1-if appended the mnemonics, 0-not implemented.
"""
return self._log()
def ev_out_operand(self, ctx, op):
"""
Generate text representation of an instructon operand.
This function shouldn't change the database, flags or anything else.
All these actions should be performed only by u_emu() function.
Returns: 1-ok, -1-operand is hidden
"""
return self._log()
def ev_out_data(self, ctx, analyze_only):
"""
Generate text represenation of data items
This function MAY change the database and create cross-references, etc.
Returns: 1-ok, 0-not implemented
"""
return self._log()
def ev_out_label(self, ctx, label):
"""
The kernel is going to generate an instruction label line
or a function header.
Returns: <0-the kernel should not generate the label, 0-not implemented/continue
"""
return self._log()
def ev_out_special_item(self, ctx, segtype):
"""
Generate text representation of an item in a special segment
i.e. absolute symbols, externs, communal definitions etc.
Returns: 1-ok, 0-not implemented, -1-overflow
"""
return self._log()
def ev_gen_stkvar_def(self, ctx, mptr, v):
"""
Generate stack variable definition line.
Default line is varname = type ptr value,
where 'type' is one of byte,word,dword,qword,tbyte.
Returns: 1-ok, 0-not implemented.
"""
return self._log()
def ev_gen_regvar_def(self, ctx, v):
"""
Generate register variable definition line.
Returns: >0-ok, 0-not implemented.
"""
return self._log()
def ev_gen_src_file_lnnum(self, ctx, filename, lnnum):
"""
Callback: generate analog of#line "file.c" 123
directive.
Returns: 1-ok, 0-not implemented
"""
return self._log()
def ev_creating_segm(self, s):
"""
A new segment is about to be created.
Returns 1-ok, <0-should not be created
"""
return self._log()
def ev_moving_segm(self, segment, to, flags):
"""
May the kernel move the segment?
returns: 0-yes, <0-the kernel should stop
"""
return self._log()
def ev_coagulate(self, start_ea):
"""
Try to define some unexplored bytes
This notification will be called if the
kernel tried all possibilities and could
not find anything more useful than to
convert to array of bytes.
The module can help the kernel and convert
the bytes into something more useful.
Returns: number of converted bytes
"""
return self._log()
def ev_undefine(self, ea):
"""
An item in the database (insn or data) is being deleted.
Returns: >=0-ok, <0-the kernel should stop
"""
return self._log()
def ev_treat_hindering_item(self, hindering_item_ea, new_item_flags, new_item_ea, new_item_length):
"""
An item hinders creation of another item
Returns: 0-no reaction, <0-the kernel may delete the hindering item
"""
return self._log()
def ev_rename(self, ea, new_name):
"""
The kernel is going to rename a byte
Returns: <0-then the kernel should not rename it
"""
return self._log()
def ev_is_far_jump(self, icode):
"""
Is indirect far jump or call instruction?
meaningful only if the processor has 'near' and 'far' reference types.
Returns: 0-not implemented, 1-yes, -1-no
"""
return self._log()
def ev_is_sane_insn(self, insn, no_crefs):
"""
Is the instruction sane for the current file type?
Returns: >=0-ok, <0-no
"""
return self._log()
def ev_is_cond_insn(self, insn):
"""
Is conditional instruction?
Returns: 1-yes, -1-no, 0-not implemented.
"""
return self._log()
def ev_is_call_insn(self, insn):
"""
Is the instruction a "call"?
Returns: 0-unknown, <0-no, 1-yes
"""
return self._log()
def ev_is_ret_insn(self, insn, flags):
"""
Is the instruction a "return"?
Returns: 0-unknown, <0-no, 1-yes
"""
return self._log()
def ev_may_be_func(self, insn, state):
"""
Can a function start here?
Returns: probability 0..100
"""
return self._log()
def ev_is_basic_block_end(self, insn, call_insn_stops_block):
"""
Is the current instruction end of a basic block?
Returns: 0-unknown, -1-no, 1-yes
"""
return self._log()
def ev_is_indirect_jump(self, insn):
"""
Callback: determine if instruction is an indrect jump
If CF_JUMP bit cannot describe all jump types
jumps, please define this callback.
Returns: 0-use CF_JUMP, 1-no, 2-yes
"""
return self._log()
def ev_is_switch(self, swi, insn):
"""
Find 'switch' idiom or override processor module's
decision.
Returns: 1-switch found, -1-no switch found, 0-not implmented
"""
return self._log()
def ev_calc_switch_cases(self, casevec, targets, insn_ea, si):
"""
Calculate case values and targets for a custom jump table.
Returns: 1-ok, <=0-failed
"""
return self._log()
def ev_create_switch_xrefs(self, jumpea, swi):
"""
Create xrefs for a custom jump table
Must return 1
"""
self._log()
return 1
def ev_is_align_insn(self, ea):
"""
Is the instruction created only for alignment purposes?
Returns: number of bytes in the instruction
"""
return self._log()
def ev_is_alloca_probe(self, ea):
"""
Does the function at 'ea' behave as __alloca_probe?
Returns: 1-yes, 0-no
"""
return self._log()
def ev_delay_slot_insn(self, ea, bexec, fexec):
"""
Get delay slot instruction.
Returns 1-yes, <=O-ordianry insn.
"""
return self._log()
def ev_is_sp_based(self, mode, insn, op):
"""
Check whether the operand is relative to stack pointer or frame pointer.
This function is used to determine how to output a stack variable
This function may be absent. If it is absent, then all operands
are sp based by default.
Define this function only if some stack references use frame pointer
instead of stack pointer.
Returns: 0-not implemented, 1-ok
"""
return self._log()
def ev_can_have_type(self, op):
"""
Can the operand have a type as offset, segment, decimal, etc?
(for example, a register AX can't have a type, meaning that the user can't
change its representation. see bytes.hpp for information about types and flags)
Returns: 0-unknown, <0-no, 1-yes
"""
return self._log()
def ev_cmp_operands(self, op1, op2):
"""
Compare instruction operands.
Returns 1-equal, -1-not equal, 0-not implemented
"""
return self._log()
def ev_adjust_refinfo(self, ri, ea, n, fd):
"""
Called from apply_fixup before converting operand to reference.
Can be used for changing the reference info.
Returns: <0-do not create an offset, 0-not implemented
"""
return self._log()
def ev_get_operand_string(self, buf, insn, opnum):
"""
Request text string for operand.
Returns: 0-no string (or empty), >0-original string length (without final 0)
"""
return self._log()
def ev_get_reg_name(self, buf, reg, width, reghi):
"""
Generate text representation of a register.
Most processor modules do not need to implement this callback.
Returns: -1-error, strlen(buf)-success
"""
return self._log()
def ev_str2reg(self, regname):
"""
Convert a register name to a register number
Returns: 0-not implemented, register number + 1
"""
return self._log()
def ev_get_autocmt(self, insn):
"""
Get instruction comment. 'insn' describes the instruction in question
@return: 1-new comment has been generated, 0-not been handled.
"""
return self._log()
def ev_get_bg_color(self, color, ea):
"""
Get item background color.
Plugins can hook this callback to color disassembly lines dynamically.
Returns: 0-not implemented, 1-color set
"""
return self._log()
def ev_is_jump_func(self, pfn, jump_target, func_pointer):
"""
Is the function a trivial "jump" function?
Returns: <0-no, 0-don't know, 1-yes
"""
return self._log()
def ev_func_bounds(self, possible_return_code, pfn, max_func_end_ea):
"""
Find_func_bounds() finished its work.
The module may fine tune the function bounds.
Returns: None
"""
return self._log()
def ev_verify_sp(self, pfn):
"""
All function instructions have been analyzed.
Now the processor module can analyze the stack pointer
for the whole function
Returns: 0-ok, <0-bad stack pointer
"""
return self._log()
def ev_verify_noreturn(self, pfn):
"""
The kernel wants to set 'noreturn' flags for a function
Returns: 0-ok, <0-do not set 'noreturn' flag
"""
return self._log()
def ev_create_func_frame(self, pfn):
"""
Create a function frame for a newly created function.
Set up frame size, its attributes etc.
Returns: 1-ok, 0-not implemented
"""
return self._log()
def ev_get_frame_retsize(self, frsize, pfn):
"""
Get size of function return address in bytes
If this function is absent, the kernel will assume
8 bytes for 64-bit function,4 bytes for 32-bit
function, c2 bytes otherwise.
Returns 1-ok, 0-not implemented
"""
return self._log()
def ev_get_stkvar_scale_factor(self):
"""
Should stack variable references be multiplied by
a coefficient before being used in the stack frame?
Currently used by TMS320C55 because the references into
the stack should be multiplied by 2.
Returns: 0-not implemented, >0-scaling factor
"""
return self._log()
def ev_demangle_name(self, out, res , demreq):
"""
Demangle a C++ (or another language) name into a user-readable string.
This event is called by ::demangle_name().
Returns: 0-not implemented, 1-success
"""
return self._log()
def ev_add_cref(self, frm, to, type):
"""
A code reference is being created.
Returns: 0-not implemented, <0-cancel cref creation
"""
return self._log()
def ev_add_dref(self, frm, to, type):
"""
A data reference is being created.
Returns: 0-not implemented, <0-cancel dref creation
"""
return self._log()
def ev_del_cref(self, frm, to, expand):
"""
A code reference is being deleted.
Returns: 0-not implemented, <0-cancel cref deletion
"""
return self._log()
def ev_del_dref(self, frm, to):
"""
A data reference is being deleted.
Retuns: 0-not implemented, <0-cancel dref deletion
"""
return self._log()
def ev_coagulate_dref(self, from_ea, to_ea, may_define, code_ea):
"""
Data reference is being analyzed.
plugin may correct code_ea (e.g. for thumb mode refs, we clear the last bit)
Returns: >0-new code_ea, -1-cancel dref analysis
"""
return self._log()
def ev_may_show_sreg(self, current_ea):
"""
The kernel wants to display the segment registers
in the messages window.
Returns: 0-not implemented, <0-kernel should not show.
"""
return self._log()
def ev_loader_elf_machine(self, li, machine_type, p_procname, p_pd, loader, reader):
"""
ELF loader machine type checkpoint.
A plugin check of the 'machine_type'. If it is the desired one,
the the plugin fills 'p_procname' with the processor name.
Returns: e_machine value
"""
pass
def ev_auto_queue_empty(self, atype):
"""
One analysis queue is empty.
Returns: an int (?)
"""
return self._log()
def ev_validate_flirt_func(self, start_ea, func_name):
"""
FLIRT has recognized a library function.
This callback can be used by a plugin or proc module
to intercept it and validate such a function.
Returns: -1-do not create, 0-validated
"""
return self._log()
def ev_adjust_libfunc_ea(self, sig, libfun, ea):
"""
Called when a signature module has been matched against
bytes in the database. This is used to compute the
offset at which a particular module's libfunc should
be applied.
Returns: 1-ea has been modified, <=0 not modified
"""
return self._log()
def ev_assemble(self, ea, cs, ip, use32, line):
"""
Assemble an instruction
(make sure that PR_ASSEMBLE flag is set in the processor flags)
(display a warning if an error occurs)
Returns opcode string-ok, None-failed
"""
return self._log()
def ev_extract_address(self, out_ea, screen_ea, string, position):
"""
Extract address from a string.
Returns: 1-ok, 0-use standard algorithm, -1-error
"""
return self._log()
def ev_realcvt(self, m,e, swt):
"""
Floating point -> IEEE conversion
Returns: 1-ok, 0-not implemented, REAL_ERROR_-error
"""
return self._log()
def ev_gen_asm_or_lst(self, starting, fp, is_asm, flags, outline):
"""
Callback generating asm orlst file.
The kernel calls this callback twice, at the beginning
and at the end of listing generation. The processor
module can intercept this event and adjust its output.
Returns: None
"""
return self._log()
def ev_gen_map_file(self, nlines, fp):
"""
Generate a map file. If not implemented
the kernel itself will create the map file.
Returns: 1-ok, 0-not implemented, -1-write error
"""
return self._log()
def ev_create_flat_group(self, image_base, bitness, dataseg_sel):
"""
Create special segment representing the flat group.
Returns: return value ignored.
"""
return self._log()
def ev_analyze_prolog(self, ea):
"""
Analyzes function prolog, epilog, and updates
purge, and function attributes
Returns: 1-ok, 0-not implemented.
"""
return self._log()
# Remove an existing hook on second run
try:
idp_hook_stat = "un"
print("IDP hook: checking for hook...")
idphook
print("IDP hook: unhooking....")
idp_hook_stat2 = ""
idphook.unhook()
del idphook
except:
print("IDP hook: not installed, installing now....")
idp_hook_stat = ""
idp_hook_stat2 = "un"
idphook = idp_logger_hooks_t()
idphook.hook()
print(f'IDP hook {idp_hook_stat}installed. Run the script again to {idp_hook_stat2}install')
+84
View File
@@ -0,0 +1,84 @@
"""
summary: Print basic information about the currently loaded IDB.
description:
In this script we display some basic information about the
current IDB:
* the compiler name and the size of some datatypes
* Other general IDB information including: application bitness,
file type, various address ranges, main address and start
addresses if exist.
For this we use some of the inf_get_xxx functions from the
ida_ida module.
"""
import ida_ida
import ida_kernwin
import ida_typeinf
import ida_idaapi
ft_dict = {
ida_ida.f_EXE_old: 'MS DOS EXE File',
ida_ida.f_COM_old: 'MS DOS COM File',
ida_ida.f_BIN: 'Binary File',
ida_ida.f_DRV: 'MS DOS Driver',
ida_ida.f_WIN: 'New Executable (NE)',
ida_ida.f_HEX: 'Intel Hex Object File',
ida_ida.f_MEX: 'MOS Technology Hex Object File',
ida_ida.f_LX: 'Linear Executable (LX)',
ida_ida.f_LE: 'Linear Executable (LE)',
ida_ida.f_NLM: 'Netware Loadable Module (NLM)',
ida_ida.f_COFF: 'Common Object File Format (COFF)',
ida_ida.f_PE: 'Portable Executable (PE)',
ida_ida.f_OMF: 'Object Module Format',
ida_ida.f_SREC: 'Motorola SREC (S-record)',
ida_ida.f_ZIP: 'ZIP file (this file is never loaded to IDA database)',
ida_ida.f_OMFLIB: 'Library of OMF Modules',
ida_ida.f_AR: 'ar library',
ida_ida.f_LOADER: 'file is loaded using LOADER DLL',
ida_ida.f_ELF: 'Executable and Linkable Format (ELF)',
ida_ida.f_W32RUN: 'Watcom DOS32 Extender (W32RUN)',
ida_ida.f_AOUT: 'Linux a.out (AOUT)',
ida_ida.f_PRC: 'PalmPilot program file',
ida_ida.f_EXE: 'MS DOS EXE File',
ida_ida.f_COM: 'MS DOS COM File',
ida_ida.f_AIXAR: 'AIX ar library',
ida_ida.f_MACHO: 'Mac OS X Mach-O',
ida_ida.f_PSXOBJ: 'Sony Playstation PSX object file',
ida_ida.f_MD1IMG: 'Mediatek Firmware Image'
}
def main():
print('\nCompiler info:')
cc = ida_ida.compiler_info_t()
ida_ida.inf_get_cc(cc)
print(f'\tCompilateur: {ida_typeinf.get_compiler_name(cc.id)}')
print(f'\t\tByte size: {ida_ida.inf_get_cc_size_b()}')
print(f'\t\tShort size: {ida_ida.inf_get_cc_size_s()}')
print(f'\t\tEnum size: {ida_ida.inf_get_cc_size_e()}')
print(f'\t\tInteger size: {ida_ida.inf_get_cc_size_i()}')
print(f'\t\tLong size: {ida_ida.inf_get_cc_size_l()}')
print(f'\t\tLong double size: {ida_ida.inf_get_cc_size_ldbl()}')
print(f'\t\tLong long size: {ida_ida.inf_get_cc_size_ll()}')
print('\nGeneral IDB information:')
print(f'\tApplication bitness: {ida_ida.inf_get_app_bitness()}-bit')
if ida_ida.inf_is_kernel_mode():
land = 'Kernel'
else:
land = 'User'
print(f'\tExecution mode: {land}')
print(f'\tFile type: {ft_dict[ida_ida.inf_get_filetype()]}')
main_ea = ida_ida.inf_get_main()
if not main_ea == ida_idaapi.BADADDR:
print(f'\tMain entry point: {main_ea:x}')
start_ea = ida_ida.inf_get_start_ea()
if not start_ea == ida_idaapi.BADADDR:
print(f'Start entry: {start_ea:x}')
print(f'\tMinimum effective address: {ida_ida.inf_get_min_ea():x}')
print(f'\tMaximum effective address: {ida_ida.inf_get_max_ea():x}')
print(f'\tPrivate range start: {ida_ida.inf_get_privrange_start_ea():x}')
print(f'\tPrivate range end: {ida_ida.inf_get_privrange_end_ea():x}')
ida_kernwin.msg_clear()
main()
@@ -0,0 +1,37 @@
"""
summary: Python plugin that print basic IDB information.
description:
Demonstrates how to turn an IDA python script into
an IDA Python plugin.
"""
import ida_idaapi
import ida_kernwin
import print_basic_info
class pbi_plugmod_t(ida_idaapi.plugmod_t):
def __del__(self):
ida_kernwin.msg("PBI >> unloaded pbi_plugmod\n")
def run(self, arg):
ida_kernwin.msg("PBI >> run() called with %d!\n" % arg)
print_basic_info.main()
return True
class pbi_plugin_t(ida_idaapi.plugin_t):
flags = ida_idaapi.PLUGIN_UNL | ida_idaapi.PLUGIN_MULTI
comment = "This is a simple plugin printing basic info"
help = ""
wanted_name = "Print Basic Info (PBI) plugin"
wanted_hotkey = "Ctrl-Alt-F12"
def init(self):
ida_kernwin.msg("PBI >> init() called!\n")
return pbi_plugmod_t()
def term(self):
ida_kernwin.msg("PBI >> ERROR: term() called (should never be called)\n")
def PLUGIN_ENTRY():
return pbi_plugin_t()
+103
View File
@@ -0,0 +1,103 @@
'''
summary: Use bin_search to find the occurences of
"mov rax, cs:___security_cookie"
description:
This example shows a way of finding the
"mov rax, cs:___security_cookie" instruction in a x64 database using
bin_search. For this we:
* check that the database is, indeed an x64 one
* build the binary pattern vector
* search for the pattern
* for each result we validate that operand 1 (Op2.addr) points to
__security_cookie
* once the list is built, print it ([index] func_name @ address)
'''
import ida_bytes
import ida_idaapi
import ida_name
import ida_funcs
import ida_ua
import ida_ida
message = 'Pattern \"mov rax, cs:__security_cookie\" found:'
pattern_bytes = b'\x48\x8B\x05\x56\xAF\x35\x00'
pattern_mask = b'\x01\x01\x01\x00\x00\x00\x01'
def is_pc_64():
if ida_ida.inf_get_procname() != 'metapc' and not ida_ida.inf_is64bit():
return False
return True
def build_pattern_vec(bytes, mask = None):
pattern = ida_bytes.compiled_binpat_t()
pattern.bytes = bytes
if mask:
pattern.mask = mask
pattern_vec = ida_bytes.compiled_binpat_vec_t()
pattern_vec.push_back(pattern)
return pattern_vec
def is_valid(ea, sc_ea):
insn = ida_ua.insn_t()
ida_ua.decode_insn(insn, ea)
op = insn.Op2
if op.type == 2 and op.dtype == 7 and op.addr == sc_ea:
return True
return False
def build_ea_list(start_ea, end_ea, pattern_vec, flags, sc_ea):
ea_list = []
while start_ea < end_ea:
start_ea, _ = ida_bytes.bin_search(start_ea, end_ea, pattern_vec, flags)
if start_ea == ida_idaapi.BADADDR:
break
if is_valid(start_ea, sc_ea):
ea_list.append(start_ea)
start_ea += 1
return ea_list
def print_result(str, lst):
print(str)
idx = 0
for ea in lst:
fname = ida_funcs.get_func_name(ea)
dname = ida_name.demangle_name(fname, 0)
pname = fname
if dname:
pname = dname
print(f'[{idx}] {pname} @ {ea:x}')
idx += 1
def main():
if not is_pc_64():
print('This script will only work for x64 databases.')
return
security_ea = ida_name.get_name_ea(ida_idaapi.BADADDR, '__security_cookie')
if security_ea == ida_idaapi.BADADDR:
print('No reference to __security_cookie.')
return
pv = build_pattern_vec(pattern_bytes, pattern_mask)
flags = ida_bytes.BIN_SEARCH_FORWARD | ida_bytes.BIN_SEARCH_NOCASE | ida_bytes.BIN_SEARCH_NOBREAK
lst = build_ea_list(ida_ida.inf_get_min_ea(), ida_ida.inf_get_max_ea(), pv, flags, security_ea)
print_result(message, lst)
if __name__ == '__main__':
main()
+27
View File
@@ -0,0 +1,27 @@
import ida_ida
import ida_idaapi
import ida_bytes
import ida_funcs
def main():
if ida_ida.inf_get_filetype() != ida_ida.f_PE or not ida_ida.inf_is_64bit() or ida_ida.inf_get_procname() != 'metapc':
return
pattern_bytes = b'\x75\x03\x0F\x05'
rstart = ida_ida.inf_get_min_ea()
found = False
while True:
rstart = ida_bytes.find_bytes(pattern_bytes, rstart)
if rstart == ida_idaapi.BADADDR:
break
fname = ida_funcs.get_func_name(rstart)
if fname and not found:
found = True
print('Syscall found:')
if fname:
print(f'\t@ {rstart + 2:x} ({fname})')
rstart += 1
if __name__ == '__main__':
main()
+21
View File
@@ -0,0 +1,21 @@
# TIL API examples:
## Beginner level examples:
* list_enum_member.py
* list_struct_member.py
* list_union_member.py
* import_type_from_til.py
* list_struct_xref.py
* create_array.py
## Intermediate level examples:
* create_structs.py
* create_libssh2.py
* create_bmenum.py
* create_bfstruct.py
* func_ti_changed_listener.py
* mark_func_spoiled.py
* setpehdr.py
## Advanced level examples:
* operand_to_struct_member.py
+71
View File
@@ -0,0 +1,71 @@
"""
summary: List the .idata section content and the corresponding
data and code references when it applies.
description:
In this script, we iterate through the .idata PE section.
For each imported function we display:
* its name
* the data references to it (when applying)
* the code references to it (when applying,
"""
import ida_segment
import ida_name
import idautils
import ida_kernwin
import ida_funcs
def is_code(ea):
return ida_segment.segtype(ea) == ida_segment.SEG_CODE
def newline():
print('')
def list_refs(refs, code):
first = True
if code:
type = 'code'
else:
type = 'data'
idx = 1
for ref in refs:
if first:
print(f'\tList of {type} references:')
first = False
ida_kernwin.msg(f'\t* [{idx}] @ {ref:x}')
if is_code(ref):
name = ida_funcs.get_func_name(ref)
if name:
print(f' ({name})')
else:
newline()
else:
newline()
idx += 1
def main():
import_seg = ida_segment.get_segm_by_name('.idata')
if import_seg:
curr_ea = import_seg.start_ea
end_ea = import_seg.end_ea
idx = 1
while curr_ea < end_ea:
name = ida_name.get_ea_name(curr_ea)
print(f'Imported function [{idx}]: {name}')
list_refs(idautils.DataRefsTo(curr_ea), False)
list_refs(idautils.CodeRefsTo(curr_ea, 0), True)
if import_seg.is_64bit():
curr_ea += 8
else:
curr_ea += 4
idx += 1
if __name__ == '__main__':
main()
+15070 -14561
View File
File diff suppressed because it is too large Load Diff
+28019 -49668
View File
File diff suppressed because it is too large Load Diff
-14228
View File
File diff suppressed because it is too large Load Diff
-67968
View File
File diff suppressed because it is too large Load Diff
+242
View File
@@ -0,0 +1,242 @@
class data_type_t(object):
"""
Information about a data type
"""
def may_create_at(self, ea, nbytes):
"""May create data?
No such callback means: always succeed (i.e., no restriction where
such a data type can be created.)
@param ea: candidate address for the data item
@param nbytes: candidate size for the data item
@return: True/False
"""
return True
def calc_item_size(self, ea, maxsize):
"""This callback is used to determine size of the (possible)
item at `ea`.
No such callback means that datatype is of fixed size `value_size`.
(thus, this callback is required only for varsize datatypes.)
@param ea: address of the item
@param maxsize: maximum size of the item
@return: 0 - no such item can be created/displayed
"""
return 0
class data_format_t(object):
"""
Information about a data format
"""
def printf(self, value, current_ea, operand_num, dtid):
"""Convert `value` to colored string using custom format.
@param value: value to print (of type 'str', sequence of bytes)
@param current_ea: current address (BADADDR if unknown)
@param operand_num: current operand number
@param dtid: custom data type id
@return: string representing data
"""
return None
def scan(self, input, current_ea, operand_num):
"""Convert uncolored string (user input) to the value.
This callback is called from the debugger when an user enters a
new value for a register with a custom data representation (e.g.,
an MMX register.)
@param input: input string
@param current_ea: current address (BADADDR if unknown)
@param operand_num: current operand number (-1 if unknown)
@return: tuple(bool, string)
(True, output value) or
(False, error message)
"""
return (False, "Not implemented")
def analyze(self, current_ea, operand_num):
"""Analyze custom data format occurrence.
This callback is called in 2 cases:
- after emulating an instruction (after a call of
'ev_emu_insn') if its operand is marked as "custom data
representation"
- when emulating data (this is done using a call of
'ev_out_data' with analyze_only == true). This is the right
place to create cross references from the current item.
@param current_ea: current address (BADADDR if unknown)
@param operand_num: current operand number
"""
pass
def register_custom_data_type(dt):
"""
Registers a custom data type.
@param dt: an instance of the data_type_t class
@return:
< 0 if failed to register
> 0 data type id
"""
pass
def unregister_custom_data_type(dtid):
"""
Unregisters a custom data type.
@param dtid: the data type id
@return: Boolean
"""
pass
def register_custom_data_format(df):
"""
Registers a custom data format with a given data type.
@param df: an instance of data_format_t
@return:
< 0 if failed to register
> 0 data format id
"""
pass
def unregister_custom_data_format(dfid):
"""
Unregisters a custom data format
@param dfid: data format id
@return: Boolean
"""
pass
def visit_patched_bytes(ea1: ida_idaapi.ea_t, ea2: ida_idaapi.ea_t, callable):
"""
Enumerates patched bytes in the given range and invokes a callable
@param ea1: start address
@param ea2: end address
@param callable: a Python callable with the following prototype:
callable(ea, fpos, org_val, patch_val).
If the callable returns non-zero then that value will be
returned to the caller and the enumeration will be
interrupted.
@return: Zero if the enumeration was successful or the return
value of the callback if enumeration was interrupted.
"""
pass
def get_bytes(ea: ida_idaapi.ea_t, size: int, gmb_flags: int=GMB_READALL):
"""
Get the specified number of bytes of the program.
@param ea: program address
@param size: number of bytes to return
@param gmb_flags: OR'ed combination of GMB_* values (defaults to GMB_READALL)
@return: the bytes (as bytes object), or None in case of failure
"""
pass
def get_bytes_and_mask(ea: ida_idaapi.ea_t, size: int, gmb_flags: int=GMB_READALL):
"""
Get the specified number of bytes of the program, and a bitmask
specifying what bytes are defined and what bytes are not.
@param ea: program address
@param size: number of bytes to return
@param gmb_flags: OR'ed combination of GMB_* values (defaults to GMB_READALL)
@return: a tuple (bytes, mask), or None in case of failure.
Both 'bytes' and 'mask' are 'str' instances.
"""
pass
# Conversion options for get_strlit_contents():
STRCONV_ESCAPE = 0x00000001 # convert non-printable characters to C escapes (\n, \xNN, \uNNNN)
def get_strlit_contents(ea: ida_idaapi.ea_t, len: int, type: int, flags: int = 0):
"""
Get contents of string literal, as UTF-8-encoded codepoints.
It works even if the string has not been created in the database yet.
Note that the returned value will be of type 'bytes'; if
you want auto-conversion to unicode strings (that is: real Python
strings), you should probably be using the idautils.Strings class.
@param ea: linear address of the string
@param len: length of the string in bytes (including terminating 0)
@param type: type of the string. Represents both the character encoding,
<u>and</u> the 'type' of string at the given location.
@param flags: combination of STRCONV_..., to perform output conversion.
@return: a bytes-filled str object.
"""
pass
def op_stroff(*args) -> bool:
"""
Set operand representation to be 'struct offset'.
This function has the following signatures:
1. op_stroff(ins: ida_ua.insn_t, n: int, path: List[int], delta: int)
2. op_stroff(ins: ida_ua.insn_t, n: int, path: ida_pro.tid_array, path_len: int, delta: int) (backward-compatibility only)
Here is an example using this function:
ins = ida_ua.insn_t()
if ida_ua.decode_insn(ins, some_address):
operand = 0
path = [ida_typeinf.get_named_type_tid("my_stucture_t")] # a one-element path
ida_bytes.op_stroff(ins, operand, path, 0)
"""
pass
def get_stroff_path(*args):
"""
Get the structure offset path for operand `n`, at the
specified address.
This function has the following signatures:
1. get_stroff_path(ea: ida_idaapi.ea_t, n : int) -> Tuple[List[int], int]
2. get_stroff_path(path: tid_array, delta: sval_pointer, ea: ida_idaapi.ea_t, n : int) (backward-compatibility only)
@param ea address where the operand holds a path to a structure offset (1st form)
@param n operand number (1st form)
@return a tuple holding a (list_of_tid_t's, delta_within_the_last_type), or (None, None)
"""
pass
def bin_search(*args):
"""
Search for a set of bytes in the program
This function has the following signatures:
1. bin_search(start_ea: ida_idaapi.ea_t, end_ea: ida_idaapi.ea_t, data: compiled_binpat_vec_t, flags: int) -> Tuple[ida_idaapi.ea_t, int]
2. bin_search(start_ea: ida_idaapi.ea_t, end_ea: ida_idaapi.ea_t, image: bytes, mask: bytes, len: int, flags: int) -> ida_idaapi.ea_t
The return value type will differ depending on the form:
1. a tuple `(matched-address, index-in-compiled_binpat_vec_t)` (1st form)
2. the address of a match, or ida_idaapi.BADADDR if not found (2nd form)
This is a low-level function; more user-friendly alternatives
are available. Please see 'find_bytes' and 'find_string'.
@param start_ea: linear address, start of range to search
@param end_ea: linear address, end of range to search (exclusive)
@param data: (1st form) the prepared data to search for (see parse_binpat_str())
@param bytes: (2nd form) a set of bytes to match
@param mask: (2nd form) a mask to apply to the set of bytes
@param flags: combination of BIN_SEARCH_* flags
@return: either a tuple holding both the address of the match and the index of the compiled pattern that matched, or the address of a match (ida_idaapi.BADADDR if not found)
"""
pass
+125
View File
@@ -0,0 +1,125 @@
def get_manual_regions(*args):
"""
Returns the manual memory regions
This function has the following signatures:
1. get_manual_regions() -> List[Tuple(ida_idaapi.ea_t, ida_idaapi.ea_t, str, str, ida_idaapi.ea_t, int, int)]
Where each tuple holds (start_ea, end_ea, name, sclass, sbase, bitness, perm)
2. get_manual_regions(storage: meminfo_vec_t) -> None
"""
pass
def dbg_is_loaded():
"""
Checks if a debugger is loaded
@return: Boolean
"""
pass
def refresh_debugger_memory():
"""
Refreshes the debugger memory
@return: Nothing
"""
pass
def py_list_bptgrps():
"""
Returns list of breakpoint group names
@return: A list of strings or None on failure
"""
pass
def internal_get_sreg_base(tid: int, sreg_value: int):
"""
Get the sreg base, for the given thread.
@param tid: the thread ID
@param sreg_value: the sreg value
@return: The sreg base, or BADADDR on failure.
"""
pass
def dbg_can_query():
"""
This function can be used to check if the debugger can be queried:
- debugger is loaded
- process is suspended
- process is not suspended but can take requests. In this case some requests like
memory read/write, bpt management succeed and register querying will fail.
Check if idaapi.get_process_state() < 0 to tell if the process is suspended
@return: Boolean
"""
pass
def get_reg_vals(tid: int, clsmask: int=-1) -> 'ida_idd.regvals_t':
"""
Fetch live registers values for the thread
@param tid The ID of the thread to read registers for
@param clsmask An OR'ed mask of register classes to
read values for (can be used to speed up the
retrieval process)
@return: a list of register values (empty if an error occurs)
"""
pass
def get_reg_val(*args):
"""
Get a register value.
This function has the following signatures:
1. get_reg_val(name: str) -> Union[int, float, bytes]
2. get_reg_val(name: str, regval: regval_t) -> bool
The first (and most user-friendly) form will return
a value whose type is related to the register type.
I.e., either an integer, a float or, in the case of large
vector registers, a bytes sequence.
@param name the register name
@return the register value (1st form)
"""
pass
def set_reg_val(*args) -> bool:
"""
Set a register value by name
This function has the following signatures:
1. set_reg_val(name: str, value: Union[int, float, bytes]) -> bool
1. set_reg_val(tid: int, regidx: int, value: Union[int, float, bytes]) -> bool
Depending on the register type, this will expect
either an integer, a float or, in the case of large
vector registers, a bytes sequence.
@param name (1st form) the register name
@param tid (2nd form) the thread ID
@param regidx (2nd form) the register index
@param value the register value
@return success
"""
pass
def list_bptgrps() -> List[str]:
"""
Retrieve the list of absolute path of all folders of bpt dirtree.
Synchronous function, Notification, none (synchronous function)
"""
pass
+16
View File
@@ -0,0 +1,16 @@
def enumerate_files(path, fname, callback):
"""
Enumerate files in the specified directory while the callback returns 0.
@param path: directory to enumerate files in
@param fname: mask of file names to enumerate
@param callback: a callable object that takes the filename as
its first argument and it returns 0 to continue
enumeration or non-zero to stop enumeration.
@return:
None in case of script errors
tuple(code, fname) : If the callback returns non-zero
"""
pass
+109
View File
@@ -0,0 +1,109 @@
class qfile_t(pyidc_opaque_object_t):
"""A helper class to work with FILE related functions."""
def __init__(self, *args):
pass
def close(self):
"""Closes the file"""
pass
def open(self, filename, mode):
"""
Opens a file
@param filename: the file name
@param mode: The mode string, ala fopen() style
@return: Boolean
"""
pass
def set_linput(self, linput):
"""Links the current loader_input_t instance to a linput_t instance"""
pass
@staticmethod
def tmpfile():
"""A static method to construct an instance using a temporary file"""
pass
def seek(self, offset, whence = ida_idaapi.SEEK_SET):
"""
Set input source position
@param offset: the seek offset
@param whence: the position to seek from
@return: the new position (not 0 as fseek!)
"""
pass
def tell(self):
"""Returns the current position"""
pass
def gets(self, len):
"""
Reads a line from the input file. Returns the read line or None
@param len: the maximum line length
"""
pass
def read(self, size):
"""
Reads from the file. Returns the buffer or None
@param size: the maximum number of bytes to read
@return: a str, or None
"""
pass
def write(self, buf):
"""
Writes to the file. Returns 0 or the number of bytes written
@param buf: the str to write
@return: result code
"""
pass
def readbytes(self, size, big_endian):
"""
Similar to read() but it respect the endianness
@param size: the maximum number of bytes to read
@param big_endian: endianness
@return a str, or None
"""
pass
def writebytes(self, size, big_endian):
"""
Similar to write() but it respect the endianness
@param buf: the str to write
@param big_endian: endianness
@return: result code
"""
pass
def flush(self):
pass
def get_byte(self):
"""Reads a single byte from the file. Returns None if EOF or the read byte"""
pass
def put_byte(self):
"""
Writes a single byte to the file
@param chr: the byte value
"""
pass
def opened(self):
"""Checks if the file is opened or not"""
pass
+63
View File
@@ -0,0 +1,63 @@
def get_fchunk_referer(ea: int, idx):
pass
def get_idasgn_desc(n):
"""
Get information about a signature in the list.
It returns: (name of signature, names of optional libraries)
See also: get_idasgn_desc_with_matches
@param n: number of signature in the list (0..get_idasgn_qty()-1)
@return: None on failure or tuple(signame, optlibs)
"""
pass
def get_idasgn_desc_with_matches(n):
"""
Get information about a signature in the list.
It returns: (name of signature, names of optional libraries, number of matches)
@param n: number of signature in the list (0..get_idasgn_qty()-1)
@return: None on failure or tuple(signame, optlibs, nmatches)
"""
pass
class func_t(object):
def get_name(self):
"""
Get the function name
@return the function name
"""
pass
def get_frame_object(self):
"""
Retrieve the function frame, in the form of a structure
where frame offsets that are accessed by the program, as well
as areas for "saved registers" and "return address", are
represented by structure members.
If the function has no associated frame, return None
@return a ida_typeinf.tinfo_t object representing the frame, or None
"""
pass
def get_prototype(self):
"""
Retrieve the function prototype.
Once you have obtained the prototype, you can:
* retrieve the return type through ida_typeinf.tinfo_t.get_rettype()
* iterate on the arguments using ida_typeinf.tinfo_t.iter_func()
If the function has no associated prototype, return None
@return a ida_typeinf.tinfo_t object representing the prototype, or None
"""
pass
+65
View File
@@ -0,0 +1,65 @@
class GraphViewer(ida_kernwin.CustomIDAMemo):
def OnGetText(self, node_id):
"""
Triggered when the graph viewer wants the text and color for a given node.
This callback is triggered one time for a given node (the value will be cached and used later without callin Python).
When you call refresh then again this callback will be called for each node.
This callback is mandatory.
@return: Return a string to describe the node text or return a tuple (node_text, node_color) to describe bot text and color
"""
return str(self[node_id])
def OnActivate(self):
"""
Triggered when the graph window gets the focus
@return: None
"""
print("Activated....")
def OnDeactivate(self):
"""Triggered when the graph window loses the focus
@return: None
"""
print("Deactivated....")
def OnHint(self, node_id):
"""
Triggered when the graph viewer wants to retrieve hint text associated with a given node
@return: None if no hint is avail or a string designating the hint
"""
return "hint for " + str(node_id)
def OnEdgeHint(self, src, dst):
"""
Triggered when the graph viewer wants to retrieve hint text associated with a edge
@return: None if no hint is avail or a string designating the hint
"""
return "hint for edge %d -> %d" % (src, dst)
def OnClose(self):
"""Triggered when the graph viewer window is being closed
@return: None
"""
print("Closing.......")
def OnClick(self, node_id):
"""
Triggered when a node is clicked
@return: False to ignore the click and True otherwise
"""
print("clicked on", self[node_id])
return True
def OnDblClick(self, node_id):
"""
Triggerd when a node is double-clicked.
@return: False to ignore the click and True otherwise
"""
print("dblclicked on", self[node_id])
return True
+31
View File
@@ -0,0 +1,31 @@
class cfunc_t(object):
def find_item_coords(self, *args):
"""
This method has the following signatures:
1. find_item_coords(item: citem_t) -> Tuple[int, int]
2. find_item_coords(item: citem_t, x: int_pointer, y: int_pointer) -> bool
NOTE: The second form is retained for backward-compatibility,
but we strongly recommend using the first.
@param item The item to find coordinates for in the pseudocode listing
"""
pass
class cfuncptr_t(object):
def find_item_coords(self, *args):
"""
This method has the following signatures:
1. find_item_coords(item: citem_t) -> Tuple[int, int]
2. find_item_coords(item: citem_t, x: int_pointer, y: int_pointer) -> bool
NOTE: The second form is retained for backward-compatibility,
but we strongly recommend using the first.
@param item The item to find coordinates for in the pseudocode listing
"""
pass
+171
View File
@@ -0,0 +1,171 @@
def parse_command_line(cmdline):
"""
Parses a space separated string (quotes and escape character are supported)
@param cmdline: The command line to parse
@return: A list of strings or None on failure
"""
pass
def set_script_timeout(timeout):
"""
Changes the script timeout value. The script wait box dialog will be hidden and shown again when the timeout elapses.
See also L{disable_script_timeout}.
@param timeout: This value is in seconds.
If this value is set to zero then the script will never timeout.
@return: Returns the old timeout value
"""
pass
def disable_script_timeout():
"""
Disables the script timeout and hides the script wait box.
Calling L{set_script_timeout} will not have any effects until the script is compiled and executed again
@return: None
"""
pass
def enable_extlang_python(enable):
"""
Enables or disables Python extlang.
When enabled, all expressions will be evaluated by Python.
@param enable: Set to True to enable, False otherwise
"""
pass
def RunPythonStatement(stmt):
"""
This is an IDC function exported from the Python plugin.
It is used to evaluate Python statements from IDC.
@param stmt: The statement to evaluate
@return: 0 - on success otherwise a string containing the error
"""
pass
class loader_input_t(pyidc_opaque_object_t):
"""
A helper class to work with linput_t related functions.
This class is also used by file loaders scripts.
"""
def __init__(self, pycapsule=None):
pass
def close(self):
"""Closes the file"""
pass
def open(self, filename, remote = False):
"""
Opens a file (or a remote file)
@param filename: the file name
@param remote: whether the file is local, or remote
@return: Boolean
"""
pass
def set_linput(self, linput):
"""
Links the current loader_input_t instance to a linput_t instance
@param linput: the linput_t to link to
"""
pass
@staticmethod
def from_fp(fp):
"""
A static method to construct an instance from a FILE*
@param fp: a FILE pointer
@return: a new instance, or None
"""
pass
def open_memory(self, start: ea_t, size: int):
"""
Create a linput for process memory (By internally calling idaapi.create_memory_linput())
This linput will use dbg->read_memory() to read data
@param start: starting address of the input
@param size: size of the memory range to represent as linput
if unknown, may be passed as 0
"""
pass
def seek(self, offset: int, whence = SEEK_SET):
"""
Set input source position
@param offset: the seek offset
@param whence: the position to seek from
@return: the new position (not 0 as fseek!)
"""
pass
def tell(self):
"""Returns the current position"""
pass
def getz(self, size: int, fpos: int=-1):
"""
Returns a zero terminated string at the given position
@param size: maximum size of the string
@param fpos: if != -1 then seek will be performed before reading
@return: The string or None on failure.
"""
pass
def gets(self, len: int):
"""
Reads a line from the input file. Returns the read line or None
@param len: the maximum line length
@return: a str, or None
"""
pass
def read(self, size: int=-1):
"""
Read up to size bytes (all data if size is negative). Return an empty bytes object on EOF.
@param size: the maximum number of bytes to read
@return a bytes object
"""
pass
def readbytes(self, size: int, big_endian: bool):
"""
Similar to read() but it respect the endianness
@param size: the maximum number of bytes to read
@param big_endian: endianness
@return a str, or None
"""
pass
def file2base(self, pos: int, ea1: ea_t, ea2: ea_t, patchable: bool):
"""
Load portion of file into the database
This function will include (ea1..ea2) into the addressing space of the
program (make it enabled)
@param li: pointer ot input source
@param pos: position in the file
@param (ea1..ea2): range of destination linear addresses
@param patchable: should the kernel remember correspondance of
file offsets to linear addresses.
@return: 1-ok,0-read error, a warning is displayed
"""
pass
def get_byte(self):
"""Reads a single byte from the file. Returns None if EOF or the read byte"""
pass
def opened(self):
"""Checks if the file is opened or not"""
pass
+71
View File
@@ -0,0 +1,71 @@
def dbg_get_registers():
"""
This function returns the register definition from the currently loaded debugger.
Basically, it returns an array of structure similar to to idd.hpp / register_info_t
@return:
None if no debugger is loaded
tuple(name, flags, class, dtype, bit_strings, default_bit_strings_mask)
The bit_strings can be a tuple of strings or None (if the register does not have bit_strings)
"""
pass
def dbg_get_thread_sreg_base(tid, sreg_value):
"""
Returns the segment register base value
@param tid: thread id
@param sreg_value: segment register (selector) value
@return:
- The base as an 'ea'
- Or None on failure
"""
pass
def dbg_read_memory(ea, sz):
"""
Reads from the debugee's memory at the specified ea
@param ea: the debuggee's memory address
@param sz: the amount of data to read
@return:
- The read buffer (as bytes)
- Or None on failure
"""
pass
def dbg_write_memory(ea, buffer):
"""
Writes a buffer to the debugee's memory
@param ea: the debuggee's memory address
@param buf: a bytes object to write
@return: Boolean
"""
pass
def dbg_get_name():
"""
This function returns the current debugger's name.
@return: Debugger name or None if no debugger is active
"""
pass
def dbg_get_memory_info():
"""
This function returns the memory configuration of a debugged process.
@return:
None if no debugger is active
tuple(start_ea, end_ea, name, sclass, sbase, bitness, perm)
"""
pass
+138
View File
@@ -0,0 +1,138 @@
def AssembleLine(ea, cs, ip, use32, line):
"""
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
@param ip: ip of instruction
@param use32: is 32bit segment
@param line: line to assemble
@return:
- None on failure
- or a string containing the assembled instruction
"""
pass
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.
"""
def ph_get_id():
"""
Returns the 'ph.id' field
"""
pass
def ph_get_version():
"""
Returns the 'ph.version'
"""
pass
def ph_get_flag():
"""
Returns the 'ph.flag'
"""
pass
def ph_get_cnbits():
"""
Returns the 'ph.cnbits'
"""
pass
def ph_get_dnbits():
"""
Returns the 'ph.dnbits'
"""
pass
def ph_get_reg_first_sreg():
"""
Returns the 'ph.reg_first_sreg'
"""
pass
def ph_get_reg_last_sreg():
"""
Returns the 'ph.reg_last_sreg'
"""
pass
def ph_get_segreg_size():
"""
Returns the 'ph.segreg_size'
"""
pass
def ph_get_reg_code_sreg():
"""
Returns the 'ph.reg_code_sreg'
"""
pass
def ph_get_reg_data_sreg():
"""
Returns the 'ph.reg_data_sreg'
"""
pass
def ph_get_icode_return():
"""
Returns the 'ph.icode_return'
"""
pass
def ph_get_instruc_start():
"""
Returns the 'ph.instruc_start'
"""
pass
def ph_get_instruc_end():
"""
Returns the 'ph.instruc_end'
"""
pass
def ph_get_tbyte_size():
"""
Returns the 'ph.tbyte_size' field as defined in he processor module
"""
pass
def ph_get_instruc():
"""
Returns a list of tuples (instruction_name, instruction_feature) containing the
instructions list as defined in he processor module
"""
pass
def ph_get_regnames():
"""
Returns the list of register names as defined in the processor module
"""
pass
def ph_get_operand_info(ea: ida_idaapi.ea_t, n: int) -> Union[Tuple[int, ida_idaapi.ea_t, int, int, int], None]:
"""
Returns the operand information given an ea and operand number.
@param ea: address
@param n: operand number
@return: Returns an idd_opinfo_t as a tuple: (modified, ea, reg_ival, regidx, value_size).
Please refer to idd_opinfo_t structure in the SDK.
"""
pass
+466
View File
@@ -0,0 +1,466 @@
class simplecustviewer_t(object):
def OnClick(self, shift):
"""
User clicked in the view
@param shift: Shift flag
@return: Boolean. True if you handled the event
"""
print("OnClick, shift=%d" % shift)
return True
def OnDblClick(self, shift):
"""
User dbl-clicked in the view
@param shift: Shift flag
@return: Boolean. True if you handled the event
"""
print("OnDblClick, shift=%d" % shift)
return True
def OnCursorPosChanged(self):
"""
Cursor position changed.
@return: Nothing
"""
print("OnCurposChanged")
def OnClose(self):
"""
The view is closing. Use this event to cleanup.
@return: Nothing
"""
print("OnClose")
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
"""
print("OnKeydown, vk=%d shift=%d" % (vkey, shift))
return False
def OnHint(self, lineno):
"""
Hint requested for the given line number.
@param lineno: The line number (zero based)
@return:
- tuple(number of important lines, hint string)
- None: if no hint available
"""
return (1, "OnHint, line=%d" % lineno)
def OnPopupMenu(self, menu_id):
"""
A context (or popup) menu item was executed.
@param menu_id: ID previously registered with add_popup_menu()
@return: Boolean
"""
print("OnPopupMenu, menu_id=" % menu_id)
return True
def register_timer(interval, callback):
"""
Register a timer
@param interval: Interval in milliseconds
@param callback: A Python callable that takes no parameters and returns an integer.
The callback may return:
-1 : to unregister the timer
>= 0 : the new or same timer interval
@return: None or a timer object
"""
pass
def unregister_timer(timer_obj):
"""
Unregister a timer
@param timer_obj: a timer object previously returned by a register_timer()
@return: Boolean
@note: After the timer has been deleted, the timer_obj will become invalid.
"""
pass
def choose_idasgn():
"""
Opens the signature chooser
@return: None or the selected signature name
"""
pass
def get_highlight(v, flags=0):
"""
Returns the currently highlighted identifier and flags
@param v: The UI widget to operate on
@param flags: Optionally specify a slot (see kernwin.hpp), current otherwise
@return: a tuple (text, flags), or None if nothing
is highlighted or in case of error.
"""
pass
def free_custom_icon(icon_id):
"""
Frees an icon loaded with load_custom_icon()
@param icon_id: The ID of the icon to free
"""
pass
def read_selection(v, p1, p2):
"""
Read the user selection, and store its information in p1 (from) and p2 (to).
This can be used as follows:
>>> p1 = ida_kernwin.twinpos_t()
p2 = ida_kernwin.twinpos_t()
view = ida_kernwin.get_current_viewer()
ida_kernwin.read_selection(view, p1, p2)
At that point, p1 and p2 hold information for the selection.
But, the 'at' property of p1 and p2 is not properly typed.
To specialize it, call #place() on it, passing it the view
they were retrieved from. Like so:
>>> place0 = p1.place(view)
place1 = p2.place(view)
This will effectively "cast" the place into a specialized type,
holding proper information, depending on the view type (e.g.,
disassembly, structures, enums, ...)
@param v: The view to retrieve the selection for.
@param p1: Storage for the "from" part of the selection.
@param p2: Storage for the "to" part of the selection.
@return: a bool value indicating success.
"""
pass
def ask_text(max_size: int, defval: str, prompt: str) -> Union[str, None]:
"""
Asks for a long text
@param max_size: Maximum text length, 0 for unlimited
@param defval: The default value
@param prompt: The prompt value
@return: None or the entered string
"""
pass
def ask_str(defval, hist, prompt):
"""
Asks for a long text
@param defval: The default value
@param hist: history id
@param prompt: The prompt value
@return: None or the entered string
"""
pass
def process_ui_action(name: str, flags: int=0):
"""
Invokes an IDA UI action by name
@param name: action name
@param flags: reserved
@return: Boolean
"""
pass
def del_hotkey(ctx):
"""
Deletes a previously registered function hotkey
@param ctx: Hotkey context previously returned by add_hotkey()
@return: Boolean.
"""
pass
def add_hotkey(hotkey, callable):
"""
Associates a function call with a hotkey.
Callable 'callable' will be called each time the hotkey is pressed
@param hotkey: The hotkey
@param callable: Callable
@return: Context object on success or None on failure.
"""
pass
MFF_FAST = 0x0000
"""execute code as soon as possible
this mode is ok call ui related functions
that do not query the database."""
MFF_READ = 0x0001
"""execute code only when ida is idle and it is safe to query the database.
this mode is recommended only for code that does not modify the database.
(nb: ida may be in the middle of executing another user request, for example it may be waiting for him to enter values into a modal dialog box)"""
MFF_WRITE = 0x0002
"""execute code only when ida is idle and it is safe to modify the database. in particular, this flag will suspend execution if there is
a modal dialog box on the screen this mode can be used to call any ida api function. MFF_WRITE implies MFF_READ"""
MFF_NOWAIT = 0x0004
"""Do not wait for the request to be executed.
he caller should ensure that the request is not
destroyed until the execution completes.
if not, the request will be ignored.
the return code of execute_sync() is meaningless
in this case.
This flag can be used to delay the code execution
until the next UI loop run even from the main thread"""
def execute_sync(callable, reqf):
"""
Executes a function in the context of the main thread.
If the current thread not the main thread, then the call is queued and
executed afterwards.
@param callable: A python callable object, must return an integer value
@param reqf: one of MFF_ flags
@return: -1 or the return value of the callable
"""
pass
def execute_ui_requests(callable_list):
"""
Inserts a list of callables into the UI message processing queue.
When the UI is ready it will call one callable.
A callable can request to be called more than once if it returns True.
@param callable_list: A list of python callable objects.
@note: A callable should return True if it wants to be called more than once.
@return: Boolean. False if the list contains a non callable item
"""
pass
def set_dock_pos(src_ctrl, dest_ctrl, orient, left = 0, top = 0, right = 0, bottom = 0):
"""
Sets the dock orientation of a window relatively to another window.
Use the left, top, right, bottom parameters if DP_FLOATING is used,
or if you want to specify the width of docked windows.
@param src_ctrl: Source docking control
@param dest_ctrl: Destination docking control
@param orient: One of DP_XXXX constants
@return: Boolean
Example:
set_dock_pos('Structures', 'Enums', DP_RIGHT) <- docks the Structures window to the right of Enums window
"""
pass
def is_idaq():
"""
Returns True or False depending if IDAPython is hosted by IDAQ
"""
pass
def attach_dynamic_action_to_popup(
unused,
popup_handle,
desc,
popuppath = None,
flags = 0):
"""
Create & insert an action into the widget's popup menu
(::ui_attach_dynamic_action_to_popup).
Note: The action description in the 'desc' parameter is modified by
this call so you should prepare a new description for each call.
For example:
desc = ida_kernwin.action_desc_t(None, 'Dynamic popup action', Handler())
ida_kernwin.attach_dynamic_action_to_popup(form, popup, desc)
@param unused: deprecated; should be None
@param popup_handle: target popup
@param desc: action description of type action_desc_t
@param popuppath: can be None
@param flags: a combination of SETMENU_ constants
@return: success
"""
pass
def set_nav_colorizer(callback):
"""
Set a new colorizer for the navigation band.
The 'callback' is a function of 2 arguments:
- ea (the EA to colorize for)
- nbytes (the number of bytes at that EA)
and must return a 'long' value.
The previous colorizer is returned, allowing
the new 'callback' to use 'call_nav_colorizer'
with it.
Note that the previous colorizer is returned
only the first time set_nav_colorizer() is called:
due to the way the colorizers API is defined in C,
it is impossible to chain more than 2 colorizers
in IDAPython: the original, IDA-provided colorizer,
and a user-provided one.
Example: colorizer inverting the color provided by the IDA colorizer:
def my_colorizer(ea, nbytes):
global ida_colorizer
orig = ida_kernwin.call_nav_colorizer(ida_colorizer, ea, nbytes)
return long(~orig)
ida_colorizer = ida_kernwin.set_nav_colorizer(my_colorizer)
@param callback: the new colorizer
"""
pass
def call_nav_colorizer(colorizer, ea: ida_idaapi.ea_t, nbytes: int):
"""
To be used with the IDA-provided colorizer, that is
returned as result of the first call to set_nav_colorizer().
@param colorizer: the Python colorizer to call
@param ea: the address to colorize
@param nbytes: the size of the range to colorize
"""
pass
def msg(message):
"""
Display a message in the message window
@param message: message to print
"""
pass
def warning(message):
"""
Display a message in a warning message box
@param message: message to print
"""
pass
def error(message):
"""
Display a fatal message in a message box and quit IDA
@param format: message to print
"""
pass
def get_navband_pixel(ea):
"""
Maps an address, onto a pixel coordinate within the navigation band
@param ea: The address to map
@return: a list [pixel, is_vertical]
"""
pass
def choose_find(title: str) -> Union[object, None]:
"""
Retrieve the chooser object by title
@param title the chooser title
@return the chooser, or None
"""
pass
class chooser_base_t(object):
def get_row(self, n: int) -> Tuple[List[str], int, chooser_item_attrs_t]:
"""
Get data & attributes for a row in a chooser.
@param n The row number
@return a tuple (list-of-strings, icon-id, row-attributes)
"""
pass
def get_chooser_data(title: str, n: int) -> List[str]:
"""
Get the text corresponding to the index N in the chooser data.
Use -1 to get the header.
@param title The chooser title
@return a list of strings, or None
"""
pass
def get_registered_actions() -> List[str]:
"""
Get a list with the names of all currently-registered actions.
@return the list of action names
"""
pass
class jobj_wrapper_t(object):
def get_dict(self) -> dict:
"""
Retrieve the contents of this object, as a dict
@return a dict containing all kvp's in this object
"""
pass
class place_t(object):
def generate(self, ud, maxsize: int) -> Tuple[List[str], int, int, int]:
"""
Generate text lines for the current location.
@param ud The user data object
@param maxsize The maximum number of lines to generate
@return a tuple (lines-of-text, default-line-number, prefix-color, background-color)
"""
pass
def restore_database_snapshot(snapshot, callback, userdata) -> bool:
"""
Restore a database snapshot.
Note: This call is asynchronous. When it is completed, the callback will be triggered.
@param snapshot the snapshot object
@param callback a callback function
@param userdata payload to pass to the callback
@return success
"""
pass
def take_database_snapshot(snapshot) -> Tuple[bool, str]:
"""
Take a database snapshot.
@param snapshot the snapshot object
@return a tuple (success, error-message)
"""
pass
def get_custom_viewer_location(*args) -> bool:
"""
Get information about the current location in a listing
This function has the following signatures:
1. get_custom_viewer_location(out_entry: ida_moves.lochist_entry_t, widget: TWidget, mouse: bool=False) -> bool
2. get_custom_viewer_location(out_entry: ida_kernwin.listing_location_t, widget: TWidget, flags: int=0) -> bool
The 2nd form is a superset of the 1st, and retrieves
the text (and tags) of the text.
"""
pass
+15
View File
@@ -0,0 +1,15 @@
def generate_disassembly(ea, max_lines, as_stack, notags):
"""
Generate disassembly lines (many lines) and put them into a buffer
@param ea: address to generate disassembly for
@param max_lines: how many lines max to generate
@param as_stack: Display undefined items as 2/4/8 bytes
@return:
- None on failure
- tuple(most_important_line_number, list(lines)) : Returns a tuple containing
the most important line number and a list of generated lines
"""
pass
+36
View File
@@ -0,0 +1,36 @@
def mem2base(mem, ea, fpos):
"""
Load database from the memory.
@param mem: the buffer
@param ea: start linear addresses
@param fpos: position in the input file the data is taken from.
if == -1, then no file position correspond to the data.
@return:
- Returns zero if the passed buffer was not a string
- Otherwise 1 is returned
"""
pass
def load_plugin(name):
"""
Loads a plugin
@param name: short plugin name without path and extension,
or absolute path to the file name
@return:
- None if plugin could not be loaded
- An opaque object representing the loaded plugin
"""
pass
def run_plugin(plg, arg):
"""
Runs a plugin
@param plg: A plugin object (returned by load_plugin())
@param arg: the code to pass to the plugin's "run()" function
@return: Boolean
"""
pass
+9
View File
@@ -0,0 +1,9 @@
def split_metadata(metadata: bytes) -> dict:
"""
Split the metadata blob into a set of KVP's
@param metadata a metadata blob
@return a set of KVP's
"""
pass
+21
View File
@@ -0,0 +1,21 @@
def get_import_module_name(mod_index):
"""
Returns the name of an imported module given its index
@param mod_index: the module index
@return: None or the module name
"""
pass
def enum_import_names(mod_index, callback):
"""
Enumerate imports from a specific module.
Please refer to list_imports.py example.
@param mod_index: The module index
@param callback: A callable object that will be invoked with an ea, name (could be None) and ordinal.
@return: 1-finished ok, -1 on error, otherwise callback return value (<=0)
"""
pass
+22
View File
@@ -0,0 +1,22 @@
class netnode(object):
def getblob(self, start, tag) -> Union[bytes, None]:
"""
Get a blob from a netnode.
@param start the index where the blob starts (it may span on multiple indexes)
@param tag the netnode tag
@return a blob, or None
"""
pass
def getclob(self, start, tag) -> Union[str, None]:
"""
Get a large amount of text from a netnode.
@param start the index where the clob starts (it may span on multiple indexes)
@param tag the netnode tag
@return a clob, or None
"""
pass
+9
View File
@@ -0,0 +1,9 @@
def str2user(str):
"""
Insert C-style escape characters to string
@param str: the input string
@return: new string with escape characters inserted, or None
"""
pass
+15
View File
@@ -0,0 +1,15 @@
def get_defsr(s, reg):
"""
Deprecated, use instead:
value = s.defsr[reg]
"""
pass
def set_defsr(s, reg, value):
"""
Deprecated, use instead:
s.defsr[reg] = value
"""
pass
+559
View File
@@ -0,0 +1,559 @@
def calc_type_size(til: til_t, type: bytes):
"""
Returns the size of a type
@param til: Type info library. 'None' can be passed.
@param type: serialized type byte string
@return:
- None on failure
- The size of the type
"""
pass
def apply_type(til: til_t, type: bytes, fields: bytes, ea: ida_idaapi.ea_t, flags: int) -> bool:
"""
Apply the specified type to the address
@param til: Type info library. 'None' can be used.
@param type: type string
@param fields: fields string (may be empty or None)
@param ea: the address of the object
@param flags: combination of TINFO_... constants or 0
@return: Boolean
"""
pass
def get_arg_addrs(caller: ida_idaapi.ea_t):
"""
Retrieve addresses of argument initialization instructions
@param caller: the address of the call instruction
@return: list of instruction addresses
"""
pass
def unpack_object_from_idb(til: til_t, type: bytes, fields: bytes, ea: ida_idaapi.ea_t, pio_flags: int = 0):
"""
Unpacks from the database at 'ea' to an object.
Please refer to unpack_object_from_bv()
"""
pass
def unpack_object_from_bv(til: til_t, type: bytes, fields: bytes, bytes, pio_flags: int = 0):
"""
Unpacks a buffer into an object.
Returns the error_t returned by idaapi.pack_object_to_idb
@param til: Type library. 'None' can be passed.
@param type: type string
@param fields: fields string (may be empty or None)
@param bytes: the bytes to unpack
@param pio_flags: flags used while unpacking
@return:
- tuple(0, err) on failure
- tuple(1, obj) on success
"""
pass
def pack_object_to_idb(obj, til: til_t, type: bytes, fields: bytes, ea: ida_idaapi.ea_t, pio_flags: int = 0):
"""
Write a typed object to the database.
Raises an exception if wrong parameters were passed or conversion fails
Returns the error_t returned by idaapi.pack_object_to_idb
@param til: Type library. 'None' can be passed.
@param type: type string
@param fields: fields string (may be empty or None)
@param ea: ea to be used while packing
@param pio_flags: flags used while unpacking
"""
pass
def pack_object_to_bv(obj, til: til_t, type: bytes, fields: bytes, base_ea: ida_idaapi.ea_t, pio_flags: int = 0):
"""
Packs a typed object to a string
@param til: Type library. 'None' can be passed.
@param type: type string
@param fields: fields string (may be empty or None)
@param base_ea: base ea used to relocate the pointers in the packed object
@param pio_flags: flags used while unpacking
@return:
tuple(0, err_code) on failure
tuple(1, packed_buf) on success
"""
pass
def get_named_type(til: til_t, name: str, ntf_flags: int):
"""
Get a type data by its name.
@param til: Type library
@param name: the type name
@param ntf_flags: a combination of NTF_* constants
@return:
None on failure
tuple(code, type_str, fields_str, cmt, field_cmts, sclass, value) on success
"""
pass
class tinfo_t(object):
def __init__(self, *args, ordinal=None, name=None, tid=None, til=None):
"""
Create a type object with the provided argumens.
This constructor has the following signatures:
1. tinfo_t(decl_type: type_t)
2. tinfo_t(decl: str, til: til_t = None, pt_flags: int = 0)
The latter form will create the type object by parsing the type declaration
Alternatively, you can use a form accepting the following keyword arguments:
* ordinal: int
* name: str
* tid: int
* til: til_t=None # `None` means `get_idati()`
E.g.,
* tinfo_t(ordinal=3)
* tinfo_t(ordinal=10, til=get_idati())
* tinfo_t(name="mytype_t")
* tinfo_t(name="thattype_t", til=my_other_til)
* tinfo_t(tid=ida_nalt.get_strid(some_address))
The constructor may raise an exception if data was invalid, or if parsing failed.
@param decl_type A simple type
@param decl A valid C declaration
@param til A type library, or `None` to use the (`get_idati()`) default
@param ordinal An ordinal in the type library
@param name A valid type name
@param pt_flags Parsing flags
"""
pass
def get_udm(self, *args) -> Union[Tuple[int, 'udm_t'], Tuple[None, None]]:
"""
Retrieve a structure/union member with either the specified name
or the specified index, in the specified tinfo_t object.
This function has the following signatures:
1. get_udm(index: int)
2. get_udm(name: str)
@param index a member index (1st form)
@param name a member name (2nd form)
@return a tuple (int, udm_t), or (-1, None) if member not found
"""
pass
def get_udm_by_offset(self, offset: int):
"""
Retrieve a structure/union member with the specified offset,
in the specified tinfo_t object.
@param offset the member offset
@return a tuple (int, udm_t), or (-1, None) if member not found
"""
pass
def add_udm(self, *args):
"""
Add a member to the current structure/union.
When creating a new structure/union from scratch, you might
want to first call `create_udt()`
This method has the following signatures:
1. add_udm(udm: udm_t, etf_flags: int = 0, times: int = 1, idx: int = -1)
2. add_udm(name: str, type: type_t | tinfo_t | str, offset: int = 0, etf_flags: int = 0, times: int = 1, idx: int = -1)
In the 2nd form, the 'type' descriptor, can be one of:
* type_t: if the type is simple (integral/floating/bool). E.g., `BTF_INT`
* tinfo_t: can handle more complex types (structures, pointers, arrays, ...)
* str: a C type declaration
If an input argument is incorrect, the constructor may raise an exception
@param udm The member, fully initialized (1st form)
@param name Member name - must not be empty
@param type Member type
@param offset the member offset in bits. It is the caller's responsibility
to specify correct offsets.
@param etf_flags an OR'ed combination of ETF_ flags
@param times how many times to add the new member
@param idx the index in the udm array where the new udm should be placed.
If the specified index cannot be honored because it would spoil
the udm sorting order, it is silently ignored.
"""
pass
def get_edm(self, *args) -> Tuple[int, 'edm_t']:
"""
Retrieve an enumerator with either the specified name
or the specified index, in the specified tinfo_t object.
This function has the following signatures:
1. get_edm(index: int)
2. get_edm(name: str)
@param index an enumerator index (1st form).
@param name an enumerator name (2nd form).
@return a tuple (int, edm_t), or (-1, None) if member not found
"""
pass
def get_edm_by_value(self, value: int, bmask: int = DEFMASK64, serial: int = 0) -> Tuple[int, 'edm_t']:
"""
Retrieve an enumerator with the specified value,
in the specified tinfo_t object.
@param value the enumerator value
@return a tuple (int, edm_t), or (-1, None) if member not found
"""
pass
def add_edm(self, *args):
"""
Add an enumerator to the current enumeration.
When creating a new enumeration from scratch, you might
want to first call `create_enum()`
This method has the following signatures:
1. add_edm(edm: edm_t, bmask: int = -1, etf_flags: int = 0, idx: int = -1)
2. add_edm(name: str, value: int, bmask: int = -1, etf_flags: int = 0, idx: int = -1)
If an input argument is incorrect, the constructor may raise an exception
@param edm The member, fully initialized (1st form)
@param name Enumerator name - must not be empty
@param value Enumerator value
@param bmask A bitmask to which the enumerator belongs
@param etf_flags an OR'ed combination of ETF_ flags
@param idx the index in the edm array where the new udm should be placed.
If the specified index cannot be honored because it would spoil
the edm sorting order, it is silently ignored.
"""
pass
def del_edm(self, *args):
"""
Delete an enumerator with the specified name
or the specified index, in the specified tinfo_t object.
This method has the following signatures:
1. del_edm(name: str) -> int
2. del_edm(index: int) -> int
@param name an enumerator name (1st form)
@param index an enumerator index (2nd form)
@return TERR_OK in case of success, or another TERR_* value in case of error
"""
pass
def del_edm_by_value(self, value: int, etf_flags: int=0, bmask: int = DEFMASK64, serial: int = 0):
"""
Delete an enumerator with the specified value,
in the specified tinfo_t object.
@param value the enumerator value
@return TERR_OK in case of success, or another TERR_* value in case of error
"""
pass
def iter_struct(self):
"""
Iterate on the members composing this structure.
Example:
til = ida_typeinf.get_idati()
tif = til.get_named_type("my_struc")
for udm in tif.iter_struct():
print(f"{udm.name} at bit offset {udm.offset}")
Will raise an exception if this type is not a structure.
@return a udm_t-producing generator
"""
pass
def iter_union(self):
"""
Iterate on the members composing this union.
Example:
til = ida_typeinf.get_idati()
tif = til.get_named_type("my_union")
for udm in tif.iter_union():
print(f"{udm.name}, with type {udm.type}")
Will raise an exception if this type is not a union.
@return a udm_t-producing generator
"""
pass
def iter_udt(self):
"""
Iterate on the members composing this structure, or union.
Example:
til = ida_typeinf.get_idati()
tif = til.get_named_type("my_type")
for udm in tif.iter_udt():
print(f"{udm.name} at bit offset {udm.offset} with type {udm.type}")
Will raise an exception if this type is not a structure, or union
@return a udm_t-producing generator
"""
pass
def iter_enum(self):
"""
Iterate on the members composing this enumeration.
Example:
til = ida_typeinf.get_idati()
tif = til.get_named_type("my_enum")
for edm in tif.iter_enum():
print(f"{edm.name} = {edm.value}")
Will raise an exception if this type is not an enumeration
@return a edm_t-producing generator
"""
pass
def iter_func(self):
"""
Iterate on the arguments contained in this function prototype
Example:
address = ...
func = ida_funcs.get_func(address)
func_type = func.prototype
for arg in func_type.iter_func():
print(f"{arg.name}, of type {arg.type}")
Will raise an exception if this type is not a function
@return a funcarg_t-producing generator
"""
pass
class edm_t(object):
def __init__(self, *args):
"""
Create an enumerator, with the specified name and value
This constructor has the following signatures:
1. edm_t(edm: edm_t)
2. edm_t(name: str, value: int, cmt: str=None)
@param name Enumerator name. Must not be empty (1st form)
@param value Enumerator value (1st form)
@param cmt Enumerator repeatable comment. May be empty (1st form)
@param edm An enum member to copy
"""
pass
class udm_t(object):
def __init__(self, *args):
"""
Create a structure/union member, with the specified name and type.
This constructor has the following signatures:
1. udm_t(udm: udm_t)
2. udm_t(name: str, type, offset: int)
The 'type' descriptor, can be one of:
* type_t: if the type is simple (integral/floating/bool). E.g., `BTF_INT`
* tinfo_t: can handle more complex types (structures, pointers, arrays, ...)
* str: a C type declaration
If an input argument is incorrect, the constructor may raise an exception
The size will be computed automatically.
@param udm a source udm_t
@param name a valid member name. Must not be empty.
@param type the member type
@param offset the member offset in bits. It is the caller's responsibility
to specify correct offsets.
"""
pass
def copy(self, src):
"""
Copy the src, into this instance
@param src The source udm_t
"""
pass
class udt_type_data_t(object):
def get_best_fit_member(self, disp):
"""
Get the member that is most likely referenced by the specified offset.
@param disp the byte offset
@return a tuple (int, udm_t), or (-1, None) if member not found
"""
pass
class funcarg_t(object):
def __init__(self, *args):
"""
Create a function argument, with the specified name and type.
This constructor has the following signatures:
1. funcarg_t(name: str, type, argloc: argloc_t)
2. funcarg_t(funcarg: funcarg_t)
In the 1st form, the 'type' descriptor, can be one of:
* type_t: if the type is simple (integral/floating/bool). E.g., `BTF_INT`
* tinfo_t: can handle more complex types (structures, pointers, arrays, ...)
* str: a C type declaration
If an input argument is incorrect, the constructor may raise an exception
@param name a valid argument name. May not be empty (1st form).
@param type the member type (1st form).
@param argloc the argument location. Can be empty (1st form).
@param funcarg a funcarg_t to copy
"""
pass
class til_t(object):
def import_type(self, src):
"""
Import a type (and all its dependencies) into this type info library.
@param src The type to import
@return the imported copy, or None
"""
def numbered_types(self):
"""
Returns a generator over the numbered types contained in this
type library.
Every iteration returns a fresh new tinfo_t object
@return a tinfo_t-producing generator
"""
pass
def named_types(self):
"""
Returns a generator over the named types contained in this
type library.
Every iteration returns a fresh new tinfo_t object
@return a tinfo_t-producing generator
"""
pass
def get_named_type(self, name):
"""
Retrieves a tinfo_t representing the named type in this type library.
@param name a type name
@return a new tinfo_t object, or None if not found
"""
pass
def get_numbered_type(self, ordinal):
"""
Retrieves a tinfo_t representing the numbered type in this type library.
@param ordinal a type ordinal
@return a new tinfo_t object, or None if not found
"""
pass
def get_named_type64(til: til_t, name: str, ntf_flags: int=0) -> Union[Tuple[int, bytes, bytes, str, str, int, int], None]:
"""
Get a named type from a type library.
Please use til_t.get_named_type instead.
"""
pass
def get_numbered_type(til: til_t, ordinal: int) -> Union[Tuple[bytes, bytes, str, str, int], None]:
"""
Get a type from a type library, by its ordinal
Please use til_t.get_numbered_type instead.
"""
pass
def idc_get_local_type_raw(ordinal) -> Tuple[bytes, bytes]:
"""
"""
pass
def idc_parse_decl(til: til_t, decl: str, flags: int) -> Tuple[str, bytes, bytes]:
"""
"""
pass
def idc_print_type(type: bytes, fields: bytes, name: str, flags: int) -> str:
"""
"""
pass
def print_decls(printer: text_sink_t, til: til_t, ordinals: List[int], flags: int) -> int:
"""
Print types (and possibly their dependencies) in a format suitable for using in
a header file. This is the reverse parse_decls().
@param printer a handler for printing text
@param til the type library holding the ordinals
@param ordinals a list of ordinals corresponding to the types to print
@param flags a combination of PDF_ constants
@return
>0: the number of types exported
0: an error occurred
<0: the negated number of types exported. There were minor errors and
the resulting output might not be compilable.
"""
pass
def remove_tinfo_pointer(tif: tinfo_t, name: str, til: til_t) -> Tuple[bool, str]:
"""
Remove pointer of a type. (i.e. convert "char *" into "char"). Optionally remove
the "lp" (or similar) prefix of the input name. If the input type is not a
pointer, then fail.
@param tif the type info
@param name the name of the type to "unpointerify"
@param til the type library
@return a tuple (success, new-name)
"""
pass
+29
View File
@@ -0,0 +1,29 @@
def decode_preceding_insn(out: insn_t, ea: ida_idaapi.ea_t) -> Tuple[ida_idaapi.ea_t, bool]:
"""
Decodes the preceding instruction.
@param out: instruction storage
@param ea: current ea
@return: tuple(preceeding_ea or BADADDR, farref = Boolean)
"""
pass
def construct_macro(*args):
"""
See ua.hpp's construct_macro().
This function has the following signatures
1. construct_macro(insn: insn_t, enable: bool, build_macro: callable) -> bool
2. construct_macro(constuctor: macro_constructor_t, insn: insn_t, enable: bool) -> bool
@param insn: the instruction to build the macro for
@param enable: enable macro generation
@param build_macro: a callable with 2 arguments: an insn_t, and
whether it is ok to consider the next instruction
for the macro
@param constructor: a macro_constructor_t implementation
@return: success
"""
pass
+47
View File
@@ -0,0 +1,47 @@
def create_switch_xrefs(ea, si):
"""
This function creates xrefs from the indirect jump.
Usually there is no need to call this function directly because the kernel
will call it for switch tables
Note: Custom switch information are not supported yet.
@param ea: address of the 'indirect jump' instruction
@param si: switch information
@return: Boolean
"""
pass
def calc_switch_cases(ea, si):
"""
Get information about a switch's cases.
The returned information can be used as follows:
for idx in range(len(results.cases)):
cur_case = results.cases[idx]
for cidx in range(len(cur_case)):
print("case: %d" % cur_case[cidx])
print(" goto 0x%x" % results.targets[idx])
@param ea: address of the 'indirect jump' instruction
@param si: switch information
@return: a structure with 2 members: 'cases', and 'targets'.
"""
pass
def create_switch_table(ea, si):
"""
Create switch table from the switch information
@param ea: address of the 'indirect jump' instruction
@param si: switch information
@return: Boolean
"""
pass
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -e
#ensure out folder exists
mkdir -p $3
IN_FOLDER=$(realpath $2)
OUT_FOLDER=$(realpath $3)
ARTIFACTS=$1
echo "[${ARTIFACTS}] GOING to COPY FILES from ${IN_FOLDER} to ${OUT_FOLDER}"
cd ${OUT_FOLDER}
echo "[${ARTIFACTS}] make the out folder p4 edit"
p4 edit ...
echo "[${ARTIFACTS}] copy new files"
rm -rf *
cp -R ${IN_FOLDER}/* .
echo "[${ARTIFACTS}] adding files to p4"
p4 add ...
p4 revert -a ...
+138
View File
@@ -0,0 +1,138 @@
"""
summary: Add missing inodes in dirtree structure in "/lost+found" directory
description:
How to collects inodes for various dirtrees ('Local Types', 'Names',
'Functions', 'Imports', 'Address bookmark' and 'Breakpoints') in both
the dirtree structure and the database.
Create a directory an links inodes to them in the dirtree structure
You cannot add all inodes to the "/lost+found" directory because inodes
can be at various places in a dirtree structure.
The early dirtree implementations were not perfect and may have missed to
add some inodes in the tree structure, this script corrects this issue.
keywords: dirtree, recovery
"""
import ida_dirtree
from ida_dirtree import dirtree_t
import ida_typeinf
import ida_funcs
import ida_name
import ida_dbg
import ida_nalt
import ida_kernwin
import ida_moves
def get_ltypes_inode(n):
inode = n + 1
name = ida_typeinf.get_numbered_type_name(None, inode)
if name is None:
# if the name is None, we have a #deleted type,
# present in flat mode but not in fulltree mode
return True, None
else:
return False, inode
def get_func_inode(n):
inode = ida_funcs.getn_func(n).start_ea
return False, inode
def get_name_inode(n):
inode = ida_name.get_nlist_ea(n)
if inode is None:
print(hex(inode))
return False, inode
list_inodes_in_idb = []
def get_import_list():
def imp_cb(ea, name, ordinal):
list_inodes_in_idb.append(ea)
return True
nimps = ida_nalt.get_import_module_qty()
for i in range(nimps):
ida_nalt.enum_import_names(i, imp_cb)
list_inodes_in_idb.sort()
return len(list_inodes_in_idb)
def get_nth_inode_in_idb(n):
return False, list_inodes_in_idb[n]
def get_idaplace_list_inodes_in_idb():
id = ida_kernwin.get_place_class_id("idaplace_t")
p = ida_kernwin.get_place_class_template(id)
r = ida_moves.renderer_info_t()
l = ida_moves.lochist_entry_t(p, r)
for idx in range(ida_moves.bookmarks_t.size(l, None)):
ida_moves.bookmarks_t.get(l, idx, None)
idaloc = ida_kernwin.place_t.as_idaplace_t(l.place())
list_inodes_in_idb.append(idaloc.ea)
list_inodes_in_idb.sort()
return len(list_inodes_in_idb)
def get_bpt_inode(n):
bpt = ida_dbg.bpt_t()
if not ida_dbg.getn_bpt(n, bpt):
return True, None
return False, bpt.bptid
class dt_collect_inode_t(ida_dirtree.dirtree_visitor_t):
def __init__(self):
ida_dirtree.dirtree_visitor_t.__init__(self)
self.list_inodes_in_dirtree = []
def visit(self, c, de):
if dirtree_t.isfile(de):
self.list_inodes_in_dirtree.append(de.idx)
return 0
std_recovery_data = [
( ida_dirtree.DIRTREE_LOCAL_TYPES, ida_typeinf.get_ordinal_count, get_ltypes_inode, "Local Types" ),
( ida_dirtree.DIRTREE_FUNCS, ida_funcs.get_func_qty, get_func_inode, "Local Types" ),
( ida_dirtree.DIRTREE_NAMES, ida_name.get_nlist_size, get_name_inode, "Names" ),
( ida_dirtree.DIRTREE_IMPORTS, get_import_list, get_nth_inode_in_idb, "Imports" ),
( ida_dirtree.DIRTREE_IDAPLACE_BOOKMARKS, get_idaplace_list_inodes_in_idb, get_nth_inode_in_idb, "Address bookmarks" ),
( ida_dirtree.DIRTREE_BPTS, ida_dbg.get_bpt_qty, get_bpt_inode, "Breakpoints" ),
]
for dt_id, get_count_and_maybe_list_inodes_in_idb, get_inode, title in std_recovery_data:
dt = ida_dirtree.get_std_dirtree(dt_id)
print("### Dirtree ", title)
list_inodes_in_idb = []
collector = dt_collect_inode_t()
dt.traverse(collector)
set_inodes_in_dirtree = set(collector.list_inodes_in_dirtree)
nb_inodes = get_count_and_maybe_list_inodes_in_idb()
nb_not_list = 0
nb_list = len(set_inodes_in_dirtree)
print("Number of unique inodes in the idb: %d\nNumber of unique inodes in fulltree mode: %d"%(nb_inodes, nb_list))
if nb_list < nb_inodes:
err = dt.mkdir("/lost+found")
if err != ida_dirtree.DTE_OK:
print(dt.errstr(err))
err = dt.chdir("/lost+found")
if err != ida_dirtree.DTE_OK:
print(dt.errstr(err))
for n in range(nb_inodes):
inc, inode = get_inode(n)
if inode is not None:
if inode not in set_inodes_in_dirtree:
err = dt.link(inode)
if err != ida_dirtree.DTE_OK:
print("Failed to link inode ", hex(inode), " ", dt.errstr(err) )
inc = True
if inc:
nb_not_list += 1
if nb_inodes == nb_list + nb_not_list:
break
@@ -0,0 +1,4 @@
"""This internal test is used to verify that pc_api tests won't swallow
exceptions while using IDAPYTHON_EXAMPLE <path_to_script>"""
raise ImportError("Nasty exception at the script")
+23
View File
@@ -18,6 +18,29 @@ with one or many examples, and those should be also put under test
rather than if it consists of a bunch of IDAPython code our
users will never see, and cannot be inspired from.)
### Best practices
* don't use `idc.py`: some of its operations are a bit too elusive
* don't use `idaapi`: that "hides" the provenance of the
function/type/item being used, and makes it that much harder to
group ideas by module
* don't `from <something> import <whatever>`: for the same reason
* use double-quotes for all string literals, unless there's a good
reason not to do so (e.g., the string literal contains some `"`
characters, and `\`-escaping them would be inconvenient & make the
code awkward to read).
Double-quoted string literals let us grep more predictably & reliably.
## Example header
Every example must have a valid header, holding a one-liner `summary:`,
as well as a description further explaining what the example is about.
Some notes:
* `summary:`: the one-liner must not end with a `.`
* `summary:`: prefer the `list something...` form over the `listing something...`
## Helping our customers, teaching IDAPython in the process
In addition, when a customer asks for help on support@ (or the forums)
-30
View File
@@ -1,30 +0,0 @@
"""
summary: triggering bits of code by pressing a shortcut (older version)
description:
This is a somewhat ancient way of registering actions & binding
shortcuts. It's still here for reference, but "fresher" alternatives
should be preferred.
keywords: actions
see_also: actions, add_hotkey
"""
import ida_expr
import ida_kernwin
def say_hi():
print("Hotkey activated!")
# IDA binds hotkeys to IDC functions so a trampoline IDC function must be created
ida_expr.compile_idc_text('static key_2() { RunPythonStatement("say_hi()"); }')
# Add the hotkey
ida_kernwin.add_idc_hotkey("2", 'key_2')
# Press 2 to activate foo()
# The hotkey can be removed with
# ida_kernwin.del_idc_hotkey('2')
-94
View File
@@ -1,94 +0,0 @@
"""
summary: showcasing `ida_bytes.bin_search`
description:
IDAPython's ida_bytes.bin_search function is pretty powerful,
but can be tough to figure out at first. This example introduces
* `ida_bytes.bin_search`, and
* `ida_bytes.parse_binpat_str`
in order to implement a simple replacement for the
'Search > Sequence of bytes...' dialog, that lets users
search for sequences of bytes that compose string literals
in the binary file (either in the default 1-byte-per-char
encoding, or as UTF-16.)
"""
import ida_kernwin
import ida_bytes
import ida_ida
import ida_idaapi
import ida_nalt
class search_strlit_form_t(ida_kernwin.Form):
def __init__(self):
ida_kernwin.Form.__init__(
self,
r"""Please enter string literal
<Text: {Text}>
<#UTF16-BE if file is big-endian, UTF16-LE otherwise#As UTF-16: {UTF16}>{Encoding}>
""",
{
"Text" : ida_kernwin.Form.StringInput(),
"Encoding" : ida_kernwin.Form.ChkGroupControl(("UTF16",)),
})
class search_strlit_ah_t(ida_kernwin.action_handler_t):
def __init__(self):
ida_kernwin.action_handler_t.__init__(self)
def activate(self, ctx):
f = search_strlit_form_t()
f, args = f.Compile()
ok = f.Execute()
if ok:
current_ea = ida_kernwin.get_screen_ea()
patterns = ida_bytes.compiled_binpat_vec_t()
encoding = ida_nalt.get_default_encoding_idx(
ida_nalt.BPU_2B if f.Encoding.value else ida_nalt.BPU_1B)
# string literals must be quoted. That's how parse_binpat_str
# recognizes them (we want to be careful though: the user
# might type in something like 'L"hello"', which should
# decode to the IDB-specific wide-char set of bytes)
text = f.Text.value
if text.find('"') < 0:
text = '"%s"' % text
err = ida_bytes.parse_binpat_str(
patterns,
current_ea,
text,
10, # radix (not that it matters though, since we're all about string literals)
encoding)
if not err:
ea = ida_bytes.bin_search(
current_ea,
ida_ida.inf_get_max_ea(),
patterns,
ida_bytes.BIN_SEARCH_FORWARD
| ida_bytes.BIN_SEARCH_NOBREAK
| ida_bytes.BIN_SEARCH_NOSHOW)
ok = ea != ida_idaapi.BADADDR
if ok:
ida_kernwin.jumpto(ea)
else:
print("Failed parsing binary pattern: \"%s\"" % err)
return ok
def update(self, ctx):
return ida_kernwin.AST_ENABLE_FOR_WIDGET \
if ctx.widget_type == ida_kernwin.BWN_DISASM \
else ida_kernwin.AST_DISABLE_FOR_WIDGET
ACTION_NAME = "bin_search:search"
ACTION_SHORTCUT = "Ctrl+Shift+S"
if ida_kernwin.register_action(
ida_kernwin.action_desc_t(
ACTION_NAME,
"Search for string literal",
search_strlit_ah_t(),
ACTION_SHORTCUT)):
print("Please use \"%s\" to search for string literals" % ACTION_SHORTCUT)
@@ -1,5 +1,5 @@
"""
summary: executing code into the application being debugged (on Linux)
summary: execute code into the application being debugged (on Linux)
description:
Using the `ida_idd.Appcall` utility to execute code in
@@ -18,6 +18,8 @@ description:
* run this script
Note: the real body of code is in `simple_appcall_common.py`.
level: advanced
"""
import os
@@ -1,5 +1,5 @@
"""
summary: executing code into the application being debugged (on Windows)
summary: execute code into the application being debugged (on Windows)
description:
Using the `ida_idd.Appcall` utility to execute code in
@@ -11,13 +11,15 @@ description:
To use this example:
* run `ida64` on test program `simple_appcall_win64.exe`, or
* run `ida` on test program `simple_appcall_win64.exe`, or
`ida` on test program `simple_appcall_win32.exe`, and wait for
auto-analysis to finish
* select the 'windows debugger' (either local, or remote)
* run this script
Note: the real body of code is in `simple_appcall_common.py`.
level: advanced
"""
import os
@@ -5,6 +5,8 @@ description:
Start a debugging session, step through the first five
instructions. Each instruction is disassembled after
execution.
level: advanced
"""
import ida_dbg
@@ -1,11 +1,13 @@
"""
summary: using the low-level tracing hook
summary: react to trace notifications
description:
This script demonstrates using the low-level tracing hook
(ida_dbg.DBG_Hooks.dbg_trace). It can be run like so:
ida[t].exe -B -Sdbg_trace.py -Ltrace.log file.exe
ida.exe -B -Sdbg_trace.py -Ltrace.log file.exe
level: advanced
"""
import time
@@ -1,18 +1,23 @@
"""
summary: print call stack (on Linux)
summary: print call stack
description: print the return addresses from the call stack at a breakpoint.
(and print also the module and the debug name from debugger)
description:
Print the return addresses from the call stack at a breakpoint,
when debugging a Linux binary.
(and also print the module and the debug name from debugger)
To use this example:
* run `ida64` on test program `simple_appcall_linux64`, or
* run `ida` on test program `simple_appcall_linux64`, or
`ida` on test program `simple_appcall_linux32`, and wait for
auto-analysis to finish
* put a breakpoint where you want to see the call stack
* select the 'linux debugger' (either local, or remote)
* start debugging
* Press Shift+C at the breakpoint
level: intermediate
"""
import os
import ida_idaapi
@@ -35,8 +40,8 @@ class print_call_stack_ah_t():
if ida_dbg.get_module_info(frame.callea, mi):
module = os.path.basename(mi.name)
name = ida_name.get_nice_colored_name(
frame.callea,
ida_name.GNCN_NOCOLOR|ida_name.GNCN_NOLABEL|ida_name.GNCN_NOSEG|ida_name.GNCN_PREFDBG)
frame.callea,
ida_name.GNCN_NOCOLOR|ida_name.GNCN_NOLABEL|ida_name.GNCN_NOSEG|ida_name.GNCN_PREFDBG)
log("Return address: " + hex(frame.callea) + " from: " + module + " with debug name: " + name)
else:
log("Return address: " + hex(frame.callea))
@@ -1,8 +1,9 @@
"""
summary: print all registers, for all threads
summary: print all registers, for all threads in the debugged process
description: iterate over the list of threads in the program being
debugged, and dump all registers contents
description:
Iterate over the list of threads in the program being
debugged, and dump all registers contents
To use this example:
@@ -13,6 +14,8 @@ description: iterate over the list of threads in the program being
* select the 'linux debugger' (either local, or remote)
* start debugging
* Press Alt+Shift+C at the breakpoint
level: beginner
"""
import ida_idd
import ida_dbg
@@ -1,5 +1,5 @@
"""
summary: adding actions to the "registers" widget(s)
summary: add a custom action to the "registers" widget
description:
It's possible to add actions to the context menu of
@@ -7,6 +7,8 @@ description:
This example shows how to do just that for
registers-displaying widgets (e.g., "General registers")
level: intermediate
"""
import ida_dbg
@@ -1,9 +1,11 @@
"""
summary: retrieving & dumping debuggee symbols
summary: dump symbols from a process being debugged
description:
Queries the debugger (possibly remotely) for the list of
symbols that the process being debugged, provides.
level: beginner
"""
import ida_dbg
@@ -1,5 +1,5 @@
"""
summary: interactively color certain pseudocode lines
summary: interactively color decompilation lines
description:
Provides an action that can be used to dynamically alter the
@@ -11,6 +11,8 @@ description:
with a special background color.
keywords: colors
level: intermediate
"""
import ida_kernwin
@@ -1,11 +1,13 @@
"""
summary: a focus on the 'curpos' hook, printing additional details about user input
summary: print information about the current position in decompilation
description:
Shows how user input information can be retrieved during
processing of a notification triggered by that input
see_also: vds_hooks
level: advanced
"""
import ida_hexrays
@@ -1,13 +1,15 @@
"""
summary: automatic decompilation of functions
summary: decompile entrypoint automatically
description:
Attempts to load a decompiler plugin corresponding to the current
architecture (and address size) right after auto-analysis is performed,
architecture right after auto-analysis is performed,
and then tries to decompile the function at the first entrypoint.
It is particularly suited for use with the '-S' flag, for example:
idat -Ldecompile.log -Sdecompile_entry_points.py -c file
level: intermediate
"""
import ida_ida
@@ -22,21 +24,17 @@ import ida_kernwin
# manually if we want to use it
def init_hexrays():
ALL_DECOMPILERS = {
ida_idp.PLFM_386: "hexrays",
ida_idp.PLFM_386: "hexx64",
ida_idp.PLFM_ARM: "hexarm",
ida_idp.PLFM_PPC: "hexppc",
ida_idp.PLFM_MIPS: "hexmips",
ida_idp.PLFM_RISCV: "hexrv",
}
cpu = ida_idp.ph.id
decompiler = ALL_DECOMPILERS.get(cpu, None)
if not decompiler:
print("No known decompilers for architecture with ID: %d" % ida_idp.ph.id)
return False
if ida_ida.inf_is_64bit():
if cpu == ida_idp.PLFM_386:
decompiler = "hexx64"
else:
decompiler += "64"
if ida_loader.load_plugin(decompiler) and ida_hexrays.init_hexrays_plugin():
return True
else:
@@ -1,5 +1,5 @@
"""
summary: decompile entire file
summary: produce C listing for the entire file
description:
automate IDA to perform auto-analysis on a file and,
@@ -15,6 +15,8 @@ description:
* -A instructs IDA to run in non-interactive mode
* -S holds a path to the script to run (note this is a single token;
there is no space between '-S' and its path.)
level: beginner
"""
import ida_pro
@@ -1,5 +1,10 @@
"""
summary: decompile & print current function.
summary: decompile & print current function
description:
Decompile the function under the cursor
level: beginner
"""
import ida_hexrays
@@ -1,5 +1,5 @@
"""
summary: a custom microcode instruction optimization rule
summary: add custom microcode instruction optimization rule
description:
Installs a custom microcode instruction optimization rule,
@@ -12,6 +12,8 @@ description:
call !DbgRaiseAssertionFailure <fast:"char *" "assertion text">.0
To see this plugin in action please use arm64_brk.i64
level: intermediate
"""
import ida_bytes
@@ -1,5 +1,5 @@
"""
summary: a custom microcode block optimization rule (resolve `goto` chains)
summary: add a custom microcode block optimization rule
description:
Installs a custom microcode block optimization rule,
@@ -16,6 +16,8 @@ description:
In other words we fix a goto target if it points to a chain of gotos.
This improves the decompiler output in some cases.
level: advanced
"""
import ida_bytes
@@ -4,6 +4,8 @@ summary: list instruction registers
description:
Shows a list of direct references to a register from the
current instruction.
level: advanced
"""
import ida_pro
@@ -1,8 +1,10 @@
"""
summary: generates microcode for selection
summary: generate microcode for the selected range of instructions
description:
Generates microcode for selection and dumps it to the output window.
level: beginner
"""
import ida_bytes
@@ -1,5 +1,5 @@
"""
summary: using the "Select offsets" widget
summary: invoke the structure offset-choosing dialog from decompilation
description:
Registers an action opens the "Select offsets" widget
@@ -9,6 +9,8 @@ description:
through Alt+Y.
Place cursor on the union field and press Shift+T
level: advanced
"""
import ida_idaapi
@@ -1,5 +1,5 @@
"""
summary: a custom microcode instruction optimization rule (`x | ~x => -1`)
summary: add a custom microcode instruction optimization rule
description:
Installs a custom microcode instruction optimization rule,
@@ -12,6 +12,8 @@ description:
-1
To see this plugin in action please use be_ornot_be.idb
level: advanced
"""
import ida_hexrays
@@ -22,6 +22,8 @@ description:
This plugin illustrates another approach to the problem:
if you happen to be able to calculate the call prototypes dynamically,
this is how to inform the decompiler about them.
level: intermediate
"""
import ida_idaapi
@@ -1,5 +1,5 @@
"""
summary: invert if/else blocks
summary: invert if/else blocks in decompilation
description:
Registers an action that can be used to invert the `if`
@@ -31,6 +31,8 @@ description:
IDA, and the changes will be present.
author: EiNSTeiN_ (einstein@g3nius.org)
level: advanced
"""
import idautils
@@ -1,5 +1,5 @@
"""
summary: dump user-defined information
summary: dump user-defined information for a function
description:
Prints user-defined information to the "Output" window.
@@ -13,6 +13,8 @@ description:
This script loads information from the database without decompiling anything.
author: EiNSTeiN_ (einstein@g3nius.org)
level: intermediate
"""
import ida_kernwin
@@ -1,5 +1,5 @@
"""
summary: show ctree graph
summary: dump C-tree graph
description:
Registers an action that can be used to show the graph of the ctree.
@@ -10,6 +10,8 @@ description:
To display the graph, we produce a .gdl file, and
request that ida displays that using `ida_gdl.display_gdl`.
level: advanced
"""
import ida_pro
@@ -6,6 +6,8 @@ description:
by removing some white spaces
Note: this is rather crude, not quite "pythonic" code.
level: intermediate
"""
import idautils
@@ -1,11 +1,13 @@
"""
summary: iterate a cblock_t object
summary: dump statement blocks
description:
Using a `ida_hexrays.ctree_visitor_t`, search for
`ida_hexrays.cit_block` instances and dump them.
author: EiNSTeiN_ (einstein@g3nius.org)
level: beginner
"""
import ida_hexrays
@@ -1,5 +1,5 @@
"""
summary: using `ida_hexrays.udc_filter_t`
summary: improve decompilation by turning specific patterns into custom function calls
description:
Registers an action that uses a `ida_hexrays.udc_filter_t` to decompile
@@ -10,6 +10,8 @@ description:
In addition to having a shortcut, the action will be present
in the context menu.
level: intermediate
"""
import ida_idaapi
@@ -1,5 +1,5 @@
"""
summary: decompiler hints
summary: provide custom decompiler hints
description:
Handle `ida_hexrays.hxe_create_hint` notification using hooks,
@@ -12,6 +12,8 @@ description:
the form of `!{varname}` (where `{varname}` is replaced with the
variable name)
* an `if` statement, replace the hint with our own, saying "condition"
level: beginner
"""
import ida_idaapi
@@ -1,5 +1,5 @@
"""
summary: various decompiler hooks
summary: react to decompiler events/notifications
description:
Shows how to hook to many notifications sent by the decompiler.
@@ -12,6 +12,8 @@ description:
subclassing `ida_hexrays.Hexrays_Hooks`
see_also: curpos_details
level: intermediate
"""
import inspect
@@ -70,7 +72,7 @@ class vds_hooks_t(ida_hexrays.Hexrays_Hooks):
print("### %s: %s" % (method_name, ", ".join(argstrs)))
return 0
def flowchart(self, fc):
def flowchart(self, fc, mba, reachable_blocks, decomp_flags):
return self._log()
def stkpnts(self, mba, stkpnts):
@@ -94,6 +96,9 @@ class vds_hooks_t(ida_hexrays.Hexrays_Hooks):
def glbopt(self, mba):
return self._log()
def begin_structural(self, out, cfunc, ctrl_graph):
return self._log()
def structural(self, ctrl_graph):
return self._log()
@@ -172,5 +177,20 @@ class vds_hooks_t(ida_hexrays.Hexrays_Hooks):
def calls_done(self, mba):
return self._log()
def begin_inlining(self, cdg, flags):
return self._log()
def inlining_func(self, cdg, blk, mbr):
return self._log()
def inlined_func(self, cdg, blk, mbr, i1, i2):
return self._log()
def pre_structural(self, ctrl_graph, cfunc, cfg):
return self._log()
def collect_warnings(self, cfunc):
return self._log()
vds_hooks = vds_hooks_t()
vds_hooks.hook()
@@ -1,9 +1,11 @@
"""
summary: modifying local variables
summary: modifying function local variables
description:
Use a `ida_hexrays.user_lvar_modifier_t` to modify names,
comments and/or types of local variables.
level: intermediate
"""
import ida_hexrays

Some files were not shown because too many files have changed in this diff Show More