分析DLL搜索顺序劫持的原理
2020-08-06 11:15:00 Author: www.4hou.com(查看原文) 阅读量:385 收藏

DLL_Search_Order_Hijacking_blog_header_1010_350_75_s_c1.jpg

Context的智能和响应团队已经看到DLL搜索命令被滥用,作为在真实环境中进行网络入侵的一种手段。滥用DLL搜索顺序并利用这种机制来加载一个流氓DLL而不是合法的被称为DLL预加载,或者在MITRE ATT&CK框架中劫持。

在这篇文章中,你将了解更多关于DLL搜索顺序的基本原理,以及合法的二进制文件如何被武器化,并介绍一个通过DLL劫持自动发现适合有效载荷执行的二进制文件的工具。

关于动态链接库

动态链接库(DLL)是一个模块,它包含可以被另一个模块(应用程序或DLL)使用的函数和数据。这些函数从库文件中导出,以供依赖于它们的应用程序或DLL使用。为了使用这些函数,应用程序必须从库文件中导入它们。应用程序从模块导入函数有两种方式:隐式(加载时动态链接)和显式(运行时动态链接),让我们各看看。

隐式链接(加载时动态库链接)

当一个应用程序被打开时,Windows加载器采取步骤在内存中映射应用程序的可执行映像,并最终启动一个托管并执行其代码的进程。在加载过程中,加载器解析可执行映像的导入表,以便将导入的模块(动态链接库)映射到该进程的地址空间中。

可执行映像可能嵌入了描述Windows并行程序集上依赖关系的清单。在加载导入的DLL之前,并行管理器(SxS Manager)检查这个可执行文件的清单文件中存在的任何依赖项是否得到满足。如果是,则从路径中加载所需的模块。

对于其余的导入模块,加载程序首先检查由KnownDLLs注册表项(HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Session Manager \ KnownDLLs)设置的列表上是否存在要导入的所有DLL。如果是,加载程序将使用此注册表项指向的DLL的副本。否则,它将通过应用DLL搜索顺序来搜索模块。有关DLL搜索顺序的更多信息,请参见本文其他章节。

显式链接(运行时动态库链接)

应用程序可能需要使用DLL中的函数,这些函数在应用程序运行时动态加载。以这种方式加载DLL称为运行时DLL动态链接,这种类型的加载发生在应用程序调用LoadLibrary或LoadLibraryEx函数时。

这两个函数接受要加载的模块的名称,名称可以是模块的文件名,也可以是模块的完整路径。如果应用程序没有指定模块的完整路径,Windows加载程序将查找应用动态库搜索顺序的DLL。

DLL搜索顺序劫持及其识别方法

滥用DLL搜索顺序并利用这种机制使应用程序加载流氓DLL(而不是合法的DLL)被称为DLL预加载。之所以称为预加载,是因为攻击者可以将其DLL放在搜索顺序的前面,从而使应用程序加载此DLL,而不是合法的DLL。该技术在MITER ATT&CK框架(T1038)中记录为DLL搜索顺序劫持。在本文的以下各节中,我们演示如何滥用合法应用程序通过搜索顺序劫持来加载和执行Cobalt Strike信标有效载荷。

DLL搜索顺序劫持主要提供两个优点,使其成为一种有效的技术。第一个优点是可以用来逃避检测。武器化的应用程序通常是合法的经过签名的二进制文件,可以通过调用此DLL导出的函数在其地址空间中加载恶意DLL。因此,为了执行恶意DLL,自动化沙箱必须首先确定要调用或执行无害二进制文件的导出函数,并设置环境以加载恶意DLL。

该技术提供的另一个优点是可以提升特权,当在其地址空间中加载DLL的合法应用程序以提升的特权运行时,在其上下文中执行的任何代码都将以相同的特权级别执行。这意味着有效载荷DLL及其实现的功能将以与加载它的进程相同的特权执行。

识别用于劫持的候选DLL有两种不同的方法:静态分析和动态分析,就像恶意软件分析中采用的方法一样。动态分析包括执行应用程序和监视其加载的库。这可以通过监视API调用的工具(例如Procmon和API Monitor)来实现。静态分析方法包括使用IDA和Ghidra等反汇编工具来识别出现的特定API调用,而不执行应用程序。

这两种方法的主要区别在于,通过使用动态分析,可以显示用于加载时和运行时动态链接的大量候选DLL,而静态分析仅显示在运行时加载的候选DLL。

DLL搜索顺序

