学到了个格式化字符串的新姿势,这也太牛逼了
TCTF/0CTF初赛的一题,应该算是最简单的一道了,可惜当时也没解出来
Simple_echoserver
程序漏洞很明显:
1 | int __fastcall sub_13C1(info *user) |
一个格式化字符串的漏洞,这题难点也是这,只有这一次的机会,后续的操作就没有可以利用的点了,连接远程的时候发现没有回显,估计是错误流被重定向到/dev/null
了
这里学到的新姿势是在听腾讯公开课的时候学到的(Homura tql!):
这个占位符在配合$
,可以实现无泄漏就能得到你想要的值,这题用这种方法的话,就会变得很简单,下个断点在fprintf(stderr_, buffer);
这:
1 | RAX 0x0 |
我们可以输入%*48$c%952504c%26$n
来把19:00c8│ 0x7ffe00299f38 —▸ 0x7fb7a4339400 (_IO_doallocbuf+144) ◂— mov eax, dword ptr [rbx]
这里原本的值改成one_gadget
,首先是%*48$
取到的会是__libc_start_main+231
这里的值,接着在加上偏移952504
,再配合%26$n
就可以直接改掉那个栈上残留的libc
的值,效果如下(有时候会该不成功,感觉可能是输出太多字符了把):
1 | 15:00a8│ 0x7ffe00299f18 —▸ 0x7ffe00299f38 —▸ 0x7f3d39edd45c (exec_comm+2508) ◂— mov rax, qword ptr [rip + 0x2e0a45] |
这里还要注意的就是我们输入的phone
长度要正好0x18
,这样栈上才会有指针指向我们要改的这里
后面的操作就只要把rbp
改到这里,这样main
函数返回的时候就会被劫持到one_gadget
了(因为从 sub_141D函数返回到main函数在加上main函数自己返回一共有两次的leave,ret
),这里要小爆破下,1/16
的几率应该挺高的了
exp:
1 | from pwn import * |
感觉这个方法唯一的缺陷就是输出了太多太多的字符,要是没有像这题一样,alarm给的是600秒,而且还重定向了错误流,估计光光接受返回的数据就把时间耗完了,不过这个真的太牛逼了,不用泄露就完成了攻击,tql