MetaRed Argentina CERTUNLP 2024 Writeup

Another CTF I played with team HCS, and it was quite a learning experience for my binary exploitation journey, even though I solved more misc challenges related to Pokemon (yes, I am a huge Pokemon fan)

Published on 11/20/2024 • Tags: ctf, pwn, buffer overflow


flagshop

5.20KB

2024-metared-flagshop.zip

Given a binary, it contained a simple flag shop program:

Basic interface of the terminal connection

I decided to open Ghidra to analyze it further.

Ghidra screenshot of decompilation

Looking at the decompiled binary, the vulnerability in this challenge is a simple integer overflow to make the total cost negative so I could add to the balance to buy the flag.

Calculating 2147483647 divided by 1200

Using a simple calculation to divide a number above the 32-bit signed integer limit with the cost of the discounted flag, I was able to do an integer overflow to buy the flag!

Obtaining the flag

Warmup

3.11KB

2024-metared-warmup.zip

I actually didn’t get to solve this challenge for the points, so I played this challenge just for practice. Given source code that looks like this:

// gcc -Wall -fno-stack-protector -z execstack -no-pie -o reto reto.c
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{

  int var;
  int check = 0x12345678;
  char buf[20];

  fgets(buf,45,stdin);

  printf("\n[buf]: %s\n", buf);
  printf("[check] %p\n", check);

  if ((check != 0x12345678) && (check != 0x54524543))
    printf ("\nClooosse!\n");

  if (check == 0x54524543)
   {
     printf("Yeah!! You win!\n");
     setreuid(geteuid(), geteuid());
     system("/bin/bash");
     printf("Byee!\n");
   }
   return 0;
}

I was able to know that this is a simple buffer overflow challenge, because the buf variable stores only 20 chars yet the fgets function reads 45 characters at maximum. We can solve this without using a debugger because it prints out the variable check for the overflow. So I tested the output with a cyclic pattern to find the offset until the variable gets overwritten.

$ ./reto
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaal

[buf]: aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaa
[check] 0x61616168

Clooosse!

$ cyclic -l 0x61616168
28

We also know that the winning check requires check == 0x54524543 which is the same thing as inputting CERT to the variable. Using this knowledge, I built a payload using python:

Testing variable overflow in local

Using this payload I was able to solve the challenge to obtain the flag using the obtained shell.

Using variable overflow in remote

Trust in my calculator

This is a calculator challenge on netcat, with randomized numbers. Even though this was a simple challenge, it really trained me to properly use pwntools to parse through bytes received from the remote. Also I was late to solving this challenge and another team member stole my points :angry:

View of terminal after connecting to netcat

Using the knowledge that the numbers always come after the : sign, this was my solver script that I brute forced the iteration range to be 20 questions :sob:

from pwn import *

host = 'calculator.ctf.cert.unlp.edu.ar'
port = 35003

io = connect(host, port)
log.info(io.recvuntil(':'))

for i in range(20):
    log.info(io.recvuntil('\n'))
    num1 = int(io.recvuntil(' ', drop=True).decode())
    operation = io.recvuntil(' ', drop=True).decode()
    num2 = int(io.recvuntil('\n', drop=True).decode())
    log.info(f'iteration {i}: {num1} {operation} {num2}')

    if operation == '+':
        result = num1 + num2
    elif operation == '-':
        result = num1 - num2
    elif operation == '*':
        result = num1 * num2

    io.sendline(bytes(str(result), 'utf-8'))

log.info(io.recvall())

io.interactive()

Using the mentioned script, I was able to obtain the flag!

iRunning pwntools script to get flag