首页
论坛
课程
招聘
[系统底层] [调试逆向] [原创]win10 1909逆向----探寻文件体系1
2020-9-27 03:37 3724

[系统底层] [调试逆向] [原创]win10 1909逆向----探寻文件体系1

2020-9-27 03:37
3724

0x0 前言

         

        本来是想学一下MiniFilter,后面觉得没什么意思,就顺道将文件这一块逆了几天,越逆越觉得有意思,特将过程记录下来,从最开始CreateFile C盘开始,卷设备、NTFS文件系统、缓存管理、IO管理、到15个重要的元文件($MFT、$BOOT等),因为文件系统较复杂和繁琐,并且是以逆向为主,所以只记录关键流程,并争取简单明了,如果有错误还请指出,借此抛砖引玉。(参考书籍:windows内核原理与实现   windows内核设计思想)



0x1 简单基础介绍

         

我们在0环中断下来,知道内核NtCreateFile的第三个参数放的就是我们要打开的对象名:"\??\C:",至于这里是怎么转过来的,可以自已去三环跟一下,没什么难度。

在解释"\??\"是个什么玩意的时候,得先初步了解一下对象管理的一些知识。

windows内部维护了一个对象层次目录(即系统全局名字空间)。

如下图:根目录:“\”(用全局变量ObpRootDirectoryObject来定义),下面的ArcName、Device、Driver等都是子目录。

对象管理器在第1阶段初始化时,会先创建"\"根目录,在第一阶段完成后根目录对象会插入以下对象。

这里Name里面并没有显示??,但实际上,是已经创建了??这个目录,并且还创建了DosDevices这个符号链接来指向它,它的创建过程:

ObInitSystem---->ObpInitializeRootNamespace---->ObpCreateDosDevicesDirectory,感兴趣的同学可以逆。


0x2 解析过程

1。对象管理器在遇到“\??\”字符串时,会进入到EPROCESS的DeviceMAP(设备表)里,找到他需要的目录来解析:

DosDevicesDirectory:指向局部空间的目录。          "\??"

GlobalDosDevicesDirectory:指向全局空间的目录。"\GLOBAL??"

注:先找局部空间目录,如果局部空间目录没找到,则进入全局空间目录查找。



2。 解析DosDevicesDirectory这个对象,找到ParseProcedure或者ParseProcedureEx的值,判断是否为NULL,如果为NULL为目录,再通过剩余的名字来解析。(后面会多次需要得到ParseProcedure,具体过程这里会详细一点,后面直接略过)

1>得到Object_Header的TypeIndex.


2>Object_Header右移8位,得到低2字节。

3>得到ObHeaderCookie(我把他理解为随机值)

4>取他们的异或0xC0 ^ 0x1D ^ 0xDE = 0x3;

5>全局变量ObTypeIndexTable是一个对象类型数组,从这里取出上面异或出来的第3个,找到ParseProcedure或者ParseProcedureEx。

3。接着解析剩余的”C:“,因为目录的对象体是:_OBJECT_DIRECTORY,里面主要是用哈希表。

1>先计算”C:“的哈希值,在计算的时候,小写c也会转成大写。 C:的ASCII码:0x43 0x00 0x3A 0x00 [WCHAR,内存16进制表示]

HashValue=(0x43*3)+(0x43/2)+0x3A=0x124

HashIndex=0x124 % 37 = 33   [为什么是37,因为他上面一个目录对象只有37个Object_Directory_Entry]


2>在DosDevicesDirectory或者GlobalDosDevicesDirectory的哈希表中查找,如果DosDevicesDirectory没有,则去GlobalDosDevicesDirectory哈希表中查找。

3>ChainLink是一个单向链表,我们一直往下判断HashValue和我们的HashValue=(0x43*3)+(0x43/2)+0x3A=0x124是否相等。


4>取出相等的Object


5>同上解析得到Object的ParseProcedure或者ParseProcedureEx的值,是否为NULL,如果不为NULL,就调用他。具体过程上面已有详细说明,则简化。

6>设置好参数,调用ParseProcedure:这里也就是ObpParseSymbolicLinkEx(解析符号链接)。


4。ObpParseSymbolicLinkEx处理非常简单。

上面得到的Object是一个_OBJECT_SYMBOLIC_LINK结构体,里面记录了符号链接的目标设备对象,ObpParseSymbolicLinkEx的主要功能是将LinkTarget这个字符串替换了前面那个"\??\C:",然后返回STATUS_REPARSE,ObpLookupObjectName再接着解析,很多过滤就是用的这种机制。

0x3 简单实验

(不经文件过滤,直接利用上述符号知识,让E盘重定位到C盘)

未实现前:

实现后:======================================================================================


代码写的比较简单,没有去考虑锁之类的:

#include <ntddk.h>
#include "KernelStruct.h"

