Skip to content

Instantly share code, notes, and snippets.

@w4kfu
Last active November 7, 2019 15:59
Show Gist options
  • Save w4kfu/4252f4c19be573eaaecceb76e1dc0c1c to your computer and use it in GitHub Desktop.
Save w4kfu/4252f4c19be573eaaecceb76e1dc0c1c to your computer and use it in GitHub Desktop.
IDA user initialisation script
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