首页 > 其他分享 >‘Proof of the pudding’: Global variables and PAGE_EXECUTE_WRITECOPY

‘Proof of the pudding’: Global variables and PAGE_EXECUTE_WRITECOPY

时间:2023-10-07 11:47:09浏览次数:38  
标签:EXECUTE variables Global notepad 001 PAE address page physical

‘Proof of the pudding’: Global variables and PAGE_EXECUTE_WRITECOPY

 

Today I was teaching a debugging class to our customers. As a foundational element we normally review the virtual-to-physical address translation mechanism, at least to a basic level. In this class we decided to go a bit deeper and show the evidence Smile

Background reading

First, if you are not familiar with PTEs, PDEs and pages, you must read the following to understand those fundamental concepts:

 

Test Setup

My laptop hosts a Windows 2008 VM, using Hyper-V. The VM has been configured for kernel debugging using the following BCDEdit command:

bcdedit -debug on

We connect the kernel debugger on my laptop to this VM by using the ‘named pipe’ COM port emulation. The virtual COM port for the VM can be setup easily, and the steps for the same are documented here. Finally, the VM in turn has WinDbg installed. Since the VM is offline (no Internet connection,) the matching OS symbols were cached on the VM using this approach for offline debugging.

Initial observations

We initially launch two notepad.exe instances on the VM. In one instance, we will switch the ‘Word wrap’ setting to checked state; the other one we will leave as default. It so happens that this setting is mapped to a global variable notepad!fWrap. How did I figure that out? Using the following command in the VM WinDbg session:

0:001> x notepad!*wrap*
001ca034          notepad!fWrap = <no type information>

So here are the actual values for each of these processes:

  <iframe frameborder="0" height="240" id="atatags-26942-337501_iframe" scrolling="no" width="320"></iframe>  

notepad.exe #1:

0:001> x notepad!*wrap*
001ca034          notepad!fWrap = <no type information>
0:001> |
.  0    id: 910    create    name: notepad.exe   <—PID is 0x910
0:001> dd 001ca034 L1
001ca034  00000001        <—as you can see, the value is set to 1, which indicates word wrap is ON.

notepad.exe #2:

0:001> x notepad!fWrap
001ca034          notepad!fWrap = <no type information>
0:001> |
.  0    id: f6c    create    name: notepad.exe         <— PID is 0xf6c
0:001> dd 001ca034 L1
001ca034  00000000       <— In this case word wrap is OFF.

Notice that the virtual address space for fWrap is the same in both processes. So the question in the mind of the participant was, while theoretically we know that the address space is translated to different pages, can we prove it?

Verification using live Kernel Debugging

To answer the above question, the only way to be absolutely sure was to hook up a live kernel debugger session and check. Firstly, we identify the processes in the kernel mode (we need to process objects in order to do this correctly.)

kd> !process 0 0 notepad.exe
PROCESS 83b73d90  SessionId: 1  Cid: 0910    Peb: 7ffde000  ParentCid: 0c24
    DirBase: 3f77b3c0  ObjectTable: 945cd440  HandleCount:  46.
    Image: notepad.exe

 

PROCESS 8366eb38  SessionId: 1  Cid: 0f6c    Peb: 7ffda000  ParentCid: 0d9c
    DirBase: 3f77b400  ObjectTable: 944e46d0  HandleCount:  46.
    Image: notepad.exe

Next, we use the extension !vtop to map these to physical addresses. In the command below, the first argument to !vtop is the ‘page directory base’, the second is the virtual address. Firstly, for the process with PID 0x910 (which has word wrap ON) and whose Directory Base is 3f77b3c0 (obtained from the above !process output.)

kd> !vtop 3f77b3c0 001ca034
X86VtoP: Virt 001ca034, pagedir 3f77b3c0
X86VtoP: PAE PDPE 3f77b3c0 – 000000000e0f5801
X86VtoP: PAE PDE e0f5000 – 000000000e0fa867
X86VtoP: PAE PTE e0fae50 – 800000000c57a867
X86VtoP: PAE Mapped phys c57a034
Virtual address 1ca034 translates to physical address c57a034.

So !vtop says the physical address is c57a034. Notice the last 3 digits (which is the offset within the 4Kb page) is 034, which is the same as offset the virtual address. This is no coincidence, it is the way we break up the 32-bit virtual address into its constituents (page directory entry, page table entry and page offset.) So let us quickly verify the contents of physical memory location c57a034. To do that we have two options:

kd> !dd c57a034 L1
# c57a034 00000001

kd> dd /p c57a034 L1
0c57a034  00000001

Either way, we can be sure that this is THE content of our fWrap variable. Let us cross-check the other process as well in a similar way.

