Blog

Solving a Capture the Flag Challenge - Step by Step

  • 22 August 2022
  • 0 replies
  • 619 views
Solving a Capture the Flag Challenge - Step by Step
Badge

Introduction

Thanks to everyone who took part in Cymulate’s Capture the Flag (CTF) challenge, “Binushka”. The challenge was created for the Blackhat 2022 event and everyone who solved it was able to claim a prize at Cymulate‘s Blackhat booth. For anyone who was curious about the full solution, this article will go through it step by step.

 

The Binushka Challenge (Reversing)

 

A rule of thumb is that before beginning to solve a CTF challenge, you should see if the name of the challenge hints to its solution. The name of this one was “Binushka”, which can be split into two parts: “bin and “ushka”.

The first part of the name is clear. “Bin” stands for binary. Something that also hints to this is that the name of the file is “bin_bin_bin”.

The second part of the name, “ushka” is from the second half of the word “babushka.” Apart from the literal meaning of “babushka” (grandmother in Russian), there is also a doll named the

babushka doll—whose official name is actually the matryoshka doll. The matryoshka doll is a set of wooden dolls of decreasing size placed one inside another.

So, taking those two words, the file named ‘bin_bin_bin’ is actually a hint that there are some binaries inside binaries—sort of like a matryoshka doll of binaries.

‘bin_bin_bin’ -> ‘bin_bin’ -> ‘bin’.

 

Now that you understand the name of the challenge, I will download it and start trying to reverse the binary.

After initially running the binary, I see that it tries to open a file that doesn’t exist:

 

So, I open the file in IDA.

I see a call to a function called ‘antidebug’, and I guess that this function checks if the binary is debugged with the ‘ptrace’ command. If the answer is yes, the process is terminated. I also see an attempt to open a file named ‘bin_bin’, if the file doesn’t exist I will get the same error you saw above.

So I create a file named ‘bin_bin’ to understand what’s going on:

It seems I hit the ‘puts’ function I saw earlier after I entered the if condition. So, apart from calculating the size of the file with the ‘ftell’ function what else happening here?

I need to check the assembly code to see the whole picture.

I see that after the last ‘fseek’ function there is a ‘cmp’ call to a variable on the stack with the value of zero. If the variable is zero, I jump to ‘loc_1503’ and this leads me to the ‘puts’ that I saw above.

 

 

If the value is not zero, I will jump to another flow that contains a validate function. The IDA decompiler didn’t show this at all because the variable value is hard coded zero so there is no scenario that I go to the second flow as long as I don’t patch the binary 😊.

 

So, I patch the binary and change the ‘jz’ to ‘jnz’ which means I will not jump to ‘loc_1503.

After I patch the file and run the binary, I get the output ‘Validation failed 😞’.

So, I return to the second flow where I saw the ‘validate’ function. Now the IDA decompiler shows me the flow of the ‘validate’ function, due to my patch.

I assume my target is to hit the ‘Validation succeeded 😊which means I have created the correct ‘bin_bin’ file. To do so, I need the ‘validate’ function to return to ‘true.’

 

Variables:

1. The variable ‘v4’ will store the size of the desired ‘bin_bin’ file

2. The variable ‘dest’ will contain a stream of bytes in the size of 0x13338

3. The ‘validate’ function will get four arguments.

  • File descriptor to our ‘bin_bin’ file
  • ‘dest’ variable which contains a stream of bytes in the size of 0x13338
  • Size of ‘bin_bin’ file
  • Value of 0x13338

The stream of bytes in the size of 0x13338 that will be copied to the ‘dest’ variable:

Now I will dive into the validate function and make some refactoring:

 I notice an interesting string, ‘Y0u_907_7h’. After analyzing the code, it looks like there is a xor operation between the ‘bin_bin’ file and the string ‘Y0u_907_7h’, and every result of the xor operation will compare to the byte stream that is stored in dest. If I encounter a byte from ‘bin_bin’ that after the xor operation doesn’t equal to the equivalent byte in the dest variable, the function will return zero (False) 😟.

 

My mission is clear: to generate a valid ‘bin_bin’ file I need to execute the xor operation between the string and the stream of bytes in the ‘dest’ variable. So, I execute a python script in IDA. Offset 0x2098 is the start of the byte stream that is copied to our ‘dest’ variable, in size 0x13338.

And…what a surprise! The ‘bin_bin’ file is an ELF file, and the validation was successful.

Long story short, the ‘bin_bin’ file has the same logic as ‘bin_bin_bin’, but the only difference is the string which used for the xor operation: the string is ‘3_Pa55w0RD’. If I concatenate the two strings, I will get the string: ‘Y0u_907_7h3_Pa55w0RD’.

And then I see ‘bin’ is an ELF file and the validation succeeded.

The last binary is a little different, so I open it in IDA after I patch the ‘jz’ command to ‘jnz,’ like in the previous binaries.

In this binary, instead of xor operation, I have the function ‘shuffle’, and this time the shuffle will be executed on the file named ‘flag.zip’ (seems like I am close to the flag!). The shuffle accepts two arguments: the desired file (‘flag.zip’) and his size. Basically, the function initiates the rand function with the seed 0x1337.

After that, it generates random numbers that will be used as indexes for swap operations.

The program opens the file and shuffles all its bytes, and later compares the shuffled file with the ‘dest’ variable in the validate function.

My mission now is to build an ‘unshuffle’ script that will be executed on the ‘dest’ variable to get the correct ‘flag.zip’ file. Due to the fact I got the seed 0x1337, building the ‘unshuffle’ script will not be a problem.

After I run the python script, I get the final file: ‘flag.zip’ which contains an image called ‘flag.jpg,’ but it’s locked with a password!

I think back to the strings I used to xor the previous binaries. After I concatenated them previously, I got the string: ‘Y0u_907_7h3_Pa55w0RD’.

Using this password, the file unlocked successfully, and I got the flag 😊

 

 

 

About the Author

Elad Beber - Vulnerability Researcher at Cymulate. A cybersecurity expert which specializes in Cloud environments and low-level reverse engineering. Before joining Cymulate, Elad worked as an offensive mobile security researcher, and he holds a BSc degree in Computer Science from HIT. Elad loves to solve CTF’s and he is a member of the CamelRiders CTF team.

 

If you want to learn more about Cymulate’s capabilities for red teamers, click here >> https://cymulate.com/resources/red-team-automation-brief/

 

Want to try our challenge? Please see it attached to this post

⬇️


0 replies

Be the first to reply!

Reply