This blog introduces tools to deal with libc
problems in pwn
and to host pwn
challenges.
Pwn Libc Part
The libc
version matters in Linux
pwn challenges. Using different libc
means having different gadgets, different heap mechanisms and maybe totally differrnt program behaviors.
Ubuntu 16.04 gets libc 2.23
, Ubuntu 18.04 gets libc 2.27
, the newer versions gets libc 2.29
, libc 2.30
and even libc 2.31
. This is always the reason why some newcomers cannot test the exploit scripts on their own machine, or they may not even run program successfully. All due to the wrong libc
using.
This part provides you with some libc
related tools.
LibcSearcher
It is a tool on github, helps determine which libc
the remote server is using (according to function addresses you leaked, like some online searching sites)
To install
1 | $ git clone https://github.com/lieanu/LibcSearcher.git |
Usage
1 | from LibcSearcher import * |
With this you can not only know the remote libc
pwn_debug
It’s like an advanced pwntools
, with the ability to run different libc
on one host machine.
Start with installation
1 | $ git clone https://github.com/ray-cp/pwn_debug.git |
Then download and compile glibc
with debug symbols
1 | # compile specific version |
They are all located in /glibc/*
1 | $ ls /glibc/ |
And the normal usage is divided into 3 steps:
- Import and declare object
- Set the mode parameters, three mode in total:
debug
,local
andremote
. - Run the mode and interactive like using
pwntools
More usages on github wiki, btw this is for1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27from pwn_debug import *
## step 1
pdbg=pwn_debug("binary") # specific the binary filename
pdbg.context.terminal=['tmux', 'splitw', '-h'] # set terminal
## step 2
pdbg.local("libc.so.6") # local libc file
pdbg.debug("2.23") # libc in /glibc/*
pdbg.remote('host','port') # remote address
## step 3
#p=pdbg.run("local")
#p=pdbg.run("debug")
p=pdbg.run("remote") # choose mode
pdbg.bp([0x9aa]) # easy to set breakpoint, regardless of PIE
# the followings are pwntools functions
elf=pdbg.elf
print hex(elf.got['printf'])
print hex(elf.plt['printf'])
libc=pdbg.libc
print libc.symbols['system']
p.interactive()Python2
,Python3
users need to modifyprint
formats and someimport
parts to make it work.
glibc-all-in-one and libc-database
glibc-all-in-one is just for debugging different version libc
with symbols (it can assist pwn_debug
), and libc-database is for ctfers to get the version of remote server responding to leaked information (the engine of LibcSearcher
).
glibc-all-in-one
You can update the libc list
1 | $ ./update_list |
use download
for packages in the list
; use download_old
for packages in the old_list
.
1 | $ glibc-all-in-one ./download 2.23-0ubuntu10_i386 |
Need additional libc packages, use extract
1 | $ ./extract |
Then build as
1 | $ ./build |
libc-database
First install some dependencies:
1 | $ apt-get update |
The online version is available and you can build one using libc-database/searchengine.
Fetch the desired libc categories and extract the symbol offsets, and update database:
1 | $ ./get # List categories |
Add a custom libc:
1 | $ ./add /usr/lib/libc-2.21.so |
Find the libc you want using leaking addresses. Only the last 12 bits are checked, because randomization usually works on page size level.
1 | $ ./find printf 260 puts f30 |
Dump some useful offsets
1 | $ ./dump libc6_2.19-0ubuntu6.6_i386 |
And check whether a library is already in the database
1 | $ ./identify /usr/lib/libc.so.6 |
patchelf
PatchELF is a simple utility for modifying existing ELF executables and libraries. It helps program run on own library path RPATH
and cunstom libc
like pwn_debug
, and so on.
Installation
1 | # apt |
Choose the dynamic loader (“ELF interpreter”) of executables
1 | $ patchelf --set-interpreter /lib/my-ld-linux.so.2 my-program |
Change (or shrink) the RPATH
of executables and libraries
1 | # set `RPATH` |
More on README.md
Host Pwn Challenges
Most of the time we debug locally due too the speed and other facters, but the exploit scripts sometimes goes wrong when testing on remote dur to details in interaction.
Here introduces several ways to host the pwn
challenges, not only for CTF
competition organizers but facilitate CTFers
to test remote
on local
.
One Command
In real challenge we are given an ip
and a port
, therefore the easiest way is to do port forwarding using socat
:
1 | $ socat tcp-l:8080,fork exec:/root/pwn_to_run,reuseaddr |
Then you can nc
to interact.
Add nohup
, even combine with screen
/&
will helps.
1 | $ nohup socat tcp-l:8080,fork exec:/root/pwn_to_run,reuseaddr |
ctf_xinetd
A docker repository for deploying CTF challenges
xinetd
- the extended Internet services daemon. It starts programs that provide Internet services.xinetd
is the only daemon process started and it listens on all service ports for the services listed in its configuration file.ctf_xinetd
uses docker
to run xinetd
and host the pwn challenge.
The brief README.md
comes
- Configuration
Put files to floder bin
. They’ll be copied to /home/ctf. Update the flag at the same time.
Edit ctf.xinetd
. replace ./helloworld
to your command.
You can also edit Dockerfile, ctf.xinetd, start.sh
to custom your environment.
- Build
1 | $ docker build -t "helloworld" . |
DO NOT use bin as challenge’s name
- Run
1 | $ docker run -d -p "0.0.0.0:pub_port:9999" -h "helloworld" --name="helloworld" $ helloworld |
pub_port
is the port you want to expose to the public network.
- Capture traffic
If you want to capture challenge traffic, just run tcpdump
on the host. Here is an example.
1 | $ tcpdump -w helloworld.pcap -i eth0 port pub_port |
pwn_deploy_chroot
A project for deploying ctf pwn challenge use chroot
Since ctf_xinetd
needs to modify flag
, ctf.xinetd
, and only deploys one challenge a time, another convenient tool pwn_deploy_chroot
comes.
pwn_deploy_chroot
is able to deploy multiple challenges in one docker
machine, and generate flag
& configurations automatically.
Replacing /bin/sh
in chroot
with statically linked catflag
gives users no chance to use sh
fork bombs. Ports starts from 10000
, +1 for each additional program.
Come the brief README.md
- Before
1 | # Install the latest version docker |
- How to use
- Put your pwn program to ./bin (Note that the filename should not contain special characters.)
- python initialize.py
- docker-compose up –build -d # please run as root
You can edit config.py
to decide whether to replace /bin/sh
with catflag
1 | # Whether to replace /bin/sh |
- Attention
The flag will be generated by the initialize.py
and it store in flags.txt
The port information of the pwn program is also inside the flags.txt
.
- Update
2018.09.17 version v1
2018.09.23 version v2:Use the catflag program instead of /bin/sh, which is more secure