What is Reverse Engineering

Reverse Engineering (RE) is an ad hoc and creative process of extracting the knowledge of design and implementation information from anything we use in reality. Similarly, reversing a software is a practice of analysing the software to examine its internals when we don’t have the source code and utilizing the knowledge we make fun from it in a beneficial manner.

Why Reverse Engineering a Software

In today’s world, there are many reasons for reversing a software. These days the primary purposes of reversing a binary or software are to develop competing products or cracking the existing commercial software. Reversing is very popular when it comes to crackers that defeat various copy protection mechanisms of the software available. Software Reverse Engineering comes in various forms; a malware analyst needs to perform RE to analyse things like malicious software, a Worm or a Trojan which are wide spread. A cryptanalyst will choose reverse engineering to learn cryptographic algorithms and subsequently attempt different ways to crack the encryption/decryption algorithms. In addition, tech companies, that develop million dollar products, will employ a reverse engineer to audit the software to comply with digital rights management (DRM). In all the above cases, we really don’t need the source code of the software. In fact, if we have the source code we don’t even need to conduct RE.

What is Radare2

radare2 is an open source reverse engineering framework used for static and dynamic analysis, digital forensics or software exploitation supporting multiple platforms, architectures and binary formats. Radare2 is shipped with a few other important tools for file metadata extraction, base conversion, unified binary diffing and many others. This program, is not only a great disassembler but also a good debugger, especially when you love working on CLI (command-line interface). Mastering radare2 is not simple since one must remember a multitude of commands in order to use it. But again, it has intuitive command-line control to write, as compared to writing code using the IDA bindings. If you are familiar with IDA Pro or Hopper and you are a CTF player then you should try radare2.

At Loginsoft, we believe that radare2 is an essential tool for reverse engineering any software. In this series of articles, we are going to walk you through the basics of software reverse engineering using radare2 by analysing the crackme challenge (crackme0x04) which can be downloaded here.

Installing radare2 on Linux

We can install radare2 either by cloning from Github repository or from the package managers like (apt install, yum install, brew install). We recommend cloning GitHub repo as following


#cloning from Github repository 
git clone https://github.com/radare/radare2
#change the current the working directory
cd radare2
# run install.sh 
sudo sys/install.sh

