直接从分页级结构更改 nx 位
Changing nx-bit directly from paging-level structures
我正在研究 Windows 10 x64 中的虚拟地址转换。我还阅读了有关 PML4、PDP、PDE 和 PTE 的内容,现在我正在尝试更改堆栈的 nx 位,以便通过修改分页结构在堆栈中执行代码。
我看到下图描述了PML4E、PDPE、PDE和PTE中的nx-bit :
Paging Structure
假设我们已经使用 VMWare 创建了一个内核调试 Windbg,并且在来宾计算机中,我们正在使用 xdbg64 调试一个简单的应用程序。
使用 xdbg64 附加到目标进程后,现在 rsp
指向 00000089F06FF848
。
我更改程序流程并执行 jmp rsp
,现在,rip
指向 rsp
但它给出了 access_violation exception
因为 DEP 所以我无法执行堆栈中的任何代码. (之前我用 xor rax,rax
之类的东西更改了堆栈,以便在那里有一个有效的汇编代码)。
现在我使用来自主机的 Windbg 暂停来宾机器并进行有效的翻译,使用 .process /f /i ffffa9841d9952c0
将显式进程更改为目标进程并在按下 g
之后,现在我们的 cr3
翻译有效。
然后我使用以下命令来获取 PML4E、PDPE、PDE、PTE 物理地址:
kd> !vtop 0 00000089F06FF848
Amd64VtoP: Virt 00000089`f06ff848, pagedir 34848000
Amd64VtoP: PML4E 34848008
Amd64VtoP: PDPE 3316e138
Amd64VtoP: PDE 340efc18
Amd64VtoP: PTE 31de77f8
Amd64VtoP: Mapped phys 68a6b848
Virtual address 89f06ff848 translates to physical address 68a6b848.
从above picture开始,第63位是NX-Bit
然后我获取所有条目(PML4E、PDPE、PDE、PTE)以查看其中的内容。
如果是 PML4E,则为:
kd> !db 34848008
#34848008 67 e8 16 33 00 00 00 0a-00 00 00 00 00 00 00 00 g..3............
#34848018 67 88 77 55 00 00 00 0a-00 00 00 00 00 00 00 00 g.wU............
#34848028 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#34848038 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#34848048 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#34848058 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#34848068 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#34848078 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
Converting 67 e8 16 33 00 00 00 0a (01100111 11101000 00010110
00110011 00000000 00000000 00000000 00001010)
到
67 e8 16 33 00 00 00 0b (01100111 11101000 00010110 00110011 00000000
00000000 00000000 00001011)
(请注意粗体部分。)
PDPE 是:
kd> !db 3316e138
#3316e138 67 f8 0e 34 00 00 00 0a-00 00 00 00 00 00 00 00 g..4............
#3316e148 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e158 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e168 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e178 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e188 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e198 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e1a8 00 00 00 00 00 00 00 00-67 f8 0e 34 00 00 00 0a00 00 00 00 00 00 00 00 ................
Converting 67 f8 0e 34 00 00 00 0a (01100111 11111000 00001110 00110100 00000000 00000000 00000000 00001010)
到
67 f8 0e 34 00 00 00 0b (01100111 11111000 00001110 00110100 00000000 00000000 00000000 00001011)
偏微分方程是:
kd> !db 340efc18
#340efc18 67 78 de 31 00 00 00 0a-00 00 00 00 00 00 00 00 gx.1............
#340efc28 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc38 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc48 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc58 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc68 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc78 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc88 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
Converting 67 78 de 31 00 00 00 0a (01100111 01111000 11011110 00110001 00000000 00000000 00000000 00001010)
到
67 78 de 31 00 00 00 0b (01100111 01111000 11011110 00110001 00000000 00000000 00000000 00001011)
而PTE是:
kd> !db 31de77f8
#31de77f8 67 b8 a6 68 00 00 00 81-00 00 00 00 00 00 00 00 g..h............
#31de7808 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7818 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7828 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7838 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7848 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7858 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7868 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
在这种情况下,我没有修改任何东西,因为 67 b8 a6 68 00 00 00 81 等于 01100111 10111000 10100110 01101000 00000000 00000000 00000000 10000001 因为它的最后一位是 1。][=36
在最后一步中,我再次 运行 !vtop
以查看它是否仍转换为相同的物理地址,我发现它是正确的(指向相同的位置。)
然后我按 g
以测试它是否可以执行堆栈内容,但我看到它仍然给出相同的错误 (access_violation) 并且无法执行该地址 ( rsp
).
所以我有以下问题:
我的修改有什么问题没有任何影响?
我听说GDT也有NX-Bit之类的东西可以防止堆栈执行,GDT执行防止和NX-Bit在分页级别有什么区别?
为什么有4个级别定义了nx位?仅更改上述条目之一(如 pml4e)会影响所有其他条目吗?
Whats wrong with my modification that doesn't have any affect ?
你应该已经修补了 PTE 的 NX 位(最高位)。
我刚刚将一些代码修补到 notepad.exe,设置入口点以执行该代码(nop 后跟 RET):
查找记事本:
kd> !process 0 0 notepad.exe PROCESS ffffe000852c5840
SessionId: 1 Cid: 0108 Peb: 7ff689a4e000 ParentCid: 0d74 FreezeCount 1
DirBase: 1b1b9000 ObjectTable: ffffc000a6b08280 HandleCount: <Data Not Accessible>
Image: notepad.exe
将上下文切换到它:
kd> .process /p /i ffffe000852c5840
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
kd> g
Break instruction exception - code 80000003 (first chance)
nt!DbgBreakPointWithStatus:
fffff803`f63d1300 cc int 3
这是RSP(0x64a9b5fdd8)的内容,只是为了确定:
kd> db 64a9b5fdd8 L10
00000064`a9b5fdd8 90 90 90 90 90 90 90 90-c3 c3 c3 c3 c3 c3 c3 c3 ................
检查虚拟到物理:
kd> !vtop 0 00000064a9b5fdd8
Amd64VtoP: Virt 00000064a9b5fdd8, pagedir 000000001b1b9000
Amd64VtoP: PML4E 000000001b1b9000
Amd64VtoP: PDPE 0000000019bbdc90
Amd64VtoP: PDE 00000000416bea68
Amd64VtoP: PTE 00000000501bfaf8
Amd64VtoP: Mapped phys 0000000039fcfdd8
Virtual address 64a9b5fdd8 translates to physical address 39fcfdd8.
再次检查物理地址:
kd> !db 0000000039fcfdd8 L10
#39fcfdd8 90 90 90 90 90 90 90 90-c3 c3 c3 c3 c3 c3 c3 c3 ................
正在考PTE:
kd> !dq 00000000501bfaf8 L1
#501bfaf8 82b00000`39fcf867
将 PTE 转换为二进制文件:
kd> .formats 82b00000`39fcf867
Evaluate expression:
Hex: 82b00000`39fcf867
Decimal: -9029717251904964505
Octal: 1012600000007177174147
Binary: 10000010 10110000 00000000 00000000 00111001 11111100 11111000 01100111
Chars: ....9..g
Time: ***** Invalid FILETIME
Float: low 0.000482503 high -2.58609e-037
Double: -9.78598e-296
设置了最高有效位,这意味着设置了NX位,所以我们不能在堆栈上执行。
我们只想删除那个位,所以从技术上讲,只需删除半字节的高位部分(而不是 0x82,我们将有 0x02):
kd> .formats 02b00000`39fcf867
Evaluate expression:
Hex: 02b00000`39fcf867
Decimal: 193654784949811303
Octal: 0012600000007177174147
Binary: 00000010 10110000 00000000 00000000 00111001 11111100 11111000 01100111
Chars: ....9..g
Time: Fri Sep 2 12:34:54.981 2214 (UTC + 1:00)
Float: low 0.000482503 high 2.58609e-037
Double: 9.78598e-296
重写PTE:
kd> !eb 501bfaf8+7 02
重写的PTE:
kd> !db 501bfaf8
#501bfaf8 67 f8 fc 39 00 00 b0 02-
kd> !dq 501bfaf8 L1
#501bfaf8 02b00000`39fcf867
执行:
kd> g
然后在user-land中执行堆栈没有问题:)
I heared that GDT also have somthing like NX-Bit that prevents the
stack execution, What are diffrences between GDT execution prevention
and NX-Bit in paging-level?
嗯,不,在 GDT 中没有 NX 位这样的东西...此外,在 x64 中,您没有任何用于 CS、DS、SS、ES 的段描述符(只有 GS 和 FS)。
Why there are 4-levels that define nx-bit? Is changing just one of the
above entries like pml4e affect all the other entries ?
确实 :) 这可能会产生有趣的副作用,例如,将 PML4E 的 U/S 位从 S(主管)更改为 U(用户)会提供 user 访问权限此条目引用的所有页面...
我正在研究 Windows 10 x64 中的虚拟地址转换。我还阅读了有关 PML4、PDP、PDE 和 PTE 的内容,现在我正在尝试更改堆栈的 nx 位,以便通过修改分页结构在堆栈中执行代码。
我看到下图描述了PML4E、PDPE、PDE和PTE中的nx-bit :
Paging Structure
假设我们已经使用 VMWare 创建了一个内核调试 Windbg,并且在来宾计算机中,我们正在使用 xdbg64 调试一个简单的应用程序。
使用 xdbg64 附加到目标进程后,现在 rsp
指向 00000089F06FF848
。
我更改程序流程并执行 jmp rsp
,现在,rip
指向 rsp
但它给出了 access_violation exception
因为 DEP 所以我无法执行堆栈中的任何代码. (之前我用 xor rax,rax
之类的东西更改了堆栈,以便在那里有一个有效的汇编代码)。
现在我使用来自主机的 Windbg 暂停来宾机器并进行有效的翻译,使用 .process /f /i ffffa9841d9952c0
将显式进程更改为目标进程并在按下 g
之后,现在我们的 cr3
翻译有效。
然后我使用以下命令来获取 PML4E、PDPE、PDE、PTE 物理地址:
kd> !vtop 0 00000089F06FF848
Amd64VtoP: Virt 00000089`f06ff848, pagedir 34848000
Amd64VtoP: PML4E 34848008
Amd64VtoP: PDPE 3316e138
Amd64VtoP: PDE 340efc18
Amd64VtoP: PTE 31de77f8
Amd64VtoP: Mapped phys 68a6b848
Virtual address 89f06ff848 translates to physical address 68a6b848.
从above picture开始,第63位是NX-Bit 然后我获取所有条目(PML4E、PDPE、PDE、PTE)以查看其中的内容。
如果是 PML4E,则为:
kd> !db 34848008
#34848008 67 e8 16 33 00 00 00 0a-00 00 00 00 00 00 00 00 g..3............
#34848018 67 88 77 55 00 00 00 0a-00 00 00 00 00 00 00 00 g.wU............
#34848028 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#34848038 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#34848048 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#34848058 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#34848068 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#34848078 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
Converting 67 e8 16 33 00 00 00 0a (01100111 11101000 00010110 00110011 00000000 00000000 00000000 00001010)
到
67 e8 16 33 00 00 00 0b (01100111 11101000 00010110 00110011 00000000 00000000 00000000 00001011)
(请注意粗体部分。)
PDPE 是:
kd> !db 3316e138
#3316e138 67 f8 0e 34 00 00 00 0a-00 00 00 00 00 00 00 00 g..4............
#3316e148 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e158 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e168 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e178 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e188 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e198 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#3316e1a8 00 00 00 00 00 00 00 00-67 f8 0e 34 00 00 00 0a00 00 00 00 00 00 00 00 ................
Converting 67 f8 0e 34 00 00 00 0a (01100111 11111000 00001110 00110100 00000000 00000000 00000000 00001010)
到
67 f8 0e 34 00 00 00 0b (01100111 11111000 00001110 00110100 00000000 00000000 00000000 00001011)
偏微分方程是:
kd> !db 340efc18
#340efc18 67 78 de 31 00 00 00 0a-00 00 00 00 00 00 00 00 gx.1............
#340efc28 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc38 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc48 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc58 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc68 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc78 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#340efc88 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
Converting 67 78 de 31 00 00 00 0a (01100111 01111000 11011110 00110001 00000000 00000000 00000000 00001010)
到
67 78 de 31 00 00 00 0b (01100111 01111000 11011110 00110001 00000000 00000000 00000000 00001011)
而PTE是:
kd> !db 31de77f8
#31de77f8 67 b8 a6 68 00 00 00 81-00 00 00 00 00 00 00 00 g..h............
#31de7808 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7818 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7828 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7838 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7848 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7858 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#31de7868 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
在这种情况下,我没有修改任何东西,因为 67 b8 a6 68 00 00 00 81 等于 01100111 10111000 10100110 01101000 00000000 00000000 00000000 10000001 因为它的最后一位是 1。][=36
在最后一步中,我再次 运行 !vtop
以查看它是否仍转换为相同的物理地址,我发现它是正确的(指向相同的位置。)
然后我按 g
以测试它是否可以执行堆栈内容,但我看到它仍然给出相同的错误 (access_violation) 并且无法执行该地址 ( rsp
).
所以我有以下问题:
我的修改有什么问题没有任何影响?
我听说GDT也有NX-Bit之类的东西可以防止堆栈执行,GDT执行防止和NX-Bit在分页级别有什么区别?
为什么有4个级别定义了nx位?仅更改上述条目之一(如 pml4e)会影响所有其他条目吗?
Whats wrong with my modification that doesn't have any affect ?
你应该已经修补了 PTE 的 NX 位(最高位)。
我刚刚将一些代码修补到 notepad.exe,设置入口点以执行该代码(nop 后跟 RET):
查找记事本:
kd> !process 0 0 notepad.exe PROCESS ffffe000852c5840
SessionId: 1 Cid: 0108 Peb: 7ff689a4e000 ParentCid: 0d74 FreezeCount 1
DirBase: 1b1b9000 ObjectTable: ffffc000a6b08280 HandleCount: <Data Not Accessible>
Image: notepad.exe
将上下文切换到它:
kd> .process /p /i ffffe000852c5840
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
kd> g
Break instruction exception - code 80000003 (first chance)
nt!DbgBreakPointWithStatus:
fffff803`f63d1300 cc int 3
这是RSP(0x64a9b5fdd8)的内容,只是为了确定:
kd> db 64a9b5fdd8 L10
00000064`a9b5fdd8 90 90 90 90 90 90 90 90-c3 c3 c3 c3 c3 c3 c3 c3 ................
检查虚拟到物理:
kd> !vtop 0 00000064a9b5fdd8
Amd64VtoP: Virt 00000064a9b5fdd8, pagedir 000000001b1b9000
Amd64VtoP: PML4E 000000001b1b9000
Amd64VtoP: PDPE 0000000019bbdc90
Amd64VtoP: PDE 00000000416bea68
Amd64VtoP: PTE 00000000501bfaf8
Amd64VtoP: Mapped phys 0000000039fcfdd8
Virtual address 64a9b5fdd8 translates to physical address 39fcfdd8.
再次检查物理地址:
kd> !db 0000000039fcfdd8 L10
#39fcfdd8 90 90 90 90 90 90 90 90-c3 c3 c3 c3 c3 c3 c3 c3 ................
正在考PTE:
kd> !dq 00000000501bfaf8 L1
#501bfaf8 82b00000`39fcf867
将 PTE 转换为二进制文件:
kd> .formats 82b00000`39fcf867
Evaluate expression:
Hex: 82b00000`39fcf867
Decimal: -9029717251904964505
Octal: 1012600000007177174147
Binary: 10000010 10110000 00000000 00000000 00111001 11111100 11111000 01100111
Chars: ....9..g
Time: ***** Invalid FILETIME
Float: low 0.000482503 high -2.58609e-037
Double: -9.78598e-296
设置了最高有效位,这意味着设置了NX位,所以我们不能在堆栈上执行。
我们只想删除那个位,所以从技术上讲,只需删除半字节的高位部分(而不是 0x82,我们将有 0x02):
kd> .formats 02b00000`39fcf867
Evaluate expression:
Hex: 02b00000`39fcf867
Decimal: 193654784949811303
Octal: 0012600000007177174147
Binary: 00000010 10110000 00000000 00000000 00111001 11111100 11111000 01100111
Chars: ....9..g
Time: Fri Sep 2 12:34:54.981 2214 (UTC + 1:00)
Float: low 0.000482503 high 2.58609e-037
Double: 9.78598e-296
重写PTE:
kd> !eb 501bfaf8+7 02
重写的PTE:
kd> !db 501bfaf8
#501bfaf8 67 f8 fc 39 00 00 b0 02-
kd> !dq 501bfaf8 L1
#501bfaf8 02b00000`39fcf867
执行:
kd> g
然后在user-land中执行堆栈没有问题:)
I heared that GDT also have somthing like NX-Bit that prevents the stack execution, What are diffrences between GDT execution prevention and NX-Bit in paging-level?
嗯,不,在 GDT 中没有 NX 位这样的东西...此外,在 x64 中,您没有任何用于 CS、DS、SS、ES 的段描述符(只有 GS 和 FS)。
Why there are 4-levels that define nx-bit? Is changing just one of the above entries like pml4e affect all the other entries ?
确实 :) 这可能会产生有趣的副作用,例如,将 PML4E 的 U/S 位从 S(主管)更改为 U(用户)会提供 user 访问权限此条目引用的所有页面...