DeconstruCT.F 2023

Hi all, I participated this year in the DeconstruCT.F event, and I thought I would share my results with you.

Summary

Avail Your Good Boy Points

When reading the rules all the way to the end, we find the first flag of this challenge :

And, that gives us our first 100 points of the game !

Hash Roll

Here, we are given two files, a PDF and a ZIP file, with the following description : “Augustine’s friend took a important file of augustine and stashed it. He was able to grab all the files from his friend’s machine but he is worried that the files are encrypted. Help him get the file back”

The Zip file looks like it has one file in it, flag.jpg, but it is protected by a password. When we open the PDF, this is what we get :

It might be hard to see at first, but there is a very small line at the end of the file, when we read it, this is what is says :

29ebf2f279da44f69a35206885cd2dbc might be something you need

Is this the password ? No, we need to look harder. This string kind of looks like a hash, don’t you think ? If we try to search for what it may be, we find :

Indeed, it was the MD5 hash of the password we were looking for, we can now decrypt the archive, and get our flag :

Here we go, another 50 points for us.

Gibberish

This flag was probably not solved the intended way, but it doesn’t matter too much. for this challenge, we get a file called flag.txt, with what looks like a really long base64 string in it :

Decoding it, it looks like an ELF binary, based on the first few bytes. We could try to run it to see what it does, but we can take a look at the strings present in this binary first, that might save us time, if the flag is stored directly as a string. And, indeed, we find this in the binary :

goodbye���mlh{REDACTED}�Wrong pass

This looks a lot like a flag, doesn’t it ? If we replace the mlh part by dsc, and try this flag, it works ! And that’s 100 more points for us !

debugzero

For this challenge, we are given a website, where the wrong version was deployed. Let’s take a look at the site :

Nothing too interesting here, let’s take a look at the source for the page :

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Todo List</title>
    <!-- CSS only -->
    <link
      href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor"
      crossorigin="anonymous"
    />
    <!-- JavaScript Bundle with Popper -->
    <script
      src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
      integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2"
      crossorigin="anonymous"
    ></script>
    <link rel="stylesheet" href="static/styles.css" />
  </head>
  <body>
    <div class="container">
      <h1>This website is currently under <i>development</i></h1>
    </div>
  </body>

  <!-- John, please don't run the app in debug mode, how many times do I have to tell you this! -->
</html>

Apparently, John ran this app in debug mode, interesting. Searching a bit on the website, we find a Werkzeug console on /console, which means that this is a Flask server :

Hmmm, looking for a bit, I couldn’t find a working way to bypass this authentication popup. Time to try somewhere else. Looking back at the code, we find another interesting file : /static/styles.css, which contains this :

/* Nothing interesting here except this number - XXXXXX */

Okay, we got the pin we were looking for. We now just have to open the debug console, read the flag, and that’s it :

Good, 500 more points for us !

Easy Peasy

This challenge revolves around binary exploitation. We get a copy of the executable file, running on a server which also has a flag :

Running the app, it asks for a password which we do not have (and, in fact, does not exist). Looking for strings did not give us anything useful, so we take a look at the code using Ghidra :

undefined8 main(void)

{
  puts("Please enter the super secret password to display the flag:");
  vuln();
  puts("Invalid password, try again\n");
  return 0;
}

void vuln(void)

{
  char pasword_input [32];
  
  gets(pasword_input);
  return;
}

void win(void)

{
  char local_58 [72];
  FILE *flag_file_pointer;
  
  flag_file_pointer = fopen("flag.txt","r");
  if (flag_file_pointer == (FILE *)0x0) {
    printf("%s %s","Please create \'flag.txt\' in this directory with your","own debugging flag.\n")
    ;
                    /* WARNING: Subroutine does not return */
    exit(0);
  }
  fgets(local_58,0x40,flag_file_pointer);
  printf(local_58);
  return;
}

Okay, basically, the main() function calls a function named vuln(), in which the user inputs his password. The function then returns and the program ends there, no matter what the supplied password is. How are we supposed to get to the flag then ? Well, there is also a win function, which reads the flag and prints it. If we could execute this function, we could receive the flag, but how can we call this function ?

The vuln() function stores the password in a char array of length 32, and does not perform any verification on the user input, this means that we can probably try a buffer overflow here !

Let’s run the program in gdb, and see if this works. To create the exploit input, I used this small python script :

padding = 'A'*32
rbp = "ABCDEFGH"
rip = "4321"

print(padding + rbp + rip)

When we run the program and input this password, it crashes, looking at the registers, we get this :

See the rip register, which controls the next instruction the CPU will execute ? It contains the hex values for the string 4321, reversed because of endianness. This means we can control where the program will go after the vuln() function ! All we have to do is find the address of the win() function using gdb, and input it into our script. This is the gdb command to do this :

info address win

And, when we try it :

Yay, it works ! Let’s try it on the real server :

Well, unfortunately, by that time, the binary running on the server had been changed, and I wasn’t aware of this 😅. Oh, well, at least it worked on my machine 🙂.

Missing

We are given a .rar file, and we can crack it open using john :

rar2john jason.rar > jason.txt
john --wordlist=/usr/share/wordlists/rockyou.txt jason.txt

This gives us the password, now, let’s take a look inside, we find two github repositories.

We can see a few traps, but one thing looks promising in the empty.txt file :

find my github pages site that i accidentaly deleted to find what u want :P

Since this is a Git repository, we can look back in time to see what it was :

aHR0cHM6Ly93d3cuaW5zdGFncmFtLmNvbS90b2RkX2phc29uX3NlY3VyZS8=

Which, decoded, is :

https://www.instagram.com/todd_jason_secure/

After creating an Instagram account ( :'( ), we find this :

We need to find his twitter account for the next step, and a weird string. After creating a Twitter account ( :'( ), we find him :

https://twitter.com/toddjasonsecure

And a bunch of base64 / base32 encoded strings :

ZHNje24wX0YhQEdfSGVSZV86cF9tQDdFfQ==
G5UF6TZVJFH(REDACTED)==

The first one translates to “dsc{n0_F!@G_HeRe_:p_m@7E}“, so it’s probably not too important. The second part is in base32, and when decoded, gives us the last part of the real flag. We are progressing !

Looking back at the Instagram account, we find the first part of the flag in the second image on the account :

And with that, we have this flag ! Hurray ! We even have the second blood on this one 🙂

Space Ahoy

This is a challenge where we are given an image to work with. Using binwalk on it gives us another image hidden inside the first :

binwalk -Me file.jpg

We can also find a peculiar string in the first image :

the aliens are here try slowscan

Using binwalk on the second image, we find a .wav file :

This time, binwalk doesn’t find anything in it. When looking at what slowscan is, I found out that it was a protocol used by radioamateurs to transmit images. Looking a bit more, I found the SSTV library on GitHub by colaclanth which is able to transform SSTV .wav recordings to an image. Using it gave me this image :

Scanning the QR code gave me the flag ! One more down !

sweet-nothing

For this challenge, we come across this website, which apparently has the flag right in front of us :

A lot of things about Italy. Playing a bit with the request, we come across this header :

Accept-Language=en-US,en;q=0.5

What if we change this to Italian ? This is what we get back :

Almost there! Your secret query is "spaghetti".

And, if we add this (query=spaghetti) to our request before sending it :

dsc{REDACTED}

And, we hot our flag for this challenge !

Conclusion

This CTF had quite a lot of guess work, but I enjoyed it. Here are my final results :

I finished 67th out of 1506 contestants, with 7 challenges completed including one second blood. I’m quite happy with this result !


Posted

in

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *