Last active
November 7, 2019 15:59
-
-
Save w4kfu/4252f4c19be573eaaecceb76e1dc0c1c to your computer and use it in GitHub Desktop.
IDA user initialisation script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import idc | |
import idautils | |
import idaapi | |
import struct | |
# > copy idapythonrc.py %APPDATA%\Hex-Rays\IDA Pro\idapythonrc.py | |
def myreload(): | |
""" | |
Reload the users personal init file | |
""" | |
idaapi.IDAPython_ExecScript(userrc, globals()) | |
def is_branch(addr): | |
branch = ['retn', 'ret', 'retf'] | |
#branch += ['call'] | |
branch += ['jmp'] | |
branch += ['jo', 'jno', 'jb', 'jnae', 'jc', 'jnb', 'jae', 'jnc', 'jz', \ | |
'je', 'jnz', 'jne', 'jbe', 'jna', 'jnbe', 'ja', 'js', 'jns', \ | |
'jp', 'jpe', 'jnp', 'jpo', 'jl', 'jnge', 'jnl', 'jge', 'jle', \ | |
'jng', 'jnle', 'jg'] | |
if GetMnem(addr) in branch: | |
return True | |
return False | |
def get_rva(ea=None): | |
""" | |
Get Relative Virtual Address from current effective address or desired | |
one | |
""" | |
if ea == None: | |
ea = here() | |
rva = ea - idaapi.get_imagebase() | |
print hex(rva).replace("L", "") | |
def get_offset(ea=None): | |
""" | |
Get Offset from current effective address or desired | |
one | |
""" | |
if ea == None: | |
ea = here() | |
offset = idaapi.get_fileregion_offset(ea) | |
print hex(offset).replace("L", "") | |
def get_va_from_offset(offset): | |
""" | |
Get Virtual Address from offset | |
""" | |
va = idaapi.get_fileregion_ea(offset) | |
print hex(va).replace("L", "") | |
def get_call_ref(ea=None): | |
""" | |
Get call instructions in the given function from current effective | |
address or desired one | |
""" | |
if ea == None: | |
ea = here() | |
func_ea = GetFunctionAttr(ea, FUNCATTR_START) | |
for item_ea in idautils.FuncItems(func_ea): | |
if idc.GetMnem(item_ea) != 'call': | |
continue | |
print "0x%X %s" % (item_ea, GetDisasm(item_ea)) | |
def get_string_ref(ea=None): | |
""" | |
Get the string references in the given function from current effective | |
address or desired one | |
""" | |
import idautils | |
if ea == None: | |
ea = idc.here() | |
func_ea = idc.get_func_attr(ea, idc.FUNCATTR_START) | |
for item_ea in idautils.FuncItems(func_ea): | |
for ref in idautils.DataRefsFrom(item_ea): | |
type = idc.get_str_type(ref) | |
if type not in range(0, 7) and type != 0x2000001: | |
continue | |
yield (item_ea, ref, type) | |
def print_string_ref(ea=None): | |
import ida_bytes | |
for item_ea, ref, type in get_string_ref(ea): | |
print("{0:#X} {1:80s} ; \"{2}\"".format(item_ea, idc.GetDisasm(item_ea), str(ida_bytes.get_strlit_contents(ref, -1, type)))) | |
def _convert_to_bytes(ea=None): | |
if ea == None: | |
ea = here() | |
if idaapi.get_inf_structure().is_64bit() == True: | |
s = struct.pack("<Q", ea).encode("hex") | |
else: | |
s = struct.pack("<I", ea).encode("hex") | |
s = ' '.join(' '.join(s[i:i + 2] for i in range(0, len(s), 2)).split()) | |
return s | |
def convert_to_bytes(ea=None): | |
""" | |
Convert effective address to little-endian bytes | |
eg : convert_to_bytes(0x41424344) => 44 43 42 41 | |
""" | |
if ea == None: | |
ea = here() | |
print _convert_to_bytes(ea) | |
def find_all(searchstr): | |
""" | |
yiel on sequence of bytes | |
""" | |
ea = idc.FindBinary(0, SEARCH_DOWN, searchstr) | |
while ea != idc.BADADDR: | |
yield ea | |
ea = idc.FindBinary(ea + 1, SEARCH_DOWN, searchstr) | |
def search_va(ea=None): | |
""" | |
Get all references to a desired effective address or the current one | |
""" | |
if ea == None: | |
ea = here() | |
for f in find_all(_convert_to_bytes(ea)): | |
print "0x%X %s" % (f, GetDisasm(f)) | |
def is_ida69(): | |
""" | |
Check if IDA version is greater or equal to 6.9 | |
""" | |
major, minor = map(int, idaapi.get_kernel_version().split(".")) | |
return (major == 6 and minor >= 9) or (major == 7) | |
def clear_output_window(): | |
""" | |
Clear output window | |
IDA 6.9 drop PySide in favor of PyQt5 | |
""" | |
if is_ida69(): | |
from PyQt5 import QtGui, QtCore, QtWidgets | |
form = idaapi.find_tform("Output window") | |
w = idaapi.PluginForm.FormToPyQtWidget(form) | |
w.setFocus() | |
else: | |
from PySide import QtGui, QtCore | |
form = idaapi.find_tform("Output window") | |
w = idaapi.PluginForm.FormToPySideWidget(form) | |
w.setFocus() | |
idaapi.process_ui_action("msglist:Clear") | |
def get_bb(ea=None): | |
""" | |
Return the basic block if a desired effective address or the current one | |
""" | |
if ea == None: | |
ea = here() | |
f = idaapi.get_func(ea) | |
if not f: | |
return None | |
fc = idaapi.FlowChart(f) | |
for block in fc: | |
if block.startEA <= ea and block.endEA > ea: | |
return block | |
return None | |
# o_void = ida_ua.o_void # No Operand ---------- * 0x00 | |
# o_reg = ida_ua.o_reg # General Register (al,ax,es,ds...) reg * 0x01 | |
# o_mem = ida_ua.o_mem # Direct Memory Reference (DATA) addr * 0x02 | |
# o_phrase = ida_ua.o_phrase # Memory Ref [Base Reg + Index Reg] phrase * 0x03 | |
# o_displ = ida_ua.o_displ # Memory Reg [Base Reg + Index Reg + Displacement] phrase+addr * 0x04 | |
# o_imm = ida_ua.o_imm # Immediate Value value * 0x05 | |
# o_far = ida_ua.o_far # Immediate Far Address (CODE) addr * 0x06 | |
# o_near = ida_ua.o_near # Immediate Near Address (CODE) addr * 0x07 | |
# | |
# o_displ | |
# | |
def get_operand_o_displ(ea, n): | |
""" | |
Extract base, index, scale address of o_displ operand | |
""" | |
insn = ida_ua.insn_t() | |
inslen = ida_ua.decode_insn(insn, ea) | |
if inslen == 0: | |
return -1, -1, -1, -1 | |
if insn.ops[n].type != o_displ: | |
return -1, -1, -1, -1 | |
disp = insn.ops[n].phrase | |
hasSIB = insn.ops[n].specflag1 | |
sib = insn.ops[n].specflag2 | |
if hasSIB: | |
base = sib & 7 | |
index = (sib >> 3) & 7 | |
scale = (sib >> 6) & 3 | |
size = 4 if insn.ops[n].dtyp == idaapi.dt_dword else 8 | |
return base, index, scale, insn.ops[n].addr | |
return -1, -1, -1, -1 | |
def get_register_num(reg_name): | |
""" | |
Get the value of the register from its name | |
""" | |
ri = idaapi.reg_info_t() | |
success = idaapi.parse_reg_name(reg_name, ri) | |
if not success: | |
raise ValueError("No register named {!r}".format(reg_name)) | |
return ri.reg | |
def find_stack_xrefs(ea, n): | |
""" | |
Return xrefs (list of ea) of stack variable | |
eg : lea rcx, [rsp+120h+var_E0] | |
all xrefs to var_E0 except the current ea | |
""" | |
func = idaapi.get_func(ea) | |
insn = ida_ua.insn_t() | |
inslen = ida_ua.decode_insn(insn, ea) | |
op = insn.ops[n] | |
addr = op.addr | |
if addr > 2**63: | |
addr = -(2**64 - addr) | |
sv = idaapi.sval_pointer() | |
sv.assign(addr) | |
member, val = idaapi.get_stkvar(insn, op, sv.value()) | |
xrefs = idaapi.xreflist_t() | |
idaapi.build_stkvar_xrefs(xrefs, func, member) | |
res = [] | |
for xref in xrefs: | |
if xref.ea != ea: | |
res.append(xref.ea) | |
return res | |
def align(nb, alignement): | |
if nb % alignement == 0: | |
return nb | |
return ((nb / alignement) + 1) * alignement | |
def align_str(s, alignement=0x08): | |
cur_len = len(s) | |
ali_len = align(cur_len, alignement) | |
s += "\x00" * (ali_len - cur_len) | |
return s | |
def hexdump(src, length=16): | |
FILTER = ''.join([(len(repr(chr(x))) == 3) and chr(x) or '.' for x in range(256)]) | |
lines = [] | |
for c in xrange(0, len(src), length): | |
chars = src[c:c+length] | |
hex = ' '.join(["%02x" % ord(x) for x in chars]) | |
printable = ''.join(["%s" % ((ord(x) <= 127 and FILTER[ord(x)]) or '.') for x in chars]) | |
lines.append("%04x %-*s %s\n" % (c, length*3, hex, printable)) | |
return ''.join(lines).rstrip('\n') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment