MiCreatePebOrTeb 函数注释
修改订正日期:2009-7-29
今天看以前关于 FS 寄存器的文章 , 看到说进程的 PEB 的地址总是 0x7FFDF000. 于是写了一个程序来验证一下 . 但是程序运行之后发现却不是这样的 :PEB 地址总是不停的变化的 , 是随机的 . 怎么回事呢 ? 找到 WRK 的代码 ,
PEB 地址的分配在函数 MiCreatePebOrTeb 函数 , 于是仔细阅读了这个函数 , 才知道了怎么回事 .
晚上在 baidu 上搜了一下 , 发现早就有人发表文章说明这个情况了 :Windows xp 从 SP2 开始 ( 包括 SP2), 就开始随机返回 PEB 的地址了 .
下面是我的代码注释 :
NTSTATUS /*++ Routine Description: This routine creates a TEB or PEB page within the target process. Arguments: TargetProcess - Supplies a pointer to the process in which to create Size - Supplies the size of the structure to create a VAD for. Base - Supplies a pointer to place the PEB/TEB virtual address on success. Return Value: NTSTATUS. Environment: Kernel mode, attached to the specified process. --*/ { Thread = PsGetCurrentThread (); // Vad = (PMMVAD_LONG) ExAllocatePoolWithTag (NonPagedPool, if (Vad == NULL) { Vad->u.LongFlags = 0; Vad->u.VadFlags.CommitCharge = BYTES_TO_PAGES (Size); // Vad->u.VadFlags.NoChange = 1; // LOCK_ADDRESS_SPACE (TargetProcess);
// 0x210 来判断是否为PEB. PEB 是随机出现的. if (Size == sizeof(PEB) LARGE_INTEGER CurrentTime; HighestVadAddress = (PVOID) ((PCHAR)MM_HIGHEST_VAD_ADDRESS + 1); //HighestVadAddress = 0x7FFE0000 KeQueryTickCount (&CurrentTime); CurrentTime.LowPart &= ((X64K >> PAGE_SHIFT) - 1); // (X64K >> PAGE_SHIFT) – 1 = 0Xf, 下面就从这个随机数中取值。 //0x7FFE0000– (3<<12 )/ 0x7FFE0000– (4<<12 ) …0x7FFE0000– (15<<12 ) if (MiCheckForConflictingVadExistence (TargetProcess, HighestVadAddress, (PVOID) ((PCHAR) HighestVadAddress + ROUND_TO_PAGES (Size) - 1)) == FALSE) { //MiCheckForConflictingVadExistence 函数用来检查指定进程的地址中从 //HighestVadAddress 到(PCHAR) HighestVadAddress + //ROUND_TO_PAGES (Size) – 1 是否已经分配了. 如果没有分配, 返回FALSE. 则表 // 示分配成功了. // 向下分配一个空闲页( 大小为0x1000). if (!NT_SUCCESS(Status)) { // UNLOCK_ADDRESS_SPACE (TargetProcess); // Vad->StartingVpn = MI_VA_TO_VPN (*Base); Vad->u3.Secured.StartVpn = (ULONG_PTR)*Base; Status = MiInsertVadCharges ((PMMVAD) Vad, TargetProcess); if (!NT_SUCCESS (Status)) { // UNLOCK_ADDRESS_SPACE (TargetProcess); return Status; LOCK_WS_UNSAFE (Thread, TargetProcess); MiInsertVad ((PMMVAD) Vad, TargetProcess); UNLOCK_WS_UNSAFE (Thread, TargetProcess); UNLOCK_ADDRESS_SPACE (TargetProcess); return Status;
|
网上有一篇文章 < 系统维护技巧 :windows xp sp2 溢出保护 > 上说到了 PEB 地址随机出现 , 该文把 0x210 看成是一个 flag 了 . 从上面的源码我们可出 0x210 是 PEB 的结构大小 .MiCreatePebOrTeb 函数就是根据此大小来判读是 PEB 还是 TEB 的分配 . 不管是 PEB 还是 TEB, 系统最终都是分配一个 1 个 PAGE.
下面是这个过程的内存示意图:
参考文献 :
< 系统维护技巧 :windows xp sp2 溢出保护 >
< 加密与解密 > 第三版 P402