计算机技术的迅速发展,为违法犯罪分子提供了新的作案平台和犯罪手段,特别是随着加密技术和无痕技术的普及,传统的电子取证手段面临巨大挑战,有些如已被删除、加密或破坏的有价值电子证据获取起来的难度加大。内存取证技术的发展在一定程度上弥补了传统的离线取证技术的不足,通过内存镜像的分析,调阅当前正在内存中运行的进程、所有载入模块和DLL库以及运行中的设备驱动程序发现各种潜在问题,如设备驱动中是否附着恶意驱动设置底层钩子程序、DLL库是否劫持等。
本文将重点讲述内存中运行的进程取证分析技术,通过分析进程结构体以识别各种可能的恶意行为,分析对象包括进程标准句柄以及引用的动态链接库等,以攻击者的典型攻击手法为例,分析如何从目标主机的异常行为表现中发现问题,并提取有效证据。
Windows系统进程取证基础
在Windows系统中,每个进程都用一个EProcess(ExecutiveProcess)结构来表示,它包含进程的可执行文件全路径、启动进程的命令行、当前工作目录、进程堆指针、进程标准句柄以及指向进程相关的其他属性和数据结构的指针。由于数据结构就是字节序列,序列中有特殊的含义和目的,所以需要调查人员对其进行分析。EProcess结构中最重要的一个成员是指向进程环境块(PEB)的指针。进程环境块中包含大量的信息,对取证比较重要的信息有:
(1)BeingDebugged:进程调试标志,判断当前进程是否处于被调试状态,一些病毒程序、安全软件常使用此标志保护自己被反调试。
(2)指向PPEB_LDR_DATA结构(其中存放的是进程的加载器使用的数据)的指针,PPEB_LDR_DATA结构中包含进程中使用的动态链接库的指针。
(3)指向可执行文件镜像加载基地址(ImageBaseAddress,在PEB偏移0x008处)的指针,通过这个指针可以找到内存中可执行文件的起始位置。
(4)指向包含进程参数结构(ProcessParameters,在PEB偏移0x010处)的指针,该结构包含进程中加载的动态链接库的路径、可执行文件镜像的原始路径以及创建进程时传递进来的参数等信息。
通过windbg调试工具,使用dt命令可以查看ProcessParameters结构体
_RTL_PROCESS_PARAMETERS的详细内容: dt(_RTL_USER_PROCESS_PARAMETERS) _RTL_USER_PROCESS_PARAMETERS(1024bytes) ….. 0x20 0x28 0x30 0x38 0x50 0x60 :StandardInput :StandardOutput :StandardError :CurrentDirectory :DllPath [pointer64,[void]]//进程标准输入句柄 [pointer64,[void]]//进程标准输出句柄 [pointer64,[void]]//进程标准错误句柄 [_CURDIR] //应用程序的当前工作目录 [_UNICODE_STRING] :ImagePathName [_UNICODE_STRING]//进程exe文件在磁盘目录上的全路径名(以unicode形式编码) 0x70 0x80 ….. :CommandLine :Environment [_UNICODE_STRING] [pointer64,[void]]
进程句柄取证分析
通过分析进程标准句柄列表,可以确定进程的输入输出值以及报错信息等。这些信息值在分析取证系统是否遭受远程攻击时,具有一定的参考价值。例如,分析系统是否遭受远程后门shell攻击等。攻击者惯用的伎俩,即创建一个shell后门命令,重定向进程句柄至命名管道或网络套接字,使得攻击者通过telnet或netcat命令随时与目标机建立连接。相关代码如下所示:
_RTL_PROCESS_PARAMETERS的详细内容: dt(_RTL_USER_PROCESS_PARAMETERS) _RTL_USER_PROCESS_PARAMETERS(1024bytes) ….. 0x20 0x28 0x30 0x38 0x50 0x60 :StandardInput :StandardOutput :StandardError :CurrentDirectory :DllPath [pointer64,[void]]//进程标准输入句柄 [pointer64,[void]]//进程标准输出句柄 [pointer64,[void]]//进程标准错误句柄 [_CURDIR] //应用程序的当前工作目录 [_UNICODE_STRING] :ImagePathName [_UNICODE_STRING]//进程exe文件在磁盘目录上的全路径名(以unicode形式编码) 0x70 0x80 ….. :CommandLine :Environment [_UNICODE_STRING] [pointer64,[void]]
上述程序主要功能是以本地为服务端,创建一个套接字,实时监听端口31337消息。一旦接到对方的连接请求,会自动调用accept函数接收消息,并返回客户端套接字mySock;然后启用标准消息块_STRANDARD_INFORMATION中的STARTF_USETDHANDLES变量,重定向hStdError,hStdInput和hStdOutput至客户端套接字mySock上,并创建子进程cmd.exe,设置bInheritHandles变量为TRUE使得子进程可继承父类句柄。上述步骤完成后,攻击者通过cmd.exe键入的任何命令,都会通过网络传输到受控主机,并自动在受控主机中按照攻击者意愿执行相关命令,如搜索文件并自动将搜索结果以文本方式回传等。
在调查分析受控主机时,在查看当前正在运行的进程列表,发现cmd.exe已被启用时,若取证分析员具有一定的敏锐性,可能会进一步分析cmd.exe的标注输入句柄,确定进程被启用的目的,如是否存在后门活动等;不然,可能会因此忽视一个重大的发现。具体的分析步骤如下:
(1)查看目标主机cmd.exe所有进程实例的标准输入输出及错误信息。
_RTL_PROCESS_PARAMETERS的详细内容: dt(_RTL_USER_PROCESS_PARAMETERS) _RTL_USER_PROCESS_PARAMETERS(1024bytes) ….. 0x20 0x28 0x30 0x38 0x50 0x60 :StandardInput :StandardOutput :StandardError :CurrentDirectory :DllPath [pointer64,[void]]//进程标准输入句柄 [pointer64,[void]]//进程标准输出句柄 [pointer64,[void]]//进程标准错误句柄 [_CURDIR] //应用程序的当前工作目录 [_UNICODE_STRING] :ImagePathName [_UNICODE_STRING]//进程exe文件在磁盘目录上的全路径名(以unicode形式编码) 0x70 0x80 ….. :CommandLine :Environment [_UNICODE_STRING] [pointer64,[void]]
从上面给出的信息,可以看出cmd.exe有三个实例进程在运行,进程ID为2160的输入输出和错误句柄消息均相同。初步判断0x68可能被重定位到一个命名管道或者网络套接字。
(2)进一步定位进程ID号为2160的进程,以查看句柄值0x68详请。
$pythonvol.py-fmemory.dmp--profile=Win7SP1x64handles-p2160-tFile VolatilityFoundationVolatilityFramework2.4 Offset(V) Pid Handle Type Details ------------------------------------------------ 0xfffffa80015c4070 2160 0xcFile \Device\HarddiskVolume1\Users\Elliot\Desktop 0xfffffa8002842130 0xfffffa80014f3af0 2160 2160 0x54 0x68 File \Device\Afd\Endpoint \Device\Afd\Endpoint File
由上述内容可知,cmd.exe访问过文件驱动Afd,AFD驱动是Windows一个网络驱动部件,与SOCKET应用接口对接实现SOCKET调用。显然cmd.exe是调用了网络套接字,若发现本地是存在网络连接,基本可以确定系统已被远程后门利用。
(3)通过pstree工具查看进程2160对应的父进程ID号以及父进程网络连接情况。
$pythonvol.py-fmemory.dmp--profile=Win7SP1x64handles-p2160-tFile VolatilityFoundationVolatilityFramework2.4 Offset(V) Pid Handle Type Details ------------------------------------------------ 0xfffffa80015c4070 2160 0xcFile \Device\HarddiskVolume1\Users\Elliot\Desktop 0xfffffa8002842130 0xfffffa80014f3af0 2160 2160 0x54 0x68 File \Device\Afd\Endpoint \Device\Afd\Endpoint File
cmd.exe进程ID2160对应的父进程为ID号1400,进程名memen.exe.父进程通过端口31337与远端地址建立连接。上述例子即通过重定向输入输出句柄,利用子进程cmd.exe以执行远程命令,并将执行结果通过继承的父类进程句柄回传给攻击者。
DLLs隐藏与检测技术
动态链接库是windows系统中的一个共享函数库,可被多个程序共同调用,实现代码重用及程序的模块化开发。但随着技术的不断发展,很多攻击者开始盯上了DLLs,因为它具备运行的天然条件,可以寄宿到目标进程中,并借助目标进程的运行而加载运行。攻击者可以构造恶意的DLLs文件,然后通过各种手段实现DLLs注入,如利用CreateRemoteThread远程建立线程的方式注入DLL、利用HooKs技术注入、利用ring0APC注入DLL等。在DLLs注入盛行的时间里,各种安全检测工具开始利用DLLs双向链表式存储特点遍历进程的所有动态链接库,以识别恶意伪造的DLLs.后期又开始使用断链技术,将三个链表指
针全部断开,以隐藏DLLs.前面基础知识小节,简单描述了PEB结构体中的ldr指针结构体PPEB_LDR_DATA,它包含进程中使用的动态链接库的指针,基地址位于TEB偏移0x30处。PPEB_LDR_DATA结构体成员信息,通过dt命令查看显示如下:
$pythonvol.py-fmemory.dmp--profile=Win7SP1x64handles-p2160-tFile VolatilityFoundationVolatilityFramework2.4 Offset(V) Pid Handle Type Details ------------------------------------------------ 0xfffffa80015c4070 2160 0xcFile \Device\HarddiskVolume1\Users\Elliot\Desktop 0xfffffa8002842130 0xfffffa80014f3af0 2160 2160 0x54 0x68 File \Device\Afd\Endpoint \Device\Afd\Endpoint File
该结构的后三个成员是指向LDR_MODULE链表结构中相应三条双向链表头的指针,分别是按照加载顺序、在内存中地址顺序和初始化顺序排列的模块信息结构的指针。图标结构如图1所示。
图1
由上图可知,通过上述三个指针可以依次遍历到指定进程加载的所有DLLs,同样为了隐藏某个DLL文件,可以断开其中的一个链。为了达到完全隐藏的效果,甚至可采用三个链指针全部断开的方式。
下面将重点介绍隐藏DLLs的检测技术。利用虚拟地址描述符VAD遍历所有DLLs文件。VAD是一棵平衡二叉搜索树,用于管理进程的虚拟内存,其中也包含着一个进程的dll模块信息。对于每个进程而言,_EPROCESS.VadRoot指向VAD树的根节点。通过windbg的dt命令可选择一个进程查看对应的VAD结构体:
$pythonvol.py-fmemory.dmp--profile=Win7SP1x64handles-p2160-tFile VolatilityFoundationVolatilityFramework2.4 Offset(V) Pid Handle Type Details ------------------------------------------------ 0xfffffa80015c4070 2160 0xcFile \Device\HarddiskVolume1\Users\Elliot\Desktop 0xfffffa8002842130 0xfffffa80014f3af0 2160 2160 0x54 0x68 File \Device\Afd\Endpoint \Device\Afd\Endpoint File
其中,0x00c,0c010分别代表该vad节点的左右孩子节点,而0x018则代表其控制区。
$pythonvol.py-fmemory.dmp--profile=Win7SP1x64handles-p2160-tFile VolatilityFoundationVolatilityFramework2.4 Offset(V) Pid Handle Type Details ------------------------------------------------ 0xfffffa80015c4070 2160 0xcFile \Device\HarddiskVolume1\Users\Elliot\Desktop 0xfffffa8002842130 0xfffffa80014f3af0 2160 2160 0x54 0x68 File \Device\Afd\Endpoint \Device\Afd\Endpoint File
结合上述分析,利用平衡二叉树的遍历算法以及DLL文件的偏移量,可搜索遍历进程加载的所有DLLs文件,具体方法可先通过PsLookupProcessByProcessId函数定位到EPROCESS结构体基地址,然后再偏移0x11c找到VadRoot,再逐个根据地址偏移值定位即可。实现代码就不再给出。除了上述方法外,还可以利用PE文件扫描技术,暴力搜索进程内存空间,寻找“MZ”签名的所有PE文件实例。
小结
本文主要描述基于PEB结构体的内存分析取证技术,通过描述进程标准句柄输入输出的重定向及DLLs隐藏技术,拟分析如何结合PEB结构体的内存存储方式,提取上述两种行为留下的痕迹。
(完)