但是使用的时候发现它不支持python3,同时代码中 bytes 和 str 对象傻傻的分不清楚,所以不得不进行了一下修改,修改后的版本在这里(可能有些地方并没有修改完善,以后使用过程中发现问题再做修改吧)。下面就对官方的介绍文档进行了一个翻译。
这是 FireEye 高级逆向工程团队公开的脚本系列的另一篇博文。今天我们分享一个新的 IDApython 库 - flare-emu,它依赖于 IDA pro和 Unicorn 仿真模拟框架,为 x86、x86_64、ARM和ARM64体系结构提供可脚本化的仿真功能,供逆向工程师使用。 除了这个库之外,我们还共享了一个使用它分析 Objective-C 代码的 IDAPython 脚本。请继续阅读以了解使用模拟器的一些创新的方法,这些方法可以帮你解决代码分析中遇到的问题,以及如何使用我们新的 IDAPython 库来节省您在此过程中的大量时间。
如果你还没有使用模拟执行来解决代码分析中的问题,那你就已经跟不上潮流了。我将重点介绍它的一些优点和一些用例,以使您了解它的强大功能。仿真模拟是非常灵活的,并且当今可用的许多仿真框架(包括 Unicorn )都是跨平台的。通过模拟执行,您可以选择要模拟执行的代码,并控制代码执行时的上下文信息。因为被模拟执行的代码无法访问运行它的操作系统的系统服务,所以几乎没有造成任何损坏的风险。所有这些优点使仿真成为临时实验,解决问题或自动化的绝佳选择。
FLARE (FireEye 高级逆向工程团队)团队正在介绍一个IDApython的库 flare-emu ,该库将IDA Pro的二进制分析功能与Unicorn的仿真框架相结合,为用户提供了易用且灵活的脚本编写仿真模拟接口。flare-emu旨在处理所有内务处理,为其支持的体系结构设置灵活而强大的仿真器,以便您专注于解决代码分析问题。 当前,它提供了三种不同的接口来满足您的仿真需求,以及一系列相关的帮助程序和实用功能。
图1: emulateRange用于跟踪GetProcAddress的返回值
图2:由 iterate API确定的仿真路径,以便到达目标地址
图3:flare-emu使用emulateBytes为ARM64启用VFP
如前所述,flare-emu 旨在让您轻松使用仿真来解决代码分析中的需求。模拟执行的一大痛点时对库函数调用的处理。flare-emu允许您选择需要跳过的call指令的同时,也支持你定义自己的hook函数来实现hook的函数被调用之后的特定功能。它自带有预定义的挂钩函数共80多个。这些函数包括许多常见的c运行时函数,这些函数将对你遇到的字符串和内存进行操作,以及与之对应的某些windows API。
图4显示了一些代码块,这些代码块调用一个函数,该函数需要一个时间戳值并将其转换为字符串。 图5显示了一个简单的脚本,该脚本使用flare-emu的迭代API在每个被调用的位置打印传递给该函数的参数。 该脚本还模拟了一个简单的XOR解码功能,并输出结果解码后的字符串。 图6显示了脚本的结果输出。
图4: 调用时间戳转换函数
图5: Simple example of flare-emu usage
图6: Output of script shown in Figure 5
这是一个示例脚本,该脚本使用flare-emu跟踪GetProcAddress的返回值并重命名它们相应存储的变量。 查看我们的自述文件以获取更多示例,并获得关于flare-emu的帮助。
############################################
# 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_emu
import struct
import idc
import idautils
import logging
def makeName(addr, name):
names = list(map(lambda x: x[1], list(idautils.Names())))
i = 0
myname = name
while myname in names:
myname = name + "_%d" % i
i += 1
idc.set_name(addr, myname, idc.SN_CHECK)
def instructionHook(uc, address, size, userData):
try:
eh = userData["EmuHelper"]
if (idc.print_insn_mnem(address) == "mov" and
idc.get_operand_type(address, 0) == 2 and
idc.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 GetProcAddress
if funcName == "GetProcAddress":
arg = eh.getEmuString(argv[1])
if len(arg) > 2:
userData["imp"] = arg
# for code that checks for a return value
eh.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 = None
mu = eh.emulateRange(sVa, eVa, instructionHook=instructionHook, callHook=callHook)
else:
print "Error: supplied addresses not within IDB address range"
(对object-c不太懂,不知道有没有说错的地方)
去年,我写了一篇博客文章向您介绍逆向macOS平台的Cocoa应用程序,文章地址在这里,该帖子包括一个简短的入门文章,介绍如何在后台调用Objective-C方法,以及这如何对IDA Pro和其他反汇编工具中的交叉引用产生的不利影响。帖子中还介绍了一个名为objc2_xrefs_helper的IDAPython脚本,以帮助解决这些交叉引用问题。 如果您尚未阅读该博文,建议您在继续阅读本博文之前先阅读该博文,因为它提供了使用objc2_analyzer特别有用的上下文。objc2_xrefs_helper的主要缺点是,如果选择器名称含糊不清,则意味着两个或多个类实现了具有相同名称的方法,脚本无法确定引用的选择器在二进制文件中任何给定位置所属的类,所以修复交叉引用时不得不忽略这种情况。现在,有了仿真支持,情况就不再如此。 objc2_analyzer使用flare-emu中的iterate API以及执行Objective-C反汇编分析的指令和调用挂钩,以确定为二进制形式的 objc_msgSend 变量的每次调用传递的id和selector。脚本功能的示例如图7和图8所示。
图7:运行objc2_analyzer之前的Objective-C IDB代码段
Figure 8: Objective-C IDB snippet after running objc2_analyzer
请注意已对引用选择器的指令进行了修补,以改为引用实现功能本身,以便于转换。 添加到每个call中的注释使分析更加容易。 还创建了来自实现功能的交叉引用,以指向指向引用它们的objc_msgSend调用,如图9所示。
图9:为函数实现添加到IDB的交叉引用
应当注意,从7.0开始的每个IDA Pro版本都对Objective-C代码分析和处理进行了改进。 但是,在撰写本文时,IDA Pro的最新版本为7.2,使用该工具仍可消除一些缺点,并添加了非常有用的注释。 objc2_analyzer以及我们的其他IDA Pro插件和脚本可在我们的GitHub页面上获得。
flare-emu是一种灵活的工具,您可以在您的军械库中收藏它,它可以应用于各种代码分析问题。 在本博文中使用它提出并解决了几个示例问题,但这只是其应用可能性的一瞥。如果您没有尝试模拟解决代码分析问题的方法,我们希望您现在可以选择它。 而且,我们希望您能从使用这些新工具中受益匪浅!