搜索内存检测进程的原理
1) 问题的提出——进程检测
Rootkit等后门为了在系统中长期驻留,需要隐藏相应的信息。这些信息包括自启动项、文件、进程、模块、端口、注册表、服务等。其中,以进程隐藏特别突出(因为用户经常会打开任务管理器看看是不是有异常的进程在自己的机器上运行)。
隐藏进程的方法有多种,例如挂钩NtQuerySystemInformation函数;从内核EPROCESS结构的ActiveProcessLinks等双向链表上摘除自身;从csrss.exe进程的句柄表上摘除自身;从PspCidTable上摘除自身等等。如果Rootkit用到了其中的某种方法,那么基于此的检测将会失败。比如,hxdef100(黑客守护者)挂钩NtQuerySystemInformation实现隐藏,如果想通过NtQuerySystemInformation函数来获取全部进程信息就会失败。再比如,FU_rootkit通过从内核EPROCESS结构的ActiveProcessLinks双向链表上摘除自身实现隐藏,如果想通过遍历该链表来检测隐藏的FU_rootkit就会失败。现在问题来了,如果上面隐藏进程的方法都用到了,该怎么检测呢?
2)解决的思路之一——搜索内存
在Windows系统中,进程由内存空间、进程打开的各种对象和进程中运行的线程所组成。线程仅仅是一个执行上下文,系统调度的最基本单位,但每一个线程的运行都必须依附(attach)一个进程。
在Windbg中可以使用dt命令来查看线程ETHREAD的结构,命令格式为“dt _ETHREAD 线程地址”。例如:
kd> dt _ETHREAD 8238F3B8
nt!_ETHREAD
+0x000 Tcb              : _KTHREAD
+0x1c0 CreateTime       : _LARGE_INTEGER 0xe4d5cd5`36b71830
……
+0x21c DeviceToVerify   : (null)
+0x220 ThreadsProcess   : 0x8234f718 _EPROCESS
+0x224 StartAddress     : 0x7c810867
+0x228 Win32StartAddress : 0x010027f2
……
+0x254 ForwardClusterOnly : 0 ''
+0x255 DisablePageFaultClustering : 0 ''
在线程控制块的偏移0x220处是一个ThreadsProcess指针,指向一个EPROCESS结构,即一个进程EPROCESS。
在Windbg中可以使用“!process”命令来查看进程的线程摘要,命令格式为“!process 进程地址
3”。我们看看上面显示的地址0x8234f718对应进程的线程摘要信息。
kd> !process 0x8234f718 3
PROCESS 8234f718  SessionId: 0  Cid: 05bc    Peb: 7ffd6000  ParentCid: 0424
DirBase: 07a00280  ObjectTable: e1975848  HandleCount:  38.
Image: wscntfy.exe
……
BasePriority       8
CommitCharge     164
THREAD 8238f3b8  Cid 05bc.05c4  Teb: 7ffdf000 Win32Thread: e1d88da8 WAIT:
(UserRequest) UserMode Non-Alertable
8258cef8  SynchronizationEvent
8259b7b8  SynchronizationEvent
从命令输出可以看出该进程名为wscntfy.exe,有一个线程地址为8238f3b8,这个地址就是最开始的那个线程控制块的地址。
现在思路有了,既然每一个线程都要依附一个进程,每一个线程控制块中有一个指向该进程的进程控制块的指针,那么,我们就可以通过搜索系统中所有线程得到所有进程。
搜索内存检测进程的具体实现
1) 问题
问题1,如何判断一个内存块是线程的ETHREAD结构?
Windows系统中存在两个系统描述符表,一个是KeServiceDescriptorTable,一个是KeServiceDescriptorTableShadow。两个系统描述符表中的KeServiceDescriptorTable描述系统基本服务,我们称之为主表;KeServiceDescriptorTableShadow除了描述系统基本服务之外,还描述GUI和USER服务,我们称之为副表。每个线程都有自己指向系统服务描述符表的指针,这个指针指向两个系统描述符表中的任意一个。线程ETHREAD偏移为0的位置是一个KTHREAD结构,这个结构的偏移0x0e0处就是这样一个指向系统描述符表的32位指针ServiceTable。
kd> dt _KTHREAD
nt!_KTHREAD
+0x000 Header           : _DISPATCHER_HEADER
+0x010 MutantListHead   : _LIST_ENTRY
……
+0x0df InitialNode      : UChar
+0x0e0 ServiceTable     : Ptr32 Void
+0x0e4 Queue            : Ptr32 _KQUEUE
……
+0x1bb DisableBoost     : Uchar
假定我们读取地址Addr的信息,如果Addr偏移0x0e0处的内容是系统服务调度表的地址,就可以初步判定这个Addr很有可能就是一个线程ETHREAD的入口。
问题2,如何获得系统服务调度表的地址?
任何一个系统的系统服务描述符表在系统运行时是不会改变的,而且从前面的分析可以看出,这个表的位置线程是知道的,这样线程在运行时才能成功找到自己要调用的服务。
可是不同版本的Windows系统的描述符表地址并不一样,同一版本的各个系统上描述符表的地址也不一样,因此最好能够有一种动态获得系统描述符表地址的方法。
基于前面对于主表和副表的分析,找到一个需要系统基本服务和GUI/USER服务的进程,获取其所有线程中的ServiceTable内容,就可以得到系统描述符表的地址。而通过这种方法得到的地址是在程序运行过程中动态获取的,可以满足我们的需求。
我们通过遍历EPROCESS中偏移0x088
处的ActiveProcessLinks来找到拟采用的进程,比如explorer.exe(偏移0x174处为ImageFileName,映像名称)。
kd> dt _EPROCESS 81405560
nt!_EPROCESS
+0x000 Pcb              : _KPROCESS
……
+0x084 UniqueProcessId  : 0x000005fc
+0x088 ActiveProcessLinks : _LIST_ENTRY [ 0x815c0c98 - 0x815a6b00 ]
……
+0x170 Session          : 0xf9ebc000
+0x174 ImageFileName    : [16]  "explorer.exe"
+0x184 JobLinks         : _LIST_ENTRY [ 0x0 - 0x0 ]
+0x18c LockedPagesList  : (null)
+0x190 ThreadListHead   : _LIST_ENTRY [ 0x81405424 - 0x813adadc ]
+0x198 SecurityPort     : (null)
……
+0x255 WorkingSetAcquiredUnsafe : 0 ''
+0x258 Cookie           : 0x70f74bdb
在找到这个进程之后,我们接着要遍历它所有的线程,以获取我们需要的系统服务描述符表的地址。EPROCESS结构偏移0x190
处的ThreadListHead是一个类型为_LIST_ENTRY的双向链表,通过它可以得到线程链表的头。
kd> dt _ETHREAD
nt!_ETHREAD
+0x000 Tcb              : _KTHREAD
……
+0x220 ThreadsProcess   : Ptr32 _EPROCESS
+0x224 StartAddress     : Ptr32 Void
+0x228 Win32StartAddress : Ptr32 Void
+0x228 LpcReceivedMessageId : Uint4B
+0x22c ThreadListEntry  : _LIST_ENTRY
+0x234 RundownProtect   : _EX_RUNDOWN_REF
……
+0x254 ForwardClusterOnly : UChar
+0x255 DisablePageFaultClustering : UChar
而线程ETHREAD结构的偏移0x22c处也是这样一个双向链表,通过它可以遍历所有线程。问题好像已经解决了,地址“EPROCESS+0x190-0x22c+0x0e0”中的内容即是ServiceTable,亦即系统描述符表的地址,其中0x190是ThreadListHead相对EPROCESS的偏移,0x22c是ThreadListEntry相对ETHREAD的偏移,0x0e0是ServiceTable相对ETHREAD的偏移。
图1给出了系统中EPROCESS和ETHREAD结构的关系,我们可以从这个图中看出上面所描述的过程(注:ServiceTable在Tcb结构中,为了使结构清晰明了,图1没有给出)。
 
图1 EPROCESS结构与ETHREAD结构的关系
问题3,如何获取系统中所有进程的EPROCESS结构?
通过图1我们可以看出,在内存中搜索线程之后,通过EPROCESS与ETHREAD的关系,可以得到线程依附的进程。“ETHREAD+
ThreadsProcess”中即是EPROCESS的地址,其中“ETHREAD”为线程ETHREAD结构的地址,“ThreadsProcess”为ThreadsProcess指针相对ETHREAD的偏移量。获得EPROCESS地址,便对应上了进程。一个线程会依附一个进程,而一个进程则可以对应多个线程。用这个方法会得到很多重复的进程地址,我们只需要把重复部分删除即可。
2)实现
获取系统服务描述符表的部分代码如下,通过遍历,能够获得两个描述符表的地址。
currlist=currlist->Flink;
ssdt=*(PULONG)((ULONG)currlist-ThreadListEntry+ServiceTable);
if(s[0]==0)
s[0]=ssdt;
else
{
if((s[1]==0)&&(s[0]!=ssdt))
s[1]=ssdt;
}
if((s[0]!=0)&&(s[1]!=0))
break;
count++;
采用链表的形式记录所有进程EPROCESS结构地址的部分代码如下,需要在内核中申请非分页的地址空间。
{
if((r=(process *)ExAllocatePool(NonPagedPool,sizeof(process)))==NULL)
{
return;
}
p->next=r;
r->addr=EPROCaddr;
r->next=NULL;
p=r;
}
具体细节的补充说明
我所给出的基本结构和原理是Windows NT架构下所有系统都采用的,因而在其他系统下这个方法依然可以实现进程检测。但由于在Winodws
2000/XP/2003下相关数据结构有一定的差别,所以在其他系统下需要对相应系统数据偏移量等值进行修改。我所给出的驱动程序在Windows XP
SP2下由Windows DDK编译,可以使用rootkit.com提供的InstDrv进行加载,使用Dbgview查看运行结果,在Windows XP
SP2下测试通过,可以成功检测FU_rootkit、hxdef100(黑客守护者)和FUTo_enhanced隐藏的进程。
目前给出的方法具有一定的不准确性。比如内核空间地址范围,线程、进程的判定,系统服务描述符表的获取等都具有一定的局限性,这些都会影响检测的准确性。虽然目前的测试结果都是准确的,但是一种从方法上能够确保准确的思路是以后努力的方向。

基于内存搜索的进程检测方法相关推荐

  1. linux跟踪内存检测原理,wooyun/Linux下基于内存分析的Rootkit检测方法.html at master · exitmsconfig/wooyun · GitHub...

    Linux下基于内存分析的Rootkit检测方法 - 路人甲 原文地址:http://drops.wooyun.org/tips/4731 0x00 引言 某Linux服务器发现异常现象如下图,确定被 ...

  2. linux下基于内存分析的rootkit检测方法

    0x00 引言 某Linux服务器发现异常现象如下图,确定被植入Rootkit,但运维人员使用常规Rootkit检测方法无效,对此情况我们还可以做什么? 图1 被植入Rootkit的Linux服务器 ...

  3. 行为检测论文笔记【综述】基于深度学习的行为检测方法综述

    摘 要: 行为检测在自动驾驶.视频监控等领域的广阔应用前景使其成为了视频分析的研究热点.近年来,基于深度学习的方法在行为检测领域取得了巨大的进展,引起了国内外研究者的关注,对这些方法进行了全面的梳理和 ...

  4. 基于机器视觉的路面裂缝检测方法研究与实现

    基于MATLAB的路面裂缝检测系统[过程图,源码] 课题背景 裂缝是最常见的路面损坏,可能会危及公路和高速公路的安全.在路面裂缝变的更糟糕之前及时进行修补,可以大大节省路面维修的资金.路面裂缝是评估道 ...

  5. 基于视角特征提取的3D检测方法汇总

    作者丨柒柒@知乎 来源丨https://zhuanlan.zhihu.com/p/458068647 编辑丨3D视觉工坊 这篇文章主要是梳理一下近期3D Detection的进展,分类列举出一些我认为 ...

  6. 基于深度学习的目标检测方法综述

    引言 现有的深度学习的目标检测方法,可以大致分为两类:一.基于候选区域的目标检测方法:二.基于回归的目标检测方法.依据方法的提出时间,可以构建出如下时间线: 2014 CVPR R-CNN[1] 20 ...

  7. LNG:首个基于图的对抗样本检测方法

    关注公众号,发现CV技术之美 Adversarial Example Detection Using Latent Neighborhood Graph 论文链接:  https://openacce ...

  8. 皮带撕裂检测matlab,基于机器视觉的皮带纵向撕裂检测方法

    基于机器视觉的皮带纵向撕裂检测方法 [技术领域] [0001] 本发明设及一种带式输送机皮带纵向撕裂检测方法,尤其设及一种基于机器视觉 的非接触式的皮带纵向撕裂检测方法. [背景技术] [0002] ...

  9. 基于深度学习的表面缺陷检测方法综述-论文阅读笔记

    //2022.3.2日阅读笔记 原文链接:基于深度学习的表面缺陷检测方法综述 (aas.net.cn) 个人对本篇综述内容的大致概括 论文首先介绍了表面缺陷检测中不同场景下的成像方案,主要根据表面颜色 ...

最新文章

  1. 前端机器学习:识别人脸,并在脸颊上画草莓
  2. Spring Cloud开发实践 - 04 - Docker部署
  3. scala for循环
  4. 在ADF 12.2.1.3中使用基于JSON的REST Web服务
  5. 使用Spring Rest和Spring Data JPA和H2以及Spring Boot示例的Restful API
  6. 怎么评价两组数据是否接近_接近组数据(组间)
  7. 加州理工学院对高超声速飞行的早期研究
  8. [常微分方程]Lecture 2: 欧拉数值方法及推广
  9. LAMP源码安装配置实战
  10. C语言程序设计基础篇
  11. mybatis实战之拦截器
  12. 中国各行各业的祖师爷是谁?
  13. 北京邮电大学计算机学院考研调剂,北京邮电大学计算机学院2020考研调剂缺额信息...
  14. nginx安装三大的命令的解释./configure make make install
  15. 微积分基础-极限,导数,反导数
  16. 微信小程序怎么安装使用WeUI组件
  17. 连接池的原理以及分析
  18. 给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。
  19. 计算机操作员初级试题及答案,计算机操作员初级试题及答案.doc
  20. [题解]LuoGu2698: [USACO12MAR]花盆Flowerpot

热门文章

  1. 美国科技大佬们最爱看的书
  2. 面试说了这几句话,offer铁定无望!
  3. openwrt c语言配置文件,OpenWrt学习笔记7 -- 让人类重建巴别塔的UCI之UCI配置文件
  4. 加密数据储存工具:Keychain 介绍与使用
  5. 豆瓣电台歌曲链接信息
  6. 大学生电子设计大赛最全资料
  7. js将多文件打包成zip下载
  8. 桂林游记, 终于完成了,
  9. (PAT)BasiclLevel_c++ #1003 我要通过!(演绎法)
  10. Clickhouse 时区