从Windows XP开始,启用SafeDllSearchMode选项时,模块将在加载时或运行时加载到应用程序的地址空间中,并且未明确指定模块的完整路径,或者未声明清单文件在可以查找依赖项的位置,操作系统按照定义的搜索顺序搜索DLL,该DLL包含以下内容:

从中加载应用程序的目录

系统目录

16位系统目录

Windows目录

当前目录(除非另有说明,否则与第一个相同)

PATH环境变量中列出的目录

当未启用SafeDllSearchMode时,以上搜索顺序略有不同,有关这方面的其他信息,请参阅Microsoft文档

当操作系统开始搜索应用程序导入的DLL时,除非指定了完整路径,否则首先搜索加载应用程序的目录。如果DLL不存在,接下来搜索系统目录,依此类推。当攻击者观察到应用程序的行为后,将他们自己的DLL放在搜索顺序的较早位置,以便应用程序加载该DLL而不是继续搜索时,就会发生滥用。Context的情报团队作为AVIVORE跟踪的威胁小组使用了这种技术,以实现在受害者环境中的有效载荷执行。

加载时动态链接的示例

为了说明加载时的加载情况,我们分析了一个已签名的Google可执行文件(GoogleCrashHandler-MD5:83bb030c71c9727dcfb2737005772c4e),Context的情报团队观察到该文件被用于入侵。

我们之所以关注此二进制文件,是因为它可以找到合适的候选人。这是什么意思呢?首先,它是来自受信任供应商的合法且经过签名的二进制文件。一旦执行了此应用程序,它将不显示可见窗口,并且在执行时终止,因此在执行此二进制文件时,不会使用户知道该二进制文件确实已在运行,并且进程不会停留在运行状态。最后一点同样重要,即使应用程序加载了恶意DLL,它也不会生成任何其他活动(例如弹出窗口),而这可能会引起用户的怀疑。因此,它可用作执行有效载荷DLL的杠杆。

为了识别此可执行文件尝试加载并可能被劫持的模块,我们将SysInternal的Procmon与以下过滤器一起使用:

1.png

应用过滤器后,我们得到以下候选DLL:

2.png

自动化DLL搜索顺序

为了武器化GoogleCrashHandler.exe,我们创建了一个自定义DLL,该DLL执行从CobaltStrike生成的beacon shellcode。我们将输出DLL命名为wkscli.dll,并将其放置在GoogleCrashHandler可执行映像所在的目录中。然后,我们打开了GoogleCrashHandler。下一张图片显示恶意DLL被映射到GoogleCrashHandler的地址空间中,并且启动了一个信标。

3.png

运行时动态链接的示例

为了说明运行时加载,我们分析了一个经过签名的Microsoft可执行文件(OleView-MD5:d1e6767900c85535f300e08d76aac9ab)。已签名的可执行文件用于加载DLL,该DLL随后解密了PlugX有效载荷。

让我们与Procmon一起查看该可执行文件一旦启动即尝试加载的DLL:

p.4_graphic_4_.png

为了确认此DLL是动态加载的,而不是在加载时加载的,我们使用API Monitor。通过挂钩LoadLibrary和LoadLibraryEx API,我们观察到该应用程序尝试动态加载多个DLL:

p.4_graphic_5_.png

将从Procmon和API监视器获得的数据进行关联,应用DLL搜索顺序确定所搜索的DLL为ACLUI.DLL。我们可以通过分析Ghidra上的可执行文件来做同样的事情。在定义字符串部分(窗口->定义字符串)我们搜索字符串ACLUI。出现了三个结果:

p.5_graphic_6_.png

然后,我们遵循对字符串ACLUI.DLL的引用,并最终完成对LoadLibraryW的调用:

p.5_graphic_7_.png

我们观察到LoadLibraryW API的参数不是完整路径,因此我们确认应用了DLL搜索顺序。

如果我们创建一个有效载荷DLL,将其放置在与可执行文件相同的目录中,然后运行该可执行文件,则会显示以下消息框:

p.5_graphic_8_.png

这意味着可执行文件从我们的有效载荷DLL请求一个不存在的函数,为了允许我们的有效载荷从应用程序执行,我们必须导出函数EditSecurity。以下屏幕快照显示了使用C / C ++代码执行此操作的方法:

p.5_graphic_9_.png

自动化DLL搜索顺序

就像我们对GoogleCrashHandler图像所做的一样,我们创建了一个自定义DLL,该DLL执行从CobaltStrike生成的beacon shellcode。我们将输出DLL命名为ACLUI.DLL,并将其放置在与OleView.exe可执行映像相同的目录中。然后,我们打开OleView。下一张图片显示恶意DLL被映射到OleView的地址空间中并启动了一个信标。

