> For the complete documentation index, see [llms.txt](https://ctf.zeyu2001.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ctf.zeyu2001.com/2021/the-infosecurity-challenge-tisc-2021/level-3-needle-in-a-greystack.md).

# Level 3 - Needle in a Greystack

> An attack was detected on an internal network that blocked off all types of executable files. How did this happen?\
> \
> Upon further investigations, we recovered these 2 grey-scale images. What could they be?

**Disclaimer:** I did not manage to fully solve this during the competition itself. I did shortly after (an hour after the CTF), though, with the help of my friend Rainbowpigeon :smile:

### Understanding the BMP Files

I noticed early on that `1.bmp` was essentially a Windows executable, but split into chunks with the order reversed. This is pretty obvious given the `MZ` and `PE` file signatures at the end. This allowed me to successfully recover the executable, but as we will see later, was insufficient for me to solve the challenge.

I did not notice that these 'chunks' were essentially the different bitmap lines, which 010 Editor would generously show me!

![](/files/pV4wQVq2cyZr3a18DSfM)

These lines consist of data followed by some padding (null bytes).

![](/files/TTjbR9FKQrZTUyZgjAER)

Extracting the data (in reverse order) and removing the padding bytes thus gives us the executable.

```python
chunk_size = 148

with open('decoded' ,'rb') as infile, open('out.txt', 'wb') as outfile:
	data = infile.read()
	i = len(data) - chunk_size
	
	while i > 0:
		outfile.write(data[i:i + chunk_size][:-3])
		i -= chunk_size
		
	outfile.write(data[:chunk_size])
```

### Understanding the Executable

First of all, we need a `.txt` file as an argument.

![Checking the File Extension](/files/o3ndBOCVhdskd74NpwTx)

Failing which, the file will not be read!

![Reading the File](/files/Q2ETvdFQ2Plz98H7d8sd)

Upon reading the file, its contents will then go thorugh a decoding algorithm (we don't actually need to know how it works for the purpose of this challenge).

![Decoding the File Contents](/files/56yusj6BCkjHJPh0unu1)

Once decoded, a second function is called. The decoded buffer must then start with 0x5A4D (i.e. `MZ`), otherwise the function exits.

![Checking the Magic Bytes](/files/4bi2z5t3emaSTcHc2YyU)

Subsequently, a DLL is loaded. Given that the decoded buffer must start with `MZ`, it is clear that we have to make our input file successfully decode into a DLL in memory, which is then executed.

![](/files/Un7h2H9Q9PRlMogsHWnA)

I figured this much out during the competition, but the missing piece was finding an appropriate input file that will decode successfully. Supplying the contents of `2.bmp` yielded the `MZ` file signature *somewhere* in the decoded contents, but not at the start as was expected.

It turns out that `2.bmp` followed the same structure as `1.bmp`, and with the newfound knowledge about the bitmap file structure, I only had to tweak the previous script to accomodate the line and padding sizes of this second bitmap file.

![](/files/g2GzUR6VruefFruGFEHi)

```python
chunk_size = 100

with open('2.bmp' ,'rb') as infile, open('out.txt', 'wb') as outfile:
	data = infile.read()
	i = len(data) - chunk_size
	
	while i > 0:
		outfile.write(data[i:i + chunk_size][:-1])
		i -= chunk_size
		
	outfile.write(data[:chunk_size])
```

Great, we have some progress!

![](/files/PegtG9eJgVjQstXVrW7x)

We want to know what the DLL is doing, so let's set a breakpoint and dump the decoded DLL from memory.

![Decoded DLL in Memory](/files/XtorvyQYSzYhxYb1UrMw)

A `key.txt` file is required.

![](/files/3yefmMo6CqqeZqOnodzw)

Now, the un-decoded version of `2.bmp` looks conspicuously like a wordlist... and it turns out that while I was staring at the "wrong" stuff and trying to figure out its purpose, I had already stumbled upon what looks like a key!

![](/files/WjCOQdXnOwln0TxgTSsH)

With the correct key file, we get the flag.

![](/files/RHQOxLPYUGluvp6DiLx9)
