Cybersecurity challenge - C++ reversing

You won't find the solution to the challenge here. That is against root-me.org rules. We are simply looking at the C++ aspects of the executable.

This challenge is available on https://www.root-me.org/ and I find it particularly interesting because it is intended to require C++ reverse engineering skills. This is an important skill to have, as detailed in this paper by Paul Vincent Sabanal: http://repository.root-me.org/Reverse%20Engineering/EN%20-%20Reversing%20C++%20-%20Blackhat%20-%20Yason%20Sabanal%20-%20slides.pdf

namely, that there is an "Increasing use of C++ code in malware". The added layer of abstraction makes C++ derived assembler code more difficult to follow than C code.

This challenge is a Linux executable that takes a password as an argument:

$ ./ch25.bin
usage : ./ch25.bin password
$ ./ch25.bin thepassword
Password incorrect.

So lets take the binary into a debugger, in this case edb.

$ ./edb --run ../../ch25.bin password1



And it's immediately obvious that is is a C++ program. Right of the bat we can see the string "usage : " which is displayed if no password is supplied and a number of stream and allocator calls. Scrolling down a little, we come across a line that makes a call to std::operator== and right after that there are string references to success or failure. With just a very basic background in C++ one would understand that this is just the terminology for what is a simple == in C. But even without such knowledge, just based on the strings visible in the code below, it stands to reason that this is a string comparison checking the entered password against the right one. Lets put a breakpoint on that line and execute up to there:

And we can see the password we passed on the command line, "password1" as well as the correct one

However, from the point of view of understanding how C++ compiles into assembly code, this is sort of cheating. Instead, lets take a look and see where this password actually came from.

The first part of the program is simply checking for presence of the password as an argument and prints usage information if it's missing. If the password is present, then we skip ahead to address 0x08048aee, where things get interesting:

And now we can follow the instructions as they perform some typical C++ operations.


lea eax, [ebp-0x15] ; load address of variable_A into eaxmov [esp], eax ; move address onto stackcall ch25.bin!std::allocator<char>::allocator()@plt ; call constructor for allocator which goes into variable_Alea eax, [ebp-0x15] ; load address of variable_A into eaxmov [esp+8], eax ; move address onto the stack 8 bytes over the stack pointermov dword [esp+4], 0x8048dc4 ; move address of variable at 0x8048dc4 onto stack 4 bytes over the stack pointerlea eax, [ebp-0xc] ; load address of variable_B into eaxmov [esp], eax ; move address onto stackcall ch25.bin!std::basic_string.........basic_string(....)@plt ; call string constructor

So all this is simply to create an allocator which can then be passed to a string constructor, i.e.

string myString1 = [whatever_0x8048dc4_points_to];

this then gets done one more time :

string myString2 = [whatever_0x8048dcc_points_to];

what follows is regular function call which gets passed the two strings and returns some result. This should be familiar to anyone with reversing C programs.

call ch25.bin!std::plouf(std::string, std::string);

Next, we see another C++ peculiarity which has nothing to do with the password check:

sub esp, 4 ; decrement stack pointer

lea eax, [ebp-0x10] ; load address of variable_C - this is pretty clearly myString2


call ch25.bin!std::basic_string.........~basic_string(....)@plt ; call string destructor

notice the ~ in front of basic string, which is the destructor taking care of any work necessary to remove the string variable

this is then called by the destructor of the allocator in variable_D

So its pretty clear that the majority of the code in this section is just for C++ housekeeping and it simply allocates two strings and passes them to the function 'plouf' which then creates the result string which the '==' compares. It deallocates the input strings before doing the '=='.

Lets look at the function 'plouf'



Now it's pretty easy to understand. First, it creates an allocator for the string constructor to use and then uses it to make a new string. Then it destructs the allocator because it does not need it any more, but keeps the string. The other functions, such as operator[] and length() are straight forward enough for anyone with experience in C.

edb can create a flow graph from this function but it's nowhere near as good as Ida Pro. So while it does not allow debugging in the free version, it is still very useful for static analysis

It's a pretty small function, and if you are familiar with C reversing, this should no longer pose a challenge.