CMD命令执行记录调查方法研究
罗文华
中国刑事警察学院计算机犯罪侦查系,沈阳 110854

作者简介:罗文华(1977— ),男,辽宁沈阳人,副教授,硕士,主要从事计算机犯罪侦查和电子数据取证等方面的研究。E-mail:luowenhua770404@126.com

摘要

作为计算机犯罪侦查中重要的证据与线索来源,CMD命令执行记录在揭示犯罪分子行为细节方面发挥着重要作用。本文在详细分析CMD命令执行记录于内存中的数据存储结构基础上,着重说明基于Windows操作系统内存转储文件的历史记录重建方法,并对过程中涉及到的具体技术与注意事项予以阐述。

关键词: 命令提示符; 数据结构; 虚拟地址; 物理地址; DOSKEY
中图分类号:DF793.2 文献标志码:A 文章编号:1008-3650(2013)01-0031-04
Research on the Method of CMD executed record investigation
LUO Wen-hua
China Criminal Police college, Shenyang 110854, China
Abstract

In this paper, the data structure of CMD record executed in RAM was analyzed and the reconstruct method of history record based on dump file in Windows was introduced.

Keyword: command prompt; data structure; virtual address; physical address; DOSKEY

在电脑安全或计算机犯罪事件中, 入侵者或犯罪分子往往倾向于使用Windows操作系统提供的“ 命令提示符” (cmd.exe)功能运行其预先准备的可执行程序, 以达到提升权限进而窃取信息的目的。此种情况下, CMD命令执行记录中往往会包含有诸如可执行文件名称及参数、被访问的文件与文件夹、IP地址及域名等重要信息。因此, 针对CMD命令执行记录的调查能够进一步揭示被入侵系统中所发生的事件, 对电子数据取证工作有着重要而积极的意义[1]

在Windows系统环境下, 可以使用“ DOSKEY” 命令显示CMD命令执行记录。遗憾的是, 这种方法只适用于“ 命令提示符” 窗口开启状态下。一旦窗口关闭, “ DOSKEY” 命令便无法显示命令执行记录, 但内存中却可能依然保留有部分或全部的命令信息。本文从“ DOSKEY” 命令存储信息所使用的数据结构入手, 揭示命令执行记录内存存储的一般性规律, 并对所涉及的地址转换技术予以详细阐述。

1 利用“ DOSKEY” 命令获取CMD命令执行记录

调查人员可以使用“ DOSKEY /history” 命令显示“ 命令提示符” 窗口中所键入执行的命令(无论是否执行成功)。如果连续键入执行同一命令, DOSKEY则会将其合并为一条记录予以显示。单击F7键还会弹出如图1所示的命令选择窗口[2], 通过UP与DOWN键可以实现命令的选择。缺省情况下, “ DOSKEY” 至多可以显示最近键入执行的50(0x32)条命令记录。但可通过修改“ HKEY_CURRENT_USER\Console\HistoryBufferSize” 注册表键值, 扩大缓冲区, 使显示的记录条数增多。“ DOSKEY” 命令存储的命令记录完全存在于内存中, 一旦关闭“ 命令提示符” 窗口便无法再通过该命令查找历史记录。

图1 “ DOSKEY/history” 命令与F7键的执行结果

2 CMD命令执行记录调查方法
2.1 内存中的CMD命令执行记录存储结构

通过对已知执行命令的调查实验发现, 命令信息以Unicode格式存储在内存中。从图2可以看出, “ DOSKEY” 以Unicode格式存储命令“ win32dd /d /f 20111218.dmp” , 该命令包含有26个字符(含空格), 需要占用52(0x0034)个字节的空间。0x26ED9FC8起始的内存空间首先存储该命令所占用的字节数0x0034(Little-Endian, 低字节序), 后紧跟具体命令信息。需要指出的是, 该信息并未出现在“ 命令提示符” 进程cmd.exe的内存地址空间中, 而是存在于csrss.exe(Client/Server Runtime Server Subsystem, 客户端/服务端运行时服务子系统)进程空间中。

图2 内存中的具体命令信息

更多的实验揭示出csrss.exe进程空间中还有一专门的数据结构(见图3)用于记录命令执行历史(本文将其命名为CommandHistory)[3]。其中RecordCount表示该结构所包含的命令记录数目, 取值范围为0至HistoryBufferSize; endOffset表示最近一次键入的命令在该结构中的序号; pointerIndex表示当用户使用UP或DOWN键进行命令选择时所选中命令的序号, 默认情况下与endOffset等值; startOffset表示最先键入的命令在该结构中的序号, 通常为0; HistoryBufferSize代表该结构所能存储的最多命令记录数目, 默认为50(0x32), 但该值可以通过修改“ HKEY_CURRENT_USER\Console\HistoryBufferSize” 注册表键进行设置。从偏移0x18开始即存放虚拟地址指针, 每个指针占4个字节, 指向图2所示的具体命令信息。

图3 CMD命令执行记录数据结构

2.2 虚拟地址与物理地址转化