kd> !vtop 3f77b400 001ca034
X86VtoP: Virt 001ca034, pagedir 3f77b400
X86VtoP: PAE PDPE 3f77b400 – 000000000bd08801
X86VtoP: PAE PDE bd08000 – 000000000beeb867
X86VtoP: PAE PTE beebe50 – 800000000bc2c867
X86VtoP: PAE Mapped phys bc2c034
Virtual address 1ca034 translates to physical address bc2c034.

Next, let us dump the content of physical address bc2c034. Again we can use either !dd or dd /p to do this.

kd> dd /p bc2c034 L1
0bc2c034  00000000


kd> !dd bc2c034 L1
# bc2c034 00000000

So we can confirm that this is accurate as well, as it rightly shows the status value of 0.

Digging deeper

Now, let’s look at some more details. From the user mode WinDbg instance (running inside the VM) let’s check what kind of memory allocation is associated with the address notepad!fWrap. To do this, we will use the !address extension.

0:001> !address 001ca034

Usage:                  Image
Base Address:           001ca000
End Address:            001cb000
Region Size:            00001000
State:                  00001000    MEM_COMMIT
Protect:                00000004    PAGE_READWRITE
Type:                   01000000    MEM_IMAGE
Allocation Base:        001c0000
Allocation Protect:     00000080    PAGE_EXECUTE_WRITECOPY
Image Path:             notepad.exe
Module Name:            notepad
Loaded Image Name:      C:WindowsSystem32notepad.exe
Mapped Image Name:     
More info:              lmv m notepad
More info:              !lmi notepad
More info:              ln 0x1ca034
More info:              !dh 0x1c0000

Very interesting! So this is actually Image memory (as evidenced by the MEM_IMAGE type) and also the page is protected as a ‘copy-on-write’ page (PAGE_EXECUTE_WRITECOPY protection). This is actually the standard technique used for global variables within an image, which of course need to be uniquely maintained per-process.

Let’s turn our attention to the executable code within notepad, to see how that is mapped to physical addresses. We will randomly focus our attention on the function notepad!FastReplaceAll, which I gathered from the x notepad!* command output. notepad!FastReplaceAll is a function at address 001c743f in my debugging session:

0:001> u notepad!FastReplaceAll
notepad!FastReplaceAll:
001c743f 8bff            mov     edi,edi
001c7441 55              push    ebp
001c7442 8bec            mov     ebp,esp
001c7444 83ec24          sub     esp,24h
001c7447 56              push    esi
001c7448 33f6            xor     esi,esi
001c744a 56              push    esi
001c744b 56              push    esi

FWIW, the address is the same on the other notepad.exe instance as well. Looking at !address output, this page is also a copy-on-write page:

0:001> !address 001c743f
Usage:                  Image
Base Address:           001c1000
End Address:            001ca000
Region Size:            00009000
State:                  00001000    MEM_COMMIT
Protect:                00000020    PAGE_EXECUTE_READ
Type:                   01000000    MEM_IMAGE
Allocation Base:        001c0000
Allocation Protect:     00000080    PAGE_EXECUTE_WRITECOPY
Image Path:             notepad.exe
Module Name:            notepad
Loaded Image Name:      C:WindowsSystem32notepad.exe
Mapped Image Name:     
More info:              lmv m notepad
More info:              !lmi notepad
More info:              ln 0x1c743f
More info:              !dh 0x1c0000

However, let us see if this page has different physical addresses or not. Firstly, for the process with PID 0x910 (which has word wrap ON)

kd> !vtop 3f77b3c0 001c743f
X86VtoP: Virt 001c743f, pagedir 3f77b3c0
X86VtoP: PAE PDPE 3f77b3c0 – 000000000e0f5801
X86VtoP: PAE PDE e0f5000 – 000000000e0fa867
X86VtoP: PAE PTE e0fae38 – 0000000028d07025
X86VtoP: PAE Mapped phys 28d0743f
Virtual address 1c743f translates to physical address 28d0743f.

For the other process, it is as follows:

kd> !vtop 3f77b400 001c743f
X86VtoP: Virt 001c743f, pagedir 3f77b400
X86VtoP: PAE PDPE 3f77b400 – 000000000bd08801
X86VtoP: PAE PDE bd08000 – 000000000beeb867
X86VtoP: PAE PTE beebe38 – 0000000028d07025
X86VtoP: PAE Mapped phys 28d0743f
Virtual address 1c743f translates to physical address 28d0743f.

Voila! They are the same physical page. This is expected (in retrospect) because this code has not been changed and is therefore mapped to the same physical page 28d0743f.

