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 libcon 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,localandremote. - Run the mode and interactive like using
pwntoolsMore 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,Python3users need to modifyprintformats and someimportparts 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