滥用PE文件中的共享节实现代码注入 - 嘶吼 RoarTalk – 回归最本质的信息安全,互联网安全新媒体,4hou.com

滥用PE文件中的共享节实现代码注入

fanyeee 技术 2022-04-14 11:55:00
收藏

导语:在本文中,我们将探讨如何滥用某些特殊的PE节(PE Sections),在无需直接访问进程的情况下将任意shellcode植入远程进程的内存中。

在本文中,我们将探讨如何滥用某些特殊的PE节(PE Sections),在无需直接访问进程的情况下将任意shellcode植入远程进程的内存中。

跨进程横向移动是恶意软件中非常常见的一种技术,以便在系统间进行传播。近年来,微软已经通过“Microsoft-Windows-Threat-Intelligence”ETW提供程序增加了安全遥测功能,以对抗这种威胁。

当这种新增的遥测功能与现有的方法(如ObRegisterCallbacks)结合在一起后,攻击者在进行横向移动过程中,相关的恶意操作很难逃过内核可见遥测的法眼。在本文中,我们将探讨如何滥用某些特殊的PE节,在无需直接访问进程的情况下将任意shellcode植入远程进程的内存中。

背景知识

现有的横向移动方法,通常都涉及危险的API调用,如OpenProcess,以获得进程句柄,并伴有与内存相关的操作,如VirtualAlloc、VirtualProtect或WriteProcessMemory。近年来,针对这些操作的检测有所增加。

例如,在旧版本的Windows上,内核驱动程序可见的唯一跨进程API调用,就是ObRegisterCallbacks,它常用于创建进程和线程句柄。

微软威胁情报ETW提供程序引入的可见性已经扩展到涵盖以下操作:

1、读/写虚拟内存调用(EtwTiLogReadWriteVm);

2、可执行内存的分配(EtwTiLogAllocExecVm);

3、将内存保护属性改为可执行文件(EtwTiLogProtectExecVm);

4、映射可执行节(EtwTiLogMapExecView)。

进入另一个进程上下文的其他方法通常与其他检测向量一起出现。例如,横向移动的另一种方法可能涉及基于磁盘的攻击,如代理Dll注入。这类攻击的问题在于,它们通常需要将恶意代码写入磁盘,这对于基于内核的防御解决方案是可见的。

由于已知的跨进程移动方法需要用到这些可见的操作,因此,要想打败防御者可用的遥测技术,就必须超越现有的方法。

发现过程 

最近,我研究了在不影响PE格式二进制文件可用性的条件下,可以将这种二进制文件破坏到哪种程度。例如,您是否可以将已知的恶意工具(如Mimikatz)破坏到这样一种程度:既不会影响其可操作性,同时,还能让反病毒软件中内置的映像解析器无法正常对其进行解析?

与Linux中的ELF可执行文件类似,Windows PE映像也是由“节”组成的。例如,代码通常存储在名为.text的节中,可变数据可以在.data节中找到,而只读数据通常存放到.rdata节中。但是,操作系统是如何知道哪些节包含代码,或是可写的呢?每个节都具有相应的“characteristics(特征)”,用于记录这段内存的相关信息。

对于PE节来说,单单记录在册的特征就超过35个。其中,最常见的特征包括IMAGE_SCN_MEM_EXECUTE、IMAGE_SCN_MEM_READ和IMAGE_SCN_MEM_WRITE,它们分别用于定义一个节是否为可执行、可读和/或可写的。然而,这些只是PE节的各种特征中的一小部分而已。

当试图破坏PE节头时,一个特定的标志引起了我的注意:

1.png

 “IMAGE_SCN_MEM_SHARED”特征

根据Microsoft的文档,IMAGE_SCN_MEM_SHARED标志表示“该节可以在内存中共享”。但是,这到底是什么意思呢?在网络中没有找到太多关于该标志的说明文档,但事实证明,如果启用该标志,该节的内存将在加载了该映像的所有进程之间共享。例如,如果进程A和B加载一个PE映像,其中包含一个“共享”(并且可写)的节,那么进程A中该节的内存中的任何变化都将反映在进程B中。

与我们将在本文中讨论的理论密切相关的一篇文献是“DLL shared sections: a ghost of the past”。在这篇文章中,Coldwind探讨了由具有IMAGE_SCN_MEM_SHARED特征的PE节的二进制文件所带来的潜在风险。

Coldwind解释说,这些PE映像带来的风险“是一个古老而众所周知的安全问题”,并引用了微软在2004年发表的一篇文章,题为“ Why shared sections are a security hole”。该文章只考察了“读/写共享节”和“只读共享节”所构成的威胁,而没有讨论第三种可能,即“读/写/执行共享节”。