Summary

  • Virtual to physical mapping is viewable in the kernel mode debug session using the !vtop extension
  • For global variables within the process, it is inevitable that though they share the same virtual address, their physical pages will be different due to the copy-on-write behavior
  • For executable code, the physical pages will be shared as long as the load address of the module was the same.

Well that’s it for now! If you liked this and want to see more ‘Proof of the pudding’, please take a minute to drop a comment, and I will be glad to oblige!

 

标签:EXECUTE,variables,Global,notepad,001,PAE,address,page,physical
From: https://www.cnblogs.com/ioriwellings/p/17745892.html

相关文章

  • Androidstudio中 unable to execute Clang-tidy clazy-standalone is not found or ca
    这个问题可能是因为AndroidStudio不支持clazy,但是在设置菜单中仍然提供了这个选项,并且在这种情况下,它似乎被启用了¹。当通过clangd启用clang-tidy时,没有什么需要做的。当通过clangd禁用clang-tidy时,如果启用了clazy,就会出现这个错误¹。要解决这个问题,你可以尝试以下步骤:1.转......
  • Codeforces Global Round 2
    C题结论就是每行每列不同的个数必须是偶数。D题首先注意到对于长度相同的询问,答案都是一样的。同时相同的s可以直接丢掉。那么我们将s排序之后,将相邻的差再进行排序,然后将询问从小到大处理。相当于是将这些段拼接在一起。#include<cstdio>#include<algorithm>#include<cstr......
  • git config --global core.autocrlf input
    我们一般希望远程仓库中的代码为LF,就用: gitconfig--globalcore.autocrlfinput 就ok了。 gitconfig--globalcore.autocrlfinput这是一个Git的配置命令,它的作用是告诉Git在检出代码时不要自动将行尾转换为CRLF(Windows风格的换行符),而是保留原来的LF(Unix风格的换行符)。......
  • Java 21 新特性:Unnamed Patterns and Variables
    Java21中除了推出JEP445:UnnamedClassesandInstanceMainMethods之外,还有另外一个预览功能:未命名模式和变量(UnnamedPatternsandVariables)。该新特性的目的是提高代码的可读性和可维护性。下面通过一个例子来理解这个功能,try-catch块相信大家都不陌生,都是这样写的:try{......
  • 8.3 NtGlobalFlag
    NtGlobalFlag是一个Windows内核全局标记,在Windows调试方案中经常用到。这个标记定义了一组系统的调试参数,包括启用或禁用调试技术的开关、造成崩溃的错误代码和处理方式等等。通过改变这个标记,可以在运行时设置和禁用不同的调试技术和错误处理方式,比如调试器只能访问当前进程、只......
  • 8.3 NtGlobalFlag
    NtGlobalFlag是一个Windows内核全局标记,在Windows调试方案中经常用到。这个标记定义了一组系统的调试参数,包括启用或禁用调试技术的开关、造成崩溃的错误代码和处理方式等等。通过改变这个标记,可以在运行时设置和禁用不同的调试技术和错误处理方式,比如调试器只能访问当前进程、只......
  • Global Mapper(地图绘制)下载_生成地形图 各个版本下载
    GlobalMapper21是一款实用的桌面GIS应用程序,包含丰富的空间数据处理工具、3D渲染和高程工具、地形修改工具和GPS数据管理工具等,可以将数据转化成光栅地图、高程地图或矢量地图,同时还具有GIS数据的编辑、转换、打印和记录等功能,支持超过250种文件格式。GlobalMapper21带来了新的......
  • GlobalMapper(地图绘制)下载 各个版本下载
    GlobalMapper23版是一款提供给所有GIS专业人士和地图爱好者们使用的多功能地图绘制工具,这款软件不仅为用户们提供了各式各样的空间数据处理工具,从而满足地理空间专业人员的不同需求。而且我们也可以利用GlobalMapper23版百度云来轻松完成地图绘制工作。GlobalMapper23版可以......
  • 微信小程序全局变量(globalData)和缓存(StorageSync)的区别和用法
    globalData和storage的区别一、app.globalData是全局变量,下次进入的时候,就要重新获取,一般用于:1、保存一些可能涉及安全类的数据,例如资源类,每次需要很准确的,就建议用全局变量。2、全局变量每次关闭小程序重新打开的时候,都会进行初始化更新。二、缓存(StorageSync)本地存储,storage......
  • WebStrom提交代码到GitLab报错Error: Cannot find any-observable implementation nor
    项目场景:前端代码完成后,提交代码问题描述提交代码到GitLab时,因自动检测机制导致项目提交失败C:\D\insper\inspur_works\custom-manage-front\node_modules\any-observable\register.js:29 thrownewError('Cannotfindany-observableimplementationnor'+ ^Error:C......