#grub.js.org

SecuritnetsCTF - Uncrackable 666points (pwn) writeup.

Overview

Uncrackable was a nice break from the usual memory corruption base challenges you typically see in CTFs. I imagine there were a few ways to approach the problem, but here's one of them.

Reversing

Running the binary through ghidra's decompiler gives us the following:

source code

We can summarise its functionality as follows:

  1. Scan a string of input
  2. Run the command echo -n '%s' |md5sum on the string, effectively hashing it.
  3. Compare the hash to a fixed hash stored within the binary.

Solution

The obvious thing to make sure of first is that the hash has no known plaintext. I quickly ran it through crackstation and found no results.

The next thing to investigate is the fact that we have a command injection vulnerability. Any string we enter is placed into the command, so long as it doesnt have spaces (since scanf is used to grab our input).

For instance, if we enter the string test';echo${IFS}hello, the program will compare the string testd8e8fca2dc0f896fd7cb4cb0031b to its internal hash, since internally the binary is executing the command

echo -n 'test';echo${IFS}hello' |md5sum.

Note: ${IFS} can ne used in the place of a space when spaced cannot be used.

In other words, we have some ability to control the string that is compared to the hash. But we have some problems/limitations.

  1. We can only input 32 characters.
  2. Any bytes we dont control directly will have to be bruteforced.

So we have a clear tradeoff between offering up determined characters versus some input that will hash to a different value every time. If we are guessing a small enough number of bytes, we should be able to brute force the binary into offering up the flag. So what is the shortest linux command that offers up a changing output?

One candidate is w:

w - Show who is logged on and what they are doing.

Example output:

w output

You might notice that it includes time in its output. This gives us the changing element that will cause the resulting hash to change. We contruct a payload like this:

3b9aafa12aceeccd29a154766194';w'

Which forces all but the last 4 characters of the hash. We are now in the realm of bruteforceability.

Full exploit:

from pwn import *

context.log_level = 'error'

while True:

	
	p = remote("54.225.38.91", 1025)
	p.sendline("3b9aafa12aceeccd29a154766194';w'")
	resp = p.recvline()
	if not "not good" in resp:
		print(resp)