Impossible Password HackTheBox Reversing Challenge

Shaswata Das
5 min readMay 9, 2020
Challenge Card

It’s an easy reversing challenge. Let’s execute it!

testing

So, it prints an * and space, then it asks for user input. Whatever we input, it will took only 20 characters and print those in a new line closed by brackets. Let’s look at all printable strings in this ELF, if we can find something interesting.

strings

We get something interesting here, SuperSeKretKey. Now let’s see what happen when we input this string.

after input

It accepts that string and print that in a new line closed by brackets, also it printed a new line with ** and asking for input. Inputting anything doesn’t output anything. Now we will use ltrace, it is a diagnostic, debugging and instructional userspace utility for Linux. It’s like strace but for library function calls.

Executing the ELF with ltrace shows us library function calls libc_main(), scanf(), printf(), strcmp(). We can see that our first input is comparing with that string. Let’s input some gibberish and analyse.

Okay, it calls time(0), srand(), malloc() and bunch of rand(). However before exiting it called another strcmp(), here it’s comparing our input with something gibberish. Let’s copy that and use it again to see what happens.

This time it’s comparing our input string with something different. Looks like it’s comparing our input with random string which is seeding by time(0). We know time(0) returns the time since the Epoch (00:00:00 UTC, January 1, 1970), measured in seconds. So, we can solve this problem by hacking our system time. But we’re doing reverse engineering here, so let’s do it in easy way. There’s a lot of reverse engineering tools such as IDA pro, Ghidra, Radare2. I prefer Radare2, it’s a featureful FOSS reversing tool. Let’s open it with analysis and write mode.

Now seek to main function and print the disassembly.

We can see lots of 64 bit integer declaration and a string which contains the first key. Lets scroll to see what’s more happening in main().

We can see those function calls we traced by ltrace.

Look, after first strcmp() call, it’s comparing our input with that string.

The highlighted instruction means if that strcmp returns 0 (which means matched in C) it’ll jump to instruction 0x400925, otherwise instruction pointer will execute next instruction moving 1 to stack and then call exit.

We found an interesting function call. Which is fcn.0040078d().

Let’s seek to that function and print the disassembly.

Hmm. It’s reminding us that library function call time(0) on 0x004007b3, srand() on 0x004007d9 as well as malloc() on 0x004007e9.

We found 20 rand() calls using ltrace and here is one rand(), 2 conditional jump and 2 unconditional jump instructions. So, this is a loop which is iterating 20 time to generate our random string. This function is a mess for us, random things are generating. Let’s back to main() and try to patch it intelligently.

On main(), it’s the second strcmp() call we’ve seen using ltrace. It will set it’s return value to eax register.

The next instruction is test, it performs a bitwise AND operation on two operands. This will set ZF(Zero_Flag) to 1 if eax is < 0.

On next instruction jne 0x400976 means, if ZF is not 1 jump to instruction 0x400976. So, on wrong input it won’t call fcn.00400978(). Lets seek to instruction pointer 0x00400966 and patch it.

We will write jmp 0x0040096a to make it jump on that instruction as if our password matched!

We can print the disassembly again and see that we patched the binary successfully. Now it’s time to execute!

flag

Hooray!!! 🎉 🎉
We got the flag, so successfully patched an ELF. 🎉

--

--

Shaswata Das

Associate Software Engineer, FOSS and InfoSec Enthusiast