首页
社区
课程
招聘
[原创]win10 1909逆向(内存区对象(SectionObject)----1.页面支撑的内存区)
发表于: 2021-4-1 00:40 14986

[原创]win10 1909逆向(内存区对象(SectionObject)----1.页面支撑的内存区)

2021-4-1 00:40
14986


          逆它纯粹就是想了解win10共享内存的原理,剖析具体的逻辑实现,了解原理后可以扫描检测游戏高地址的注入,下面只会简单介绍一下基础,详细可以参考《windows内核原理与实现》书籍,这里会以展示核心代码为主,将复杂的旁支简化,尽量做到一目了然,里面创建的结构体是根据逆多少写多少的原则赋值,正确性不一定完全正确,能明白意思即可,尽量写的简单,0E异常会另写一个帖子!

          对了这两天无聊顺便写了个WIN10 64位下HOOK内核函数不会触发PG的代码,算是取巧了windows机制,总共100行代码,不VT和不用网上的过PG代码,等这几天找完工作,也会分享出来,下面的Windbg是特意让他触发显示,否则也会和PCHunter显示一样的内容,物理机测试60小时不PG。


           内存区对象(SectionObject):被称为文件映射对象。表示可以被两个或更多进程所共享的内存块,当两个进程对同一个内存区对象建立视图时,便发生了对内存区对象的共享。

          内存区对象是一种使用物理内存资源的方式,主要用于进程映像的加载,进程间共享内存,文件映射,缓存管理 等等。

          


         



     这是三环代码,最终会进入内核NtCreateSection。原型如下:

   typedef  NTSTATUS (*ZWCREATESECTION)(

OUT PHANDLE SectionHandle,

IN ACCESS_MASK DesiredAccess,

IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,

IN PLARGE_INTEGER MaximumSize OPTIONAL,

IN ULONG SectionPageProtection,

IN ULONG AllocationAttributes,

IN HANDLE FileHandle OPTIONAL

);

     

当FileHandle和FileObject为NULL的时候,会直接MiCreatePageFileMap创建页面文件支撑的内存区。

MiCreatePageFileMap-->MiChargeCommit【判断提交的页面是否足够】

MyControlArea= ExAllocatePoolWithTag(0x200, 0x58 * Index+sizeof(CONTROL_AREA), 'aCmM');

struct _MyControlArea

{

_CONTROL_AREA ControlArea;

_SUBSECTION Subsection;

LIST_ENTRY SubSectionList;

PRTL_BALANCED_NODE pSubSectionNode; //pSubSectionNode-0x38=_Subsection

PVOID SubSectionNodeMark;

};


NewSegment = ExAllocatePoolWithTag(PagedPool, 0x50, 'geSM') //sizeof(_SEGMENT)+8;

struct _NewSegment

{

_SEGMENT Segment;

PMYSEGMENTEXTEND pSegmentExtend; //这里是在后面通过打开对象的回调产生,MiOpenSection里产生。

};


struct _MYSEGMENTEXTEND

{

PVOID NextMySegmentExtend;

PVOID u2;

PVOID u3;

PEPROCESS Process;

PVOID u5;

LIST_ENTRY ProcessSharedCommitLinks;

PVOID ControlArea;

};


ControlArea->NumberOfSubsections = 1;

ControlArea.ListHead.Blink = &ControlArea.ListHead;

ControlArea.ListHead.Flink = &ControlArea.ListHead;

ControlArea->Segment = NewSegment;

ControlArea->ControlArea.LockedPages = 1;

ControlArea->NumberOfSectionReferences = 1;

ControlArea->NumberOfUserReferences = 1;

if (AllocationAttributes & SEC_BASED) {

ControlArea->u.Flags.Based = 1;

}

if (AllocationAttributes & SEC_RESERVE) {

ControlArea->u.Flags.Reserve = 1;

}

if (AllocationAttributes & SEC_COMMIT) {

ControlArea->u.Flags.Commit = 1;

}

if (AllocationAttributes & SEC_64K_PAGES) {

ControlArea->u.Flags.PageSize64K= 1;

}

ControlArea.FileObjectLock.Value = 0;

memset(NewSegment , 0, sizeof(_SEGMENT));

if (AllocationAttributes & SEC_NOCACHE) {

NewSegment->SegmentFlags.Unused = 1;

}