POBJECT_DIRECTORY_ENTRY GetDirectoryEntry(PDEVICE_MAP pDeviceMap, PWCHAR pDriverLetter);
BOOLEAN isReloc = FALSE;
PUNICODE_STRING OldAddr;
PWCHAR OldBuffer;
VOID Unload(PDRIVER_OBJECT pDriverObject)
{
	//还原
	if (isReloc) OldAddr->Buffer = OldBuffer;
	KdPrint(("Over\n"));
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pReg)
{
	KdPrint(("Start\n"));
	NTSTATUS status = STATUS_SUCCESS;
	pDriverObject->DriverUnload = Unload;
	//第一步得到当前进程的EPROCESS
	PEPROCESS CurrentProcess = PsGetCurrentProcess();
	
	//第二步得到进程的设备表DeviceMap
	PDEVICE_MAP DeviceMap = (PDEVICE_MAP)(*(PUINT64)((UINT64)CurrentProcess + DEVICEMAP));

	//第三步计算将E盘重定位到C盘的两个盘符的HashValue,并得到目录对象。	
	//这里要用大写,在windows里,会将小写转为大写计算Hash
	POBJECT_DIRECTORY_ENTRY pDirectoryEntry0 = GetDirectoryEntry(DeviceMap, L"C:");
	POBJECT_DIRECTORY_ENTRY pDirectoryEntry1 = GetDirectoryEntry(DeviceMap, L"E:");
	
	if (!pDirectoryEntry0 | !pDirectoryEntry1)
	{
		
		KdPrint(("参数错误\n"));
		return status;
	}

    //第四步
	
	POBJECT_SYMBOLIC_LINK pSymbolicLink0 = (POBJECT_SYMBOLIC_LINK)pDirectoryEntry0->Object;
	POBJECT_SYMBOLIC_LINK pSymbolicLink1 = (POBJECT_SYMBOLIC_LINK)pDirectoryEntry1->Object;
	OldAddr = &pSymbolicLink1->LinkTarget;
	OldBuffer = *(&pSymbolicLink1->LinkTarget.Buffer);
	*(&pSymbolicLink1->LinkTarget.Buffer) = *(&pSymbolicLink0->LinkTarget.Buffer);
	isReloc = TRUE;
	

	return status;
}
POBJECT_DIRECTORY_ENTRY GetDirectoryEntry(PDEVICE_MAP pDeviceMap,PWCHAR pDriverLetter)
{
	PCHAR var = (PCHAR)pDriverLetter;
	UINT32 vHashValue = (*var * 3) + (*var / 2) + *(var+2);
	UINT32 vHashIndex = vHashValue % 0x25;
	POBJECT_DIRECTORY pDirectoryObject = pDeviceMap->DosDevicesDirectory;
	if (!pDirectoryObject)
	{
		pDirectoryObject = pDeviceMap->GlobalDosDevicesDirectory;
	}
	POBJECT_DIRECTORY_ENTRY pDirectoryEntry = pDirectoryObject->HashBuckets[vHashIndex];
	if (!pDirectoryEntry)
	{
		//打印直接返回
		KdPrint(("没有找到目录项\n"));
		return NULL;
	}
	do
	{
		if (pDirectoryEntry->HashValue == vHashValue)
		{
			break;
		}
		pDirectoryEntry = pDirectoryEntry->ChainLink;
	} while (pDirectoryEntry);

	return pDirectoryEntry;
}
KernelStruct.h
#include <ntddk.h>
#define DEVICEMAP 0x430

typedef struct _EX_PUSH_LOCK
{
	union
	{
		struct
		{
			ULONGLONG Locked : 1;                                             //0x0
			ULONGLONG Waiting : 1;                                            //0x0
			ULONGLONG Waking : 1;                                             //0x0
			ULONGLONG MultipleShared : 1;                                     //0x0
			ULONGLONG Shared : 60;                                            //0x0
		};
		ULONGLONG Value;                                                    //0x0
		VOID* Ptr;                                                          //0x0
	};
}EX_PUSH_LOCK, *PEX_PUSH_LOCK;

typedef struct _OBJECT_DIRECTORY_ENTRY
{
	struct _OBJECT_DIRECTORY_ENTRY* ChainLink;                              //0x0
	VOID* Object;                                                           //0x8
	ULONG HashValue;                                                        //0x10
}OBJECT_DIRECTORY_ENTRY, *POBJECT_DIRECTORY_ENTRY;


typedef struct _OBJECT_DIRECTORY
{
	struct _OBJECT_DIRECTORY_ENTRY* HashBuckets[37];                        //0x0
	struct _EX_PUSH_LOCK Lock;                                              //0x128
	struct _DEVICE_MAP* DeviceMap;                                          //0x130
	struct _OBJECT_DIRECTORY* ShadowDirectory;                              //0x138
	VOID* NamespaceEntry;                                                   //0x140
	VOID* SessionObject;                                                    //0x148
	ULONG Flags;                                                            //0x150
	ULONG SessionId;                                                        //0x154
}OBJECT_DIRECTORY, *POBJECT_DIRECTORY;

typedef struct _DEVICE_MAP
{
	struct _OBJECT_DIRECTORY* DosDevicesDirectory;                          //0x0
	struct _OBJECT_DIRECTORY* GlobalDosDevicesDirectory;                    //0x8
	VOID* DosDevicesDirectoryHandle;                                        //0x10
	volatile LONG ReferenceCount;                                           //0x18
	ULONG DriveMap;                                                         //0x1c
	UCHAR DriveType[32];                                                    //0x20
	struct _EJOB* ServerSilo;                                               //0x40
}DEVICE_MAP,*PDEVICE_MAP;

