[第五空间2019 决赛]PWN5
1 | from pwn import * |
1 | from pwn import * |
线程退出的时候,需要释放掉这个线程所占有的资源,并且停止内核和CPU对其的调度,才算是结束了这个线程。换句话说,线程退出需要用户层面和内核层面的共同工作。内核层面,glibc通过_exit()系统调用来终止线程,用户层面则通过exit()函数。在pwn中,系统调用很难被利用,我们通常重点关注exit函数。
1 | int __fastcall main(int argc, const char **argv, const char **envp) |
main函数开头要我们绕过一个随机数检查才有输入点。gift函数会打印puts函数的libc地址,libc地址不请自来。接着read函数溢出14个字节,只能覆盖六个字节到ret地址,所以想要在这里写one gadget是不可能的了,因为libc地址占七个字节。
x86架构的ret2text,非常简单,程序有栈溢出,没有canary保护,所以只要溢出覆盖ebp后,将ret地址覆盖为ret2win函数的地址即可。
1 | from pwn import * |
最近学习堆题的时候接触到了unsortedbin的利用,感觉还挺有意思的,所以先把它的源码读了,方便以后构建利用思路。之所以这里分析glibc2.23的代码而非2.35的代码,是因为从2.29开始,unsortedbin加入了一坨检查机制以至于它在高版本下难以被攻击,所以索性读低版本的了。
glibc2.23在unsortedbin中取chunk的时候的检查:
正好最近在学习堆入门,想起来去年还有newstar的题没复现完,所以干脆拿来当堆入门的练手了。但是在做完准备写wp用动调分析的时候遇到了一个问题。我的主力Linux是Ubuntu22,glibc版本是2.35,我学习堆也是从2.35开始往低版本对比学习,如果题目环境glibc不一样(一般都不一样,2.35版本太高了),则需要用patchelf来修改动态链接库以便gdb分析,但是按照网上的流程来patch怎么都不能成功。
1 | patchelf --set-interpreter ~/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc.so.6 --set-rpath ~/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/ Double |
根据源代码我们可以得知,高版本的glibc给tcachebin引入了检查机制,使得攻击没那么方便了,但正所谓道高一尺魔高一丈,没有攻不破的系统,只有不努力的黑客。tcache的检查机制主要有两个:对double free的检查和对chunk对齐的检查。前者的分析见TcacheBin存取chunk。这里对chunk对齐的机制进行溯源。