当前位置: 首页 > 科技观察

如何破解MassLogger使用的反分析策略

时间:2023-03-20 15:13:50 科技观察

FLARE团队最近刚刚完成了对MassLogger的分析,这是一个相当新的凭据窃取程序。虽然MassLogger缺乏新颖的功能,但它采用了一种在运行时取代Microsoft中间语言(MSIL)的复杂技术,阻碍了静态分析。截至发稿,只有一篇文章详细介绍了MassLogger的混淆技术。在本文中,了解FLARE团队如何深入研究MassLogger凭据窃取程序和.NET运行时。MassLogger的基础知识MassLogger是一个.NET凭据窃取程序,它从启动器(6b975fd7e3eb0d30b6dbe71b8004b06de6bba4d0870e165de4bde7ab82154871)开始攻击,它使用简单的反调试技术,可以在识别时轻松绕过安全监控。在解密、加载和执行名为Bin-123.exe(bc07c3090befb5e94624ca4a49ee88b3265a3d1d288f79588be7bb356a0f9fae)的最终MassLogger有效负载之前,此第一阶段加载程序最终对第二阶段程序集进行异或运算。最终的有效载荷可以很容易地提取并独立执行。因此,我们将专注于使用主要反分析技术的最后一个有效载荷。基本的静态分析不会揭示任何有价值的东西,虽然我们注意到了一些有趣的字符串,但它们不足以给我们提供有关此恶意软件功能的任何提示。在受控环境中执行有效载荷表明,样本会丢弃一个日志文件,该文件标识恶意软件系列、版本以及最重要的一些配置选项。图1中描述了一个示例日志文件,在示例运行时,我们还可以从内存中提取一些有趣的字符串。然而,基本的动态分析不足以提取所有基于主机的指标(HBI)、基于网络的指标(NBI)和完整的恶意软件功能。我们必须进行更深入的分析,以更好地了解样本及其功能。MassLogger日志样本反编译处理与许多其他.NET恶意软件一样,MassLogger混淆了它的所有方法名称,甚至方法控制流。我们可以使用de4dot自动混淆MassLogger有效负载。然而,在查看混淆后的payload后,我们很快发现了一个主要问题:大多数方法都包含很少的逻辑,如图2所示。dnSpy显示空方法查看dnSpy的中间语言(IL)视图中的原始MassLogger有效负载,可以确认大多数方法不包含任何逻辑,并且不返回任何内容。这显然不是真正的恶意软件,正如我们通过动态分析观察到的那样,该样本确实在执行恶意活动并将其记录到日志文件中。我们只剩下几个方法,最值得注意的是在主模块构造函数中首先调用的标记为0x0600049D的方法。显示方法细节的dnSpyIL视图方法0x0600049D的控制流已被混淆成一系列switch语句,并且在dnSpy作为调试器的帮助下,我们仍然可以在一定程度上遵循该方法的高级逻辑。然而,对该方法的全面分析将非常耗时。相反,在第一次分析此有效负载时,我选择快速扫描整个模块以寻找提示。幸运的是,我发现了一些在基本静态分析过程中被忽略的有趣字符串:clrjit.dll、VirtualAlloc、VirtualProtect和WriteProcessMemory,如图4所示。有趣的字符串散布在整个模块中快速互联网搜索“clrjit.dll”和“VirtualProtect”提供了对通常称为“即时挂钩”的技术的快速概述。本质上,JIT挂钩涉及在compileMethod()函数上安装一个挂钩,JIT编译器将在该函数上将MSIL编译为程序集(x86、x64等)。挂钩到位后,恶意软件可以轻松地将每个方法体替换为包含原始恶意软件逻辑的真实MSIL。为了完全理解这个过程,让我们首先探讨.NET可执行文件、.NET方法以及MSIL如何成为x86或x64程序集等问题。.NET可执行方法.NET可执行文件只是另一个可执行(PE)格式的二进制文件,现在网上有大量资源详细介绍PE文件格式、.NET元数据和.NET令牌表。不过,这些都不是本文的重点。在本书中,我们将重点关注.NET方法。.NET程序集中的每个.NET方法都由一个令牌标识,事实上,.NET程序集中的所有内容,无论是模块、类、方法原型还是字符串,都由一个令牌标识。让我们看一下由令牌0x0600049D标识的方法,如图5所示。最高有效字节(0x06)告诉我们此令牌是方法令牌(类型0x06),而不是模块令牌(类型0x00)、TypeDef令牌(类型0x02)或LocalVarSig令牌(类型0x11)。三个最低有效字节告诉我们方法的ID,在本例中为0x49D(十进制为1181)。此ID也称为方法ID(MID)或方法的行ID。rowid是一个伪列,用于唯一标识表中的行。是行数据在物理表中的内部地址,包括两个地址,一个是指向数据表中包含该行的块存储的数据文件的地址,一个是可以直接定位到的行在数据行本身中的数据块地址中。方法0x0600049D的方法详细信息要了解有关此方法的更多信息,请查看.NET元数据目录中.NET元数据流的“#~”流的表查找,如图6所示。我们遍历方法表这个入口的编号1181或0x49D找到方法元数据,其中包括方法体的相对虚拟地址(RVA),各种标志,指向方法名的指针,指向方法签名的指针,最后这个方法指向以下参数的参数说明。请注意,MID从1开始,而不是0。来自PE文件头的方法详细信息对于方法0x0600049D,方法体的RVA是0xB690。这个RVA属于.text段,它的RVA是0x2000。所以这个方法体从.text部分的0x9690(0xB690–0x2000)字节开始。根据标头,.text部分从文件的0x200字节开始。结果,我们可以在文件中偏移0x9890(0x9690+0x200)字节处找到方法体。我们可以在图7中看到方法主体。十六进制编辑器中的方法0x0600049D主体NET方法主体NET方法主体以方法主体标头开头,后跟MSIL字节。有两种类型的.NET方法:小方法和大方法。查看方法体标头的第一个字节,两个最低有效位告诉我们该方法是小的(最后两位为10)还是大的(最后两位为11)。NET小方法我们来看看方法0x06000495,按照前面介绍的相同步骤,我们查看方法表行号0x495(十进制是1173,对于SQLServer,Decimal可以用来保存一个带小数点和后缀的值定值,它不像float和real是用来存储近似值的。),发现方法体RVA为0x7A7C,翻译过来就是0x5C7C为文件的偏移量。在此偏移处,方法体的第一个字节是0x0A(二进制格式为101010)。Method0x06000495metadataandbody由于两个最低有效位是10,我们知道0x06000495是一个小方法。对于一个小方法,方法文字头只有一个字节长。两个最低有效位是10,表明这是一个小方法,六个最高有效位告诉我们要跟踪的MSIL的大小(即MSIL的长度)。在这个例子中,六个最高有效位是000010,这告诉我们方法主体是两个字节长。0x06000495的整个方法体是0A162A后面跟着一个NULL字节,已经被dnSpy反汇编了,如图9所示。dnSpyIL视图中的方法0x06000495NET大方法返回到方法0x0600049D(入口号1181)中偏移量为0x9890的文件(RVA0xB690),方法主体的第一个字节为0x1B(或二进制为00011011)。最低两位是11,说明0x0600049D是一个大方法。大型方法主体标头有12个字节长,但对其结构的介绍超出了本博文的范围。我们真正关心的字段是这个大头中偏移量为0x04字节的四字节字段。此字段指定此方法文字标头之后的MSIL的长度。对于方法0x0600049D,整个方法体头部为“1B300800A861000075000011”,后面的MSIL长度为“A8610000”或0x61A8(十进制为25000)字节。Method0x0600049Dbody在十六进制编辑器中进行JIT编译方法无论大小,都不会按原样执行。当.NET运行时需要执行一个方法时,它会查找方法主体,包括方法主体标头和MSIL字节,与前面描述的完全一样。如果这是第一次运行该方法,.NET运行时会调用即时编译器,它会提取MSIL字节并将它们编译成x86或x64程序集,具体取决于当前进程是32位还是64位少量。经过一些准备,JIT编译器最终会调用compileMethod()函数。整个.NET运行时项目是开源的,可在GitHub上获取。我们不难发现compileMethod()函数有如下原型(图11):compileMethod()函数原型下图展示了CORINFO_METHOD_INFO结构。CORINFO_METHOD_INFO结构体ILCode是指向待编译方法的MSIL的指针,ILCodeSize告诉我们MSIL的具体时间。compileMethod()的返回值是表示成功或失败的错误码。如果成功,nativeEntry指针将填充包含从MSIL编译的x86或x64指令的可执行内存区域的地址。MassLoggerJIT挂钩将我们带回MassLogger,一旦主模块初始化运行,它将首先解密其他方法的MSIL。然后它安装一个钩子来执行它自己的compileMethod()版本(方法0x06000499)。该方法用原始compileMethod()的info参数的ILCode和ILCodeSize字段替换了真正的恶意软件的MSIL字节。除了替换MSIL字节之外,MassLogger还在模块初始化时修补方法主体标头。从图13中可以看出,磁盘上的方法0x060003DD的方法体标头(文件偏移量0x3CE0)与内存中的标头(RVA0x5AE0)不同。唯一一致的两件事是两个最低有效位,它们指示方法是小还是大。要成功击败这种反分析技术,我们必须恢复真正的MSIL字节以及正确的方法主体标头。与加载到内存时相比,驻留在磁盘上的相同方法体具有不同的标头JIT方法体替换击败了JITM要自动恢复MSIL和方法体标头,另一位FLARE团队成员建议的一种可能方法是在compileMethod()上安装我们自己的钩子在加载并允许MassLogger模块构造函数运行之前运行。有许多关于使用托管挂钩(新的compileMethod()是用C#编写的托管方法)和本机挂钩(新的compileMethod()是用C或C++编写的本机挂钩)和开源项目挂钩compileMethod()的教程。但是,由于MassLogger挂钩compileMethod()的独特方式,我们无法使用上述许多项目实现的vtable挂钩技术。除了挂钩之外,JITM还包括一个.NET加载程序。此加载程序首先加载本机钩子DLL(jitmhook.dll)并安装钩子。然后加载程序加载MassLogger有效负载并执行其入口点。这会导致MassLogger的模块初始化代码执行并安装它自己的钩子,但是钩住jitmhook.dll代码而不是原来的compileMethod()。执行MassLogger入口点的另一种方法是调用RuntimeHelpers.PrepareMethod()API以强制JIT编译器在所有方法上运行。这种方法更好,因为它避免了运行恶意软件,并且有可能在样本的自然代码路径中恢复未调用的方法。但是,这需要额外的工作来强制所有方法正确编译。要加载和恢复MassLogger方法,请运行以下命令(图14):在运行jitm的命令超时结束后,您应该会看到在当前目录中创建的文件jitm.log和jitm.json。jitm.json包含方法标记、方法主体标头和从Bin-123.exe恢复的所有方法的MSIL。唯一剩下要做的就是重建.NET元数据,以便我们可以执行静态分析。示例jitm.json重建由于解密的方法主体标头和MSIL可能不适合原始的.NET程序集,因此最简单的方法是向MassLogger添加一个新的部分和相应的标头。JITM还包括以下Python2.7帮助程序脚本来自动执行此过程:Script\pydnet.py。通过将方法主体标头和每个方法的MSIL添加到新的PE部分(如XXX所示),我们可以轻松解析.NET元数据并修复每个方法的RVA以指向新部分中正确的方法主体。不幸的是,我没有找到任何Python库来轻松解析.NET元数据和MethodDef表。因此,JITM还包括一个部分实现的.NET元数据解析器:Script\pydnet.py。该脚本使用pefile和vivisect模块并将PE文件解析到方法表中以提取所有方法及其关联的RVA。Bin-123.exe在添加另一个名为FLARE的部分之前和之后最后,为了将所有内容联系在一起,JITM提供了Script\fix_assembly.py来执行以下任务:1.将每个方法的方法体标头和MSIL写入临时二进制文件名为“section.bin”的文件,记住相关的方法标记和section.bin中的偏移量。2.使用addsection.py将section.bin添加到Bin-123.exe中,并将数据保存到一个新文件中,例如Bin-123.fixed.exe。3.使用pydnet.py解析Bin-123.fixed.exe,更新MethodDef表中每个方法入口的RVA字段,将正确的RVA指向新的section。最终结果是部分重构的.NE程序集,虽然需要额外的工作才能使程序集正常运行,但静态分析足以了解恶意软件的高级功能。让我们看看重构的方法0x0600043E,它实现了恶意软件配置的解密逻辑。与原始MSIL相比,重建的MSIL表明恶意软件在CBC模式下使用AES-256和PKCS7填充。通过结合动态和静态分析,我们还可以轻松地将密钥识别为“Vewgbprxvhvjktmyxofjvpzgazqszaoo”,并将IV作为Base64编码缓冲区的一部分作为参数传递。修复程序集之前和之后的方法0x0600043有了这些知识,我们能够编写一个简单的工具来解密恶意软件配置并恢复所有HBI和NBI(图18)。解密配置总结用JIT编译器钩子替换MSIL是一种强大的反分析技术,几乎无法静态分析。虽然这项技术并不新鲜,但我还没有看到很多.NET恶意软件使用它。希望通过这篇文章,分析师将拥有分析MassLogger或任何使用类似技术的恶意软件的工具。本文翻译自:https://www.fireeye.com/blog/threat-research/2020/08/bypassing-masslogger-anti-analysis-man-in-the-middle-approach.html如有转载请注明原文地址。