利用共享节 

尽管研究人员和微软本身知道共享节的一般风险已经有很长一段时间了,但还没有文献对可读、可写和可执行(RWX-S)的共享节的潜在滥用进行过深入介绍。 

RWX-S二进制文件具有极大的进攻潜力,这是因为:如果您可以使远程进程加载指定的RWX-S二进制文件,那么您就在远程进程中获得了一个可执行的内存页,即使您对这个内存页进行修改,基于内核的防御解决方案也是看不到的。为了注入代码,攻击者可以将RWX-S二进制文件加载到自己的进程中,并在内存中使用他们想要的任何恶意代码编辑该节,然后将RWX-S二进制文件加载到远程进程中,这时,他们自己进程中的修改也会反映在受害者进程中。

加载RWX-S二进制文件本身的操作对防御性解决方案仍然是可见的,但正如我们将在后面的部分中讨论的那样,对于在恶意上下文之外使用的合法RWX-S二进制文件,实际上有很多选择的余地。

使用这种技术时,有几点需要注意:

1、攻击者必须能够将RWX-S二进制文件加载到远程进程中。不过,该二进制文件不需要包含任何恶意代码,但是,必须有一个PE节是RWX-S的。

2、如果RWX-S二进制文件是用于x86架构的,则x64进程内的LoadLibrary调用将失败。不过,我们仍然可以通过打开文件、创建具有属性SEC_IMAGE的节并映射节的视图,在x64进程中手动映射x86二进制文件。

3、RWX-S二进制文件不在会话之间共享。RWX-S二进制文件由同一会话中的非特权进程和特权进程共享。

4、对共享节的修改不会写入磁盘。例如,由ReadFile返回的缓冲区,以及映射具有属性SEC_COMMIT的映像时所返回的缓冲区,都不包含对共享节的任何修改。只有当二进制文件映射为SEC_IMAGE时,才会存在这些更改。这也意味着对共享节的任何修改都不会破坏磁盘上的验证码签名。

5、除非所使用的RWX-S二进制文件的入口点位于共享可执行节中,否则攻击者必须能够在远程进程中的任意地址执行代码。这不需要直接的进程访问。例如,SetWindowsHookEx可用于在没有直接进程访问权限的情况下执行模块中的任意指针。

接下来,我们将为读者介绍该理论的实际实现,以及RWX-S宿主二进制文件的在野普及情况。

通过修改入口点以获得执行权限

在某些情况下,可以绕过攻击者必须能够在远程进程中执行任意指针的限制。

如果RWX-S宿主二进制文件的入口点位于RWX-S节内,则攻击者不需要特殊的执行方法。

相反,在将RWX-S宿主二进制文件加载到远程进程之前,攻击者可以修改位于映像入口点的内存,使其指向指定的shellcode。当受害进程加载RWX-S宿主二进制文件并试图执行入口点时,攻击者的shellcode将被执行。

在野外寻找RWX-S二进制文件

这项研究试图解决的问题之一是“RWX-S的威胁有多广泛?”。为了确定这项技术的流行程度,我使用了VirusTotal的Retrohunt功能,该功能允许用户“使用……YARA规则扫描过去12个月中发送给VirusTotal的所有文件”。

为了在野外检测无签名的RWX-S二进制文件,我们创建了一个自定义YARA规则,专门用于检查PE映像中的RWX-S节:

import "pe"
rule RWX_S_Search
{
         meta:
                  description = "Detects RWX-S binaries."
                  author = "Bill Demirkapi"
         condition:
                  for any i in (0..pe.number_of_sections - 1): (
                          (pe.sections[i].characteristics & pe.SECTION_MEM_READ) and
                          (pe.sections[i].characteristics & pe.SECTION_MEM_EXECUTE) and
                          (pe.sections[i].characteristics & pe.SECTION_MEM_WRITE) and
                          (pe.sections[i].characteristics & pe.SECTION_MEM_SHARED) )
}

这个规则所做的事情,就是枚举二进制文件的PE节,并检查它是否可读、可写、可执行和共享的。

当通过Retrohunt功能搜索这个规则时,会发现超过10,000个无签名的二进制文件(当结果超过10,000个时,Retrohunt功能就会停止搜索)。

当再次搜索该规则时,可以稍微修改一下,以检查PE映像对应的机器类型是否为MACHINE_AMD64机,这时,只找到了99个x64架构的RWX-S二进制文件。

