A few weeks ago i just started with binary exploitation and as learning and understanding this topic is not enough challenging, i encountered different problems with the tools and some basics. One of these problems i will describe today.
Intro
there are many good tutorials, challanges and ctfs out there, where you can start learning the topic. After some reverse engineering lessons and understanding the basics i decided to do the ropemporium series, also because CryptoCat has a good youtube series about it, so you can watch them if you get stuck or want to proof if there are other solutions.
first i decided to concentrate on the 64bit binaries (ropemporium always provide each challenge in different architectures). Completed the first challenge without any problem. The second challenge (split) is about providing a correct parameter to your Gadget. I remembered from LiveOverflow binexp. series that there is a difference between how 32bit and 64bit binaries handle function arguments (stack vs. registers). So i short decided to do the 32bit challenges as well to get a better understanding and practice about that.
long story short, this was the point where my struggle begin.
The problem
doing reverse engineering and binary exploitation can involve a lots of different tools, frameworks and libraries which partial depends on each other.
My main toolset is basically (next to some standalone tools):
- python2 and python3
- gdb and gdbserver
- pwndbg
- pwntools
I already learned, to avoid memory address differences between the (i will call it standalone) debugging when you run gdb <binary>
and the „normal“ execution, i try to start as soon as possible with a pwntools script and start the debugger from there with gdb.debug(<binary>)
.
This was working fine for me with 64bit binares, but with the 32bit version of the binary it always crashes just before the main function was reached.
here is my script that i used for troubleshooting
from pwn import *
binary = './split32'
e = ELF(binary, checksec=False) # setting pwntools context os/arch
context.os = 'linux' # so that we won't have to specify it explicitly
context.arch = e.arch # when using pwntools functions like asm etc.
context.log_level = 'info'
target = gdb.debug(binary)
target.interactive()
setting a breakpoint at main and continuing to it crashes the binary
i stepped further to find the exactly instruction that causes this crash and found the _dl_init
The interesting thing is, if you start the binary with in gdb standalone gdb ./split32
everything is fine and you can debug through the hole binary without any crash. So i thought it must have been related to pwntools. I googled a lot about the missing cache file (cacheinfo.c) gdb is claiming about but cant found any one else having this problem.
Looking at the involved tools:
gdbserver depends on gdb. pwndbg depends on gdb and the inbuild python of the gdb build, pwntools depends on gdb, the gdbserver and python and all of these exists in different versions
so this was a little nightmare.
- the problem is not binary related, so it comes up with any other 32 binary
- gdb attach works but i was not able to debug further (it just hangs)
i thought maybe something in my environment is broken so i installed a fresh new Ubuntu and a fresh new Debian, same problem on both VMs. Ubuntu 20.04.3 comes with gdb and gdbserver version 9.2, debian 11.2.0 comes with version 10.1-1-7 and also the python version is different (3.8 vs 3.9 etc.). So i decided to update the gdb version on the Debian VM, found out that on debian it was working at some time, tried different python versions, building gdb on the ubuntu vm with a different python version and so on…this was not a fast process, because you need to build python and gdb every time from the source and that takes time. But to make this short, gdbserver version 11.1 solves the problem! Thanks also to Peace-Maker from the pwntools discord server who finally pointed me to the correct issue: https://github.com/Gallopsled/pwntools/issues/1783
so if you ever encounter some problems and gdb gives you some strange error messages like:
ctype-info.c: No such file or directory
or
../sysdemps/x86/cacheinfo.c: No such file or directory
Make sure you have the latest gdbserver version installed. This makes sense because with gdb.debug pwntools using the gdbserver and not gdb itself, so this is also the reason why debugging in gdb standalone was always working.
For me this versions of gdbserver where NOT working:
- 9.2
- 10.1-1-7
- 10.1.90
How to update GDB and GDBServer
As i said, unfortunately you need to build it by your self and this takes some time (at least 5-10 minutes).
there are also some pitfalls, so here is a little step by step guide that worked for me
- download the latest release from here https://ftp.gnu.org/gnu/gdb/ (i have used the gdb-11.1.tar.gz)
- change to root and copy it to any place where you want to store it, i decided for /opt
- Extract it
tar xvzf gdb-11.1.tar.gz
- change to the directory
cd gdb-11.1
- make sure all dependencies are installed for the build process
apt install libgmp-dev libreadline-dev texinfo
- make sure your python version is stored at
/usr/bin/python3
or adjust the path in the configure statement - start the build process with
mkdir build &&
cd build &&
../configure --prefix=/usr \
--with-system-readline \
--with-python=/usr/bin/python3 &&
make
if it fails and claims about missing dependencies, install them, delete the build folder and run it again
finally test if gdb is working with starting it directly from the build folder ./opt/gdb-11-1/build/gdb/gdb
on my tests i had some issue with building gdb 9.2 and a python version 3.9.2, it builds but then failed to start, so better test it before you roll it out the system.
if everything is fine you can install it finally with
make -C gdb install && make -C gdbserver install
Sources:
https://www.linuxfromscratch.org/blfs/view/svn/general/gdb.html
https://github.com/Gallopsled/pwntools/issues/1783