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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

Windows内存管理学习笔记(一)—— 线性地址的管理

發布時間:2025/3/21 windows 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Windows内存管理学习笔记(一)—— 线性地址的管理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Windows內存管理學習筆記(一)—— 線性地址的管理

    • 用戶空間線性地址的管理
      • 實驗一:理解用戶空間線性地址管理
    • Private Memory
      • 實驗二:理解Private Memory
        • 實驗三:理解堆
    • Mapped Memory
      • 實驗四:理解共享內存
      • 實驗五:理解共享文件
      • Mapped Exe
        • 實驗六:理解Mapped Exe
    • 總結

用戶空間線性地址的管理

基本概念:每一個進程都有一個4GB的線性地址空間

描述

  • 每個進程都有自己的用戶空間需要管理,當我們使用VirtualAlloc等函數申請一塊固定的地址空間時,首先需要確認這塊空間是否被占用,如果該空間已被占用則申請失敗
  • 用戶空間并非像內核空間一樣通過一塊鏈表去管理已占用的線性地址空間(效率低), 而是通過搜索二叉樹
  • 申請內存的兩種方式

  • 通過VirtualAlloc/VirtualAllocEx申請:Private Memory(獨享物理頁)
  • 通過CreateFileMapping進行映射:Mapped Memory(共享物理頁)
  • 進程空間地址劃分

    注意:
    1)只有用戶模式區是用戶能夠訪問的
    2)所謂的“無法訪問”只是目標地址沒有被掛上有效的物理頁(詳見保護模式章節)
    3)通常,當我們需要申請一塊內存時,通過系統提供的API去申請
    4)當我們申請一塊內存時,系統需要對這塊內存做記錄,表示它已經被申請了,之后再進行申請時,系統就不會再分配這塊地址給我們了
    5)在內核層,通過一塊鏈表,將所有未進行分配的空間的地址串起來,當我們需要分配空間時,在這一塊鏈表中尋找
    6)內核空間線性地址管理相對簡單(參考《Windows內核原理與實現》)
    7)本章主要介紹用戶空間線性地址管理(相對復雜)

    實驗一:理解用戶空間線性地址管理

    1)使用WinDbg查看進程列表

    命令:!process 0 0

    2)定位一個exe程序

    3)查看EPROCESS結構體

    命令:dt _EPROCESS 86360440

    ntdll!_EPROCESS......+0x11c VadRoot : 0x8656ef48 Void //入口點,進去后是搜索二叉樹//每一個節點記錄了一塊已被占用的線性地址空間//對應_MMVAD結構體......

    4)查看MMVAD結構體

    命令:dt _MMVAD 0x8656ef48

    nt!_MMVAD+0x000 StartingVpn : 0x400 //重要,以頁為單位,后面添上三個0即是當前節點所描述的線性地址的起始位置+0x004 EndingVpn : 0x42b //重要,以頁為單位,后面添上三個0即是當前節點所描述的線性地址的結束位置+0x008 Parent : (null) //根節點,不存在父節點+0x00c LeftChild : 0x86237d60 _MMVAD //左子樹+0x010 RightChild : 0x863e6a20 _MMVAD //右子樹+0x014 u : __unnamed //對應_MMVAD_FLAGS結構體+0x018 ControlArea : 0x86610220 _CONTROL_AREA //包含該節點所對應的線性地址被誰占用等信息+0x01c FirstPrototypePte : 0xe11e1048 _MMPTE+0x020 LastContiguousPte : 0xfffffffc _MMPTE+0x024 u2 : __unnamed

    5)查看CONTROL_AREA結構體

    命令:dt _CONTROL_AREA 0x86610220

    nt!_CONTROL_AREA+0x000 Segment : 0xe11e1008 _SEGMENT+0x004 DereferenceList : _LIST_ENTRY [ 0x0 - 0x0 ]+0x00c NumberOfSectionReferences : 1+0x010 NumberOfPfnReferences : 0x13+0x014 NumberOfMappedViews : 1+0x018 NumberOfSubsections : 6+0x01a FlushInProgressCount : 0+0x01c NumberOfUserReferences : 2+0x020 u : __unnamed+0x024 FilePointer : 0x863219d0 _FILE_OBJECT //若為空,表示線性地址指向真正的物理頁+0x028 WaitingForDeletion : (null) +0x02c ModifiedWriteCount : 0+0x02e NumberOfSystemCacheViews : 0

    6)查看FILE_OBJECT結構體

    命令:dt _FILE_OBJECT 0x863219d0

    ntdll!_FILE_OBJECT......+0x030 FileName : _UNICODE_STRING "\Documents and Settings\User\桌面\test\Debug\test.exe"//線性地址屬于主模塊......

    7)查看MMVAD_FLAGS結構體

    命令:kd> dt _MMVAD_FLAGS 86237d60+0x14

    nt!_MMVAD_FLAGS+0x000 CommitCharge : 0y0000000000000000111 (0x7)+0x000 PhysicalMapping : 0y0+0x000 ImageMap : 0y1 //為1表示鏡像文件(可執行文件),0表示其他+0x000 UserPhysicalPages : 0y0+0x000 NoChange : 0y0+0x000 WriteWatch : 0y0+0x000 Protection : 0y00111 (0x7) //表示內存權限為EXECUTE_WRITECOPY+0x000 LargePages : 0y0+0x000 MemCommit : 0y0+0x000 PrivateMemory : 0y0 //0表示Mapped Memory

    8)遍歷所有節點

    命令:!vad 0x8656ef48

    VAD Level Start End Commit 86237d60 1 10 10 1 Private READWRITE 85e1adc0 2 20 20 1 Private READWRITE 866df830 3 30 12f 3 Private READWRITE 86320ac0 4 130 132 0 Mapped READONLY Pagefile section, shared commit 0x3 86425598 5 140 23f 4 Private READWRITE 867c49d0 6 240 24f 6 Private READWRITE 862ff800 7 250 25f 0 Mapped READWRITE Pagefile section, shared commit 0x3 864bcad8 8 260 275 0 Mapped READONLY \WINDOWS\system32\unicode.nls 86348070 9 280 2c0 0 Mapped READONLY \WINDOWS\system32\locale.nls 863ec958 10 2d0 310 0 Mapped READONLY \WINDOWS\system32\sortkey.nls 86673f10 11 320 325 0 Mapped READONLY \WINDOWS\system32\sorttbls.nls 85dd0b40 12 330 370 0 Mapped READONLY Pagefile section, shared commit 0x41 86425fe8 13 380 38f 5 Private READWRITE 86588948 14 390 392 0 Mapped READONLY \WINDOWS\system32\ctype.nls 8656ef48 0 400 42b 7 Mapped Exe EXECUTE_WRITECOPY \Documents and Settings\JinXiangcheng\桌面\test\Debug\test.exe 862664c0 2 7c800 7c91d 5 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\kernel32.dll 863e6a20 1 7c920 7c9b2 5 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\ntdll.dll 862f4cb0 3 7f6f0 7f7ef 0 Mapped EXECUTE_READ Pagefile section, shared commit 0x7 8633aa60 2 7ffa0 7ffd2 0 Mapped READONLY Pagefile section, shared commit 0x33 8648b448 3 7ffdb 7ffdb 1 Private READWRITE 86244d88 4 7ffdf 7ffdf 1 Private READWRITE Total VADs: 21, average level: 6, maximum depth: 14 Total private commit: 0x27 pages (156 KB) Total shared commit: 0x81 pages (516 KB)

    總結:
    1)所有的線性地址空間是需要管理的(哪些地址是占用的,哪些地址是未占用的)
    2)所有用戶線性地址空間通過搜索二叉樹進行管理(占用大小占用方式內存屬性
    4)所有已占用的線性地址可以分為兩類

  • VirtualAlloc分配的普通內存
  • 文件映射(Mapped)的內存(例如dll/exe/txt等)
  • 5)傳統的模塊隱藏技術,終究會在VadRoot中留下痕跡,假設摘除,操作系統會誤認為該地址空間未被分配,從而產生非預期中的錯誤

    Private Memory

    描述:通過VirtualAlloc/VirtualAllocEx申請的內存,叫做Private Memory

    LPVOID VirtualAlloc{LPVOID lpAddress, // 要分配的內存區域的地址,填0則隨機分配一塊符合條件的地址DWORD dwSize, // 分配的大小,4kb對齊DWORD flAllocationType, // 分配的類型// MEM_RESERVE:只保留線性地址,不分配物理頁// MEM_COMMIT:既保留線性地址,又分配物理頁DWORD flProtect // 該內存的初始保護屬性 };

    實驗二:理解Private Memory

    1)編譯并運行以下代碼

    #include <stdio.h> #include <windows.h>LPVOID lpAddress;int main() {printf("程序運行了...內存還沒有申請\n");getchar();lpAddress = VirtualAlloc(NULL, 0x1000*2, MEM_COMMIT, PAGE_READWRITE);printf("內存地址:%x\n", lpAddress);getchar();return 0; }

    2)遍歷VadRoot

    kd> !process 0 0 **** NT ACTIVE PROCESS DUMP **** ...... Failed to get VadRoot PROCESS 86498ca0 SessionId: 0 Cid: 026c Peb: 7ffd3000 ParentCid: 0b80DirBase: 0e800380 ObjectTable: e2abfd10 HandleCount: 18.Image: test.exe kd> dt _EPROCESS 86498ca0 ntdll!_EPROCESS......+0x11c VadRoot : 0x86543ed8 Void...... kd> !vad 0x86543ed8 VAD Level Start End Commit 8621f160 1 10 10 1 Private READWRITE 866d04e0 2 20 20 1 Private READWRITE 86591aa8 3 30 12f 3 Private READWRITE 862f9658 4 130 132 0 Mapped READONLY Pagefile section, shared commit 0x3 865d7920 5 140 23f 3 Private READWRITE 85decda0 6 240 24f 6 Private READWRITE 862d7068 7 250 25f 0 Mapped READWRITE Pagefile section, shared commit 0x3 862df620 8 260 275 0 Mapped READONLY \WINDOWS\system32\unicode.nls 85e009d0 9 280 2c0 0 Mapped READONLY \WINDOWS\system32\locale.nls 85e4b6b0 10 2d0 310 0 Mapped READONLY \WINDOWS\system32\sortkey.nls 86588988 11 320 325 0 Mapped READONLY \WINDOWS\system32\sorttbls.nls 865e7bb8 12 330 370 0 Mapped READONLY Pagefile section, shared commit 0x41 8642b528 13 380 38f 5 Private READWRITE 8665e1b0 14 390 392 0 Mapped READONLY \WINDOWS\system32\ctype.nls 86543ed8 0 400 42c 8 Mapped Exe EXECUTE_WRITECOPY \Documents and Settings\JinXiangcheng\桌面\test\Debug\test.exe 865feaf8 2 7c800 7c91d 5 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\kernel32.dll 85df5180 1 7c920 7c9b2 5 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\ntdll.dll 86487da0 3 7f6f0 7f7ef 0 Mapped EXECUTE_READ Pagefile section, shared commit 0x7 863b1100 2 7ffa0 7ffd2 0 Mapped READONLY Pagefile section, shared commit 0x33 863ef410 3 7ffd3 7ffd3 1 Private READWRITE 8640f148 4 7ffdf 7ffdf 1 Private READWRITE Total VADs: 21, average level: 6, maximum depth: 14 Total private commit: 0x27 pages (156 KB) Total shared commit: 0x81 pages (516 KB)

    3)繼續運行程序,查看分配到的地址

    4)再次遍歷VadRoot,觀察變化

    kd> !vad 0x86543ed8 VAD Level Start End Commit 862f9658 2 130 132 0 Mapped READONLY Pagefile section, shared commit 0x3 865d7920 1 140 23f 3 Private READWRITE 85decda0 3 240 24f 6 Private READWRITE 862d7068 2 250 25f 0 Mapped READWRITE Pagefile section, shared commit 0x3 862df620 4 260 275 0 Mapped READONLY \WINDOWS\system32\unicode.nls 85e009d0 3 280 2c0 0 Mapped READONLY \WINDOWS\system32\locale.nls 85e4b6b0 5 2d0 310 0 Mapped READONLY \WINDOWS\system32\sortkey.nls 86588988 4 320 325 0 Mapped READONLY \WINDOWS\system32\sorttbls.nls 865e7bb8 6 330 370 0 Mapped READONLY Pagefile section, shared commit 0x41 8642b528 5 380 38f 5 Private READWRITE 8665e1b0 6 390 392 0 Mapped READONLY \WINDOWS\system32\ctype.nls --------------------------------------------------------------------- 86600dc0 7 3a0 3a1 2 Private READWRITE //新增節點 --------------------------------------------------------------------- 86543ed8 0 400 42c 8 Mapped Exe EXECUTE_WRITECOPY \Documents and Settings\JinXiangcheng\桌面\test\Debug\test.exe 865feaf8 2 7c800 7c91d 5 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\kernel32.dll 85df5180 1 7c920 7c9b2 5 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\ntdll.dll 86487da0 3 7f6f0 7f7ef 0 Mapped EXECUTE_READ Pagefile section, shared commit 0x7 863b1100 2 7ffa0 7ffd2 0 Mapped READONLY Pagefile section, shared commit 0x33 863ef410 3 7ffd3 7ffd3 1 Private READWRITE 8640f148 4 7ffdf 7ffdf 1 Private READWRITE Total VADs: 19, average level: 4, maximum depth: 7 Total private commit: 0x24 pages (144 KB) Total shared commit: 0x81 pages (516 KB)

    描述

  • 堆是操作系統提前通過VirtualAlloc/VirtualAllocEx申請的一塊內存,存在于VadRoot
  • 在C++中,若是想創建一個對象,需要用到new,此時,會在堆中創建一個對象,new的底層實現就是malloc,malloc的底層都是通過HeapAlloc實現的,HeapAlloc要做的事就是在堆中分配一塊內存
  • 簡而言之,操作系統“批發”了一塊很大的內存,無論是通過malloc還是new申請的內存,本質上都是從這塊內存中“零售”出了一小塊
  • malloc的底層并沒有進0環,因此系統并沒有分配出一塊新的內存(跟蹤malloc實現得知)
  • 只有當使用VirtualAlloc/VirtualAllocEx或者Mapped時,才會分配出一塊新的內存
  • 實驗三:理解堆

    1)編譯并運行以下代碼(在首行設置斷點)

    #include <stdio.h> #include <windows.h>int x = 0x1234;int main() {int y = 0x5678;int *z = (int*)malloc(sizeof(int)*128);printf("全局變量:%x\n", &x);printf("棧:%x\n", &y);printf("堆:%x\n", z);getchar();return 0; }

    2)查看當前進程的VadRoot

    3)繼續運行程序,觀察結果
    4)再次查看VadRoot,發現并無任何變化

    結論:

  • 在棧中定義變量或者通過malloc申請內存時,系統并沒有新分配一塊內存,而是從事先分配好的空間中劃分出一小塊
  • 全局變量在編譯代碼時,地址已經被綁定在了可執行文件
  • Mapped Memory

    描述
    1)通過CreateFileMapping映射的內存,叫做Mapped Memory,一個進程中大部分的內存都屬于Mapped Memory
    2)Mapped Memory可以分為兩類

  • 共享內存:當內存為共享內存時,本質是共享一份物理頁
  • 共享文件:當內存為共享文件時,這塊內存可能被映射到多個進程空間中,但真正占用的物理頁只有一份
  • 3)無論是共享內存還是文件,在底層實現都是一樣的,當我們需要共享物理頁的時候,系統只需將物理頁準備好,當我們需要共享文件時,系統先將物理頁準備好,然后將物理頁與文件進行關聯

    實驗四:理解共享內存

    1)編譯并運行以下代碼(進程A)

    #include <stdio.h> #include <windows.h>#define MapFileName "共享內存"int main() {//內核對象:1.物理頁 2. 文件//準備一塊內存,若第一個參數為INVALID_HANDLE_VALUE(-1)表示共享物理頁HANDLE g_hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, BUFSIZ, MapFileName);//將物理頁與線性地址進行映射LPTSTR g_lpBuff = (LPTSTR)MapViewOfFile(g_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUFSIZ);*(PDWORD)g_lpBuff = 0x12345678;printf("A進程寫入地址,內容:%p - %x", g_lpBuff, *(PDWORD)g_lpBuff);getchar();return 0; }

    2)查看進程A的執行結果

    3)查看進程A的VadRoot

    4)保持進程A運行,編譯并運行以下代碼(進程B)

    #include <stdio.h> #include <windows.h>#define MapFileName "共享內存"int main() {//內核對象:1.物理頁 2. 文件HANDLE g_hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, MapFileName);//將物理頁與線性地址進行映射LPTSTR g_lpBuff = (LPTSTR)MapViewOfFile(g_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUFSIZ);printf("B進程讀取地址,內容:%p - %x", g_lpBuff, *(PDWORD)g_lpBuff);getchar();return 0; }

    5)查看進程B執行結果

    6)查看進程B的VadRoot

    實驗五:理解共享文件

    1)編譯并運行以下代碼(在return處設置斷點)

    #include <stdio.h> #include <windows.h>int main() {//內核對象:1.物理頁 2. 文件HANDLE g_hFile = CreateFile("C:\\NOTEPAD.EXE",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); HANDLE g_hMapFile = CreateFileMapping(g_hFile,NULL,PAGE_READWRITE,0, BUFSIZ,NULL);//將物理頁與線性地址進行映射LPTSTR g_lpBuff = (LPTSTR)MapViewOfFile(g_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUFSIZ);return 0; }

    2)查看g_lpBuff的地址

    3)查看當前進程的VadRoot

    Mapped Exe

    描述

  • 當一個程序通過LoadLibrary進行加載時,此時該文件所在的線性地址空間的屬性為Mapped Exe權限為EXECUTE_WRITECOPY
  • 由于權限為EXECUTE_WRITECOPY的地址空間是需要共享給所有程序使用的,因此當我們對權限為EXECUTE_WRITECOPY的線性地址空間的任何位置進行修改時,系統會先給這塊內存重新映射一份物理頁,然后再進行修改
  • 實驗六:理解Mapped Exe

    1)編譯并運行以下代碼(在return處設置斷點)

    #include <stdio.h> #include <windows.h>int main() {HMODULE hModule = LoadLibrary("C:\\NOTEPAD.EXE");return 0; }

    2)查看當前進程的VadRoot

    總結

    1)線性地址分為三類:私有內存 | 共享內存 | 共享文件
    2)共享內存和共享文件本質相同,都是分配了一塊物理頁,不同的是共享文件將物理頁和文件關聯了起來
    3)傳統的模塊隱藏技術很難在VadRoot中進行隱藏(脫鉤可能會導致程序崩潰),除非通過VirtualAlloc分配私有內存,手動將文件進行拉伸與貼入等一系列操作,此時能夠大大增加尋找該模塊的難度

    思考:當使用VirtualAlloc進行模塊隱藏并且抹去特征時,如何找到這個模塊?
    答案:內存搜索

    《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

    總結

    以上是生活随笔為你收集整理的Windows内存管理学习笔记(一)—— 线性地址的管理的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 91porny丨首页入口在线 | 免费裸体视频女性 | 在线观看黄色国产 | 国产性色av| 黑人黄色录像 | 成人毛毛片 | 91干网| 51av在线 | 2025av在线播放 | av影院在线观看 | 亚洲色图小说 | 欧美永久视频 | 在线精品视频免费观看 | 在线免费观看h片 | 热热热热色 | 成人乱人乱一区二区三区一级视频 | 久久久极品 | 四虎影视在线播放 | 蜜桃av噜噜一区二区三区网址 | 欧美xxxx黑人 | 97成人在线观看 | 欧洲亚洲天堂 | 欧美天天性影院 | 久青草视频在线观看 | 黄色片a级片 | 成人区精品一区二区婷婷 | 国产黄片一区二区三区 | 五月天堂婷婷 | 国产欧美亚洲一区二区 | 亚洲欧洲国产精品 | 一区二区三区精 | 亚洲男女视频 | 夜夜爽夜夜爽 | 蜜桃av久久久亚洲精品 | 亚洲伊人av | 91超薄肉色丝袜交足高跟凉鞋 | 精品91自产拍在线观看二区 | 欧美激情一区二区三区蜜桃视频 | 亚洲成av人在线观看 | 国产免费久久精品国产传媒 | 日本视频久久 | 亚洲精品久久久久久久久久久久久 | 草久久av| 精品aaa| 精品视频在线免费看 | 欧美91精品 | 色一情一伦一子一伦一区 | 开心春色激情网 | 91狠狠综合 | 亚洲AV无码国产日韩久久 | 国产福利一区二区视频 | 午夜精品福利视频 | aaa黄色| 欧美两根一起进3p做受视频 | 婷婷综合av | 免费观看成人在线视频 | 在线观看中文字幕码 | 国产在线精品一区 | 色婷婷av一区二区三区之e本道 | jizz国产在线 | 在线视频一区二区三区 | 色五婷婷 | 成年人黄网站 | 捆绑无遮挡打光屁股 | 加勒比一区在线 | 日韩人妻精品一区二区三区 | 日韩精品成人av | 韩国妻子的朋友 | 一区二区三区视频 | 国产精品视频免费在线观看 | 人人舔| 亚洲无卡视频 | 欧美日韩高清丝袜 | 黄色三级av | 欧美激情免费在线观看 | av毛片大全 | 波多野结衣中文在线 | 国产日本亚洲 | 调教一区二区三区 | 日日夜夜综合 | av直播在线观看 | 国产又粗又长又硬免费视频 | 中文字幕第一页在线 | 澳门黄色 | 国产一精品一aⅴ一免费 | 黄大片18满岁| 欧美第三页 | 国产精品毛片久久久 | 三上悠亚一区二区在线观看 | 成人黄色免费视频 | 久久综合网址 | 国产又粗又黄又爽又硬的视频 | 人人爽人人爱 | 极品五月天 | 精品人妻一区二区三区三区四区 | 日韩av在线直播 | 播播网色播播 | 国产精品白浆一区二小说 | 国产在线网站 |