Radare2 can be installed on Windows platform just by downloading the executable (https://www.radare.org/r/)

Set of utilities comes with radare2

1. rax2 – A base converter utility
rax2 -s 0x61646164 returns ‘adad’

2. rabin2 – Binary program info extractor
rabin2 -e $binary: Show the entrypoints
rabin2 -i $binary: Returns information about the binary

3. radiff2 — unified binary diffing utility
radiff2 $original_binary $modified_binary

4. radare2 (r2) – Main binary for reversing the software
r2 -w $binary – Running the binary in writable format

Cracking the Challenge crackme0x04

Once we have the binary downloaded, we need to learn the behaviour by dynamic analysis; run it with different set of inputs in order to do this.

Now, it is very clear that a simple ordinary brute force technique is not going to work to capture the flag. It’s time to utilize radare2 libraries to extract the information of the binary ‘crackme0x04’. Using rabin2, retrieve information out of a binary like strings, sections, entry points.

This tells us that this program will run on Linux and it was coded in the C programming language. We can also see the bin-type being “elf”. And there are few strings used in the binary. Let’s roll up radare2 (r2), the main binary.

‘r2’ command takes path of the binary as an argument along with few useful switches (‘-w’,’-d’) which will be covered in the next article. Following the syntax ‘r2 ./crackme0x04’ will bring up the binary on neat and intuitive radare2 CLI.

One of the most important commands in radare2 is ‘?’. It not only lists all the commands available but also works with almost every subcommand. For any binary which we want to dissect, ir can be analysed by the command ‘aaa’. In our case, to find the list of functions in the binary and the address of entry point and main function, we use the commands

  • ‘afll’ – List the available functions
  • ‘ie’ – Returns the address of the entrypoint
  • ‘iM’ – Returns the address of the main function

By observing the functions listed above, we can see several functions ‘printf’, ‘scanf’, ‘main’, ‘check’ being used in the binary. On performing dynamic analysis initially, the function ‘sym.check’ seems interesting. We can use command ‘axt $address’ to check where exactly the code was referenced. The function ‘check’ is called in the ‘main’ function at the address ‘0x8048559’. From this we can determine whether or not the validation part exists in the function. Let’s dig into the function using the command seek ‘s’. As previously mentioned, we can view a list of subcommands by using ‘?’ as a suffix to the seek command.

Now the fun part comes with disassembling the function ‘check’. Radare2 provides another command to print disassembly code of the function using ‘pdf’. ‘pdf @ main’ will analyse the main function and print its disassembly. Similarly, ‘pdf @ sym.check’ prints its disassembly of the ‘check’ function.

[0x080483d0]> pdf @ sym.check 
/ (fcn) sym.check 133
|   sym.check (int arg_8h);
|           ; var int local_dh @ ebp-0xd
|           ; var int local_ch @ ebp-0xc
|           ; var int local_8h @ ebp-0x8
|           ; var int local_4h @ ebp-0x4
|           ; arg int arg_8h @ ebp+0x8
|           ; var int local_4h_2 @ esp+0x4
|           ; var int local_8h_2 @ esp+0x8
|              ; CALL XREF from 0x08048559 (sym.main)
|           0x08048484      55             push ebp
|           0x08048485      89e5           mov ebp, esp
|           0x08048487      83ec28         sub esp, 0x28               ; '('
|           0x0804848a      c745f8000000.  mov dword [local_8h], 0
|           0x08048491      c745f4000000.  mov dword [local_ch], 0
|              ; JMP XREF from 0x080484f9 (sym.check)
|       .-> 0x08048498      8b4508         mov eax, dword [arg_8h]     ; [0x8:4]=0
|       |   0x0804849b      890424         mov dword [esp], eax        ; const char * s
|       |   0x0804849e      e8e1feffff     call sym.imp.strlen         ; size_t strlen(const char *s)
|       |   0x080484a3      3945f4         cmp dword [local_ch], eax   ; [0x13:4]=256
|      ,==< 0x080484a6      7353           jae 0x80484fb
|      ||   0x080484a8      8b45f4         mov eax, dword [local_ch]
|      ||   0x080484ab      034508         add eax, dword [arg_8h]
|      ||   0x080484ae      0fb600         movzx eax, byte [eax]
|      ||   0x080484b1      8845f3         mov byte [local_dh], al
|      ||   0x080484b4      8d45fc         lea eax, dword [local_4h]
|      ||   0x080484b7      89442408       mov dword [local_8h_2], eax
|      ||   0x080484bb      c74424043886.  mov dword [local_4h_2], 0x8048638 ; [0x8048638:4]=0x50006425 ; "%d"
|      ||   0x080484c3      8d45f3         lea eax, dword [local_dh]
|      ||   0x080484c6      890424         mov dword [esp], eax        ; ...
|      ||   0x080484c9      e8d6feffff     call sym.imp.sscanf         ; int sscanf(const char *s,
|      ||   0x080484ce      8b55fc         mov edx, dword [local_4h]
|      ||   0x080484d1      8d45f8         lea eax, dword [local_8h]
|      ||   0x080484d4      0110           add dword [eax], edx
|      ||   0x080484d6      837df80f       cmp dword [local_8h], 0xf   ; [0xf:4]=0x3000200
|     ,===< 0x080484da 7518 jne 0x80484f4 | ||| 0x080484dc c704243b8604. mov dword [esp], str.Password_OK__n ; [0x804863b:4]=0x73736150 ; "Password OK!\n" ; const char * format | ||| 0x080484e3 e8acfeffff call sym.imp.printf ; int printf(const char *format) | ||| 0x080484e8 c70424000000. mov dword [esp], 0 ; int status | ||| 0x080484ef e8c0feffff call sym.imp.exit ; void exit(int status) | `---> 0x080484f4      8d45f4         lea eax, dword [local_ch]
|      ||   0x080484f7      ff00           inc dword [eax]
|      |`=< 0x080484f9 eb9d jmp 0x8048498 | `--> 0x080484fb      c70424498604.  mov dword [esp], str.Password_Incorrect__n ; [0x8048649:4]=0x73736150 ; "Password Incorrect!\n" ; const char * format
|           0x08048502      e88dfeffff     call sym.imp.printf         ; int printf(const char *format)
|           0x08048507      c9             leave
\           0x08048508      c3             ret
[0x080483d0]>

In addition to the command ‘pdf’, radare2 has a great feature called Visual Mode which can be seen by running ‘V’ command. To view various modes we can use the command ‘p/P’ as shown below:

Observing the above disassembled code, we can see a comparison happening ‘cmp dword [local_8h], 0xf’ at the address ‘0x080484d6’ after the call ‘sscanf’. We can crack this challenge by analysing the instruction ‘cmp dword [ebp-0x8], 0xf’ (which compares the sum of input with 15 in decimal); once it matches, it prints the text “Password OK!”

Another way we can do this is by modifying the binary at address ‘0x080484da’ by overwriting with NOP (\x90) to avoid the conditional jump and to print “Password OK!” on any input that user provides. In order to do that, we must run the binary with writable mode (-w) using radare2. Here comes the final solution.

Challenges like ‘crackme’ will help us learn how to reverse software. We will look at a few other features of radare2 by cracking another challenge in the next article. We hope this guide has given you a better understanding of radare2.

Reference:

Radare2 book: https://www.radare.org/get/radare.pdf

Github: https://github.com/radare/radare2

 

Credit: ACE Team – Loginsoft