flare-emu的剖析功用被进一步拓展 | 申博官网
登录
  • 欢迎进入申博官网!
  • 如果您觉得申博官网对你有帮助,那么赶紧使用Ctrl+D 收藏申博官网并分享出去吧
  • 这里是申博官方网!
  • 申博官网是菲律宾sunbet官网品牌平台!
  • 申博开户专业品牌平台!

flare-emu的剖析功用被进一步拓展

申博_安全防护 申博 81次浏览 已收录 0个评论

flare-emu的剖析功用被进一步拓展

IDAPython 库 flare-emu团队新开辟的一个库,这个库是依赖于 IDA Pro 和 Unicorn 模仿框架,并为让逆向工程师可以经由过程剧本对代码的功用举行模仿,Unicorn 支撑 x86, x86_64, ARM 以及 ARM64 架构。

flare-emu为用户的剧本模仿供应了一个易于运用而且天真的接口,旨在为差别的体系架构设置天真且硬朗的模仿器的一切基本事变,如许你便可以专注于处置惩罚代码剖析的题目。

5个差别的接口

它现在供应了5个差别的接口来处置惩罚你的代码模仿需求,而且它还有一系列相干的协助和东西函数。

1.emulateRange

这个API可以在用户指定的高低文中模仿一系列指令或函数,关于用户定义的钩子,它既可用于单个指令,也可以用于在挪用 call 指令的时刻,用户可以决议模仿器是单步跳过照样单步实行(进入函数挪用)。此接口为用户供应了一种为指定寄存器和栈参数指定值的轻便要领。假如指定了字节串,则将其写入模仿器的内存,并将指针写入寄存器或栈变量。模仿后,用户可以运用flare-emu的有用效用函数从模仿内存或寄存器中读取数据,或运用返回的Unicorn模仿对象举行直接探测。 

别的, flare-emu 还供应了一个关于 emulateRange 的一个小的封装,名为 emulateSelection,可以用来模仿当前在 IDA Pro 中凸起显现的部份指令。假如 flare-emu 没有供应你须要的一些功用,你可以直接运用返回的 Unicorn 模仿器对象。

2. iterate

这个API是用来强迫模仿函数中的特定分支,以抵达预期的运转途径。用户可以指定一个目标地点列表,或许指定一个函数的地点,从该函数中运用对该函数的交织援用列表作为目标,以及一个用于抵达目标时的回调。递次会实行到给定的目标地点上,只管当前的前提能够会跳转到其他的分支上。

与emulateRange API相似,也供应了用户定义的钩子选项,用于零丁的指令和什么时候碰到“挪用”指令。iterate API的一个例子是完成与我们的argtracker东西相似的功用。

3.emulateBytes

这个API供应了一种简朴模仿一个外部 shellcode 的要领,供应的字节不会增加到IDB,只是直接的模仿实行,这关于预备模仿环境异常有用。比方,flare-emu自身运用此API来操纵ARM64 CPU的模子特定寄存器(MSR),该模块不是由Unicorn公然的,以便启用向量浮点(VFP)指令和寄存器接见。与emulateRange一样,假如 flare-emu 没有供应你须要的一些功用,你可以直接运用返回的 Unicorn 模仿器对象。

4.iterateAllPaths

这个API异常相似于iterate,只供应目标函数,不供应目标地点,它将尝试查找一切途径并举行模仿。这在实行代码剖析时异常有用,因为代码剖析须要接见函数的每一个基本块。

5.emulateFrom

这个API在函数边境未明肯定义的状况下异常有用,因为殽杂处置惩罚过的二进制文件或shellcode一般就是如许定义的。只需你供应了一个肇端地点,它将举行模仿,直到没有任何东西可以模仿,或许你在个中一个钩子中住手举行模仿。这可以经由过程将strict参数设置为False来挪用,并启用动态代码举行探测,flare-emu将让IDA Pro在模仿过程当中实行指令。

要装置flare-emu,只需将flare_emu.py和flare_emu_hooks.py放入IDA Pro的python目次,然后将其作为IDApython剧本中的模块导入,flare-emu依赖于Unicorn及其Python绑定。

注重事项

flare-emu是运用新的IDA Pro 7x API编写的,它不与之前版本的IDA Pro版本不兼容。

详细用法

