断链隐藏进程及恢复(附代码)
断链隐藏进程及恢复(附代码)
一.前言:
继Strider上次问了我如何隐藏一个进程之后,这周仔细研究了一下,首先去了解了一下隐藏进程的各种方法,其实有很多方法很多也很杂,然后有些隐藏只是能躲过任务管理器还有ntdll里面ZwQuerySystemInformation函数(枚举进程的函数),然后通过一些暴力的枚举方法还是会露馅,就总结一些常见的吧:
1.比较简单的即是内核中映射的进程列表进行断链操作,此处是一个双链表(后文会详细赘述)
2.其次就是修改内核映射中的EPROCESS中对应的pid,也能实现隐藏
3.然后就是对于DriveObject信息的抹除(没看懂,系统学内核了再复现)
而本文也是就第一种方法展开复现,来进行进程的隐藏。
二.踩坑:
首先,我们知道,进程体EPROCESS是被系统维护在一个双向链表LIST_ENTRY中的,那么,我们只要把进程的EPROCESS从这个链表中摘除,就可以实现进程隐藏了,当然,这只能瞒过进程管理器和ntdll中的zwQuerySystemInformation,暴力枚举依旧可以发现断链隐藏的进程,因为进程体还在内存中。
然后开始进行断链操作,借助windbg实现操作,一直在纠结一个问题就是能否在自己的本机上调试本机的内核,然后问了一下鹏哥,确实是可以的,然后就有点踩坑地开始复现了,网上很多关于windbg使用的教学都是老版本的,然后微软好像22年就开始禁用了离线符号包的下载使用了,我在本机上下载了老版本的windbg,在配置符号文件的时候一直卡着过不去。
一开始使用的时候,先附加了需要隐藏的一个进程,输入命令dt _eprocess
,一开始看到了eprocess 的结构,没意识到犯了很严重的错误(后续文章中会讲述)。
直到后面查看内核映射中的进程列表信息的时候才意识到有点蠢,继续输入命令! process 0 0
,开始出现最头疼的报错了
然后一直搜一直搜,搜到了问题是得修复一下ntdll的符号文件,然后这个符号文件一般是可以进行离线下载的,但是按照网上说的设置符号下载位置的方法srv*yourpath*http://msdl.microsoft.com/download/symbols
,设置完成之后我们重启计算机,用windbg 附加一个进程来下载符号,然后还是不太好使!
然后我就搜到了这个。。。
不甘心没有,然后进了上述命令中的http://msdl.microsoft.com/download/symbols地址一探究竟,然后我就放弃了。。。
遇到困难了,由于辉哥这两天比较忙,所以求助了一下鹏哥,由于鹏哥之前是在XP上使用的windbg,然后就得到了鹏哥XP的克隆(真香),同时也得到了一份老版windbg的32位和64位安装包,以及最最重要的符号文件!!!
三.正文开始
1.严重错误剖析
开始在XP上进行实验,正常的安装windbg和下载符号文件(打包成exe太爽了)之后,开始进行调试。
?!woc,换了个方式又报了个错,然后搜了一下,感觉有被自己蠢到,发现了上文中所说的严重错误,体会到了再没熟悉windbg使用就瞎敲命令的下场:
windbg命令分为标准命令(40个左右),元命令(一百多个)和扩展命令。
标准命令提供最基本的调试功能,不区分大小写。如:bp g dt dv k等
元命令提供标准命令没有提供的功能,也内建在调试引擎中,以.开头。如.sympath .reload等
扩展命令用于扩展某一方面的调试功能,实现在动态加载的扩展模块中,以!开头。如!analyze等
每个调试命令都各有使用范围,有些命令只能用于内核调试,有些命令只能用于用户调试,有些命令只能用于活动调试。但用户也不必记得这许多,一旦在某个环境下,使用了不被支持的命令,都会显示“No export XXX found”的字样。就拿!process命令来说吧,它显示进程信息,但只能用于内核调试中,如果在用户调试中使用,就是下面的情景:
1 | 0:001> ! process 0 0 |
所以,在使用windbg进行调试的时候,一定要搞清楚你是在那种模式下进行调试,还是那句老话,在使用之前,你要清楚你自己在干什么。关闭windbg之后,重新启动并切换windbg模式至内核debug
选至本地:
然后你就会惊奇的发现左下角的开头变了:(lkd也算是内核调试的标志了)
输入命令! process 0 0
,即可看到进程列表
2.真正的正文开始
首先我们遇到两个问题:
1.既然要遍历链表,我们就要知道每个结构的前后结构;
2.既然要对比进程名,我们就要知道进程名放在哪个地方;
先查看一手该版本系统下的eporcess结构体中各项数值的偏移量(基于windows的版本不同各有偏差,并不唯一)
输入命令dt _eprocess
,主要查看下图中标记的两处位置的偏移量
(1). ActiveProcessLinks
EPROCESS块中有一个ActiveProcessLinks成员,它是一个PLIST_ENTRY结构的双向链表。当一个新进程建立的时候父进程负责完成EPROCESS块,然后把ActiveProcessLinks链接到一个全局内核变量PsActiveProcessHead链表中。(可以看成双链表中的一个节点地址,而此节点中分别存储的是该进程在链表中的上下进程的指针地址)
紧接着输入命令dt _LIST_ENTRY
,查看LIST_ENTRY的结构
可以看到变量FLink和BLink,FLink指向当前节点的后一个节点的ActiveProcessLinks地址,BLink指向当前结点的前一个节点的ActiveProcessLinks地址,这块儿的两个地址一定别记反,后面即是通过他们来找到锁定进程的上下进程的。
(2).ImageFileName
在上上图中,我们可以看到在偏移0x174处,出现了ImageFileName,这里存的就是我们要找的进程名。
接着再输入一遍命令! process 0 0
,随便选择一个进程,这里选择 vmtoolsd.exe,注意记住它的上下邻接进程
然后查看该进程的eprocess,输入命令dt _eprocess 85f5ab28
,可看出 ActiveProcessLinks 处由两个数值相减,相比他们就是上文中提到的变量FLink和BLink吧,然后反复思考,一个进程的ActiveProcessLinks由两个变量组成,双指针,那尾减去头一定就是本身的地址了。故下图中0x85f42e28应该是BLink,而0x85f34ca0也就是FLink,分别指向当前结点的前后两个节点的ActiveProcessLinks地址。
OK,那么事情已经明了了,进程被映射到内核之中后被列举成了这一串双链表,而我们只需要摘除掉其中的那个目标就行,也就是说需要通过检索到的目标进程之后,通过它的eprocess中的ActiveProcessLinks进而实现断链操作,所以我们现在要做的就是通过ActiveProcessLinks中存储的两个值,访问到应该在进程链表中排与目标进程前后的两个进程的eprocess。
1.按着上图中的例子走,先试着访问一手目标进程后面的进程是啥,输入命令dd 0x85f34ca0
,查看地址0x85f34ca0中的内容
已知0x85f34ca0中存储的是指向目标进程的下一个进程的ActiveProcessLinks信息,再由上文中总结出来的“后减前原则”,故可知
85f3b688中存储的是后一个进程再后一个进程的ActiveProcessLinks,而85f5abb0中存储的是前一个进程(此时也就是我们的目标进程的ActiveProcessLinks),不信可以输入命令dd 0x85f5abb0
进行如下验证:(对照上上图中目标进程的ActiveProcessLinks的值即可)
注意,因为FLink指向当前节点的后一个节点的ActiveProcessLinks地址,所以后一个节点的EPROCESS地址为ActiveProcessLinks地址中的(0x85f34ca0)减去偏移0x88,成功。
2.同理,这块采用比较笨的方法进行运算,因为我对地址偏移的操作还不太那么熟悉,那么我只要拿到了目标进程中指向前一个进程ActiveProcessLinks的地址,然后输入命令dd 0x85f42e28
,再拿出前一个进程中指向再前一个进程的ActiveProcessLinks的地址中的指向后一个进程的FLink,在用这个Flink地址-0x88,故可得到结果:
综上所述,我们已经由已知的目标进程求出了起前后两个进程的eprocess,接下来直接进行断链操作即可,然后实现对于进程的隐藏,贴出大佬的脚本如下:(我还没写过驱动程序,所以脚本的复现还没进行,不过指日可待)
1 |
|