English :https://cysinfo.com/detecting-deceptive-hollowing-techniques/
本文将介绍几种不同类型的Process hollowing技术,这种技术被用来绕过、混淆、欺骗取证分析工具。
同时也会介绍如何使用Volatility的插件,HollowFind(https://github.com/monnappa22/HollowFind )来检测这些Process Hollowing攻击。
在介绍这些Process Hollowing技术之前,先让我们来看看最简单的Process Hollowing是如何工作,以及如何检测它。
这里我使用一个被Stuxnet(震网病毒)感染过的image进程内存dump文件来演示。
Process Hollowing 或 Hollow Process Injection 是一种代码注入技术,通俗来讲就是,在内存中,一个合法进程的代码数据,被替换成了恶意代码。
黑客将恶意代码注入一个合法进程中,通过这种方式可以让一个合法进程来执行恶意行为。优点就是被注入的进程路径依然指向原合法文件路径,有了合法进程的外壳,恶意代码可以绕过防火墙和一些主机防御系统。
假如,Svchost.exe进程的内容被替换了,该进程的路径仍然指向磁盘上未被替换前的svchost.exe,只有Svchost.exe在内存中的代码段内容被替换成了恶意代码,这样黑客就可以绕过一些取证软件。
关于Process Hollowing的原理以及如何检测,已经在《Art Memory Forensics Detecting》https://www.amazon.com/Art-Memory-Forensics-Detecting-Paperback/dp/B00RI5ZKCI
这本书中解释的很清楚了,以及我的视频和demo中也有解释: https://cysinfo.com/7th-meetup-reversing-and-investigating-malware-evasive-tactics-hollow-process-injection/
下面介绍病毒木马是如何应用Process Hollowing技术的:假设有两个进程,A(恶意进程)和B(合法进程)
这部分我们来看看如何检测Process Hollowing技术,因为代码注入是在内存中发生的,所以最好的方式是通过内存取证工具来检测。
Stuxnet(震网病毒)就是通过上面提到的步骤,实现了了Process Hollowing技术。这篇文章中有完整的分析报告,使用内存取证工具来详细分析震网病毒:http://mnin.blogspot.com/2011/06/examining-stuxnets-footprint-in-memory.html
但是这篇文章,我们只讲如何通过取证工具来检测Process Hollowing技术。
下面进程列表中,有两个可疑的lsass.exe进程(PID 868和 PID1928),这两个进程并不是由winlogon.exe或winitit.exe启动,而是由services.exe(PID 668)启动。
这就是一种检测Process Hollow技术的方法,在干净的系统环境中, 在Vista之前的系统lsass.exe的父进程是winlogon.exe,而在Vista以及之后的系统中lsass.exe的父进程是wininit.exe
Hollow Process Injection 也可以通过比较PEB(Process Environment Block)和VAD(Virtual Address Descriptor)结构。
PEB结构位于进程内存中,该结构中保存着当前进程的磁盘绝对路径,以及内存加载基址。
而VAD结构位于内核内存中,包含进程连续虚拟内存空间分配信息,如果加载了可执行文件,则VAD节点中会记录有关可执行文件的起始地址,结束地址,和完整路径信息。
通过比较两个结构的差异,可以检测到该进程是否被注入了
在下面截图中,通过dlllist插件来查看lsass.exe(PID868)的全路径,以及基址(0x1000000)
这些信息是dlllist插件是从lsass.exe进程的PEB中获取的
下面截图中,使用ldrmodules插件查看模块列表时(位于内核中VAD的内容),没有显示lsass.exe模块的全路径,这是因为病毒取消映射了原来lsass.exe进程内存,
导致后面新申请的0x1000000内存中的内容和lsass.exe这个文件无关,所以也就不显示了。通过这点可以给我们一些提示,该进程是否被注入了
Hollow Process Injection 同样可以通过查看可以可疑内存的保护属性。
通过malfind插件(用来查找可疑内存保护属性)可以看到lsass.exe进程中0x1000000内存的保护属性为读写执行。
由于0x1000000是lsass.exe的基址,说明该进程没有被正常加载,(被注入了恶意代码)。任何可执行文件正常加载到内存后会有一个PAGE_EXECUTE_WRITECOPY的内存保护属性。
这点更加说明lsass.exe(PID868)进程被加载到0x1000000是有问题的
HollowFind是一个Volatility插件,通过对比PEB和AVD中的差异来检测Process Hollowing。
下面截图展示如何使用HollowFind来检测一个被Stuxnet感染过的内存镜像,并识别出了两个可疑的进程lsass.exe(PID1928和 PID868)。
并且还检测到了可疑的内存保护属性(PAGE_EXECUTE_READWRITE),以及PEB和VAD中进程路径的差异,最后还会显示反汇编入口点的反汇编代码, 可以看到在入口点有个跳转jmp 0x1003121
一旦这个插件发现了Process Hollow,还会显示当前进程中是否有相同的Process Hollow。
在下面截图中,注意两个lsass.exe进程(PID 868和PID 1928)与之关联的父进程services.exe(PID 668),
表示两个lsass.exe并不是正常启动的进程。而正常的系统进程lsass.exe的父进程是winlogon.exe(PID 624)。
HollowFind插件同时还检测到了可疑的内存,可以帮我我们识别被注入的代码。
下面截图中发现的可疑内存地址一个是0x1000000(可执行文件的基址),还有一个地址是0x80000,同时在这两个地址中找到了PE文件,并且内存的保护属性被设置成了PAGE_EXECUTE_READWRITE权限,
表示一个可执行文件被注入到这个地址中了。
我们可以使用 - D 参数来把0x80000这块可疑内存dump下来,然后提交打破VirusTotal上,VT扫描结果显示它就是Stuxnet震网病毒
这部分我们来看看病毒木马使用的其它类型的Process hollwing技术,并解释为何这些技术会混淆分析人员以及欺骗取证工具。
同样我们也是展示如何使用hollwfind来检测这些攻击
Skeeyah使用了上面提到过的步骤,但是有一点不同,木马以挂起模式创建Svchost.exe进程,并加载到地址0x0100000,如下所示:
木马通过读取系统进程svchost.exe的PEB.ImageBaseAddress,来得到进程加载基址,然后释放这块内存,如下所示:
然后木马会修改系统进程PEB结构中的ImageBaseAddress字段的值,为新申请的那块内存地址(0x0400000)。
这个操作将svchost.exe进程的基址从0x1000000修改成了0x040000(包含恶意可执行文件)
木马随后通过SetThreadContext函数将CONTEXT.EAX修改为注入pe的入口地址,然后恢复线程时,svchost.exe将从恶意pe入口点开始执行。
这种类型的Process Hollowing可以通过比较PEB和VAD来检测。下面截图中,通过dlllist插件可以看到svchost.exe(PID 1824)进程的全路径,和基址(0x00400000)
而 ldrmodules插件没有找到任何svchost.exe这个模块入口相关信息。因为当木马hollow系统进程svchost.exe后,这个模块从VAD链表中被移除了。
通过对比这个差异信息,也可以确认程序被hollow注入了。
上面这种对比差异,已经在HollowFind插件中实现了。
在下面截图中,展示通过该插件来检测出被Hollow的进程svchost.exe(PID 1824),同时也检测出了在VAD中没有找到svchost.exe模块的入口。
同样还显示出了PEB和VAD结构的对比的差异,PEB中显示出了svchost.exe被注入后新基址0x00400000,以及内存保护属性。
在HollowFind插件检测到存在Holloed进程的时候,同时还会显示出当前进程列表中相似的进程。
在下面截图中,被注入的进程svchost.exe(PID 1824)没有显示出父进程名字,是因为它的父进程已经退出了。
而其它正常的系统进程svchost.exe的都是同一个父进程services.exe(PID 696),注意这里也显示了进程创建时间的差异。
在正常的系统环境中,svchost.exe的父进程应该是services.exe,通过这点可以判断svchost.exe(PID 1824)是恶意的。HollowFind插件同时还检测到了被注入恶意代码的可疑内存区域。
在这个案例中,我们来看看另一个木马样本,同样也使用了另外一种Process Hollowing,它会导致一些插件检测的结果出现差异,可能是用来迷惑分析人员或取证工具。
首先来看看这个病毒是如何工作的,木马以挂起模式创建svchost.exe进程,并加载到地址0x01000000,如下图所示:
木马样本然后在0x00400000地址上申请了一块RWX权限的内存,这次这个木马并没有像其它病毒一样:“取消映射被挂起的svchost.exe进程基址上的内存0x01000000”
而是保留了源svchost.exe进程基址上的内存。
木马把一个pe文件写入到目标系统进程svchost.exe新申请的内存地址(0x00400000)中。
木马然后通过SetThreadContext函数,修改了被挂起进程svchost.exe的 CONTEXT.EAX的值,指向注入到0x0040000中pe的入口点,然后恢复线程执行。
这个样本所使用技术,并没有挖空进程内存,但是只通过修改PEB,就欺骗了一些插件。在下面截图中,dlllist插件显示了svchost.exe(PID 2020)的基址在0x0040000。
而基于VAD的ldrmodules插件显示的模块列表中,svchost.exe进程的基址却是0x1000000。
除了通过两个插件可以看到同一个模块基址的差异,我们可以看到svchost.exe模块中的Inload InInit InMem这3列属性,显示为False
意味着这个svchost.exe模块可能是个隐藏的模块(这个隐藏模块的现象是假的,因为我们通过dlllist这个插件是可以看到svchost.exe模块的存在)。
同一个进程,两个插件检测出来的基址不同,这可能会让一些安全分析人员感到困惑。正常的反映可能是依赖于ldrmodules的输出结果。
因为ldrmodules的输出结果是从内核结构链表中读取出来的。正因此,可能会给人一种svchost.exe模块可能被断链了的错觉。
让我们来基于这个ldrmodules(0x01000000)报告的内容,进一步分析,看看能发现什么。首先我们重点分析基址为0x01000000的svchost.exe模块,后面再分析基址为0x00400000的svchost.exe模块。
我们可以使用dllmudp插件来把0x0100000这个基址上的svchost.exe模块dump下来,它支持通过基址来dump。然后使用file命令确认是个pe文件。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课