虽然flare-emu可用于处置惩罚许多差别的代码剖析题目,但其更罕见的用处之一是协助研究职员解密歹意软件二进制文件中的字符串。 在此,我们简朴提一下FLOSS,FLOSS是一个很好的东西,一般可以经由过程尝试辨认字符串解密函数并运用模仿来解密在每次交织援用时传入的字符串来自动实行此操纵。然则,FLOSS并不老是可以辨认这些函数并运用其通用要领准确模仿它们。偶然你须要做更多的事变。此时,就是flare-emu大显神通的机会了。只需你运用随手了,flare-emu便可以为你节约许多时候。下面,就让我们来看看歹意软件剖析职员在处置惩罚加密字符串时碰到的一些罕见场景。

简朴的字符串解密场景

假如你已肯定相识密x86_64二进制文件中的一切字符串的函数这个函数就会随处被挪用,并解密许多差别的字符串。在IDA Pro中,你可以此函数定名为decryptString。下面就是你的flare-emu剧本,用于解密一切这些字符串,并在每次函数挪用时运用解密的字符串作为解释,同时纪录每一个解密的字符串及其解密的地点。

from __future__ import print_function
import idc
import idaapi
import idautils
import flare_emu

def decrypt(argv):
    myEH = flare_emu.EmuHelper()
    myEH.emulateRange(idc.get_name_ea_simple("decryptString"), registers = {"arg1":argv[0], "arg2":argv[1], 
                           "arg3":argv[2], "arg4":argv[3]})
    return myEH.getEmuString(argv[0])
    
def iterateCallback(eh, address, argv, userData):
    s = decrypt(argv)
    print("%016X: %s" % (address, s))
    idc.set_cmt(address, s, 0)
    
if __name__ == '__main__':   
    eh = flare_emu.EmuHelper()
    eh.iterate(idc.get_name_ea_simple("decryptString"), iterateCallback)

在__main__中,我们首先从flare-emu建立一个EmuHelper类的实例,这是我们运用flare-emu做一切事变的类。接下来,我们运用iterate API,为它供应decryptString函数的地点和回调函数的称号,EmuHelper将为模仿的每一个交织援用挪用回调函数。

iterateCallback函数吸收名为eh的EmuHelper实例,以及交织援用的地点,通报给此特定挪用的参数以及此处名为userData的特别字典。在这个简朴的示例中虽然没有运用userData,但将其视为模仿器的耐久高低文,你可以在个中存储本身的自定义数据。但要警惕,因为flare-emu自身也运用这个字典来存储实行任务所需的症结信息。。个中一个数据片断就是EmuHelper实例自身,它存储在“EmuHelper”中。假如您感兴趣,可以搜刮源代码以相识更多关于本词典的信息。此回调函数只挪用decrypt函数,打印解密的字符串,并在对decryptString的挪用地点处为其建立解释。

decrypt建立了EmuHelper的第二个实例,用于模仿decryptString函数自身,它将为我们解密字符串。这个decryptString函数的原型以下:char * decryptString(char * text,int textLength,char * key,int keyLength)。它只是简朴地解密字符串。我们的decrypt函数将iterateCallback函数吸收的参数通报给我们对EmuHelper的emulateRange API的挪用。因为这是一个x86_64二进制文件,因而挪用商定运用寄存器来通报参数而不是栈。 flare-emu依据IDA Pro肯定的二进制文件的体系构造和文件花样自动肯定哪些寄存器代表哪些参数,如许你便可以编写一些与架构无关的代码。假如这是32位x86,则你可以运用stack参数来通报参数,以下所示:myEH.emulateRange(idc.get_name_ea_simple(“decryptString”), stack = [0, argv[0], argv[1], argv[2], argv[3]])。第一个栈值是x86中的返回地点,所以我们在这里只运用0作为占位符值。模仿完成后,我们挪用getEmuString API来检索存储在内存位置的以null末尾的字符串,该位置由通报给函数的第一个参数指定。

模仿函数

emulateRange(startAddr, endAddr=None, registers=None, stack=None, instructionHook=None, callHook=None, memAccessHook=None, hookData=None, skipCalls=True, hookApis=True, strict=True, count=0):模仿的指令局限从startAddress最先到endAddress完毕,不包括endAddress的指令。假如endAddress为None,则在模仿最先的统一函数中碰到“返回”范例指令时,模仿住手。

