0x01 背景
前两周的时候一次应急中遇到了攻击者使用的windows rookit技术,虽然最后排查出来的结果是通过注册系统文件过滤驱动去做的文件隐藏;排查的过程中有师傅把这个项目丢出来了,说怀疑是使用这个项目做的(https://github.com/bytecode77/r77-rootkit
),这个项目之前23年4、5月份的时候有师傅给我推荐看来着,后来忙着忙着把这个事情忘记,就不了了之了;这次应急的时候当时我简单看了下这个项目的源码,看到项目是通过iathook r3层底层winapi来实现的,于是简单粗暴的对受害机器进行了排查,直接上调试器,attach cmd或者explorer文件资源管理器,给ntdll模块的NtQueryDirectoryFiel/EX打上断点,然后运行dir或者跳转目录操作,发现断是断下来了,但是没被hook;(这里也可以直接上火绒剑,但是因为对火绒剑的底层扫描内存钩子的原理以及调用的api不是很了解,害怕有些恶意软件做了对抗,就没选择火绒,后续看这个项目的源码,火绒剑应该没啥问题)排除了这种可能之后,就没管这个项目了;
周末的时候闲来无事上github看了下这个项目的实现,发现这个项目没有想象的那么简单,于是过了遍源码,简单记录下其各个模块的实现和其内部使用的一些比较有趣的技术点;最后从应急的角度简单的写了下如何检测和对抗这款rootkit;
0x02 整体流程
这里我们直接从该项目github主页可以看到大体的功能逻辑流程:
0x03 各模块实现分析
一、Installer
(1、获取Resource 文件资源里面的stager.exe ,并写入到注册表\HKEY_LOCAL_MACHINE\SOFTWARE\$77stager
(2、创建计划任务($77svc32/$77svc64),运行内置的powershell命令
二、Powershell
三、Stager
(1、卸载 ntdll上的挂钩
卸载挂钩的方式(UnhookDll())十分简单粗暴:
直接重新读系统文件上的ntdll.dll的文件内容,然后拉伸,将其.text节来替换当前进程所加载的ntdll.dll模块所在内存的.text节
(2、将stager.exe资源Resource里面的$77x32/x64.dll
解密并写入到注册表:计算机\HKEY_LOCAL_MACHINE\SOFTWARE下面的$77.dll32/64
(3、将stager.exe资源Resource里面的R77服务
所需要的可执行程序,service.exe读取出来,然后运行这个服务程序,这里运行的时候使用了两个技术,一个是父进程伪造技术,一个是进程镂空技术(傀儡进程),先是利用父进程伪造技术,启动一个dllhost.exe程序伪造其是winlogon的子进程;然后利用进程漏洞技术,在内存中卸载dllhost.exe,加载services.exe;
父进程伪造(PPID伪造)参见FakePPID原理及其检测对抗技术
进程镂空(傀儡进程)参见blog中进程镂空相关文章
四、Service
r77services
(1、卸载ntdll、kernel32的钩子,实现方式和上面一样
(2、读取Stager运行时写入到注册表的\HKEY_LOCAL_MACHINE\SOFTWARE\$77dll
的值,也就是r77x64/r77x86.dll文件的内容
(3、加载配置相关的,比如隐藏设定的哪些pid、路径等(存在注册表里面的)
(4、实现一个类似全局注入的逻辑 创建一个监控进程,并提供一个回调函数;这个监控进程是尝试连接指定名称的管道pipe,当连接成功的时候(在后面的Rootkit模块里面是会去hook NtResumeThread这个位于r3层底层的进程创建函数,修改后的逻辑里面会创建对应管道,并写入被创建的子进程PID),读取获取到的内容(这个内容其实就是一个pid),然后调用提供的回调函数操作这个pid;这个回调函数是一个远程进程注入函数,通过指定的目的pid,向对应的进程注入第二步获取的r77x64/32.dll;
五、RootKit
这里就是上面r77x32/x64.dll的实现了(Stager写入注册表,servcie从注册表中读出的)
(1、hookwinapi
DllMain里面直接通过detours 来hook如下的所有api,从而来实现进程隐藏和文件隐藏等
六、Uninstall
卸载模块:
(1、删除注册表里面的\HKEY_LOCAL_MACHINE\SOFTWARE
下的stager、dll32、dll64
(2、删除计划任务
$77svc32\$77svc64
(3、关闭服务:
遍历进程,判断模块头中是否存在r77服务(R77_SERVICE_SIGNATURE)的标记,找到标记直接结束进程
(4、解除挂钩
遍历进程,判断模块头中是否存在r77 被注入进程标记(R77_SIGNATURE),如果存在就创建进程执行指定地址(调用ntdll.dll里面的NtCreateThreadEx创建进程,指定位置就是DetachRootkit)卸载winapi的hook;
卸载hook
0x04 其他
一、关于注册表中存的内容
把相关恶意payload存到注册表中也是常见的免杀手段之一,这里我们修改rootkit模块的hook范围,取消隐藏注册表查询看下,如下:
如下可以看到,隐藏在SOFTWARE里面的三个文件,并且还有
$77config
配置
二、关于文件隐藏和注册表隐藏的效果
1、文件隐藏可以通过火绒剑看到,因为火绒剑不是通过被hook函数(ntdll.dll#NtQueryDirectoryFile/Ex
)来遍历文件的,直接使用x64dbg调试火绒剑,在对应api打上断点,然后使用响应的文件模块,没有断点;cmd进程和文件资源管理器进程explore.exe 进程是可以断下来的。
2、注册表隐藏通过火绒剑也看不到,因为火绒剑是通过被hook的函数(ntdll.dll#NtEnumerateKey/NtEnumerateValueKey
)来查看注册表的;
三、该项目免杀使用技术点
1、反射DLL加载,无落地文件 2、将恶意payload隐藏到注册表的键值中 3、ProcessHollowing(傀儡进程/进程镂空) 4、Fake PPID (父进程伪造) 5、r3底层ntdll/kernel32反劫持,通过重读ntdll文件来重写内存空间来解杀软的r3hook检测,从而绕过杀软监测
0x05 如何检测、对抗该工具
如下是笔者给到对于这个工具的检测和对抗的点:
一、检测
1、利用Windows etw来检测Fake PPID操作;参见xxx文章
2、通过PCHunter进程扫描可以检测ProcessHollowing操作,会校验失败;
3、通过火绒剑或者pchunter行为检测可以看到注册表的写入操作,因为先是通过注册表来存储一些恶意payload文件,然后才hook的,所以即使后面hook了相关注册表读写操作的r3底层api,这里前面的读写操作都是可以看到的,对\HKEY_LOCAL_MACHINE\SOFTWARE\$77xxx
的键值写入操作;
4、使用火绒剑扫描被注入的进程,可以找到所有挂钩,r3层挂在ntdll/kernel32模块上的hook都会被找到;
二、对抗清除
这里我们直接看其uninstall实例的实现就行:
1、删注册表:\HKEY_LOCAL_MACHINE\SOFTWARE
下的stager、dll32、dll64
2、删计划任务:$77svc32\$77svc64
3、终止服务进程:这里手动做比较难,因为实现的时候需要去判断那个服务是r77起的,其本身的uninstall里面是通过进程头部的标记来判断是否是其相关进程的;所以建议最好还是使用uninstall去做;当然我们也可以自己写脚本去做,脚本的思路就是遍历所有进程,去判断进程特定范围位置是否存在被打的特殊标记,然后去执行清除终止操作即可;
4、unhook所有被打标注入的进程,这里和3同理;
0x06 代办
刨析下火绒剑其内部是如何遍历文件夹的,是否是自带驱动(记得之前的火绒剑是带了一个sys文件的,应该是加载驱动,笔者一般用的都是一体包),为什么没有使用ntdll里面的NtQueryDirectoryFile/Ex的;