逆它纯粹就是想了解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放入)。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!