作者:0x7F@了解于闯404实验室
一个

2020年12月,网络安全管理软件产品袭击事件引起全球关注。2020年初,攻击团队攻击了网络安全管理软件产品猎户座产品,导致多家厂商受到攻击,造成不可估量的损失。这种国与国之间的APT攻击包含了大量的技术细节,其中供应链攻击的实现,也就是旭日后门的植入,引起了我极大的兴趣。
2021年1月,旭日后门植入分析在网上公开,随后安全研究人员进一步优化了植入细节。根据这些内容,我开始了对dll劫持的学习和研究。详细介绍了dll劫持,并试图模仿旭日后门植入的方法,在C编译器上实施“供应链攻击”。本文的测试环境是Windows7 x64 sp1,开发环境是MinGW-x64+Python3.62后门植入和优化先简单看一下旭日后门植入的过程:它是由一个名为taskhostsvc.exe的程序完成的,通过预定的任务设置,随主机启动运行。
在taskhostsvc.exe启动后,通过创建互斥体保证只有一个实例在运行,然后每秒从进程中搜索MsBuild.exe进程。找到它之后,通过读取MsBuild.exe的内存,从命令行参数中获得构建项目的目录路径。然后,在项目目录中搜索猎户产品InventoryManager.cs的源代码文件,替换为包含恶意代码的源代码文件,等待MsBuild.exe编译完成,最后还原文件完成后门的植入;如下图:[1.旭日后门植入过程]当然,这个过程中需要大量的技术细节,保证后门与原项目代码的兼容性,以及植入过程的隐蔽性等。后来有安全研究人员表示,上述植入过程在APT攻击中并不完美。例如,通过规划任务和周期性的进程扫描,很容易暴露攻击行为。其次,监控MsBuild.exe到最终替换源文件的执行时间可能会影响后门植入的成功率。安全研究人员提出利用dll劫持来优化后门植入过程。在研究过程中,他们发现指定目录中的dll会在MSBuild.exe启动时优先加载,如下所示:[2.MSBuild优先加载的部分dll文件]如果我们重命名恶意的dll并把它放在这些“load-not-found-dll”路径中,我们就可以劫持dll并执行我们的恶意代码。原作者就是按照这种方式写代码来演示的。与taskhostsvc.exe相比,这种方法不需要额外的进程来监控,dll在程序执行前加载,程序执行后释放,也非常适合控制和清理程序。三dll劫持概述dll作为windows的函数库,有助于促进代码模块化、代码重用、有效内存使用、减少磁盘空;当一个应用程序运行时,可能需要依靠多个dll的函数来完成它的功能。如果控制了任何一个DLL,就可以控制应用程序的执行过程。
学习dll劫持,首先要知道dll的搜索顺序,这也是攻守双方兵家必争之地。微软近年来一直在加强这一块。对于桌面程序,当前默认的DLL搜索顺序是:应用程序加载的目录系统目录,使用GetSystemDirectory获取该路径。
16位系统目录
Windows目录,使用GetWindowsDirectory获取路径。
当前目录
PATH环境变量中列出的目录
默认情况下,HKEY _ local _ machine system current control set control session manager safedllsearchmode处于打开状态;如果手动设置为0,则关闭安全选项,搜索顺序为:在上述顺序的基础上,修改5。当前目录到2。系统目录,并将其他目录向前移动。当应用程序加载dll时,如果只指定了dll名称,将按上述顺序搜索dll文件;但是,在加载前需要满足以下两个规格:1.当内存中已经加载了一个具有相同模块名的dll时,系统会直接加载该dll而不进行搜索;除非设置了dll重定向选项。2.如果要加载的dll模块属于已知的DLL,系统会直接在系统目录中加载DLL,而不会进行搜索;已知dll列表:HKEY _本地_机器系统当前控制集控制会话管理器已知dll由于dll迭代更新的不兼容性,微软提出了dll重定向的解决方案,让应用程序可以自行选择加载dll。了解以上基本内容后,替换dll搜索路径上的文件,就可以实现dll劫持了。请参考https://docs . Microsoft . com/en-us/windows/Win32/DLL/dynamic-link-library-security了解微软DLL中安全加固的详细信息。四Dll函数转发通过用恶意dll替换原文件,应用程序可以加载我们的dll并执行恶意代码,但是应用程序的运行依赖于dll提供的函数,而恶意dll必须提供相同的函数才能保证应用程序的正常运行。所以我们先来了解一下dll函数转发。
1.手动转发当dll的导出函数较少时,我们可以按照正常的dll开发流程逐个定义函数名,然后使用函数内部的LoadLibrary函数调用原dll的对应函数来完成函数,如下:[3.加载库转发功能]2.def文件当dll的导出函数过多时,我们无法手动转发。用模块定义文件写导出函数的信息,链接器会自动转发函数。详情请参考https://docs . Microsoft . com/en-us/CPP/build/reference/module-definition-dot-def-files view = msvc-160。我们尝试生成version.dll的恶意dll:在test.c文件中编写恶意代码,插入到DllMain的执行过程中,在test.def中编写函数转发规则:[4.使用dll模块定义的函数转发]然后编译生成dll文件。gcc编译如下:gcc-墙-共享测试. c测试. def-o version.dll在。def文件,我们将原始文件命名为version_origin.dll应用运行时,我们的恶意version.dll会被加载,调用函数时,恶意version.dll会转发函数:something.exe = > version.dll = >版本_起源. dll这里我写了一个Python脚本,可以根据DLL自动生成模块定义文件dllProxy _ def _ generate.py,使用方法如下:[5.自动生成模块定义文件]有些dll导出函数没有导出名称,只有导出序列号。Gcc和Tcc不支持通过序列号导出的函数的转发。读者遇到可以用VisualStdio。3.pragma预处理除了上述模块定义文件实现函数转发,还可以使用pragma实现。详见https://docs . Microsoft . com/en-us/CPP/preprocessor/comment-c-CPP view = msvc-160。也以version.dll为例。函数转发的源代码如下:[6.pragma实现dll函数转发]但是,pragma关键字仅由Microsoft编译器提供。五路径劫持根据以上知识,我们可以自由生成恶意dll文件,并通过函数转发使其调用原dll函数,根本不会影响应用程序的正常运行。此外,恶意代码一般可以添加到DllMain中,使代码在加载dll时被触发,或者添加到指定函数中准确劫持程序进程,具体要看实际场景。这里我们的恶意dll已经准备好了。

