代码之家  ›  专栏  ›  技术社区  ›  Migo Lopak

直接从分页级结构更改nx位

  •  0
  • Migo Lopak  · 技术社区  · 8 年前

    我正在研究Windows 10 x64中的虚拟地址转换。我还阅读了关于PML4、PDP、PDE和PTE的内容,现在我正试图更改堆栈的nx位,以便通过修改分页结构来执行堆栈中的代码。

    我看到了下图,它描述了PML4E、PDPE、PDE和PTE中的nx位:

    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位 然后我获取所有条目(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 ................
    

    转换67 e8 16 33 00 00 00 00 00 0a (01100111 11101000 00010110 00110011 00000000 00000000 00000000 0000101 0 )

    67 e8 16 33 00 00 00 00 00 0b (011001111 11101000 00010110 00110011 00000000 00000000 00000000 0000101 1. )

    (请注意粗体部分。)

    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 ................
    

    转换67 f8 0e 34 00 00 00 00 00 0a (011001111 11111 000 00001110 00110100 00000000 00000000 00000000 0000101 0 )

    67 f8 0e 34 00 00 00 00 00 0b (011001111 11111 000 00001110 00110100 00000000 00000000 00000000 0000101 1. )

    PDE是:

    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 ................
    

    转换67 78 de 31 00 00 00 00 0a (01100111 0111000 11011110 00110001 00000000 00000000 00000000 0000101 0 )

    67 78 de 31 00 00 00 00 0b (01100111 0111000 11011110 00110001 00000000 00000000 00000000 0000101 1. )

    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等于0110111000 10100110 011000 00000000 00000000 00000000 10000001,因为它的最后一位是1。

    在最后一步中,我运行 !vtop 再次查看它是否仍然转换为相同的物理地址,我发现它是正确的(指向相同的位置)

    然后我按 g级 为了测试它,看看它是否可以执行堆栈内容,但我看到它仍然会给出相同的错误(access\u冲突),并且无法执行该地址( rsp )。

    因此,我有以下问题:

    1. 我的修改有什么不对吗?

    2. 我听说GDT也有NX位这样的东西来阻止堆栈执行,GDT执行阻止和分页级别的NX位有什么区别?

    3. 为什么有4个级别定义nx位?仅更改上述条目之一(如pml4e)是否会影响所有其他条目?

    1 回复  |  直到 8 年前
        1
  •  0
  •   Neitsa    8 年前

    我的修改有什么不对吗?

    您应该已经修补了PTE的NX位(这是最重要的位)。

    我刚刚在记事本上补了一些代码。exe,设置入口点以执行该代码(nops后跟RET):

    Notepad with some code

    查找记事本:

    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
    

    那么在用户区执行堆栈就没有问题了:)

    enter image description here

    我听说GDT也有类似NX位的东西,可以防止 堆栈执行,GDT执行预防之间的区别是什么 和分页级别中的NX位?

    嗯,不,GDT中没有NX位之类的东西。。。此外,在x64中没有CS、DS、SS、ES的任何段描述符(仅GS和FS)。

    为什么有4个级别定义nx位?只是改变了 以上条目(如pml4e)是否影响所有其他条目?

    确切地说:)这可能会产生有趣的副作用,例如,将PML4E的U/S位从S(主管)更改为U(用户)给出 使用者 访问此条目引用的所有页面。。。

    推荐文章