安装
安装模拟器: unicorn
https://github.com/unicorn-engine/unicorn
一般通过pip安装:
pip install unicorn
安装 flareEmu
从FireEye的Git下载 : https://github.com/fireeye/flare-emu
下载 flare_emu.py 就好, 是FireEye针对unicorn模拟器开发的一个帮助类
使用Emu
在使用时, 可不关心解密函数的算法, 然后直接模拟参数传递, 和结果的读取就好
decodeStr
from __future__ import print_functionimport idcimport idaapiimport idautilsimport flare_emudef decrypt(address, argv):print("%08X" % address, argv)myEH = flare_emu.EmuHelper()stack = []dwRet = idc.next_head(address)stack.append(dwRet) # RetAddrstack.append(argv[0])print(stack)# 用于设置栈, 栈的0号元素为返回地址 为 [EBP+4], 1号为第一个Arg [EBP+8]myEH.emulateRange(idc.get_name_ea_simple("sub_401667"), stack=stack)dwEAX = myEH.getRegVal("eax") # 从虚拟机中获得eax的值print ("EAX:%08X" % dwEAX)return myEH.getEmuString(dwEAX) # 从虚拟机中获得字符串, 地址是EAX的值def decrypt1(argv):myEH = flare_emu.EmuHelper()# 用于设置寄存器myEH.emulateRange(idc.get_name_ea_simple("q_decodeStr"), registers={'eax': argv[0]})dwEAX = myEH.getRegVal("eax")print ("EAX:%08X" % dwEAX)return myEH.getEmuString(dwEAX)g_bIsNotIter = False# 迭代地址def iterateCallback(eh, address, argv, userData):global g_bIsNotIterif g_bIsNotIter:returng_bIsNotIter = Trueprint("=" * 80)print("%08X" % address)print(argv)# print(userData)print("%08X" % argv[0])#returns = decrypt(address, argv)#s = decrypt(argv)print("%016X: %s" % (address, s))idc.set_cmt(address, s, 0)idc.set_cmt(argv[0], s, 0)if __name__ == '__main__':eh = flare_emu.EmuHelper()# 启动一个虚拟机 模拟器#eh.iterate(idc.get_name_ea_simple("q_decodeStr"), iterateCallback)eh.iterate(idc.get_name_ea_simple("sub_401667"), iterateCallback)
官方示例: rename_dynamic_imports.py
############################################# Copyright (C) 2018 FireEye, Inc.## Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or# http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-BSD-3-CLAUSE or# https://opensource.org/licenses/BSD-3-Clause>, at your option. This file may not be# copied, modified, or distributed except according to those terms.## Author: James T. Bennett## IDApython script that names global variables after their import names when dynamically resolved using GetProcAddress# Point it to a target function (or somewhere within the function) to begin emulation from## Dependencies:# https://github.com/fireeye/flare-emu############################################import flare_emuimport structimport idcimport idautilsimport loggingdef makeName(addr, name):names = list(map(lambda x: x[1], list(idautils.Names())))i = 0myname = namewhile myname in names:myname = name + "_%d" % ii += 1idc.set_name(addr, myname, idc.SN_CHECK)def instructionHook(uc, address, size, userData):try:eh = userData["EmuHelper"]if (idc.print_insn_mnem(address) == "mov" andidc.get_operand_type(address, 0) == 2 andidc.get_name(idc.get_operand_value(address, 0))[:6] == "dword_"):if "imp" in userData:makeName(idc.get_operand_value(address, 0), userData["imp"])del(userData["imp"])except Exception as err:print "Error in instructionHook: %s" % str(err)eh.stopEmulation(userData)def callHook(address, argv, funcName, userData):try:eh = userData["EmuHelper"]# save last import string passed to a call to GetProcAddressif funcName == "GetProcAddress":arg = eh.getEmuString(argv[1])if len(arg) > 2:userData["imp"] = arg# for code that checks for a return valueeh.uc.reg_write(eh.regs["ret"], 1)except Exception as err:print "Error in callHook: %s" % str(err)eh.stopEmulation(userData)if __name__ == '__main__':eh = flare_emu.EmuHelper()sVa = idc.ida_kernwin.ask_str("0", 0, "Enter the start address (hex)")sVa = int(sVa, 16)eVa = idc.ida_kernwin.ask_str("0", 0, "Enter the end address (hex), specify 0 to emulate to end of function")eVa = int(eVa, 16)if (sVa >= idc.get_inf_attr(idc.INF_MIN_EA) and sVa <= idc.get_inf_attr(idc.INF_MAX_EA) and(eVa == 0 or (eVa >= idc.get_inf_attr(idc.INF_MIN_EA) and eVa <= idc.get_inf_attr(idc.INF_MAX_EA)))):if eVa == 0:eVa = Nonemu = eh.emulateRange(sVa, eVa, instructionHook=instructionHook, callHook=callHook)else:print "Error: supplied addresses not within IDB address range"