我们在学习的过程中发现,有些应用程序仅仅依赖于系统dll,而这些dll已经被其他程序加载了。例如,kernel32.dll和msvcrt.dll是MinGW唯一的依靠。除了以上公开的DLL劫持,还有没有更好的办法?
在对0x02 dll劫持的总结中,我们还提到了一个特例:dll重定向。当其他应用程序将具有相同模块名称的dll加载到内存中时,可以使用此方法强制加载指定的dll文件。这样也可以实现dll劫持。dll重定向的默认状态是关闭。我们在注册表中的HKLM 软件微软 Windows NT 当前版本镜像文件执行选项中添加DevOverrideEnable字段并设置为1来开启该功能,重启后生效。[8.注册表打开dll重定向]我们有两种使用dll重定向的方法:1.。当地的在与应用程序相同的目录下,创建AppName.exe.local目录当应用程序启动时,将首先从该目录加载dll文件。我们编写了一个HelloWorld的C程序来生成恶意msvcrt.dll进行演示。目录结构是:。test.exe├──test . exe . local│├──msvcrt . dll│└──msvcrt_origin.dll├──helloworld.c└──运行演示如下:[9.本地重定向的示例]2.manifest也可以使用清单配置文件,它的优先级高于。本地的。详情请参考https://docs . Microsoft . com/en-us/windows/win32/sbscs/application-manifest。目录结构如下:。├──helloworld.c├──msvcrt_origin.dll├──msvcrt.dll├──msvcrt.dll.manifest├──test.exe└──测试清单文件的内容包括:[10 .清单内容示例]您还可以加载恶意的dll文件。七Tcc劫持实现Tcc是一个相当小的C编译器。我们从一个简单的对C编译器的“供应链攻击”开始。
我这里用的是TCC 0 . 9 . 27版本。结合逆向分析,可以确定tcc.exe依赖的是同一个目录下的libtcc.dll文件,所以直接替换dll文件即可。我们模仿旭日后门植入的方法,编写如下恶意代码演示:[11.Tcc劫持代码演示]编译后,恶意dll被用来替换libtcc.dll,原文件被重命名为libtcc_origin.dll运行演示如下:[12.Tcc劫持演示]可以看到Tcc编译的程序在执行时触发了恶意代码后门。八Gcc劫持实施我们再试试Gcc。通过分析发现,它只取决于kernel32.dll和msvcrt.dll。所以在这里,我们劫持msvcrt.dll文件,并使用dll重定向方法,使Gcc加载恶意的dll文件。
用Tcc中的测试代码进行编译,然后在Gcc目录中添加Gcc.exe.local文件夹,将msvcrt.dll/msvcrt _ origin.dll放入该文件夹,如下所示:[13.gcc目录中的dll重定向文件夹]运行演示如下:[14.Gcc劫持演示]九摘要在此,感谢大午@知乎于闯404实验室伙伴对我学习和研究的帮助。在dll劫持的基础上,一步步讲解和演示dll劫持,讲解dll劫持的一些场景和利用,最后模仿旭日后门植入的方法,实现对C编译器的“供应链攻击”。
其实文中提到的“供应链攻击”对编译器的方法还可以进一步优化,因为我们的方法会重写文件,会修改文件的写入时间,可能暴露攻击行为;我们还可以逆向分析编译器的执行过程,更准确地劫持读取文件的功能,在内存中植入恶意代码,读者可以自己尝试。但是dll劫持的攻防对抗已经发展了很久,微软在保证功能的前提下提供了相对完善的防御措施;对于上面描述的劫持方式和场景,可以根据文中的技术细节进行防御,比如路径、注册表、文件等。10参考
https://us-cert . cisa . gov/ncas/alerts/aa20-352 a https://www . crowd strike . com/blog/黑子-malware-technical-analysis/https://www . a12d 404 . net/ranting/2021/01/17/msbuild-back door . html https://en . Wikipedia . org/wiki/2020 _ United _ States _ federal _ government _ data _ breake https://docs . Microsoft . com/en-us/windows