if (AllocationAttributes & SEC_WriteCombined) {

NewSegment->SegmentFlags.WriteCombined= 1;

}

NewSegment->SegmentFlags.DefaultProtectionMask=ProtectionMask;

NewSegment->u1.CreatingProcessId= KeGetCurrentThread()->ApcState.Process->UniqueProcessId; //被创建进程的pid

NewSegment->SizeOfSegment = (UINT64)NumberOfPtes * PAGE_SIZE;

NewSegment->ControlArea = ControlArea;

NewSegment->TotalNumberOfPtes = NumberOfPtes;

Subsection = (PSUBSECTION)(ControlArea + 1);

Subsection->ControlArea = ControlArea;

Subsection->PtesInSubsection = (ULONG)NumberOfPtes;

Subsection->StartingSector = 0;

Subsection->SubsectionFlags.Protection=ProtectionMask;

if (AllocationAttributes & SEC_COMMIT)

{

PointPte = ExAllocatePoolWithTag(0x80000001, 8 * NumberOfPtes, 'tSmM');

Subsection->SubsectionBase = PointerPte

}

//Subsection->NextSubsection=(ULONG64)Subsection+0x58;

Subsection->NextSubsection=0;

NewSegment->PrototypePte=PointPte;


MiUpdateControlAreaCommitCount(ControlArea, NumberOfPtes);

1.增加内存分区MmPartition.Vp.SharedCommit+=NumberOfPtes;

2.如果ControlArea->FilePointer.Value有值,则ControlArea->Segment->NumberOfCommittedPages += NumberOfPtes;

否则ControlArea->u3.CommittedPageCount+=NumberOfPtes;

3.MiGetSubsectionHoldingCrossPartitionReferences[得到subsection的地址]


MiInitializePrototypePtes(SubsectionBase, NumberOfPtes,SubSection, isNotUsingFileExtents)

初始化SubsectionBase的原型PTE为(_MMPTE):0000200000000080 ,200000000000为MMPTE_SWIZZLE_BIT,0x80为

MiUpdateSystemProtoPtesTree(&ControlArea->subsection.SubsectionNode, Insert);  将susection加入到红黑树节点里。


MiFinishCreateSection(SectionPacket);

1。计算PagedPoolCharge和NonPagedPoolCharge。

2。ObCreateObjectEx( SectionPacket->PreviosMode,  MmSectionObjectType, SectionPacket->ObjectAttributes, SectionPacket->PreviosMode,

ObjectHeader, ObjectBodySize, PagedPoolCharge, NonPagedPoolCharge, &SectionObject, 0);

3。初始化SectionObject(最重要的是将ControlArea放入)。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 8
支持
分享
最新回复 (23)
雪    币: 400
活跃值: (4096)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
6666
2021-4-1 00:48
0
雪    币: 789
活跃值: (2014)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
厉害
2021-4-1 00:49
0
雪    币: 51
活跃值: (138)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
厉害
2021-4-1 00:51
0
雪    币: 198
活跃值: (256)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
牛皮豆豆
2021-4-1 02:32
0
雪    币: 1420
活跃值: (2151)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
豆总牛逼
2021-4-1 08:51
0
雪    币: 919
活跃值: (1340)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
7
bitmap利用的地方,我感觉是挺多的,比如 UMAB,可以先导VirtualAllocEx/NUAM,申请空间的范畴
2021-4-1 09:33
0
雪    币: 198
活跃值: (8548)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
8
丿一叶知秋 bitmap利用的地方,我感觉是挺多的,比如 UMAB,可以先导VirtualAllocEx/NUAM,申请空间的范畴
如果不嫌麻烦,利用点很多。
2021-4-1 10:32
0
雪    币: 1129
活跃值: (2731)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
感谢分享
2021-4-1 10:34
0
雪    币: 2428
活跃值: (2566)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
感觉高地址注入就是申请一块非分页内存,然后手动映射dll,然后把内存对应的各级页表的U/S位改成1。因为是手动映射,所以不存在什么section,controlarea,原型pte,vad之类的玩意。那么应该怎么用这个来检测高地址注入?
2021-4-1 10:37
0
雪    币: 2428
活跃值: (2566)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11

hook内核函数不PG,原理是不是给目标进程的内核函数地址挂一个新的物理页来hook?因为不同进程的pml4前XX项都是相同的,所以要从pml4这一层开始构造各级页表来避免内核地址共享?只要System进程的内核函数地址挂的还是原来的物理页,就不会PG?