Registers:Registers是一个字典,个中键是寄存器称号,值是寄存器值。键值(key)是windows中注册表中的观点。键值位于注册表构造链末尾,和文件体系的文件相似,包括当前计算机及应用递次实行时运用的现实设置信息和数据。键值包括几种数据范例,以顺应差别环境的运用需求。一些特别的寄存器称号由flare-emu建立,可以在这里运用,比方arg1,arg2,ret和pc。

Stack:stack是一组以相反的递次在栈上推送的值,就像x86中函数的参数一样。在x86中,请记着将此数组中的第一个值用作函数挪用的返回地点,而不是函数的第一个参数。 flare-emu将依据寄存器和栈参数中指定的值初始化模仿线程的高低文和内存。假如为这些值中的任何一个指定了字符串,它将被写入内存中的某个位置,而指向该内存的指针将被写入指定的寄存器或栈位置。

instructionHook:instructionHook可所以定义为在模仿每一个指令之前挪用的函数,它的原型以下:instructionHook(unicornObject,address,instructionSize,userData)。

callHook:callHook可所以定义为在模仿每一个指令之前挪用的函数,它的原型以下:callHook(address,arguments,functionName,userData)。

理解网络安全领域的纵深防御策略

网络安全领域的发展速度太快,隔一段时间就会有一些流行语和技术术语冒出来。如果你有一段时间不关注该领域,则感觉已经跟不上时代了。“纵深防御”(Defence-in-Depth, DiD)就是这样一个技术术语。 那么为什么会出现这个术语呢?简单地说,DiD要求将安全性应用于多个层,其工作原理是为每个层提供不同类型的保护,以便为提供阻止攻击的最佳手段。这些层也可以防止不同的问题,全方位覆盖多

hookData:hookData是一个字典,个中包括用户定义的数据,可用于钩子函数。它是在悉数模仿过程当中耐久保留数据的一种要领。flare-emu也出于本身的目标运用这个字典,因而必需注重不要定义已定义的键。因为它在Unicorn中定名,此变量一般在用户定义的钩子函数中定名为userData。

skipCalls:skipCalls将致使模仿器跳过“挪用”范例指令并响应地调解栈,默以为True。

hookApis:hookApis致使flare-emu对它在仿真过程当中碰到的一些更罕见的运转时和OS库函数实行简朴的完成,这使你无需忧郁对memcpy,strcat,malloc等函数的挪用,而且默以为True。

memAccessHook:memAccessHook可以定义为一个函数,在接见内存举行读写时挪用它。它的原型以下:memAccessHook(unicornObject, accessType, memAccessAddress, memAccessSize, memValue, userData)。

Strict:当设置为True(默认值)时,搜检分支目标,以确保反汇编递次希冀获得指令。不然它会跳过分支指令。假如设置为False,flare-emu将在IDA Pro中模仿它们。

Count:count是要模仿的最大指令数,默认值为0,示意没有限定。

iterate(target, targetCallback, preEmuCallback=None, callHook=None, instructionHook=None, hookData=None, resetEmuMem=False, hookApis=True, memAccessHook=None):关于target指定的每一个目标,从头最先实行零丁的模仿包括函数直到目标地点。模仿将被强迫沿着必要的分支抵达每一个目标。 target可所以函数的地点,在这类状况下,目标列表将添补指定函数的一切交织援用。或许,target可所以一个明白的目标列表。

targetCallback:targetCallback是你建立的一个函数,它将由flare-emu为模仿时期找到的每一个目标挪用。它的原型以下:targetHook(emuHelper, address, arguments, userData)。

preEmuCallback:preEmuCallback是你建立的一个函数,将在每一个目标的模仿最先之前挪用。假如须要,你可以在此处完成一些设置代码。

resetEmuMem:resetEmuMem将致使flare-emu在每一个目标的模仿最先之前重置模仿内存,默以为False。

iterateAllPaths(target, targetCallback, preEmuCallback=None, callHook=None, instructionHook=None, hookData=None, resetEmuMem=False, hookApis=True, memAccessHook=None, maxPaths=MAXCODEPATHS, maxNodes=MAXNODESEARCH) :关于包括地点目标的函数,为每一个经由过程它发明的途径实行零丁的模仿,直到maxPaths。

maxPaths:maxPaths将搜刮和模仿的函数的最大途径数,,一些较庞杂的函数能够会致使图形搜刮函数消费很长时候或永久没法完成,在合理的时候内调解此参数以满足你的须要。

maxNodes:经由过程目标函数查找途径时要搜刮的基本块的最大数目,这是一个安全措施,可以防备不合理的搜刮时候和挂起。

