首页
论坛
课程
招聘
[原创]休眠文件那些事儿
2010-11-9 17:34 21928

[原创]休眠文件那些事儿

2010-11-9 17:34
21928
发这份笔记时,比较惶恐,因为连我自己都觉得,这个东西没用。但是事实上,在很多偏门或机密的领域里,它仍然是非常有价值的。鉴于国内这方面资料比较少,所以写了一篇笔记,与大家共享。

Analyze Hibernation File

Introduction
        What’s Hibernation File?
Hibernation File也就是系统的休眠文件Hiberfil.sys,位于系统卷的根目录下。windows在系统休眠时,将物理内存中的数据(包括系统运行时的状态数据)dump到Hiberfil.sys,并生成一个有效的文件头。下次系统开机的时候,利用hiberfil.sys文件中的数据恢复系统。

        How to generate a valid Hiberfil.sys?
从用户的角度来说,系统停机时,按下休眠按钮,则会自动生成一个有效的Hiberfil.sys。
从电源管理器的角度来说,只有当系统电源状态从S0àS4的时候,才会生成一个有效的休眠文件。
注:当系统正常运行时,电源状态为S0;完全关闭时,电源状态S5;休眠状态时,电源状态S4,此时只有电源电路和唤醒电路才有点滴电流;中间的几个状态S1,S2,S3,都是不同程度的睡眠状态。
        从S4àS0的过程,也就是利用Hiberfil.sys恢复系统的过程。

Valuation of Hibernation File
        It is quick and easy
恢复系统比重启系统要快。不解释(除特殊情况)。
        A new method to dump physical memory
        利用hibernation技术dump系统物理内存中的数据。这些数据包括处理器状态,当前EIP, IDT table, GDT table, SSDT table,当前状态的可执行代码和数据…
        利用这些数据可以分析系统状态。

        Leak Information?
        Yes。正常情况下,利用Hiberfil.sys恢复系统,虽然恢复后会清除掉Hiberfil的Header数据(one page),使之无效,但是Header之后的数据还会保留。利用外部工具,构造一个Header,就可以读取该Hiberfil.sys的所有信息了。

        Defensive uses
kernel –land malwares detection
分析hibernation file, 可以通过检查SSDT, IDT, GDT表的完整性来判断系统是否被修改。虽然在内核层有了更为轻量级的方法去检测系统关键表的完整性,但是存在anti对抗问题,hibernation提供了一种终极检测方式。
        根据hibernation恢复原理,不在hibernation file中的代码,将不会被恢复执行。基于此,可以对抗SMM rootkit。(不做介绍)
        Offensive uses
可以获取敏感数据,如:password, keys.
修改hibernation file, 提高某个进程的执行权限;绕过系统登录密码…

Hibernation file internals
        Headline of hibernation process
当磁盘被挂起时(S0àS4),Windows内核(ntoskrnl.exe)执行体创建一个hibernation file,并将物理内存中的数据用LZ77算法压缩后,写入文件。
系统恢复时(S4àS0),OSLoader.exe读取hibernation file,加载解压后的数据到物理内存中,使系统以一种快捷方式恢复到休眠时的状态。
        注:恢复过程的分析,见appendix 1。

        Hibernation file structure
先直观的看下文件结构图:(左侧,域列表,是文件结构的组成域)



File Header
位于休眠文件的第一页(0x1000 bytes)数据空间。该结构PO_MEMORY_IMAGE由内核调试符号导出。结构中主要包含了休眠文件的创建日期,版本号,校验和,有效标志,物理页数量等信息。
注:用休眠文件恢复系统时,只有第一页数据被清0,也就是file header,其他数据保留不变。

FreeMap Page
包含一个ulong数组,保存了空闲内存页的映射信息。

Processor State
处理器状态,由内核函数KiSaveProcessorControlState保存。包括控制寄存器CRX,GDT, IDT, EIP…
结构定义如下:
typedef struct _KPROCESSOR_STATE32
{
    CONTEXT ContextFrame;                                //
    KSPECIAL_REGISTERS SpecialRegisters;        //
} KPROCESSOR_STATE32, *PKPROCESSOR_STATE32;

        注:从vista版本以后,字段2和3的位置就交换过来了。

Memory Range Array
存储物理内存页的压缩数据。
typedef struct _MEMORY_RANGE_ARRAY
{
    MEMORY_RANGE_ARRAY_LINK MemArrayLink;
    MEMORY_RANGE_ARRAY_RANGE MemArrayRange[MAX_ARRAY_ENTRY];
} MEMORY_RANGE_ARRAY, *PMEMORY_RANGE_ARRAY;