最后于 2021-4-1 11:27 被dearfuture编辑 ,原因:
2021-4-1 11:27
0
雪    币: 198
活跃值: (8548)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
12
dearfuture 感觉高地址注入就是申请一块非分页内存,然后手动映射dll,然后把内存对应的各级页表的U/S位改成1。因为是手动映射,所以不存在什么section,controlarea,原型pte,vad之类的玩意。 ...
手法
2021-4-1 11:48
0
雪    币: 198
活跃值: (8548)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
13
dearfuture hook内核函数不PG,原理是不是给目标进程的内核函数地址挂一个新的物理页来hook?因为不同进程的pml4前XX项都是相同的,所以要从pml4这一层开始构造各级页表来避免内核地址共享?只要Syste ...
原理如此,但样本测试过少,不敢保证说肯定过PG
2021-4-1 11:55
0
雪    币: 12848
活跃值: (9142)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
14
学技术打豆豆 原理如此,但样本测试过少,不敢保证说肯定过PG
只要不碰pg自己保存的关键函数(kebugcheckex那些什么的)一切都好说,非关键函数只会在workitem里面扫描,保存在context中的关键函数是在dpc下刚进context时就验证的,改了就炸
2021-4-1 12:16
0
雪    币: 2428
活跃值: (2566)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
hzqst 只要不碰pg自己保存的关键函数(kebugcheckex那些什么的)一切都好说,非关键函数只会在workitem里面扫描,保存在context中的关键函数是在dpc下刚进context时就验证的,改了 ...
dpc执行时的cr3有可能是目标进程的cr3?
2021-4-1 13:11
0
雪    币: 12848
活跃值: (9142)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
16
dearfuture dpc执行时的cr3有可能是目标进程的cr3?
dpc执行的时候cr3可以是任何进程,dpc是进程/线程无关的
2021-4-1 16:42
0
雪    币: 198
活跃值: (8548)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
17
hzqst 只要不碰pg自己保存的关键函数(kebugcheckex那些什么的)一切都好说,非关键函数只会在workitem里面扫描,保存在context中的关键函数是在dpc下刚进context时就验证的,改了 ...
666
2021-4-1 16:54
0
雪    币: 1510
活跃值: (3407)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
hzqst dpc执行的时候cr3可以是任何进程,dpc是进程/线程无关的
意思是不要hook dpc里保护的地方那这种方法就可以,否则在hook的时候刚好遇到dpc在目标进程cr3就gg
2021-4-2 03:50
0
雪    币: 1519
活跃值: (2112)
能力值: ( LV3,RANK:35 )
在线值:
发帖
回帖
粉丝
19
dearfuture 感觉高地址注入就是申请一块非分页内存,然后手动映射dll,然后把内存对应的各级页表的U/S位改成1。因为是手动映射,所以不存在什么section,controlarea,原型pte,vad之类的玩意。 ...
把pte的用户位修改为1 既对r3 可见,但是这个在1809-1909不适用,因为windows在1809开始增加了校验至于2004 好像已经去掉了这个校验了
2021-4-3 15:50
0
雪    币: 2133
活跃值: (5158)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
20
学技术打豆豆 666[em_1]
打豆豆大佬 我试了一遍您的PTE Hook 但是我Hook的是大页 一替换PML4E 就直接虚拟机立刻死机了 请问这是为啥
哪怕把大页替换成小页都不会死机 但是过一会多重错误
2022-12-2 19:23
0
雪    币: 1281
活跃值: (4515)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
21
Oxygen1a1 打豆豆大佬 我试了一遍您的PTE Hook 但是我Hook的是大页 一替换PML4E 就直接虚拟机立刻死机了 请问这是为啥 哪怕把大页替换成小页都不会死机 但是过一会多重错误
看一下内核内存布局就明白了
2023-7-5 16:35
0
雪    币: 140
活跃值: (451)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
R0g 看一下内核内存布局就明白了
大佬带带
2023-7-5 21:22
0
雪    币: 2948
活跃值: (30846)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
感谢分享
2023-7-6 11:07
1
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
感谢分享!!!!!!!!!!!
2024-4-15 20:40
0
游客
登录 | 注册 方可回帖
返回
//