typedef struct _OBJECT_SYMBOLIC_LINK
{
	union _LARGE_INTEGER CreationTime;                                      //0x0
	union
	{
		struct _UNICODE_STRING LinkTarget;                                  //0x8
		struct
		{
			LONG(*Callback)(struct _OBJECT_SYMBOLIC_LINK* arg1, VOID* arg2, struct _UNICODE_STRING* arg3, VOID** arg4); //0x8
			VOID* CallbackContext;                                          //0x10
		};
	};
	ULONG DosDeviceDriveIndex;                                              //0x18
	ULONG Flags;                                                            //0x1c
	ULONG AccessMask;                                                       //0x20
}OBJECT_SYMBOLIC_LINK, *POBJECT_SYMBOLIC_LINK;

完,下周再见!


第五届安全开发者峰会(SDC 2021)议题征集正式开启!

收藏
点赞7
打赏
分享
最新回复 (21)
雪    币: 458
活跃值: 活跃值 (310)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
青丝梦 活跃值 2020-9-27 07:49
2
0
豆总牛逼
雪    币: 9377
活跃值: 活跃值 (1310)
能力值: ( LV5,RANK:61 )
在线值:
发帖
回帖
粉丝
Sprite雪碧 活跃值 1 2020-9-27 08:22
3
0
写的挺好
雪    币: 331
活跃值: 活跃值 (354)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
浅笑心柔 活跃值 2020-9-27 08:24
4
0
写的挺好
雪    币: 2116
活跃值: 活跃值 (512)
能力值: (RANK:520 )
在线值:
发帖
回帖
粉丝
netwind 活跃值 13 2020-9-27 09:53
5
0
写得挺好
雪    币: 4370
活跃值: 活跃值 (406)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
如斯咩咩咩 活跃值 2020-9-27 10:39
6
0
整挺好
雪    币: 6233
活跃值: 活跃值 (293)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
二娃 活跃值 2020-9-27 13:53
7
0
写的挺好
雪    币: 315
活跃值: 活跃值 (420)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dz默契 活跃值 2020-9-27 14:59
8
0
看懂看不懂无所谓,先赞着再说
雪    币: 609
活跃值: 活跃值 (1050)
能力值: ( LV6,RANK:84 )
在线值:
发帖
回帖
粉丝
情话布墨 活跃值 2020-9-27 15:18
9
0
豆总牛逼
雪    币: 509
活跃值: 活跃值 (1680)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
随风行 活跃值 1 2020-9-27 15:48
10
0
学习一下
雪    币: 3131
活跃值: 活跃值 (3367)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
学技术打豆豆 活跃值 1 2020-9-27 17:03
11
0
争取一周一章!
雪    币: 4402
活跃值: 活跃值 (1828)
能力值: ( LV7,RANK:150 )
在线值:
发帖
回帖
粉丝
淡然他徒弟 活跃值 1 2020-9-27 18:08
12
0
奥利给
雪    币: 159
活跃值: 活跃值 (657)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
fengyunabc 活跃值 1 2020-9-27 19:50
13
0
感谢分享!
雪    币: 71
活跃值: 活跃值 (349)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
killpy 活跃值 2 2020-9-28 04:06
14
0
666
雪    币: 84
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
墨瑾萱 活跃值 2020-9-28 09:00
15
0
豆总 6666
雪    币: 473
活跃值: 活跃值 (642)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
库尔 活跃值 2020-9-28 09:49
16
0
......可以看下文件操作系统ntfs这类管理,把每个相关irp例程详细说一遍就好了。
雪    币: 215
活跃值: 活跃值 (2326)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
不懂就不懂 活跃值 2 2020-9-28 09:52
17
0
豆总666
雪    币: 871
活跃值: 活跃值 (437)
能力值: (RANK:50 )
在线值:
发帖
回帖
粉丝
backer 活跃值 1 2020-9-28 16:04
18
0
写的挺好
雪    币: 3131
活跃值: 活跃值 (3367)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
学技术打豆豆 活跃值 1 2020-9-29 17:17
19
0
库尔 ......可以看下文件操作系统ntfs这类管理,把每个相关irp例程详细说一遍就好了。
看时间允不允许吧,但NtfsMountVolume流程我估计是会写的,一般这个你会了,别的一般不难了~
雪    币: 59
活跃值: 活跃值 (168)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ookkaa 活跃值 2021-4-19 20:13
20
0

okok了

最后于 2021-4-19 22:46 被ookkaa编辑 ,原因:
雪    币: 59
活跃值: 活跃值 (168)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ookkaa 活跃值 2021-4-19 20:31
21
0

。。。

最后于 2021-4-19 21:05 被ookkaa编辑 ,原因:
雪    币: 247
活跃值: 活跃值 (53)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
chengqiyan 活跃值 2021-4-20 01:21
22
0
WIN10 NtCreateFile R3层代码都变了
游客
登录 | 注册 方可回帖
返回