HackTheBox – Headache2

In this write-up we will be visiting theĀ headache2 challenge from HackTheBox.

OwO What’s dis anomaly?


We are given a file named headache2 but it does not appear to be an ELF binary. We can attempt to detect the filetype using the UNIX file command or read the first few bytes to determine if the file contains a magic number.

The file appears to be a data blob. We can use binwalk to check if the data blob contains any embedded files or compressed blobs.

There appears to be a 64-bit ELF file embedded in the data blob. We can extract it using binwalk once more as shown below.

Now that we have extracted the ELF file, we can open it in our disassembler of choice for further analysis.

The _start function seems to invoke a function named kernel::kernel_main. Inside the kernel_main function we find a buffer initialization area as shown below.

The above area initializes a bunch of distinct buffers which are all used in a trailing switch-statement. The first case is shown below.

If the switch-statement expression evaluates to “ateam”, then the above case is executed. One of the initialized buffers is XOR cipher transformed using 0x7c as the XOR key, and the result is printed to the standard output.

We can retrieve the contents of the decoded buffer by applying the same XOR cipher transformation on the contents of the buffer as shown in the illustration above. This turned out to be a fake flag.

If the switch-statement expression evaluates to “goeo_”, then the above case is executed. One of the initialized buffers is XOR cipher transformed using 0x5c as the XOR key, and the result is printed to the standard output. In this case however, the loop is unrolled.

We can retrieve the contents of the decoded buffer by applying the same XOR cipher transformation on the contents of the buffer as shown in the illustration above. This turned out to be a fake flag.

If the switch-statement expression evaluates to “morph3”, then the above case is executed. One of the initialized buffers is XOR cipher transformed using 0x5b as the XOR key, and the result is printed to the standard output.

We can retrieve the contents of the decoded buffer by applying the same XOR cipher transformation on the contents of the buffer as shown in the illustration above. This turned out to be a fake flag.

If the switch-statement expression evaluates to “r4j”, then the above case is executed. One of the initialized buffers is XOR cipher transformed using 0x2c as the XOR key, and the result is printed to the standard output. Another one of the initialized buffers is however also XOR cipher transformed using a dynamically generated XOR key, and the result is once again printed to the standard output.

We can retrieve the contents of the first decoded buffer by applying the same XOR cipher transformation on the contents of the buffer as shown in the illustration above. This turned out to be a fake flag.

To decode the second buffer we must first compute the XOR key used by the application. We can compute the XOR key by tracing the variable used to derive the XOR key back to the initialization area and reuse the variable contents to generate the same XOR key as shown below.

0x0d ^ 0x25 ^ 0x0d ^ 0x25 ^ 0x0d ^ 0x25 ^ 0x0d ^ 0x25 ^ 0x0d ^ 0x25 = 0x28

We find that the XOR key generation expression should evaluate to 0x28.

We can retrieve the contents of the decoded buffer by applying the same XOR cipher transformation on the contents of the buffer as shown in the illustration above. Interestingly, this did not yield a valid printable result.

If the switch-statement expression evaluates to “xct”, then the above case is executed. One of the initialized buffers is XOR cipher transformed using 0x6f as the XOR key, and the result is printed to the standard output.

We can retrieve the contents of the decoded buffer by applying the same XOR cipher transformation on the contents of the buffer as shown in the above illustration. This turned out to be a fake flag.

Since all decoded buffers except the second buffer in the “r4j” case turned out to be fake flags, we should once again attempt to retrieve the decoded contents of that buffer. The generated XOR key appeared to be wrong, but since we know that the buffer is decoded using a single-byte XOR key, we can simply brute-force the XOR key by attempting to XOR cipher transform the buffer using all 256 possible byte values as shown below.

We find that XOR key 0x02 yields a readable result, HTB{r4j_1s_My_Senp4i!}, which turned out to be the real flag.

And there you have it – the challenge has been solved!

Leave a Reply