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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

(30)保护模式阶段测试

發布時間:2025/3/21 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (30)保护模式阶段测试 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、給定一個線性地址,和長度,讀取內容

int ReadMemory(OUT BYTE* buffer,IN DWORD dwAddr,IN DWORD dwLeght)
要求:

  • 可以自己指定分頁方式。
  • 頁不存在,要提示,不能報錯。
  • 可以正確讀取數據。
  • // ReadMemory.cpp : Defines the entry point for the console application. //#include "stdafx.h" #include <Windows.h>typedef ULONG (WINAPI *DBGPRINT)(PCSTR Format,... );DBGPRINT DbgPrint = NULL;#define DATALEN 0x4000 DWORD somedata[DATALEN]; // 數據源 DWORD mybuff[DATALEN]; // 空白緩沖區DWORD *GetPDE(DWORD addr) {return (DWORD *)(0xc0600000 + ((addr >> 18) & 0x3ff8));DWORD PDPTI = addr >> 30;DWORD PDI = (addr >> 21) & 0x000001FF;DWORD PTI = (addr >> 12) & 0x000001FF;return (DWORD *)(0xC0600000 + PDPTI * 0x1000 + PDI * 8); }DWORD *GetPTE(DWORD addr) {return (DWORD *)(0xc0000000 + ((addr >> 9) & 0x7ffff8));DWORD PDPTI = addr >> 30;DWORD PDI = (addr >> 21) & 0x000001FF;DWORD PTI = (addr >> 12) & 0x000001FF;return (DWORD *)(0xC0000000 + PDPTI * 0x200000 + PDI * 0x1000 + PTI * 8); }// 2-9-9-12分頁讀內存,要判斷線性地址有效性,要能正確處理跨頁的情況 BOOL ReadMemory(OUT BYTE* buffer, IN DWORD dwAddr, IN DWORD dwLength) {// 以字節為單位讀取for (DWORD i = 0; i < dwLength; i++){DWORD PDE = *GetPDE(dwAddr + i);DWORD PTE = *GetPTE(dwAddr + i);// PDE P==0,返回0if (PDE & 0x00000001 == 0){__asm push fsDbgPrint("\n\nPDE無效.\n");__asm pop fsreturn FALSE;}if ((PTE & 0x00000001) == 0) // ==優先級比&高{if (PTE == 0 || (PTE & 0xFFFFFC1F) == 0){__asm push fsDbgPrint("\n\n訪問空地址或其他錯誤.\n");__asm pop fsreturn FALSE;}}buffer[i] = ((PBYTE)dwAddr)[i];}return TRUE; }void __declspec(naked) R0Function() {__asm{pushadpushfd}// 讀NULL指針,錯誤原因:請求零頁面ReadMemory((PBYTE)mybuff,0,0x1000);//ReadMemory((PBYTE)mybuff,(DWORD)somedata,DATALEN);__asm{popfdpopad iretd} }int _tmain(int argc, _TCHAR* argv[]) {// 初始化數據for (int i = 0; i < DATALEN; i++) somedata[i] = i;memset(mybuff, 0, DATALEN);// 提權到R0測試 ReadMemory 函數DbgPrint = (DBGPRINT)GetProcAddress(LoadLibraryA("ntdll.dll"),"DbgPrint"); // 載入函數printf("在IDT表構建中斷門,請在windbg中執行下面的指令:\n");printf("eq 8003f500 %04xee00`0008%04x\n",(DWORD)R0Function>>16,(DWORD)R0Function & 0x0000FFFF);getchar();__asm int 0x20if (memcmp(mybuff, somedata, DATALEN) != 0){printf("讀取失敗.\n");}else{printf("讀取成功.\n");}return 0; }

    先看看讀取NULL的運行情況:


    修改代碼:

    void __declspec(naked) R0Function() {__asm{pushadpushfd}// 讀NULL指針,錯誤原因:請求零頁面//ReadMemory((PBYTE)mybuff,0,0x1000);ReadMemory((PBYTE)mybuff,(DWORD)somedata,DATALEN);__asm{popfdpopad iretd} }

    再看看正確讀取數據的情況:

    二、用線性地址0x1000打印數組

    題目要求

    申請長度為100的DWORD的數組,且每項用該項的地址初始化;
    把這個數組所在的物理頁掛到0x1000的地址上;
    定義一個指針,指向0x1000這個頁里的數組所在的地址,用0x1000這個頁的線性地址打印出這數組的值;

    要求:
    數組所在的物理頁,是同一個頁;

    思路

    用 VirtualAlloc 申請一個頁,得到頁基址指針,按要求進行初始化。然后給線性地址 0x1000 掛物理頁指向這個數組,并打印。

    代碼

    // PrintArrayWith0x1000.cpp : Defines the entry point for the console application. //#include "stdafx.h" #include <Windows.h>DWORD *arr;DWORD *GetPDE(DWORD addr) {return (DWORD *)(0xc0600000 + ((addr >> 18) & 0x3ff8));DWORD PDPTI = addr >> 30;DWORD PDI = (addr >> 21) & 0x000001FF;DWORD PTI = (addr >> 12) & 0x000001FF;return (DWORD *)(0xC0600000 + PDPTI * 0x1000 + PDI * 8); }DWORD *GetPTE(DWORD addr) {return (DWORD *)(0xc0000000 + ((addr >> 9) & 0x7ffff8));DWORD PDPTI = addr >> 30;DWORD PDI = (addr >> 21) & 0x000001FF;DWORD PTI = (addr >> 12) & 0x000001FF;return (DWORD *)(0xC0000000 + PDPTI * 0x200000 + PDI * 0x1000 + PTI * 8); }void __declspec(naked) R0Function() {__asm{pushadpushfd}//*GetPDE(0x1000) = *GetPDE((DWORD)arr);*GetPTE(0x1000) = *GetPTE((DWORD)arr);__asm{popfdpopad iretd} }int _tmain(int argc, _TCHAR* argv[]) {// 申請數組并初始化arr = (DWORD *)VirtualAlloc(0,0x1000,MEM_COMMIT,PAGE_READWRITE);for (int i = 0; i < 100; i++){arr[i] = (DWORD)(arr + i);}// 定義0x1000指針DWORD *ptr = (DWORD *)0x1000;// 掛物理頁printf("在IDT表構建中斷門,請在windbg中執行下面的指令:\n");printf("eq 8003f500 %04xee00`0008%04x\n",(DWORD)R0Function>>16,(DWORD)R0Function & 0x0000FFFF);getchar();__asm int 0x20// 通過0x1000打印數組for (int i = 0; i < 100; i++){printf("%x\n",ptr[i]);}return 0; }

    運行結果

    總結

    以上是生活随笔為你收集整理的(30)保护模式阶段测试的全部內容,希望文章能夠幫你解決所遇到的問題。

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