Saturday 26 January 2013

Primer on !vtop, !pte and Virtual Address to Physical Page mapping in x64


Intro

The best reference I could find on the topic was the post from the MSDN NtDebugging blog, Series - Part 3: Understanding !PTE - Non-PAE and X64 article http://blogs.msdn.com/b/ntdebugging/archive/2010/06/22/part-3-understanding-pte-non-pae-and-x64.aspx.

It helped but I needed to really delve into the mapping mechanisms with an example, as well as call out some of the pitfalls in using the relevant WinDbg commands.

Setup

Taking a look at a instance of notepad as example running on a Windows 7 x64 system (this was performed in WinDbg, using sysinterals livekd)

0: kd> !dml_proc 0xfffffa800c0cd890
Address           PID  Image file name
fffffa80`0c0cd890 bbc  notepad.exe       Full details

Switching to process

0: kd> .process /p /r 0xfffffa800c0cd890
Implicit process is now fffffa80`0c0cd890
Loading User Symbols
.........................

Display loaded modules

0: kd> lmuD
start     
<snip>
00000000`ff460000 00000000`ff495000   notepad    (deferred)
<snip>
  
And let's take a look (using the virtual address), MZ header has we'd expect.

0: kd> db 00000000`ff460000 L100
00000000`ff460000  4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00  MZ..............
00000000`ff460010  b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00  ........@.......
00000000`ff460020  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
00000000`ff460030  00 00 00 00 00 00 00 00-00 00 00 00 e8 00 00 00  ................
00000000`ff460040  0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68  ........!..L.!Th
00000000`ff460050  69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f  is program canno
00000000`ff460060  74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20  t be run in DOS
00000000`ff460070  6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00  mode....$.......

(I did do a quick compare with the rest of the image to be sure this was notepad and not just some random MZ header)
  
In order to convert this to the physical address, WinDbg provides two commands to help

!pte
!vtop

Both of these commands walk the below diagram (from the Intel 64 and IA-32 Architecture software development manual volume 3)

!vtop

 !vtop performs the conversion between the virtual address to the corresponding physical address, quite seamlessly  however there's a few minor pitfalls. 

There's two principle formats

!vtop PFN VA 
!vtop 0 VA

PFN - Page Frame Number
VA - Virtual Address

Where 0 is current process context as  set by the .process command (above)
 0: kd> !vtop 0 00000000ff460000
Amd64VtoP: Virt 00000000`ff460000, pagedir 1bf52000
Amd64VtoP: PML4E 1bf52000
Amd64VtoP: PDPE 2`21b80018
Amd64VtoP: PDE 3a001fd0
Amd64VtoP: PTE 17402300
Amd64VtoP: Mapped phys 25051000
Virtual address ff460000 translates to physical address 25051000.

Had we not applied the .process command earlier, our !vtop 0 VA would not have worked :( )  You would get a output like
 0: kd> !vtop 0 00000000ff460000
Amd64VtoP: Virt 00000000`ff460000, pagedir ce985000
Amd64VtoP: PML4E ce985000
Amd64VtoP: PDPE 21bf6018
Amd64VtoP: zero PDPE
Virtual address ff460000 translation fails, error 0xD000014

Alternatively we could have specified the PFN (Page Frame Number) directly. Now you might think (well I did at first) that the pfns from the !pte output should be used. Well actually no, you need the pfn from the DirBase and unlike in 32 bit mode, the pfn is the entire address. 

0: kd> !process 0xfffffa800c0cd890 7
PROCESS fffffa800c0cd890
    SessionId: 1  Cid: 0bbc    Peb: 7fffffdd000  ParentCid: 0484
    DirBase: 1bf52000  ObjectTable: fffff8a00d50a560  HandleCount:  58.
    Image: notepad.exe
    VadRoot fffffa800dcd4870 Vads 58 Clone 0 Private 548. Modified 0. Locked 0.
    DeviceMap fffff8a003ffc4e0

Thus the pfn is 1bf52000 

 0: kd> !vtop 1bf52000  00000000ff460000
Amd64VtoP: Virt 00000000`ff460000, pagedir 1bf52000
Amd64VtoP: PML4E 1bf52000
Amd64VtoP: PDPE 2`21b80018
Amd64VtoP: PDE 3a001fd0
Amd64VtoP: PTE 17402300
Amd64VtoP: Mapped phys 25051000
Virtual address ff460000 translates to physical address 25051000.

So let's take a a look at 0x25051000 physical address (notice the # to indicate physical addresses) Here we use !d* to examine a physical address as opposed d* for a virtual address

