Wargames MY 2024

Writeup by Pleiades

Pwn/Screenwriter

Challenge Description : Use our software to craft your next blockbuster hit!

Challenge Summary : This challenge involves overwriting the FILE struct to gain arbitrary read and write

Author : Ren

Source Code
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

void init(){
    setvbuf(stdin,0,2,0);
    setvbuf(stdout,0,2,0);
    return;
}

void menu(){
    puts("1. Set screenwriter name");
    puts("2. Write script");
    puts("3. View reference");
    puts("4. Exit");
}

int get_choice(){
    char tmp[5] = "";
    printf("Choice: ");
    fgets(tmp,4,stdin);
    return atoi(tmp);
}

void main(){
    init();
    char* name = malloc(0x28);
    FILE *ref_script = fopen("bee-movie.txt","r");
    FILE *own_script = fopen("script.txt","w");
    puts("Welcome to our latest screenwriting program!");
    
    while (true){
        int choice = 0;
        menu();

        switch (get_choice()) {
            case 1:
                printf("What's your name: ");
                read(0,name,0x280);
                break;        

            case 2:
                char own_buf[0x101] = "";
                printf("Your masterpiece: ");
                read(0,own_buf,0x100);
                fwrite(own_buf,1,0x100,own_script);
                break;

            case 3:
                char ref_buf[0x11] = "";
                memset(ref_buf,0,0x11);
                fread(ref_buf,1,0x10,ref_script);
                puts("From the reference:");
                puts(ref_buf);
                break;

            default:
                printf("Goodbye %s",name);
                exit(0);
        }
    }
}

Looking at the source code, we can see an obvious buffer overflow in option 1 which lets us overwrite data in the heap. However, it is not immediately clear what we are suppose to overwrite.

image

Looking at it in gdb, we can see our name chunk with size 0x31 at the top. After that, theres another chunk with size 0x1e1 followed by the value 0xfbad2488. When I saw this value, FSOP immediately came to mind. What is a FILE struct? Lets let @Ren explain

image

You can take a look at the definition in elixir bootlin

FILE Struct

The FILE Struct contains many fields which manage buffering.

Analysis

image

After using option 3, we can see that the struct is now populated with values.

image

The contents of the bee script is read into 0x405690 which corresponds to the values in the struct above. Now, our goal will be to overwrite the pointers on the struct to trick it into thinking theres a buffer located somewhere else. Then we will use option 3 to leak this value. Our target will be the GOT entry of puts()

image

Now that we know where is libc, maybe we can spawn a shell on the server. To do that, we need to be able to freely write anywhere in memory. Luckily for us, there is a 2nd file struct which lets us write data. Now, we should overwrite the struct fields to trick libc into thinking that the buffer is located somewhere else. But where should we write to? I used angry-FSROP to spawn shell on server.

Getting Arbitrary Write

image

Now, the buffer for our write is located at _IO_2_1_stdout_. The next thing to do would be to overwrite stdout with our fake file struct.

image
Solve Script

Side Note

There are multiple ways to solve this challenge, potentially overwriting the return address of read() or overwriting the exit functions handler with a one gadget. I tried both but it didnt work for me so I guess its a skill issue. Though, I was very satisfied with this because its my first time solving a FSOP challenge after reading writeups about it.

Game/World 1

When saving the game, we get a RMMZSave file which we can edit using this Save Edit

image

Then, just play the game and one shot the bosses to get all the flag. Flag 1, 2 and 3 is obtainable by killing the boss. Flag 4 can be obtained by killing the lava world boss and walking back out. The flag is written on the floor. The final flag is obtained by unlocking the chest and entering the password "wgmy". Hints about the password is given as "23 7 13 25".

Game/World 2

Open the apk in APKLab and look for interesting things. One thing I found was the Enemies.json

image

"params":[600,0,20,20,20,20,20,20]

I assumed the params are the stats of the monster and just modified the biggest number (assuming to be HP) to 1. Then, recompile the APK and sign it. Then install the game in BlueStacks and play through the game to get all the flags. Flags are obtained in the same way as World 1

Rev/Stones

Running strings on the file shows that its a python executable

image

Use pyinstxtractor on the exe.

Extracted

From the challenge description, theres a /flag endpoint on the server so just navigate to http://3.142.133.106:8000/flag and the server will respond with a YouTube video link. Send a get request to http://3.142.133.106:8000 with the date set to the upload date of the YouTube video will give us the flag.

