def get_fixup_va_and_size(va): fva = idaapi.get_next_fixup_ea(va) ftype = get_fixup_target_type(fva) fsize = ida_fixup.calc_fixup_size(ftype) return fva, fsize
def get_basic_block_rule(bb): ''' create and format a YARA rule for a single basic block. mask relocation bytes into unknown bytes (like '??'). do not include final instructions if they are jumps. ''' # fetch the instruction start addresses insns = [] va = bb.va while va < bb.va + bb.size: insns.append(va) va = idc.next_head(va) # drop the last instruction if its a jump if is_jump(insns[-1]): insns = insns[:-1] bytes = [] # `masked_bytes` is the list of formatted bytes, # not yet join'd for performance. masked_bytes = [] for va in insns: size = idc.get_item_size(va) if idaapi.contains_fixups(va, size): # fetch the fixup locations within this one instruction. fixups = [] fixupva = idaapi.get_next_fixup_ea(va) fixups.append(fixupva) # TODO: assume the fixup size is four bytes, probably bad. fixupva += 4 while fixupva < va + size: fixupva = idaapi.get_next_fixup_ea(fixupva) fixups.append(fixupva) # TODO: assume the fixup size is four bytes, probably bad. fixupva += 4 # assume each fixup is four bytes (TODO!), # and compute the addresses of each component byte. fixup_byte_addrs = set([]) for fixup in fixups: for i in range(fixup, fixup + 4): fixup_byte_addrs.add(i) # fetch and format each byte of the instruction, # possibly masking it into an unknown byte if its a fixup. for i, byte in enumerate(idc.get_bytes(va, size)): byte_addr = i + va if byte_addr in fixup_byte_addrs: bytes.append(byte) masked_bytes.append('??') else: bytes.append(byte) masked_bytes.append('%02X' % (byte)) elif 'call' in idc.print_insn_mnem(va): for i, byte in enumerate(idc.get_bytes(va, size)): bytes.append(byte) masked_bytes.append('??') else: for byte in idc.get_bytes(va, size): bytes.append(byte) masked_bytes.append('%02X' % (byte)) return Rule('$0x%x' % (bb.va), bytes, masked_bytes)