Reverse Engineering a Binary 2


Through this paper I am not encouraging people to hack, destroy or steal anything, you must comply with laws and you shall take entire responsibility if you use this knowledge for bad behavior. With great power comes great responsibilities. Reverse engineering is not always legal, check EULA/laws in your country.


In this example we have a bit more complicated program which assigns two integers to varibles then performs a multiplication on them to get our code :

#include < iostream>
int main() {
using namespace std;

 int a;
 int b;
 int c;
 int d;

 b = 10;
 c = 24;
 d = b * c;

 cout << "Please enter your code: ";
 cin >> a;

if ( a == d )
       cout << "Correct!\n";
    } else {
       cout << "Incorrect...\n";
    return 0;

Again this binary is not stripped of its symbols so we can easily debug:

$ file sample
sample: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked
(uses shared libs), for GNU/Linux 2.6.15, not stripped


Lets go ahead and see if strings offers any hide secrets:

$ strings sample
l$ L
Please enter your code:

So we know a bit about this application, it ask for a “code” and depending on your answer will give one an answer “Correct!” or “Incorrect…”

Alright lets go ahead and start disassembling with GDB :

$ gdb -q sample
Reading symbols from /home/jness/tm/sample...done.
(gdb) disass main
Dump of assembler code for function main:
0x0000000000400844 <main+0>:  push   %rbp
0x0000000000400845 <main+1>:  mov    %rsp,%rbp
0x0000000000400848 <main+4>:  sub    $0x10,%rsp
0x000000000040084c <main+8>:  movl   $0xa,-0x8(%rbp)
0x0000000000400853 <main+15>: movl   $0x18,-0xc(%rbp)
0x000000000040085a <main+22>: mov    -0x8(%rbp),%eax
0x000000000040085d <main+25>: imul   -0xc(%rbp),%eax
0x0000000000400861 <main+29>: mov    %eax,-0x10(%rbp)
0x0000000000400864 <main+32>: mov    $0x4009fc,%esi
0x0000000000400869 <main+37>: mov    $0x601180,%edi
0x000000000040086e <main+42>: callq  0x400730 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
0x0000000000400873 <main+47>: lea    -0x4(%rbp),%rax
0x0000000000400877 <main+51>: mov    %rax,%rsi
0x000000000040087a <main+54>: mov    $0x601060,%edi
0x000000000040087f <main+59>: callq  0x400740 <_ZNSirsERi@plt>
0x0000000000400884 <main+64>: mov    -0x4(%rbp),%eax
0x0000000000400887 <main+67>: cmp    -0x10(%rbp),%eax
0x000000000040088a <main+70>: jne    0x40089d <main+89>
0x000000000040088c <main+72>: mov    $0x400a15,%esi
0x0000000000400891 <main+77>: mov    $0x601180,%edi
0x0000000000400896 <main+82>: callq  0x400730 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
0x000000000040089b <main+87>: jmp    0x4008ac <main+104>
0x000000000040089d <main+89>: mov    $0x400a1f,%esi
0x00000000004008a2 <main+94>: mov    $0x601180,%edi
0x00000000004008a7 <main+99>: callq  0x400730 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
0x00000000004008ac <main+104>:        mov    $0x0,%eax
0x00000000004008b1 <main+109>:        leaveq
0x00000000004008b2 <main+110>:        retq
End of assembler dump.

Looking at the above output I find the cmp to stand out as it appears to lead to the jne which decides our fate in this program:

0x0000000000400887 <main+67>: cmp    -0x10(%rbp),%eax

We can see something is being compared against %eax register, lets go ahead and see where -0x10(%rbp) leads:

0x0000000000400845 <main+1>:  mov    %rsp,%rbp
0x000000000040084c <main+8>:  movl   $0xa,-0x8(%rbp)
0x0000000000400853 <main+15>: movl   $0x18,-0xc(%rbp)
0x000000000040085a <main+22>: mov    -0x8(%rbp),%eax
0x000000000040085d <main+25>: imul   -0xc(%rbp),%eax
0x0000000000400861 <main+29>: mov    %eax,-0x10(%rbp)
0x0000000000400887 <main+67>: cmp    -0x10(%rbp),%eax

Ok so it seems we are moving some what appears to be hex values to some of our registers, lets go ahead and see if we can find out the values in a interger:

(gdb) print 0xa
$1 = 10
(gdb) print 0x18
$2 = 24

This is starting to look promising. Lets contiune on and see what happens with this data:

0x000000000040085a <main+22>:mov    -0x8(%rbp),%eax

Alright so first the value in the register (which we know to be 10) is moved to %eax , lets contiune on:

0x000000000040085d <main+25>:imul   -0xc(%rbp),%eax

Ok so the funtion imul is taking our data in the next register, lets go ahead and look that function on at basics_of_assembler.pdf

IMUL multiplies either EAX with value (IMUL value) or it multiplies two values and puts
them into a destination register (IMUL dest, value, value) or it multiplies a register
with a value (IMUL dest, value).

So now that we now that IMUL will perform multiplication all that is left is to try our theory out (10 * 24 = 240):

$ ./sample
Please enter your code: 240