日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

(18)修改 PTE 实现挂物理页读写空指针

發布時間:2025/3/21 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (18)修改 PTE 实现挂物理页读写空指针 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、10-10-12二級映射

下圖是101012二級映射結構:

二、讀寫NULL指針

正常編程中,不能讀寫NULL,原因是NULL指針沒有對應的物理頁,因此,只要我們讓NULL指針最終映射到一塊可讀寫的物理頁,就可以用NULL去讀寫數據了。

代碼短小精悍,也很好理解,關鍵步驟都在windbg里操作。下面先讓程序跑起來,停在getchar()處。

// PDE_PTE.cpp : Defines the entry point for the console application. //#include "stdafx.h"int _tmain(int argc, _TCHAR* argv[]) {int x = 1; // 讓NULL指向x所在的物理頁printf("x的地址:%x\n", &x);getchar(); // 在windbg里修改NULL 的PTE// NULL不能讀寫,原因是PTE為0,即沒有分配物理頁// 所以只要給NULL的PTE分配物理頁,就能讀寫NULL了 printf("NULL地址數據:%x\n",*(int*)NULL);*(int*)NULL = 0x112233; printf("NULL地址數據:%x\n",*(int*)NULL); // 0x112233return 0; }

然后,在windbg里按照上一節課的做法,找到 x 的物理地址。
拆分x的地址 0x0012ff60
00000000?00 0x0
0100101111 0x12f
111101100000? 0xf60

!process 0 0 查到CR3=1915d000,CR3的值是PDT表的基址。
!dd 1915d000+40 查到x對應的PDE也就是PDT[0]=07842067,屬性清零后是 07842000,這個值是x的PTT的基址。
!dd 07842000+412f 查x的PTE也就是PTT[12f]=0ce53067,屬性清零后就得到x的物理頁基址 0ce53000
!dd 0ce53000+f60 以dword形式查看x的內存

NULL = 0
拆分得:
00000000?00
00000000?00
00000000?0000
下標全是0。
CR3是一樣的,一個進程只有一個,CR3=1915d000
找NULL的PDE,!dd 1915d000,因為下標都是0,所以NULL 的PDE 和 x的PDE是一樣的,不用改,都是 07842067。
所以 07842000 就是NULL的PTT,然后NULL的第二個下標也是0,所以 !dd 07842000 就能查到PTT[0] 即 NULL的PTE,值是0.

用!ed指令改寫成x的PTE 0ce53067
!ed 7842000 0ce53067

回顧一下剛開始的二級映射結構圖:

現在x和NULL的PTE值相同,NULL和x處于同一個物理頁,物理頁基址是 0ce53000,但是物理地址仍然是不同的,因為x在物理頁內的偏移是 0xf60,而NULL的偏移是0。

但是沒有關系,NULL已經指向了一塊可用的物理頁了,現在可以對NULL進行讀寫了。

三、為變量x再映射一個線性地址,并通過這個新的地址讀取x的值

方法是調用 VirtualAlloc 申請一個物理頁,得到一個指針p,拆分地址,將p后12位改成和x的后12位相同,這樣就構造好了一個新的線性地址。

解釋一下為什么要VirtualAlloc,目的是確保有一塊可用的物理頁,并且和x的物理頁不是同一個;而修改p的后12位,目的是讓p的物理頁偏移和x一樣。

接下來,只需要修改p的PDE和PTE,使得p和x指向同一個物理頁即可。

// PDE_PTE.cpp : Defines the entry point for the console application. //#include "stdafx.h" #include <Windows.h>int _tmain(int argc, _TCHAR* argv[]) {int x = 0x1;printf("x的地址:%x\n", &x);// 申請一個新的物理頁,將p的PTE和物理頁內偏移改成和x一樣int p = (int)VirtualAlloc(NULL,0x1000,MEM_COMMIT,PAGE_READWRITE);int p_bak = p;memset((int*)p,0,0x1000);p &= 0xFFFFF000;p |= ((int)&x & 0x00000FFF);printf("新的線性地址:%x\n", p);getchar(); // 在windbg里修改 p 的 PTE// 用新的線性地址讀xprintf("*addr:%x\n",*(int*)p); // 0x1// 用新的線性地址寫x*(int*)p = 0x112233;printf("x:%x\n",x); // 0x112233getchar();VirtualFree((int*)p_bak,0x1000,MEM_DECOMMIT);return 0; }

讓程序跑起來:

然后將p的PTE改成和x的PTE一樣,這個過程步驟繁瑣:

拆分x:
0x0012ff60
00000000?00 0x0
0100101111 0x12f
111101100000? 0xf60

拆分p:
0x003b0f60
00000000?00 0x0
1110110000 0x3b0
111101100000? 0xf60

查CR3:
!process 0 0
CR3 = 0ef6f000

查PDEx
!dd 0ef6f000
PDEx = 09f43067

查PTEx
!dd 09f43000+4*12f
PTEx = 0f461047

查PTEp
!dd 09f43000+4*3b0

改PTEp
!ed 9f43ec0 0f461047

執行剩余的代碼:

實驗成功,用新的線性地址讀寫了x。
然后,就藍屏了,我不知道是什么原因。報錯說是 Probably caused by : memory_corruption ( nt!MiSwapWslEntries+157 ),看不懂呀!

四、10-10-12分頁模式物理內存能夠識別的最多范圍是多少

頁目錄表有1024項,頁表有1024項,物理頁有4KB

尋址范圍:1024 * 1024 * 4096 = 4GB

五、如何判斷2個線性地址是否在同一個物理頁?

看線性地址前20位,只要相同就在同一個物理頁。
因為前20位確定了PDE 和 PTE,PTE相同一定是同一個物理頁。

總結

以上是生活随笔為你收集整理的(18)修改 PTE 实现挂物理页读写空指针的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。