emulateBytes(bytes, registers=None, stack=None, baseAddress=0x400000, instructionHook=None, hookData=None):假如能够,将包括在字节中的代码写入baseAddress的模仿存储器,并模仿从字节的开首到末尾的悉数指令。

emulateFrom(startAddr, registers=None, stack=None, instructionHook=None, callHook=None, memAccessHook=None, hookData=None, skipCalls=True, hookApis=True, strict=True, count=0):这个API在函数边境没有明肯定义的状况下异常有用,而隐约的二进制文件或shellcode一般是如许定义的。假如你供应一个肇端地点作为startAddr,它将模仿,直到没有任何东西可以模仿,或许你在个中一个钩子中住手模仿为止。这可以经由过程将strict参数设置为False来挪用,以启用动态代码发明。别的, flare-emu将在模仿过程当中碰到IDA Pro指令。

效用函数

以下是EmuHelper类供应的一些有用的有用效用函数的不完整列表。

hexString(value):返回的值为十六进制花样化字符串,用于日记纪录和打印语句;

getIDBString(address):返回位于IDB中地点的字符串,直到null终止符。不过,字符不一定是可打印的,用于在没有模仿高低文的状况下检索字符串。

skipInstruction(userData, useIDA=False):从模仿钩子挪用这个函数来跳过当前的指令,将递次计数器移动到下一条指令。增加了useIDA选项来处置惩罚IDA Pro将多个指令折叠成一个伪指令的状况,并你愿望跳过一切这些指令。此函数不能从单个指令钩子屡次挪用以跳过多个指令。要跳过多个指令,发起在模仿ARM代码时不要直接写入递次计数器,因为这能够会致使拇指形式( thumb mode.)出现题目。所以,请尝试运用EmuHelper的changeProgramCounter API(以下所述)。

changeProgramCounter(userData, newAddress):从模仿钩子挪用它来变动递次计数器寄存器的值,此API担任ARM体系构造的拇指形式跟踪。

getRegVal(registerName):检索指定寄存器的值,对子寄存器寻址敏感。比方,“ax”将返回x86中EAX/RAX寄存器的下级16位。

stopEmulation(userData):从模仿钩子中挪用它来住手模仿,运用它而不是挪用emu_stop Unicorn API,如许EmuHelper对象便可以处置惩罚与iterate功用相干的簿记。

getEmuString(address):返回位于模仿内存中某个地点的字符串,直到null终止符,字符不一定可以打印。

getEmuWideString(address):返回位于模仿内存中的一个地点的“宽字符”字符串,直到一个空终止符。“宽字符”在这里指的是每隔一个字节包括一个空字节的任何字节序列,就像UTF-16 LE编码的ASCII字符串一样,字符不一定可以打印。

getEmuBytes(address, length):返回位于模仿内存中地点的字节字符串;

getEmuPtr(address):返回位于给定地点的指针值;

writeEmuPtr(address):将指针值写入模仿内存中的给定地点;

loadBytes(bytes, address=None):在模仿器中分派内存并将字节写入个中;

isValidEmuPtr(address):假如供应的地点指向有用的模仿内存,则返回True;

getEmuMemRegion(address):返回一个元组,个中有包括所供应地点的内存地区的肇端和完毕地点,假如地点无效,则返回None。

getArgv():从“挪用”范例指令的模仿钩子中挪用它,以吸收函数的参数数组。

addApiHook(apiName, hook):为此EmuHelper实例增加一个新的API钩子,每当在模仿时期碰到对apiName的挪用指令时,EmuHelper将挪用钩子指定的函数。假如hook是一个字符串,那末它应该是EmuHelper已挂起的API的称号,在这类状况下,它将挪用它现有的钩子函数。假如钩子是一个函数,它将挪用该函数。

addApiHook(apiName, hook):分派充足的模仿器内存以包括大小字节,它尝试实行要求的地点,然则假如它与现有内存地区堆叠,它将在未运用的内存地区中分派并返回新地点。假如地点没有页面对齐,它将返回一个地点,该地点将在新地区内坚持雷同的页面对齐偏移量。比方,当0x1000已被分派时,要求地点0x1234能够会让它分派到0x2000并返回0x2234。

本文翻译自:https://github.com/fireeye/flare-emu


申博|网络安全巴士站声明:该文看法仅代表作者自己,与本平台无关。版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明flare-emu的剖析功用被进一步拓展
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址