字段MemArrayLink作为链接表指针,将多个这样的结构链接维护起来;
字段MemArrayRange指向数据区,最多包含255个入口。这也就是为什么要存在一个指向下一个MEMORY_RANGE_ARRAY结构的指针MemArrayLink,因为当休眠文件很大的时候,一个MEMORY_RANGE_ARRAY存储不了所有数据。

结构MEMORY_RANGE_ARRAY_RANGE定义如下:

typedef struct _MEMORY_RANGE_ARRAY_RANGE
{
    ULONG PageNo;       // ???
    ULONG StartPage;    // Block start (physical address)
    ULONG EndPage;      // Block stop (physical address)
    ULONG CheckSum;     // Always zero, but used under Windows 2000.
} MEMORY_RANGE_ARRAY_RANGE, *PMEMORY_RANGE_ARRAY_RANGE;
指定了页开始地址和页结束地址,在这些地址范围内的数据都是经过压缩算法来压缩后存储的,这个结构所对应的整块数据就是一个压缩块PageCompressedData,压缩快的起始部分是一个结构体,如下:
struct IMAGE_XPRESS_HEADER
{
     CHAR Signature[8] = 81h, 81h, "xpress";
     BYTE UncompressedPages = 15;
     UINT32 CompressedSize;
     BYTE Reserved[19] = 0;
};
也就是说,压缩块的标识是:\x81\x81xpress;之后就是压缩数据了。

        注:每个压缩快所对应的解压后的块大小为64KB(0x10 pages)。
        compression algorithm
This algorithm has been publicly documented since recent Microsoft Interoperability initiative (February 2008)
压缩块算法使用LZ77+DIRECT2;
LZ77用于压缩内存数据,DIRECT2对字节的位置进行编码和解码。

Project and Application
        Sandman Project
该开源项目的主要特点是定义了休眠文件的文件结构,并给出了解析休眠文件的代码。
不过,这份代码中存在问题。在虚拟地址转换成物理地址时,作者将页面映射的PAE部分解析错了。
如果开启了PAE页面映射机制(实事上,几乎所有多核计算机都开启了PAE),那么MMU将会用三级表来实现地址转译,分别是:页目录指针表,页目录索引,页表索引,页字节偏移,其中前三项都是8字节长,而作者解析时将其作为4字节处理了。
具体改法:在mm.c文件à MmGetPhysicalAddress函数中,将处理PAE的偏移,改为8;

注:4KB分页时,地址转译只需二级表,页目录索引,页表索引,每项4字节长。
       
        Tiamo NTLDR Project
作者Tiamo基本实现了一个完整的NTLDR,可以替换系统NTLDR,主要包括了利用休眠文件hiberfil.sys恢复系统的C++实现。不过我没有测试过可行性。
项目包括两部分:
16位实模式代码;
32位模式代码,即OsLoader.exe,是windows真正的32位入口程序。作者这部分代码参考了NT4代码,但是NT4代码中并没有实现恢复hiberfil的代码,估计作者是通过逆向写的。

        Useful application
利用Sandman,开发了若干免费小工具,一般开发人员用不上。
可访问:http://www.moonsols.com

解析hiberfil.sys,获取系统版本号,休眠文件的创建时间,从休眠文件dump物理内存内容(见附件)。

ANTI SMM Rootkit应用;

其他方面,取证分析,以及未知的应用…

APPENDIX
        简述用休眠文件恢复系统的过程

开机过程中,BIOS代码首先获得控制权,执行完硬件检测后跳转到MBR,MBR代码部分主要读取分区表信息,然后将控制权交给系统卷的引导扇区DBR,DBR执行一些初始化后,读取文件NTLDR,NTLDR中的16位模式代码开始执行,同样进行一些必要的初始化工作,然后将处理器切换到32位保护模式。
控制权交给osloader.exe, 此时处理器虽然已经工作在保护模式下,但是它的虚拟地址转译机制尚未开启,所以,处理器仍然直接使用物理地址。
Osloader 在入口函数NtProcessStartup里,调用全局初始化内存函数:
DoGlobalInitialization()-> InitializeMemorySubsystem() ->
实现的功能是: 用一个内存描述符数组把每一段内存的大小和用途记录下来,然后构造页目录和页表,使得16M一下的内存能够通过页面映射(paging)机制进行访问,在loader阶段是不使用高于16M以上的物理内存的,在设置好页目录寄存器,并打开页面映射机制。
之后,osloader 继续执行其他的初始化工作,包括IO设备的初始化。
分配PCR的页面-> 分配TSS的页面-> 初始化内存描述符-> 初始化IO系统BlIoInitialize。

