Wednesday, 20 September 2017

Practical Reverse Engineering Exercise Solutions: Page 35 / Exercise 11

Read the Virtual Memory chapter in Intel Software Developer Manual, 
Volume 3 and AMD64 Architecture Programmer’s Manual, Volume 2: System Programming. Perform a few virtual address to physical address translations yourself and verify the result with a kernel debugger. Explain how data execution prevention (DEP) works.

For this exercise, we first have to set up a remote kernel debugging session. (see https://codemetrix.net/windows-kernel-debugging-setup/https://securityblog.gr/3253/debug-user-mode-processes-using-a-kernel-debugger/ and http://securityblog.gr/3023/windows-kernel-debugging/ for excellent explanations)
Local kernel debugging is not an option in this case since examining register contents requires remote kernel debugging.
As a reminder, WinDbg has two different commands for inspecting memory contents:

d* commands (e.g., db): Display memory data at a specified virtual address
!d* commands (e.g., !db): Display data at a specified physical address

We perform a couple of translations from virtual addresses to physical addresses:

1) Virtual address: 0x8283c054

kd> db 8283c054 L8
8283c054  72 6f 67 72 61 6d 20 63 rogram c

The binary representation of this address yields:

10000010100000111100000001010100‬

By splitting this binary representation into groups, we obtain the indices for the PT:

‭10 000010100 000111100 000001010100‬

Index into page directory pointer table (PDPT): 10  (0x2)
Index into page directory (PD): 000010100 (0x14)
Index into  page table (PT):000111100 (0x3C)
Page offset: 000001010100‬ (0x54)

kd> r @cr3
cr3=00185000

The CR3 register contains the base address of the page directory pointer table (PDPT).
We continue to calculate the PDPT entry:

kd> !dq @cr3+2*8 L1
#  185010 00000000`00188001

Of course, we could employ another program for converting, such as hexadecimal to binary representations.
But WinDbg has already implemented a command for this very purpose, namely .formats.

kd> .formats 00000000`00188001
Evaluate expression:
  Hex:     00188001
  Decimal: 1605633
  Octal:   00006100001
  Binary:  00000000 00011000 10000000 00000001
  Chars:   ....
  Time:    Mon Jan 19 15:00:33 1970
  Float:   low 2.24997e-039 high 0
  Double:  7.93288e-318

The bottom 12 bits of the PDPT entry have to be cleared, which yields:

00000000 00011000 10000000 00000000 

Converted to hex: 0x188000

The page directory entry is in turn calculated by adding the index into PD to the PDPT base:

kd> !dq 188000+0x14*8 L1
#  1880a0 00000000`001d0063

Converted to binary: 00000000 00011101 00000000 01100011

Similarly to the previous step, we have to clear the lowest 12 bits to calculate the base of the page table (PT):

00000000 00011101 00000000 00000000

Converted to hex: 0x‭1D0000

The page table entry is calculated as follows:

kd> !dq 1D0000+0x3C*8 L1
#  1d01e0 00000000`0283c963

Converted to binary: 00000010 10000011 11001001 01100011

Similarly to the previous step, we clear the lowest 12 bits and obtain:

00000010 10000011 11000000 00000000

Converted to hex: 0x283C000

Finally, we can add the page offset to the page entry base to calculate the page's physical address:

kd> !db 0x283C000+0x54 L8
# 283c054 72 6f 67 72 61 6d 20 63 rogram c .L.....

We can confirm the contents of physical address 0x283c054 and virtual address 0x8283c054 are identical:

kd> db 0x8283c054 L8
8283c054  72 6f 67 72 61 6d 20 63 rogram c

As the manual calculation is a rather cumbersome process, WinDbg has already implemented a function to calculate the physical address of a virtual address. In addition to the virtual address, it requires the base address of the page directory pointer table as an input (https://zerosum0x0.blogspot.de/2015/01/practical-reverse-engineering-p-36-11.html)

kd> !vtop 00185000 8283c054
X86VtoP: Virt 8283c054, pagedir 185000
X86VtoP: PAE PDPE 185010 - 0000000000188001
X86VtoP: PAE PDE 1880a0 - 00000000001d0063
X86VtoP: PAE PTE 1d01e0 - 000000000283c963
X86VtoP: PAE Mapped phys 283c054
Virtual address 8283c054 translates to physical address 283c054.

Nevertheless, we perform another translation from virtual to physical address manually:

2) Virtual address: 0x83e31738 

kd> db 83e31738 L8
83e31738  41 db e8 59 e9 0c 00 00

Binary representation of virtual address:

‭10 000011111 000110001 011100111000‬

PDPT Index: 0x2
PD Index: 0x1F
PT Index: 0x31
Page Offset: 0738

kd> r @cr3
cr3=00185000

PDPT base: 
kd> !dq @cr3+0x2*8 L1
#  185010 00000000`00188001

Binary: 110001000000000000001
Truncated: 110001000000000000000 (0x188000)

PD Base: 
kd> !dq 188000+0x1F*8 L1
#  1880f8 00000000`1ff80863

Binary: 11111111110000000100001100011
Truncated: 11111111110000000000000000000 (0x1FF80000)

PT Base:
kd> !dq 0x1FF80000+0x31*8 L1
#1ff80188 00000000`1fc31963

Binary: 11111110000110001100101100011
Truncated: 11111110000110001000000000000 (0x1FC31000)

Physical address and contents:
kd> !db 1FC31000+0x738 L8
#1fc31738 41 db e8 59 e9 0c 00


How does DEP work?

Processors supporting the PAE (Physical Address Extension) can set a flag in the page directory entry, which specifies whether or not the contents of the page can be executed. More precisely, bit 63 of the page directory entry sets the NX flag, which control whether or not instruction fetches from the memory region controlled by this entry are allowed.

No comments:

Post a Comment