几经周折rop
信号与系统实在复习不下去
题目
链接:https://pan.baidu.com/s/1_EXQHF0uumBE2tWhloeiNg
提取码:2thf
某大学冬令营,题目本来是很简单的,但是刚开始出题方靶机环境可能出现了某些问题,导致exp一直可以打通本地,打远程一直打不出flag,也不敢质疑是官方的问题,一直在改自己的exp,不过也引发了自己的一些思考,写出了多种思路,最后官方修复了,写的几个exp也都打通了
初探
运行
查看保护
好家伙保护开满了
ida静态分析
很快发现了两处输入都有漏洞函数点,buf只有8byte容量,却分别读入0x1e和0x5a,还有后门函数win嘿嘿
很明显,后门函数提供给我们伪造栈帧的便利,读取flag.txt文件并打印出来,但是缺少fla,那么思路大致有了,伪造栈帧并进行rop
调试并编写exp
- 由于开启了canary保护,我需要先泄露canary,利用canary最low一个byte恒为0,且canary恒在push rbp的上方,buf距离rbp0x12=18,我们我们只需要10byte就可以到canary,再覆盖canary最low一个byte就可以利用printf(“You said: %s\n”, (const char *)&buf);把canary输出出来,paylaod为b’a’*11,泄露canary的同时我们也泄露了保存的rbp,后面伪造栈帧时有用,泄露完之后我们在下一次read要填补上canary,进行下一下循环,getfeedback()
- 由于开启pie保护,我们还要泄露pie基址
b’a’*26泄露地址,减去elf处改地址即为pie基址,这里不用担心我们会覆盖canary,canary只有在该函数返回时,才会检测canary,
下面还有一次read函数,这次read我们构造rop链,恢复canary
- 在构造前我们先分析下win
win函数汇编 |
我们把断点断到leave ret处 发现rbp指向就是我们ret的下方,如果我们把ret下方覆盖为fla的话,只需要把原来的栈提高0x6c,(0x0000555555555263 <+26>: mov BYTE PTR [rbp-0x6c],al )就可以伪造栈,伪造flag.txt,故payload为 payload=b’a’*10+p64(canary)+p64(rbp_ad+0x6c)+p64(win_ad)+b’a\x00\x00\x00’+b’l\x00\x00\x00’+b’f\x00\x00\x00’
exp
from pwn import * |
再探
官方的问题,前一个exp没打通,奇怪了,难道名字不叫flag.txt?,或许叫flag,又开始分析win汇编,我们可以直接控制栈和rsp,又从下面汇编的<+62>或者<+99>可以看出要打开的文件名字的存储地址为rbp-0x4a处,干嘛不直接覆盖这里,这样我们还可以控制文件名字
0x0000555555555283 <+58>: movzx eax,BYTE PTR [rbp-0x64] ;参数转移 |
exp
把前一个exp的
win_ad=0x1273+base |
很生气呀,拿tm的shell
本地也通了,远程还是不行,试了好几个文件名字还不行,内心开始怀疑,也不想就这样放弃,继续分析发现可以直接拿shell
和前面一样先泄露canary rbp 和pie基址,程序有使用puts函数,我们可以利用puts泄露puts地址,由于是64为需要一个pop rdi的gadget给puts传参
payload=b’a’*10+p64(canary)+b’deadbeef’+p64(poprdi)+p64(puts_got)+p64(puts_plt)+p64(getFeedback)
这里再次返回canary是不会变得,即使是再次生成;变了的话也好说,在泄露一次就是了,或者rop返回时跳过生成
泄露后找到libc,就可以常规rop
payload=b’a’*10+p64(canary)+b’deadbeef’+p64(poprdi)+p64(bin_sh)+p64(ret)+p64(system_ad)
这里在ret到system前多个ret是为了ubuntu18版本以上调用64位程序中的system函数的栈对齐问题
64位下system函数有个movaps指令,这个指令要求内存地址必须16字节对齐,因为64位程序的地址是8字节的,而十六进制又是满16就会进位,因此我们看到的栈地址末尾要么是0要么是8。
只有当地址的末尾是0的时候,才算是与16字节对齐了,如果末尾是8的话,那就是没有对齐。而我们想要在ubuntu18以上的64位程序中执行system函数,必须要在执行system栈顶地址末尾是0。
exp
from pwn import * |
拿到shell,发现文件里有flag.txt,拿到flag,还在疑惑前两个为什么不行,又去试了一下前两个exp,这次发现都能打通,我….