Prologue
Welcome back to the second part of our journey into the guts of radare2! In this part we’ll cover more of the features of radare2, this time with the focus on binary exploitation.
A lot of you waited for the second part, so here it is! Hope to publish the next part faster, much faster. If you didn’t read the first part of the series I highly recommend you to do so. It describes the basics of radare2 and explains many of the commands that I’ll use here.
In this part of the series we’ll focus on exploiting a simple binary. radare2 has many features which will help us in exploitation, such as mitigation detection, ROP gadget searching, random patterns generation, register telescoping and more. You can find a Reference Sheet at the end of this post. Today I’ll show you some of these great features and together we’ll use radare2 to bypass nx
protected binary on an ASLR enabled system. I assume that you are already familiar with the following prerequisites:
- Assembly code
- Exploit mitigations (NX, ASLR)
- Stack structure
- Buffer Overflow
- Return Oriented Programming
- x86 Calling Conventions
It’s really important to be familiar with these topics because I won’t get deep into them, or even won’t briefly explain some of them.
Updating radare2
First of all, let’s update radare2 to its newest git version:
$ git clone https://github.com/radare/radare2.git # clone radare2 if you didn't do it yet for some reason. $ cd radare2 $ ./sys/install.sh
We have a long journey ahead so while we’re waiting for the update to finish, let’s get some motivation boost — cute cats video!
Getting familiar with our binary
You can download the binary from here, and the source from here.
If you want to compile the source by yourself, use the following command:
$ gcc -m32 -fno-stack-protector -no-pie megabeets_0x2.c -o megabeets_0x2
Our binary this time is quite similar to the one from the previous post with a few slight changes to the main()
function:
- Compiled without
-z execstac
to enableNX bit
- Receives user input with
scanf
and not from program’s arguments - Uses mostly
puts
to print to screen - Little changes to the program’s output
This was the previous main()
:
int main(int argc, char *argv[]) { printf("\n .:: Megabeets ::.\n"); printf("Think you can make it?\n"); if (argc >= 2 && beet(argv[1])) { printf("Success!\n\n"); } else printf("Nop, Wrong argument.\n\n"); return 0; }
And now main
looks like this:
int main(int argc, char *argv[]) { char *input; puts("\n .:: Megabeets ::.\n"); puts("Show me what you got:"); scanf("%ms", &input); if (beet(input)) { printf("Success!\n\n"); } else puts("Nop, Wrong argument.\n\n"); return 0; }
The functionality of the binary is pretty simple and we went through it in the previous post — It asks for user input, performs rot13
on the input and compares it with the result of rot13
on the string “Megabeets”. Id est, the input should be ‘Zrtnorrgf’.
$ ./megabeets_0x2 .:: Megabeets ::. Show me what you got: blablablabla Nop, Wrong argument. $ ./megabeets_0x2 .:: Megabeets ::. Show me what you got: Zrtnorrgf Success!
It’s all well and good but today our post is not about cracking a simple Crackme but about exploiting it. Wooho! Let’s get to the work.
The second part of “A journey into #radare2” is finally out – and this time: Exploitation! Check it out @ https://t.co/sKH1YhxJwK@radareorg
— Itay Cohen (@megabeets_) September 3, 2017
Understanding the vulnerability
As with every exploitation challenge, it is always a good habit to check the binary for implemented security protections. We can do it with rabin2
which I demonstrated in the last post or simply by executing i
from inside radare’s shell. Because we haven’t opened the binary with radare yet, we’ll go for the rabin2
method:
$ rabin2 -I megabeets_0x2 arch x86 binsz 6072 bintype elf bits 32 canary false class ELF32 crypto false endian little havecode true intrp /lib/ld-linux.so.2 lang c linenum true lsyms true machine Intel 80386 maxopsz 16 minopsz 1 nx true os linux pcalign 0 pic false relocs true relro partial rpath NONE static false stripped false subsys linux va true
As you can see in the marked lines, the binary is NX
protected which means that we won’t have an executable stack to rely on. Moreover, the file isn’t protected with canaries
, pic
or relro
.