Snippets
Created by
Alexander Hanel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | '''
Author: Alexander Hanel
Date: 20171007
Purpose: calculates a structure members and size based off of offsets into an address
'''
import idautils
import idaapi
DISTANCE = 0x8
def get_reg_type(register):
if register in ['al', 'ah', 'ax', 'eax', 'rax']:
return 'accumulator'
if register in ['bl', 'bh', 'bx', 'ebx', 'rbx']:
return 'base'
if register in ['cl', 'ch', 'cx', 'ecx', 'rcx']:
return 'counter'
if register in ['dl', 'dh', 'dx', 'edx', 'rdx']:
return 'extend'
if register in ['si', 'esi', 'rsi']:
return 'source'
if register in ['di', 'edi', 'rdi']:
return 'dest'
if register in ['sp', 'esp', 'rbp']:
return 'stack'
if register in ['bp', 'ebp', 'rbp']:
return 'base'
if register in ['ip', 'eip', 'rip']:
return 'instru'
return None
def get_arch_bit():
info = idaapi.get_inf_structure()
if info.is_64bit():
bits = 64
elif info.is_32bit():
bits = 32
else:
bits = 16
return bits
def get_to_xrefs(ea):
xref_set = set([])
for xref in idautils.XrefsTo(ea, 1):
xref_set.add(xref.frm)
return xref_set
def read_offset(addr, op):
idaapi.decode_insn(addr)
if op == 1:
offset = idaapi.cmd.Op1.addr
else:
offset = idaapi.cmd.Op2.addr
return offset
def get_reg(addr, op):
"""
get register from displacement
example: mov [edx+12Ch], eax
"""
idaapi.decode_insn(addr)
bit = get_arch_bit()
if bit == 16:
if op == 1:
return idaapi.get_reg_name(idaapi.cmd.Op1.reg, 2)
else:
return idaapi.get_reg_name(idaapi.cmd.Op2.reg, 2)
if bit == 32:
if op == 1:
return idaapi.get_reg_name(idaapi.cmd.Op1.reg, 4)
else:
return idaapi.get_reg_name(idaapi.cmd.Op2.reg, 4)
if bit == 64:
if op == 1:
return idaapi.get_reg_name(idaapi.cmd.Op1.reg, 8)
else:
return idaapi.get_reg_name(idaapi.cmd.Op2.reg, 8)
return None
def add_struct(size_offset):
sid = idc.AddStrucEx(-1, 'name_me', 0)
for count, offset in enumerate(size_offset):
struct_name = "field_%x" % (count)
if count == len(size_offset) - 1:
# unknown size
idc.AddStrucMember(sid, struct_name, offset, FF_BYTE, -1, 1)
else:
size = size_offset[count +1] - offset
idc.AddStrucMember(sid, struct_name, offset, FF_BYTE, -1, size)
def forward_trace(addr, og_reg):
global DISTANCE
og_reg_type = get_reg_type(og_reg)
# forward trace n (DISTANCE) from xref to struct offset
for x in xrange(0, DISTANCE):
idaapi.decode_insn(addr)
# TODO: add mov and calcualte lea check
# check for write to struct value
reg_type_op1 = get_reg_type(get_reg(addr, 1))
if idaapi.cmd.Op1.type == idaapi.o_displ:
if og_reg_type == reg_type_op1:
temp_offset = read_offset(addr, 1)
return (True, temp_offset, addr)
# check for read to struct value
reg_type_op2 = get_reg_type(get_reg(addr, 2))
if idaapi.cmd.Op2.type == idaapi.o_displ:
if og_reg_type == reg_type_op2:
temp_offset = read_offset(addr, 2)
return (True, temp_offset, addr)
# check for 0 offset
if idaapi.cmd.Op1.type == idaapi.o_phrase:
if og_reg_type == reg_type_op1:
return (True, 0,addr)
if idaapi.cmd.Op2.type == idaapi.o_phrase:
if og_reg_type == reg_type_op2:
return (True, 0,addr)
addr = idc.NextHead(addr)
return(False, None, None)
def run(struct_addr):
struct_offsets = set([])
out = {}
xrefs_2_struct = get_to_xrefs(struct_addr)
for addr in xrefs_2_struct:
if idc.GetOperandValue(addr,1) != struct_addr:
continue
if idc.GetOpType(addr,0) != o_reg:
continue
reg = idc.GetOpnd(addr,0)
next_addr = idc.NextHead(addr)
status, offset, address = forward_trace(next_addr, reg)
if status:
struct_offsets.add(offset)
temp = list(sorted(struct_offsets))
add_struct(temp)
# cursor at address of struct
run(here())
|
Comments (0)
You can clone a snippet to your computer for local editing. Learn more.