“ 2.1” 节所述数据结构存储的是指向具体命令的虚拟地址指针, 若要找出真正的执行命令信息还需将虚拟地址映射为物理地址[4]。Windows操作系统在加载每个进程的时候都要为该进程分配内存, 而内存管理则通过页目录、页表和页目录指针表等数据结构实现。首先, 为每个进程分配一个页目录; 所谓页目录是指用来存放页目录表项(Page-Drectory Entry, 简称PDE)的线性表; 每个进程的进程环境块(Process Environment Block, 简称PEB)中会记录该进程页目录的地址; 在进程切换时, 该地址会传递给CPU的CR3寄存器以便CPU进行地址转换。每个页目录最多含有1024个PDE记录, 因此将虚拟地址转化为线性地址后, 通过CR3寄存器定位到页目录的起始地址, 截取线性地址的高10位作为索引, 即可选定页目录中的表项(即PDE)。

每个PDE的长度为32个比特位, 其高20位代表该PDE所指向页表的起始物理地址的高20位。页表是用来存放页表表项(Page-Table Entry, 简称PTE)的数据结构。截取线性地址第12位到第21位(共10位), 作为索引可选定页表中的特定表项(即PTE)。

每个PTE的长度也为32个比特位, 其高20位代表4KB内存页起始物理地址的高20位; 取出PTE中内存页基地址(低12位设置为0); 截取线性地址的低12位作为页内偏移与内存页基地址相加便可得到物理地址。图4所示即为将线性地址映射为物理地址的过程[5]

图4 将线性地址映射为物理地址

上述转换过程主要针对页面大小为4KB的分页机制。对于大页面机制(如4MB), 则PDE记录的高10位即为内存页起始物理地址的高10位, 该起始物理地址的低22位固定为0, 不需要使用页表。而在系统启用物理地址扩展(Physical Address Extension, 简称PAE)的情况下, 则需要使用页目录指针表(Page-Directory-Pointer Table, 简称PDPT)。启用PAE后, 每个PDE和PTE的长度都增大为64位。PDPT则对应包含4个64位的表项, 每个表项用于指向一个页目录。

2.3 调查分析实例

依据“ 2.1” 节所述规律, 在扩展名为dmp的内存转储文件中, 利用通配符搜索到指向数据结构CommandHistory。从图5可以看出, 0x5D6DAD58起始的内存空间存储着0x0003(低字节序, 下同), 表示该数据结构所包含的记录数目为3; 紧接着的0x0002表示最近一次键入的命令在该数据结构中的序号为2; 接下来0x0002代表当前被选中的命令记录序号也为2; 后接0x0000表示最先键入的命令在该数据结构中的序号为0; 0x0032则代表该数据结构所能存储的最多命令记录数目为50(0x32)。从0x5D6DAD70处即开始存放指向具体命令的虚拟地址指针, 每个占4个字节, 图5标记出的0x06150f20即为最先键入命令(即第0号记录)的虚拟地址。

图5 指向具体执行命令的虚拟地址指针

根据“ 2.2” 节所述步骤, 虚拟地址转换需要首先获取页目录起始地址。因为命令执行记录存放在csrss进程空间中, 因此需要获取csrss(而不是cmd.exe)进程的页目录起始地址。启动WinDBG, 在WinDBG的命令区通过“ !process” 命令, 得到如图6所示的执行结果。其中DirBase的值10f60000即为所需的该进程页目录起始地址。同时可得PROCESS值为876ed788。

图6 获取csrss.exe进程的页目录起始地址

切换至csrss.exe进程领空后, 查看寄存器信息。从图7可以看出CS寄存器值为0008, DS寄存器值为0023。继续查看代码段与数据段基地址信息, 获知其基地址均为0(Base值域)。因此虚拟地址即为线性地址, 使用分页地址转换机制即可将虚拟地址转换为物理地址(无需考虑分段机制)。

图7 获取代码段与数据段基地址信息

将虚拟地址0x06150f20分解为线性地址00000110 00010101 00001111 00100000(见图8)。按照“ 2.2” 节所述的线性地址组成, 将其分割为10-10-12的形式, 得到如下信息:页表项偏移0000011000(0x18), 即第24项; 页表偏移0101010000, 即0x150; 页内偏移111100100000, 即0xf20。

图8 将虚拟地址转化为线性地址

读取具体页目录信息。因为线性地址的页表项偏移为0x18, 对应第24项, 即20507000 (页表项的高20位代表页表地址, 低12位则为属性位); 页表地址20507000代表所需页表的起始地址, 从该地址开始的每一项(4个字节)即对应一内存物理页, 因此该起始地址加上页表偏移(0x150* 4), 即可得到所需内存物理页。从图9可以看出0x20507540处存储的0x62354867的高20位0x62354000即为物理页的真实地址(页地址的低12位为属性位)。最后将物理页真实地址加上页内偏移(0xf20), 即得物理地址。使用“ !du” 命令即可查看0x62354f20处所存放的具体执行命令信息“ cd..” (见图9)。

图9 最终得到具体命令信息“ cd..”