这表明,在过去的12个月中,用于x64机器的RWX-S二进制文件相对不常见,同时还表明防御性解决方案可能能够过滤RWX-S二进制文件,而不会在受保护的机器上产生明显的噪声。

为了检测已签名的RWX-S二进制文件,只需对上面的YARA规则稍加修改,以包含对authenticode签名的检查。

import "pe"
rule RWX_S_Signed_Search
{
         meta:
                  description = "Detects RWX-S signed binaries. This only verifies that the image contains a signature, not that it is valid."
                  author = "Bill Demirkapi"
         condition:
                  for any i in (0..pe.number_of_sections - 1): (
                          (pe.sections[i].characteristics & pe.SECTION_MEM_READ) and
                          (pe.sections[i].characteristics & pe.SECTION_MEM_EXECUTE) and
                          (pe.sections[i].characteristics & pe.SECTION_MEM_WRITE) and
                          (pe.sections[i].characteristics & pe.SECTION_MEM_SHARED) )
                  and pe.number_of_signatures > 0
}

不幸的是,对于YARA规则,没有一个简单的方法来确定一个PE映像是否包含基于有效证书的authenticode签名——所谓有效证书,指的是还未过期,或在证书有效期内用有效的时间戳签名的。这意味着上面的YARA规则会包含一些具有无效签名的二进制文件的误报。由于存在误报,上面的规则无法直接给出一个具有有效的authenticode签名的RWX-S二进制文件清单。为了提取已签名的二进制文件,我们编写了一个简单的Python脚本,下载低于检测阈值的每个样本并验证每个二进制文件的签名。

经过这一处理,发现了大约15个具有有效签名的独特二进制文件。正如未签名的二进制文件检查结果所示,在过去12个月里,具有签名的RWX-S二进制文件在野外并不是很多。此外,15个独特的已签名二进制文件中只有5个是用于x64机器。值得注意的是,虽然这个数字看起来很低,但使用已签名的二进制文件只是为了方便,在大多数情况下肯定不是必需的。

滥用未签名的RWX-S二进制文件

修改未签名的二进制文件

鉴于诸如用户模式代码完整性之类的缓解措施尚未得到广泛采用,因此,修改现有的未签名二进制文件仍然是一种可行的方法。

若要通过未签名的二进制文件来滥用RWX-S节,攻击者可以:

1、查找要修改的、合法但未签名的宿主DLL。

2、将未签名的DLL读入内存,并修改节的特征,使其具有可读、可写、可执行和共享的特性。

3、在使用之前,将这个新修补的RWX-S宿主二进制文件写入磁盘的某个位置。

以下是维护操作安全的几点建议:

1、建议攻击者不要修补磁盘上现有的二进制文件。例如,如果攻击者只修改了现有二进制文件的节特征,并将修改过的程序写入磁盘上的同一路径,则防御解决方案可以检测到RWX-S补丁已应用于现有的文件。因此,建议将修补后的二进制文件写入磁盘上的不同位置。

2、建议攻击者添加RWX-S以外的其他补丁程序,比如修改与节特征相关的其他无意义的属性,或者随机修改部分代码(重要的是这些修改看上去并不是恶意的)。这样做,是为了迷惑对手。

使用现有的未签名二进制文件

实际上,攻击者并不需要创建自定义的、应用过补丁的二进制文件。例如,使用上一节中的YARA规则,攻击者可以使用任何可能用于合法应用程序的现有未签名RWX-S二进制文件。

在内核中滥用已签名的RWX-S二进制文件 

尽管在过去的12个月内只发现了15个有签名的RWX-S二进制文件,但在利用可能需要已签名模块的进程时,具有有效的authenticode签名这一事实可能非常有用。

搜索显示的一个有趣的已签名的RWX-S二进制文件是一个已签名驱动程序。当试图测试共享节是否可以从用户模式复制到内核模式时,发现内存没有共享,即使已经通过Session 0中的进程映射和修改了该映像。

小结 

尽管共享节的稀有性为防御者提供了获得高保真遥测的独特机会,但RWX-S二进制文件仍然是一种强大的方法,它戳破了关于跨进程内存分配和执行的常见臆想。围绕这一技术,防御者面临的主要挑战是它在未签名代码中的普遍性。检测RWX-S二进制文件可能相对简单,但你如何判断它是否被用于合法的应用程序呢?

本文翻译自:https://billdemirkapi.me/sharing-is-caring-abusing-shared-sections-for-code-injection/如若转载,请注明原文地址
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论