0: kd> !db 25051000 L100
#25051000 4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00 MZ..............
#25051010 b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00 ........@.......
#25051020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#25051030 00 00 00 00 00 00 00 00-00 00 00 00 e8 00 00 00 ................
#25051040 0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68 ........!..L.!Th
#25051050 69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f is program canno
#25051060 74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20 t be run in DOS
#25051070 6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00 mode....$.......
   

!pte


0: kd> !pte 00000000`ff460000
                                           VA 00000000ff460000
PXE at FFFFF6FB7DBED000    PPE at FFFFF6FB7DA00018    PDE at FFFFF6FB40003FD0    PTE at FFFFF680007FA300
contains 02A0000221B80867  contains 1C1000003A001867  contains 03A0000017402867  contains 82D0000025051025
pfn 221b80    ---DA--UWEV  pfn 3a001     ---DA--UWEV  pfn 17402     ---DA--UWEV  pfn 25051     ----A--UR-V

What does this all mean?

Well the pte entry at address FFFFF680007FA300 contains the PAE Page-Table Entry containing 82D0000025051025, of which the physical address is bits 12 to (M–1) or more precisely 0x25051000

And of course this gives the same result

0: kd> !db 25051000 L100
#25051000 4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00 MZ..............
#25051010 b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00 ........@.......
#25051020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#25051030 00 00 00 00 00 00 00 00-00 00 00 00 e8 00 00 00 ................
#25051040 0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68 ........!..L.!Th
#25051050 69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f is program canno
#25051060 74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20 t be run in DOS
#25051070 6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00 mode....$.......


Hope this helps your WinDbg en devours. 

Wednesday 9 January 2013

Integer storage & overflow using Haskell


I was curious to see how integer overflow, truncation and type conversion behavior manifested itself in Haskell programs. I also wanted to see what type of warnings were produced and what was allowed or not. Whether it was possible to to detect it. Yes, these are the type of things I think about.

The reference I always go back to when auditing C code for these issues, is Mark Dowd's The Art of Software Security Assessments, specifically chapter 6. Take a look at http://pentest.cryptocity.net/code-audits/. While you're there that whole website is full of great material from a number of excellent courses.

So, let's take a look at the following haskell integer datatypes.

Word(x):  Unsigned integer, bounded
Int(x): Signed integer, bounded.
Integer: Signed integer, unbounded.

(x) refers to size specifiers for Word and Int size (8/16/32/64)

The system used was:
Linux ubuntu 3.2.0-29-generic #46-Ubuntu SMP Fri Jul 27 17:03:23 UTC 2012 x86_64 x86_64 x86_64
GHCi, version 7.4.1

We will look at a few examples in the following areas:

- Basic Representation
- Truncation
- Arithmetic Overflow
- Basic Type Conversion
- Type Conversions in Operations
- Rotate signed extensions

Focusing primarily on the Int and Word types, as Integer is supposed to be signed and unbounded.

Basic Representation
Beginning with a few basic assignments 
Prelude Data.Word Data.Int> 1000 :: Int16 
1000
Prelude Data.Word Data.Int> 1000 :: Word16
1000
Prelude Data.Word Data.Int> -1000 :: Int16
1000

(which is 1111101000)

Consider the Unsigned Word8 type with a range of [0,255]
Prelude Data.Word Data.Int> let a=254::Word8
Prelude Data.Word Data.Int> a
254
Prelude Data.Word Data.Int> let a=256::Word8
Prelude Data.Word Data.Int> a
0
Prelude Data.Word Data.Int> let a=257::Word8
Prelude Data.Word Data.Int> a
1

One interesting thing is the interpreter doesn't complain about assigning a negative number to a unsigned type. 
Prelude Data.Word Data.Int> let a = -100 :: Word8
Prelude Data.Word Data.Int> :t a
a :: Word8
Prelude Data.Word Data.Int> a
156

Where does the 156 come from? Well the 2's complete representation of -100 is 10011100 which when treated as unsigned binary number is 156. (http://en.wikipedia.org/wiki/Two's_complement)

Now I looked for a means to detect if a overflow or out-of-range assignment had occurred but I could not find a mechanism in the exception handling or other documents. One reference stated that overflows are considered programmer errors and are up to the programmer to detect/correct (http://www.haskell.org/haskellwiki/Error_vs._Exception). If there is a mechanism please do let me know. 

Or something like some of the C techniques to programmatically check. 

Truncation
Next the signed Int8 type with a range of [-128 127] is assigned a value which is too large. 
Prelude Data.Word Data.Int> 1000 :: Int8 
232
1111101000
11101000 = 232


The value is simply truncated to the lower 8 bits and displayed
Prelude Data.Word Data.Int> 1000 :: Int8 
-24
1111101000
11101000 (Treated as Two's Complement) = -24


In this case the value is truncated to the lower 8 bits and rendered as a two's complement.

Arithmetic Overflow
Now for a simple case integer addition overflow.
Prelude Data.Word Data.Int> let b = 1 :: Int8
Prelude Data.Word Data.Int> let c = 127 :: Int8
Prelude Data.Word Data.Int> let d = b + c
Prelude Data.Word Data.Int> d
-128
Prelude Data.Word Data.Int> :t d
d :: Int8

What I found interesting is that the Int8 type was propagated to the result regardless of the overflow. 
Prelude Data.Word Data.Int> let a= -128 :: Int8
Prelude Data.Word Data.Int> let b= -1 :: Int8
Prelude Data.Word Data.Int> let c = a + b
Prelude Data.Word Data.Int> :t c
c :: Int8
Prelude Data.Word Data.Int> c
127

And now with Word8 [0 255], we see the type is propagated and the value wraps.  
Prelude Data.Word Data.Int> let a = 5 :: Word8
Prelude Data.Word Data.Int> let b = 255 :: Word8
Prelude Data.Word Data.Int> let c = a + b
Prelude Data.Word Data.Int> c
4
Prelude Data.Word Data.Int> :t c
c :: Word8

In a later post will take a look at sign extensions in shift / rotations, type conversions (with to/fromIntegral) and greater examination of the Integer type.



Wednesday 3 October 2012

CSAW 2012 CTF - WEB 300 - Writeup


For this problem, we were given login credentials and told the administrator has the key. After mapping the application and trying some test inputs it was clear that there was a SQL injection in the horse.php page for the id parameter, the errors were readily displayed. .

sqlmap made short work of dumping the database structure

./sqlmap.py -u http://128.238.66.217/horse.php?id=1 –dump-all

<...snip...>
Database: csaw_chal1
Table: sessions
[0 entries]
+---------+------------+---------+
| user_id | session_id | session |
+---------+------------+---------+
+---------+------------+---------+
<...snip...>

Database: csaw_chal1
Table: users
[0 entries]
+---------+------+-------+----------+----------+
| user_id | name | level | username | password |
+---------+------+-------+----------+----------+
+---------+------+-------+----------+----------+

Unfortunately due to the “WAF” the database contents weren't automatically dumped. After some manual attempts a suitable bypass was found. The password hash for the administrator user (Mr. Corgi) was retrieved from the users table. I let john attempt to crack it for awhile while I finished off the reversing problems. However after a hour or so the password wasn't cracked, so I looked at impersonating the administrator. Fortunately in the sessions table there was a active session for the admin user.
  



Using burp, I used the extracted session key to impersonate the admin user, which produced the key. 



Some other great write-ups on CSAW 2012.

http://eindbazen.net/
http://blog.lse.epita.fr/cat/writeups-csaw-ctf-2012-quals/
http://raidersec.blogspot.ca/2012/09/csaw-ctf-quals-2012-recon-1-3-writeup.html

Thanks again to the CSAW folks for putting this together.

Monday 1 October 2012

CSAW 2012 CTF - WEB 600 – Write Up


After accessing the challenge website, one was presented with a directory listing containing two files submit.php and submit.phps. It was possible to view the contents of submit.phps (below), furthermore both files were the same size. 

<?php
$key = "key{XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}";
$pass = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
echo $_GET['pass'];
if ( strcasecmp( $_GET['pass'], $pass ) == 0 ) {
echo($key);
echo "got it";
}
?>

It's apparent the program will compare a GET parameter named pass against a hardcoded string using the strcasecmp function, if the result of this comparison is 0 the key is displayed. Unfortunately the key was not a bunch of Xs. 

Focusing on the the strcasecmp function, where there other ways of making it output 0, besides the obvious case where the strings were equal.

A quick trip to php.net, yielded nothing useful for strcasecmp, however since this function is a wrapper for strcmp (I believe), I took a look there, and sure enough the first two comments yielded the answer.


In short in modern php versions, the function will return a 0, if any of the parameters is an array. So the following url was constructed to create array for pass.


The key was:
key{this_is_how_our_scoreboard_was_owned_last_night}

And let me just add that this was a really fun CTF and great weekend, well worth working to well past sun up. I look forward to CSAW each year. Anyone who is interested in security and especially CTFs, I always recommend CSAW as the questions start accessible and ramp up to quite challenging. (Although I did miss having to call for Dan's burritos this year)