接下来判断控制启动的方式。
函数:BlStartup(BootPartitionName);
过程大概这样:打开启动分区,以便加载驱动;初始化屏幕; 读取hiberfil.sys,如果是一个有效的休眠文件,则系统以hiberfil.sys方式恢复系统。如果不是,打开boot.ini文件,并显示一个引导选择菜单。如果boot.ini只包含一个引导选项,那么,此菜单不显示,而是立即应用该引导选项。

如果检测到hiberfil.sys有效,osloader将控制权交给一段能恢复系统的代码。大致流程如下:
打开hiberfil,不成功则返回-->成功则继续恢复 --> 分配页面缓冲-->解析头文件,判断image signature,有三种标志,分别处理,如果判断标志出错,就直接返回-->进行一些其他的校验工作->接下来分配PTE,读取内存映射页面的数据-> 分配压缩数据的缓冲->解压缩数据到物理内存—> 再经过一系列的恢复工作-> 读取处理器的状态......

        通过NT4代码,分析NTLDR的工作流
boot/bootcode/mbr/i386/x86mboot.asm        ->
这里执行MBR引导代码,读取分区表,获得引导分区,将引导分区的第一个扇区,即DBR读入到内存,然后将EIP调到DBR引导代码,执行。
boot/bootcode/ntfs/i386/ntfsboot.asm          ->
该函数主要用来读取卷上的数据,主要是将ntldr读入到内存,然后执行。(卷上的数据是根据文件系统格式存储和管理的,所以访问卷上的文件内容,需借助文件系统代码去读。)到目前为止,程序还是在实模式下,即16-bit模式。
boot/startup/i386/su.asm                     ->
直接跳到 JMP RealStart,准备stack和segment,然后去执行suMain函数,该函数位于:
boot/startup/i386/main.c                                ->
来到了C代码。这里实现一些初始化,包括video ,memory,foppy等。之后在回到su.asm,进行模式切换,至32-bit;
boot/lib/i386/entry.c                                        ->
入口函数NtProcessStartup,这里,进行一些初始化,调用DoGlobalInitialization 初始化16M以下的内存,分页机制开始启动。又进行了一些system memory和I/O system的初始化工作后,理解调用BlStartup函数,也就是说ntldr在BlStartup函数中执行完毕后,就返回了。该函数在:
boot/bldr/i386/initx86.c                                ->
这个函数打开boot.ini,获取启动选项,继续调用osloader.c;
\boot\bldr\osloader.c       

注:NT4不支持hiberfil休眠机制,在XP以后的系统中,恢复hiberfil的过程在 BlStartup过程中被调用。

        通过逆向分析NTLDR,分析hibernation file
这里只说下分析方法,省去细节。
恢复Hiberfil的工作是由osloader完成的,所以,通过逆向分析osloader.exe,可以了解恢复hiberfil的一些具体细节。

NTLDR位于系统盘根目录下,是一个具有隐藏只读属性的binary系统文件,不能直接使用IDA进行分析。
NTLDR由两个image组成,一个是16-bit下的binary image,就像是一个.com 文件;另一个是32-bit 下的PE file image,主要包含加载任务,这个PE image对应的文件就是osloader.exe。

提取osloader.exe的方法
用一个16进制编辑器(e.g. WinHex),打开NTLDR, 查找'MZ'或'PE'标志,然后从'MZ'标志开始,将剩下的hex data全部复制并粘贴到另外一个空文件,重命名为:osloader.exe。用winhex的话,会很简单(找到'MZ'标志,ALT+1,然后拖到文件末尾,ALT+2,这样就选中的从'MZ'到文件末尾的区块,然后右键'edit'->'copy block'->'into a new file')。
提取出osloader之后,用IDA加载,加载的时候会提示从MS官方下载'未公开'的符号,选择YES或NO,等待分析,可能要花2分钟左右时间。

分析osloader.exe文件
常理来说,osloader应该是一个native app,其入口函数是:NtProcessStartup。但是IDA分析后,入口函数为DriverEntry,当成驱动程序来分析了。但是,事实上,native app本质上就是一个驱动。
接下来就是利用各种资源,找自己关注的代码区分析了。

References
1, http://sandman.msuiche.net/docs/SandMan_Project.pdf
2, http://www.blackhat.com/presentations/bh-usa-06/BH-US-06-Burdach.pdf
3, https://www.volatilesystems.com/default/volatility
4, http://sandman.msuiche.net/
5, http://www.msuiche.net/con/euro2008/Exploiting_Windows_Hibernation_File.pdf

