Speed up your binary exploits! An introduction to gef and pwntools

March 23, 2019 - 3 minute read - parzel

Recently I was at an awesome security conference in Heidelberg called Troopers. During this event there was a two hour CTF event that consisted of two different stages. First stage was getting an initial foothold into a system while the second stage was to pivot to other machines in the hosted network. These other machines were running different services and I was working on a service called CVE launcher (you can get it here, I also made a writeup here). CVE launcher was a binary that was vulnerable against heap overflows due to several integer overflows. Because I was not able to finish my exploit during the game time I decided that I want to speed up my exploit development. In this blog post I will explain how I was able to speed up my workflow and hopefully give you some ideas for faster exploit development as well.

So let’s get started!

While some of you may already use either pwntools or some gdb extension I will start to explain this from scratch, so nobody gets lost right away.

Pwntools is a really neat library for python which allows you to speed up binary exploitation in several ways. The full scope of its features is huge and I am merely scratching the surface here. If you want to dive deeper into pwntools have a look at the very detailed documentation.

The feature I like most about pwntools is its tubes. These allow you to easily talk with service in a network or for example a binary.

from pwn import *

sh = process("/path/to/binary")
# sh = remote('host', port)
sh.sendline("someinput")
oneline = sh.recvline(timeout=0.2)

Tubes are also easily interchangable, therefore you can develop your exploit locally and just change from process to remote to use the same exploit an a network.

You can perform several automated steps and afterwards drop into an interactive shell. With this feature you can speed up processes that are necessary to get to a certain point in the application state without having to perform these either manually or write overhead code. Instead you can focus on the exploit logic itself.

Let’s say your exploit needs several actions to be performed as setup until you are able to have a deeper look with gdb into the heap or stack and check the structure of it.

This brings us to the second feature which is really cool about pwntools. It allows you to connect with gdb easily. You can either start a process directly connected to gdb with

from pwn import *

sh = gdb.debug("/path/to/binary")
sh.sendline("someinput")
oneline = sh.recvline(timeout=2)

or if you prefer you can attach it anytime later. If you specify tmux as your terminal in the context variable you are even able to spawn the gdb shell directly in the same pane - That’s super handy!

from pwn import *

context.terminal = ['tmux', 'splitw', '-v']

sh = process("/path/to/binary")
sh.sendline("someinput")
oneline = sh.recvline(timeout=2)
gdb.attach(sh)

At this point gef comes into play. For those of you that already know extensions for gdb like pwdbg or peda - basically gef is the same thing. Big plus about gef though is that you can easily install it in less than 20 seconds.

$ wget -q -O- https://github.com/hugsy/gef/raw/master/scripts/gef.sh | sh

And done! Gef is an extension for gdb that allows you to perform easier debugging and also has lots of features which you should get familiar with. In this case I used the “heap” command, which allows you to easily visualize chunks on the heap.

Not lets get to the last thing in the toolchain. pwntools also allows you to execute commands in gdb. This allows you to perform tedious gdb commands in a fast way directly when the exploit is executed.

from pwn import *

context.terminal = ['tmux', 'splitw', '-v']

sh = process("/path/to/binary")
sh.sendline("someinput")
oneline = sh.recvline(timeout=2)

gdb.attach(sh, '''
break somefunction
heap chunks
''')

sh.interactive()

By this we can perform different actions in the binary, start gdb in a our tmux pane, set a breakpoint at a certain function and display the heap.

That’s it for this blog post. I hope it gave you some new insights. If you have comments or improvements feel free to write me at twitter @parzel2