Challenges in Containers
Sometimes you get challenges provided with a Dockerfile
. In most cases, it's best to use it, as you can be sure it acts the same locally and remotely.
Unfortunately, that can be rough. There are a few steps. In essence, we want to use gdbserver
to set up a debug session, then connect to gdbserver
from our host to leverage the full power of whatever we want to debug with. These steps work for debugging a binary hosted via socat
.
Quick Copy
Add:
RUN apt-get install -y gdb gdbserver
-- OR --
RUN apk add gdb
-p 9090:9090 --cap-add=SYS_PTRACE
Run:
docker exec -it challenge /bin/bash
gdbserver :9090 --attach $(pidof challenge)
Connect:
r2 -d gdb://localhost:9090
OR
gdb challenge
target remote :9090
Explanation
Install
Add some installs to the Dockerfile:
RUN apt-get install -y gdb gdbserver
If the Dockerfile is an alpine image, instead use
RUN apk add gdb
gdbserver
is automatically installed as part of the package.
Change Run Command in build_docker.sh
Add the
-p 9090:9090 --cap-add=SYS_PTRACE
flags to the docker run ...
command in build_docker.sh
.
-p 9090:9090
binds the internal port9090
to the external port9090
, so we can connect tolocalhost:9090
for thegdbserver
--cap-add=SYS_PTRACE
gives the container the capability toptrace
a process, which we need for debugging. The alternative is to run it in--privileged
mode, which is far more unsafe
Start the Executable and get the PID
Get a shell with docker exec
:
docker exec -it challenge /bin/bash
Note that to get a binary started with socat
, we have to connect to the service first in order to start a process. So, outside the container, connect with nc
:
$ nc localhost 1337
<pwnable binary>
Don't end the process. Switch back to the Docker root
shell:
root@096c4ec3bca6:/# pidof challenge
22
Grab the PID of the subprocess, in this case 22
.
Starting GDBserver
Now start a gdbserver
:
gdbserver :9090 --attach 22
And on your host you can now connect to it with radare2 or GDB:
$ r2 -d gdb://localhost:9090
$ gdb challenge
(gdb) target remote :9090
Remote debugging using 172.17.0.2:9090
[...]
(gdb)
And boom.
Note the issue is that you have to restart gdbserver every time you connect again. Don't forget! Maybe there's a better way, but I don't know.
Did try and replace the shell commands with a single docker exec
, but the $()
is resolved before it is piped to the Docker:
$ docker exec -it challenge gdbserver :9090 --attach $(pidof challenge)
Cannot attach to process 7196: No such process (3)
Exiting
But when connecting via shell and running, it worked:
$ docker exec -it challenge /bin/bash
root@e2cd6b6e2e2c:/# gdbserver :9090 --attach $(pidof challenge)
Attached; pid = 201
Listening on port 9090
If anybody finds a fix, please let me know!
Last updated
Was this helpful?