Rev/Sudoku

Once again, another python executable. Just use pyinstxtractor and pycdc to get the original code back

Extracted

Solve

Solve Script
image

Our output is w.my2ba914045b56c5e58..1b4a593b05746 but since we know the flag format and we know that the hash is hex values, we can just fix the flag to wgmy{2ba914045b56c5e58ff1b4a593b05746}

Crypto/Rick's Algorithm

To bypass c % pow(flag,e,n) we need to add n onto the ciphertext and then to bypass flag % pow(c,d,n), we can just multiply 2**e to the ciphertext. Now send it to the server which it will decrypt for us and we will get the flag in the form of 2m so divide 2 and we will get the flag.

Solve Script

Crypto/Hohoho3

Basically it checks the lsb of our (crc xor name) and only xor with m if it's 1 that means if we send 127 we will be skipping 7 iterations of this xor operation only the right shift is applied every iteration which we can still calculate at the 8th iteration we let it xor with m cuz now we know our token and crc value meaning m can be calculated by xoring the other two values

Solve Script

Crypto/Hohoho3 Continue

We can reuse the script from Hohoho3 to solve this too.

Solve Script

Forensic/I Cant Manipulate People

The challenge is about network analysis and they provided us with a pcap file called traffic.pcap. Therefore, I used Wireshark to further analyze the traffic, and I observed that there are multiple ICMP protocol that are being sent as ping requests, so I checked out the packets.

image

Inside the first ICMP packet, I was able to observe that the last byte of the data was a readable ASCII character, so I continued to look at the other ICMP packets based on their sequence

image

It seems that the last byte of the ICMP packets are printing an ASCII character that resembles the flag format of the competition which is WGMY{flag}

image

Retrieving the characters manually could be time consuming and there is a high possibility of human errors so I create a simple python script that will retrieve every single last byte of the ICMP packets and convert them into readable ASCII characters using scapy. By running the script, we will be able to retrieve the entire flag.

image

Flag: WGMY{1e3b71d57e466ab71b43c2641a4b34f4}

Forensic/Oh Man

The challenge is related to network analysis and it provided us with a file called wgmy-ohman.pcapng. My initial analysis was to use Wireshark to inspect the packets and analyze the traffic. We can see that there are multiple encrypted SMB3 packets, and it requires us to decrypt to further investigate the traffic. Fortunately, we can simply decrypt the packets using NTLM hashes.

image

We can gather the NTLM hashes information from the SMB2 protocol starting from the challenge packet.

image

After successfully gathering all the relevant NTLM hashes, it should look something like this

image

Now we need to convert them into hashcat readable format and then use hashcat to brute force the NTLMSSP password using the rockyou.txt wordlist.

image

After a moment, hashcat should be able to find the correct password which is password<3. Then, we can decrypt the SMB3 encrypted traffic by using Wireshark and placing the password into the NTLMSSP protocol. The SMB3 traffic should be decrypted now, and we can use the export objects function to obtain the files used in the traffic. One of the files called ‘RxHmEj’ contains information on how to restore the corrupted log.

image

I simply created a python script that will restore the minidump by correcting its signature. After that, I used pypykatz minidump feature to extract the credentials from the log.

image

After dumping all the extracted credentials, we can retrieve the flag from one of the passwords

image

Flag: wgmy{fbba48bee397414246f864fe4d2925e4}

Forensic/Unwanted Meow

The challenge provided us with a corrupted JPEG file called flag.shredded and my initial analysis was to check the headers of the image to ensure that the image is in correct signature format.

image

By using xxd, it seems the hex headers of the image are in correct signature format, so I further analyze the image. Eventually, I found out that there are weird ‘meow’ strings contained inside the data of the image.

image

By removing all the ‘meow’ strings from the image data using hex editor, the correct image will be formed, and we will be able to retrieve the flag.

image

Flag: WGMY{4a4be40c96ac6314e91d93f38043a634}

Misc/The DCM Meta

The challenge provided us with a Dicom file and upon opening the file with a text editor, we can see that there are random ASCII characters along with the flag format WGMY contain inside the file

image

The challenge description provided us with some sort of indices that could represents the index of each ASCII characters inside the Dicom file. Therefore, I create a simple python script to rearrange their orders based on the provided indices. By running the python script, we will obtain the flag.

image

Last updated