
显然是全绿。
add
只能控制一个chunk,size也有限制。
edit
以回车结束。
这里有一个off by null。
show
就输出。
free

有个uaf。
其实比起lonelywolf来说就是开了个沙箱。
整个看下来,那个index就是那种逗你玩那种。
然后libc当时给的是2.27,但是做半天发现是最新的2.27……里面更新了对那些tcache链表的那些检查,就挺离谱的,所以可以当成2.29来做。
那想想怎么来利用那个uaf。
uaf,在得到libc的条件下,我们可以直接攻击free_hook,来getshell。
但问题就是怎么来得到libc的地址。
现在的情况是有输出函数,但是chunk的大小收到了限制。
我们只能去攻击tcache头
也就是
也就是tcache_perthread_struct,我们直接先攻击他,然后对他进行污染,也就是把counts数组中对0x250chunk的count改的比较大,因为tcache头大小就是0x250.
然后直接free掉,就可以泄露libc地址。
那么问题来了,我们还是要去用double free的,因为它只能利用一个chunk。
libc是2.29,我们还要去做一下bypass。
libc2.29是怎样去限制double free的,他会在bk的位置去加一个key值,free的时候如果这个地方是这个值,就会检查链表中是否已经有了这个chunk。这个值是个啥?

也就是我们的tcache头的内容部分的地址。
我们只要把他改掉就好了,那么我们的思路就非常清晰了。
绕过libc2.29对double free的检查,对tcache头进行污染,然后泄露libc地址,攻击free_hook就可以了。
要注意一个小细节,在我们攻击tcache头的时候,一定要保证链表空空,不然会导致链表中出现tcacahe fd的值,导致一会malloc错误。
按照题目环境2.27,应该是攻击free_hook,把它的值改成set_context+53
但是因为我这里用的是2.29,set_context变成了rdx寻址,所以把free_hook改成这样的一段gadget。
mov rdx, qword ptr [rdi + 8];
mov qword ptr [rsp], rax;
call qword ptr [rdx + 0x20];
然后在要free的 [chunkptr+8]+0x20 的位置填上 setcontext+61。
这个gadget通过
ropper --file libc.so.6 --search “mov rdx”
来找

原理是
free()的参数是rdi,通过gadget的转换,现在rdx是[rdi+8],我们可以控制这个地址,然后rdx+20的地方开始跑setcontext。
然后就可以根据rdx来控制各种寄存器。
setcontext是个啥,大家应该还记得SROP,SROP用来恢复栈环境的时候用的就是setcontext,所以我们可以在写的时候直接用pwntools的模板。
然后我们就布置rop,把rop读到bss上,然后跳过去执行一下就好了。
然后需要找个地方布置srop。
一个chunk最大只有0x78,地方不大够,需要两个。
最后的效果。
free的时候首先跳到gadget。

然后我的setcontext+53就写在freechunk的前八个字节,通过把free的chunk的+0x8 写成了写着setcontext+53的地方的地址减去0x20,然后就做到跳了过去。

然后就是一个srop的过程。
然后读入rop,跳过去就行
exp
# -*- coding: utf-8 -*-
from pwn import*
context.log_level = "debug"
context.arch = "amd64"
context.os = "linux"
r = process("./silverwolf")
libc = ELF("/home/wuangwuang/glibc-all-in-one-master/glibc-all-in-one-master/libs/2.29-0ubuntu2_amd64/libc.so.6")
def allocate

本文讲述了在限制条件下的内存攻击,通过UAF漏洞攻击tcache头,绕过 libc 2.29 的doublefree检查,最终泄露libc地址并利用free_hook实现shell。作者详细介绍了利用setcontext gadget和ROP技术的步骤。
最低0.47元/天 解锁文章
1544

被折叠的 条评论
为什么被折叠?