p.6_graphic_10_.png

缓解策略

基于我们所观察到的事件以及过去如何滥用DLL搜索顺序,我们可以推荐在这些环境中应用的特定最佳实践。这些建议旨在减少攻击面,限制潜在攻击的后果,并减少检测相关攻击所需的时间。

通常建议公司在其环境中部署功能和策略,作为功能的一部分,强烈建议部署事件检测和响应(EDR)软件。在策略方面,填充和维护授权在该环境中运行的所有应用程序的列表,并实现应用程序白名单,以防止不属于该列表的应用程序运行,这是一个很好的实践。为了检测流氓DLL,建议对环境中观察到的DLL进行频率分析。DLL的低频发生可能是值得进一步分析的指标。可以防止其他DLL劫持攻击的另一件事是启用SafeDllSearchMode并在系统上配置CWDIllegalInDLLSearch注册表。

软件开发人员也必须遵循最佳实践,例如,当应用程序在运行时加载模块时,建议为提供给LoadLibrary和LoadLibraryEx API的模块指定绝对路径,或使用API SetDllDirectory专门设置Windows加载器将从中加载提供的模块的路径。这样,就不会查找正常的搜索顺序。根据最佳实践,另一项建议是通过“应用程序清单”对加载的模块实施完整性检查。通过这样做,应用程序将防止恶意DLL的加载,并有可能将识别出的异常通知用户。

DLLHSC简介

DLLHSC是一个应用程序,旨在自动扫描提供的可执行映像,生成潜在顾客(以后可以手动评估)并报告利用DLL搜索顺序的潜在路径,最终目的是在地址空间中加载有效载荷DLL。通过搜索顺序劫持提供的图像。

操作模式

该工具实现3种操作模式,如下所述。

轻量级的模式

在内存中加载可执行映像,解析导入表,然后用有效载荷DLL替换导入表中引用的任何DLL。该工具将一个模块(DLL)放在应用程序目录中,该模块不存在于应用程序目录中,不属于WinSxS,也不属于KnownDLLs。

然后,它启动应用程序并报告是否执行了有效载荷DLL。有效载荷DLL在执行后会在路径C:\ Users \%USERNAME%\ AppData \ Local \ Temp \ DLLHSC.tmp中创建一个临时文件。如果临时文件存在,则表明扫描的应用程序可能被滥用。当某些可执行文件从它们加载的DLL导入函数时,当提供的DLL无法导出这些函数并因此满足提供的映像的依赖性时,可能会显示错误消息框。

但是,消息框表明,如果满足依赖关系,DLL可能是有效载荷执行的好候选对象。在这种情况下,需要进行额外的分析。这些消息框的标题可能包含以下字符串:“找不到常规”或“找不到入口点”。 DLLHSC会查找包含这些字符串的窗口,并在出现这些窗口时立即关闭它们并报告结果。

模块列表模式

使用提供的可执行映像创建一个进程,枚举此进程的地址空间中加载的模块,并在应用过滤器后报告结果。

该工具仅报告从系统目录加载的模块,不属于KnownDLL。结果是需要进一步分析的线索。然后,分析人员可以将报告的模块放在应用程序目录中,并检查应用程序是否加载了提供的模块。

运行模式

通过Microsoft Detours(Detours是微软开发的一个函数库,可用于捕获系统API)挂钩LoadLibrary和LoadLibraryEx API时,并报告在运行时加载的模块。

每次扫描的应用程序调用LoadLibrary和LoadLibraryEx时,该工具都会拦截该调用,并将请求的模块写入文件C:\Users\%USERNAME%\AppData\Local\Temp\DLLHSCRTLOG.tmp中。如果使用标志LOAD_LIBRARY_SEARCH_SYSTEM32专门调用LoadLibraryEx,则不会将任何输出写入文件。完成所有拦截之后,该工具将读取文件并打印结果。对于进一步的分析,我们感兴趣的是KnownDLLs注册表键中不存在的模块、系统目录中不存在的模块以及没有完整路径的模块(对于这些模块,加载器应用正常的搜索顺序)。

你可以在我们的GitHub页面上找到DLLHSC的源代码以及x86和x64体系结构的编译二进制文件。

本文翻译自:https://www.contextis.com/en/blog/dll-search-order-hijacking如若转载,请注明原文地址:


文章来源: https://www.4hou.com/posts/PrJ4
如有侵权请联系:admin#unsafe.sh