code and docs:
ShareHiberfil.rar

[2022冬季班]《安卓高级研修班(网课)》月薪两万班招生中~

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (33)
雪    币: 280
活跃值: 活跃值 (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
风雨夜 活跃值 2010-11-9 17:43
2
0
发这么好的东西还用恐慌
支持支持
雪    币: 336
活跃值: 活跃值 (29)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
microdebug 活跃值 6 2010-11-9 17:44
3
0
排版面目全非,感兴趣的话,下载附件,看DOC吧
雪    币: 114
活跃值: 活跃值 (33)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dousao 活跃值 2010-11-9 18:02
4
0
这些天正纠结这些东西呢 留下MSN 求指点
雪    币: 70
活跃值: 活跃值 (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yanxizhen 活跃值 2010-11-9 18:08
5
0
不错
雪    币: 42
活跃值: 活跃值 (17)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
nevergone 活跃值 3 2010-11-9 18:53
6
0
谢谢分享
雪    币: 1144
活跃值: 活跃值 (867)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hackroad 活跃值 2010-11-9 19:33
7
0
不错的思路用来找关键数据 。。。
雪    币: 326
活跃值: 活跃值 (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
快雪时晴 活跃值 4 2010-11-9 20:04
8
0
的确没有染指过这家伙,留存备用
雪    币: 336
活跃值: 活跃值 (29)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
microdebug 活跃值 6 2010-11-11 18:20
9
0
确实没有太多人染指这家伙;
染指这家伙的人,都是属于“不可说”一类的;

我目前还是属于观望的,不过离action也快啦
雪    币: 326
活跃值: 活跃值 (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
快雪时晴 活跃值 4 2010-11-11 20:26
10
0
等你action后,千万要“说一说”
雪    币: 284
活跃值: 活跃值 (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jerrynpc 活跃值 2010-11-12 00:52
11
0
太强大了,只能膜拜,无法学习,下载收藏
雪    币: 30
活跃值: 活跃值 (1210)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
riusksk 活跃值 41 2010-11-12 07:22
12
0
页目录指针表,页目录索引,页表索引,页字节偏移,其中前三项都是8字节长,而作者解析时将其作为4字节处理了。


在《windows内核原理与实现》是说上面四项各占2,9,9,12字节,如果是x64的就会使用多级页表。
雪    币: 336
活跃值: 活跃值 (29)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
microdebug 活跃值 6 2010-11-12 09:36
13
0
谢谢, 正如你说的是每个字段所占的位数确实是,2,9,9,12;
我描述有误,应该是表示前三项在内存中所占的(偏移)变量长度是8字节。
雪    币: 213
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ahyanglf 活跃值 2010-11-12 19:58
14
0
很不错的文章,,貌似win8可能用到这来快速启动和关机
雪    币: 237
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
小公媛 活跃值 2010-11-12 20:04
15
0
謝謝樓主,學習了
雪    币: 336
活跃值: 活跃值 (29)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
microdebug 活跃值 6 2010-11-13 13:09
16
0
很有见地
雪    币: 1901
活跃值: 活跃值 (1068)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
kagayaki 活跃值 2010-11-14 00:23
17
0
不会, 先收藏!!!
雪    币: 239
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yinning 活跃值 2010-11-14 05:49
18
0
谢谢楼主发这么好的东西。
雪    币: 147
活跃值: 活跃值 (41)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
大色秘密 活跃值 2010-12-2 16:36
19
0
严重顶大牛啊!
雪    币: 201
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
robar 活跃值 2010-12-3 17:26
20
0
好复杂。先看着
雪    币: 516
活跃值: 活跃值 (282)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
guxinyi 活跃值 5 2010-12-21 16:04
21
0
好东西啊,
标记,
雪    币: 135
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
低调flying 活跃值 2010-12-22 11:14
22
0
这个还真没关注过,领教了!
雪    币: 1259
活跃值: 活跃值 (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
stu 活跃值 2010-12-22 12:17
23
0
不错啊,学习了。
雪    币: 309
活跃值: 活跃值 (286)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
shell800 活跃值 2010-12-23 00:50
24
0
开拓新领域,内核知识就是这样一点点挖出来的,以前哪有人知道windows内部的东西。
雪    币: 12516
活跃值: 活跃值 (656)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
suiyingjie 活跃值 2011-5-19 15:29
25
0
很好的内容,谢谢。
游客
登录 | 注册 方可回帖
返回