def find_unusual_xors(functions):
# TODO find xors in tight loops
candidate_functions = []
for fva in functions:
cva = fva
while cva != idaapi.BADADDR and cva < idc.FindFuncEnd(fva):
if idc.GetMnem(cva) == "xor":
if idc.GetOpnd(cva, 0) != idc.GetOpnd(cva, 1):
g_logger.debug("suspicious XOR instruction at 0x%08X in function 0x%08X: %s", cva, fva,
idc.GetDisasm(cva))
ph = idc.PrevHead(cva)
nh = idc.NextHead(cva)
ip = idc.GetDisasm(ph)
ia = idc.GetDisasm(nh)
if ip and ia:
g_logger.debug("Instructions: %s; %s; %s", ip, idc.GetDisasm(cva), ia)
if ph or nh:
if is_security_cookie(cva, ph, nh):
g_logger.debug("XOR related to security cookie: %s", idc.GetDisasm(cva))
else:
g_logger.debug("unusual XOR: %s", idc.GetDisasm(cva))
candidate_functions.append(fva)
break
cva = idc.NextHead(cva)
return candidate_functions
python类PrevHead()的实例源码
def find_all_ioctls():
"""
From the currently selected address attempts to traverse all blocks inside the current function to find all immediate values which
are used for a comparison/sub immediately before a jz. Returns a list of address, second operand pairs.
"""
ioctls = []
# Find the currently selected function and get a list of all of it's basic blocks
addr = idc.ScreenEA()
f = idaapi.get_func(addr)
fc = idaapi.FlowChart(f, flags=idaapi.FC_PREDS)
for block in fc:
# grab the last two instructions in the block
last_inst = idc.PrevHead(block.endEA)
penultimate_inst = idc.PrevHead(last_inst)
# If the penultimate instruction is cmp or sub against an immediate value immediatly preceding a 'jz'
# then it's a decent guess that it's an IOCTL code (if this is a disptach function)
if idc.GetMnem(penultimate_inst) in ['cmp', 'sub'] and idc.GetOpType(penultimate_inst, 1) == 5:
if idc.GetMnem(last_inst) == 'jz':
ioctl_tracker.add_ioctl(penultimate_inst)
for inst in ioctl_tracker.ioctl_locs:
value = get_operand_value(inst)
ioctls.append((inst, value))
return ioctls
def highlight_non_zero_xor(self, ea):
highlight_eas = []
if self.get_mnem(ea) == "xor":
if idc.GetOpnd(ea, 0) != idc.GetOpnd(ea, 1):
ph = idc.PrevHead(ea)
nh = idc.NextHead(ea)
ip = idc.GetDisasm(ph)
ia = idc.GetDisasm(nh)
if ph or nh:
if not self.is_security_cookie(ea, ph, nh):
highlight_eas.append(ea)
MySetColor(ea, self.color)
return highlight_eas
def find_tight_loops(fva):
""" Code from Willi Ballenthin """
tight_loops = []
function = idaapi.get_func(fva)
for bb in idaapi.FlowChart(function):
# bb.endEA is the first addr not in the basic block
bb_end = idc.PrevHead(bb.endEA)
for x in idautils.XrefsFrom(bb_end):
if x.to == bb.startEA and bb.startEA < bb_end:
tight_loops.append((bb.startEA, bb_end))
if tight_loops:
g_logger.debug("Tight loops in 0x%x: %s", fva, ["0x%x - 0x%x" % (s, e) for (s, e) in tight_loops])
return tight_loops
def prevMnemonic(ea, mnem, minaddr=0):
res = idc.GetMnem(ea)
#print "%x -> %s"% (ea, res)
if res == "": return idc.BADADDR
if res == mnem: return ea
return prevMnemonic( idc.PrevHead(ea, minaddr), mnem, minaddr )
def getMinorDispatchTableAddress(ea):
"""find address of last lea in function"""
start = idc.GetFunctionAttr(ea, idc.FUNCATTR_START)
end = idc.PrevHead( idc.GetFunctionAttr(ea, idc.FUNCATTR_END), start)
res = prevMnemonic(end, 'lea', start)
assert res != idc.BADADDR
return idc.GetOperandValue(res, 1)
def find_function_arg(addr):
min_addr = addr - 10
while True:
addr = idc.PrevHead(addr)
if addr > min_addr:
if GetMnem(addr) == "mov" and "ecx" in GetOpnd(addr, 0) and GetOpType(addr, 1) != 1 and GetOpType(addr, 1) != 4 and GetOpType(addr, 1) != 3 :
#print "%s => %s => %s" % (hex(addr), GetOpnd(addr, 1), hex(GetOperandValue(addr, 1)) )
return GetOperandValue(addr, 1)
else:
break
def get_args(addr):
""" Retreives the passed arguments to the decryption function. We are only interested in the key
and offset to the encrypted string.
addr: (int) Address at which the decryption function was called.
Returns:
key: (int) The key used to decrypt the string.
enc_str: (list) Byte array of encrypted string.
ins_addr: (int) Address at which the encrypted byte array is referenced.
"""
found = False
foundstr = False
foundkey = False
while not found:
addr = idc.PrevHead(addr)
if idc.GetMnem(addr) == "mov" and "r8d" in idc.GetOpnd(addr,0):
#print "[+] Found key: 0x%08x at 0x%016x" % (idc.GetOperandValue(addr,1)& 0xffffffff, addr)
key = idc.GetOperandValue(addr,1) & 0xffffffff
foundkey = True
if idc.GetMnem(addr) == "lea" and "rdx" in idc.GetOpnd(addr,0):
#print "[+] Found str: 0x%016x at 0x%016x" % (idc.GetOperandValue(addr,1), addr)
enc_str_addr = idc.GetOperandValue(addr,1)
enc_str = get_encoded_string(enc_str_addr)
ins_addr = addr
foundstr = True
if foundkey and foundstr:
found = True
return key, enc_str, ins_addr