The Official Site of David Guest

HTB Reversing: Exatlon

Who doesn’t enjoy a little reverse engineering? This Hack the Box reversing challenge is listed as ‘Easy’, and wants us to ‘find the password’. Let’s dive in…

After unzipping the contents of the challenge we have a single ELF binary called exatlon_v1. It’s one we can’t immediately disassemble either, so that’ll need some looking at.

When we run the executable it builds this lovely text artwork a couple of lines at a time slowly. It does this before asking for a password. Incorrect passwords loop back to the beginning. It’s probably been coded like this to prevent brute forcing.

We need to start pulling this binary apart. A hexdump of the exatlon_v1 file showed that it had been packed using UPX:

Thats nothing we can’t handle trivially. If UPX packed it, then it can unpack it too. The following does an in-place unpack – I could have provided a different output file, but I’m not too worried about needing the packed version again!

upx -d exatlon_v1

With the file now unpacked we can start our analysis. Utilising both radare2 and Cutter (which is a nice GUI on radare2), it was time to get into reversing this properly. My screenshots will switch back and forth between the two – as it follows my workflow. Opening the binary at the main function we can see how this program flows.

At the bottom of the main chunk of code, there’s a JNE (opcode 0x75) which I decided to try changing to JE (opcode 0x74) to see what would happen on execution. It quickly confirmed that program doesn’t do anything exciting upon entering the correct password.

One thing that this proved was that I needn’t worry about anything downstream of this JNE. Let’s have a deeper look at this main code block and see what’s going on. The early part of the code is clearly what builds the art slowly, with multiple call __sleep entries. As we go on further we can see where the program asks for the password and a call to a function exatlon. Straight after we can see a string at 0x00404d2d which I’m pretty sure is the flag we want.

0x00404d2d 488d35bc6714. lea rsi, str.1152_1344_1056_1968_1728_816_1648_784_1584_816_1728_1520_1840_1664_784_1632_1856_1520_1728_816_1632_1856_1520_784_1760_1840_1824_816_1584_1856_784_1776_1760_528_528_2000_ ; 0x54b4f0 ; "1152 1344 1056 1968 1728 816 1648 784 1584 816 1728 1520 1840 1664 784 1632 1856 1520 1728 816 1632 1856 1520 784 1760 1840 1824 816 1584 1856 784 1776 1760 528 528 2000 " ; int64_t arg2

If it is: then it has been encoded. That exatlon function at 0x00404d24 must be encoding what we enter before comparing it to this string. Using radare2 lets set a breakpoint right after at 0x00404d29, then enter a character and see what the registers reveal.

Well r10 has an interesting value: 1552. Thats in the range we’re expecting. I checked entering ‘H’ into program next to see if this would return a value of 1152. Why? Because we know the flag will start with ‘HTB’ and that is the starting number in the string we suspect is the password.

Oh look! We’re right! I’d like to know a bit about this encoding thats going on. In theory I could brute-force this backwards but that seems like a cop-out. Something is telling me there’s a simple pattern to this encoding, so I try ‘A’, ‘B’ and ‘C’ as entries into the program. Each number that is returned is 16 higher than last. Aha: Bit-shifting!

With this in mind I opened up the exatlon function and the ‘encryption’ this function was doing caught my eye almost immediately.

Anything stick out like a sore thumb for you? It should, I’ve even selected the bit you want to look at.

shl eax, 4

shl shifts bits to the left by the number given to it in the second argument. In this case 4 positions. So it’s just the ASCII code for the character, bit shifted left by 4. I double checked this using a programmers calculator. Being incredibly lazy, I wasn’t about to go looking up ASCII codes to decrypt the string. Not when I can write a perfectly good bit of python to do that for me. I grabbed the string and formatted it to be used in my decoder.

cat encodedstr | sed -e 's/ /,/g'                                                                                                                                                                                      
1152,1344,1056,1968,1728,816,1648,784,1584,816,1728,1520,1840,1664,784,1632,1856,1520,1728,816,1632,1856,1520,784,1760,1840,1824,816,1584,1856,784,1776,1760,528,528,2000

I needed these comma separated values so that I could make this super easy as you can see below:

#!/usr/bin/python3                                                                                                                                                                                                         
encstr=[1152,1344,1056,1968,1728,816,1648,784,1584,816,1728,1520,1840,1664,784,1632,1856,1520,1728,816,1632,1856,1520,784,1760,1840,1824,816,1584,1856,784,1776,1760,528,528,2000]
strv=""
for x in encstr:
        tbc=x >> 4
        strv=strv+chr(tbc)
print(strv)

Running this gave me the flag and another 20 points.

Leave a Reply

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

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.