在启用PAE机制后, 32位线性地址则被分割为如下四个部分:第30至第31位(共2位), 页目录指针表索引, 用于索引本地址在页目录指针表中的对应表项; 第21至第29位(共9位), 页目录表索引, 用于索引本地址在页目录表中的对应表项; 第12至第20位(共9位), 页表索引, 用于索引本地址在页表中的对应表项; 第0位至第11位(共12位), 页内偏移。具体映射步骤与未启用PAE情况类似, 在此不再赘述。

3 针对调查研究的补充实验

更多的补充实验表明, 在开启多个“ 命令提示符” 窗口的情况下, 内存也会相应开辟多个独立空间对象以存放命令执行记录[6]。即使“ 命令提示符” 窗口关闭, 使用“ 2.1” 节所述规律, 依然可以定位到各自的数据结构CommandHistory。另外, 窗口未关闭时寻找到的命令信息均是完整的。窗口关闭情况下, 则可能有部分信息被覆盖。情况之一是CommandHistory中的虚拟地址信息不完整, 或是具体命令信息中所占字节数或命令信息缺失。

另外, 相对于“ DOSKEY /history” 命令用来查看执行命令历史, “ DOSKEY /reinstall” 命令功能则是重新安装doskey, 清除命令历史缓冲区。实验表明, 一旦“ 命令提示符” 窗口执行“ DOSKEY /reinstall” , 利用“ 2.1” 节所述规律将无法有效定位命令执行记录数据结构[7]。因为执行“ DOSKEY / reinstall” 后, 原数据结构CommandHistory中的元素会被初始化为如图10所示的数据; 同时虚拟地址指针信息也会发生一定的改变。

图10 “ DOSKEY / reinstall” 命令会重新初始化数据结构中的元素

利用“ DOSKEY [宏命令名]=[命令名]” 可以将具体命令定义为宏, 执行宏命令即相当于执行对应命令, 以达到提高效率的目的。实验表明, 用于定义宏的命令信息同样以2.1节所述格式保存在内存中。图11所示即为利用“ doskey di=dir /w /p” 将命令“ dir /w /p” 定义为宏“ di” , 并紧接着执行该宏。因此, 在具体调查时, 如遇未知命令, 可通过研究之前键入的执行记录, 确认其是否为宏, 以获得更为深入的执行命令信息。

图11 利用“ DOSKEY” 命令定义的宏

4 讨 论

在计算机法庭科学技术蓬勃发展的今天, 数据加密、数据隐藏、数据擦除等诸多手段往往使针对磁盘的调查取证工作效果大打折扣[8]。因此, 内存信息调查分析研究业已成为电子数据取证领域的新热点。本文阐述的CMD命令执行记录调查方法即是针对内存信息分析研究的重要实例之一, 文中重点分析对象是Windows操作系统内存转储(DUMP)文件, DD(已升级到Windows和Linux环境下均可使用)、ProDiscover IR、Mantech mdd、Win32dd、Mandiant Memoryze、Moonsols DumpIt等多种工具均生成该格式文件。内存实验室取证工具Volatility framework提供有“ cmd_history.py” 插件, 号称能够获取CMD命令执行记录信息。但在实际中发现, 该插件所分析出的命令记录前后存在有大量的冗余信息, 很难将具体命令剥离整理出来。可见实际工作中不可过分依赖工具的使用, 特殊情况下还是需要在深入研究的基础上手工进行分析。本文内容虽然主要针对Windows XP Service Pack 3版本, 但其所述研究方法与分析步骤对Windows 7等后续版本仍具有积极意义。“ 2.1” 节分析得出了CommandHistory数据结构中绝大部分元素含义, 但仍有一部分元素(如偏移0x10和0x14处存储的信息)含义仍有待于进一步分析挖掘。文中描述的是内存信息的人工调查方法, 如何实现分析过程自动化, 进而形成针对内存对象的功能全面且行之有效的调查工具, 也将是未来电子数据取证领域的主要研究方向。

The authors have declared that no competing interests exist.

参考文献
[1] Carvey H. Windows forensic analysis[M]. US: Syngress, 2008: 134-156. [本文引用:1]
[2] Hill T. http://technet.microsoft.com/enus/library/cc750982.aspx#XSLTsection126121120120, 1998, 5. [本文引用:1]
[3] Richard M. Stevens, Eoghan Casey. Extracting Windows command line details from physical memory[J]. Digital Investigation, 2010, 5(8): 57-63. [本文引用:1]
[4] Russinovich MR, Solomon DA. Microsoft windows Internals: Microsoft windows server 2003, windows, and windows 2000(4th ed)[M]. USA: Microsoft Press, 2005: 53-55. [本文引用:1]
[5] 张银奎. 软件调试[M]. 北京: 电子工业出版社, 2008: 55-62. [本文引用:1]
[6] NISThttp://www.cfreds.nist.gov/mem/Basic_Memory_Images.html,2009. [本文引用:1]
[7] Forensics Rodeo. http://dfrws.org/2008/rodeo.shtml,2008. [本文引用:1]
[8] Aqulina JM, Casey E, Malin CH. Malware forensics: investigating and analyzing Malicious Code[M]. USA: Syngress Publishing, 2008: 60-63. [本文引用:1]