攻防世界pwn之echo_back
涉及知识点
函数:getchar,scanf
_IO_FILE
格式化字符串
参考链接:https://blog.csdn.net/seaaseesa/article/details/103114909
因为第一次做这么难的格式化字符串, 特此详细记录, 以为日后和我一样的萌新解惑
1.检查保护:
可以看到保护全开:
FULL RELRO代表我们无法在通过劫持got表来执行system函数
PIE enabled代表我们除了libc的偏移外, 还要寻找elf文件的偏移
2.看一下程序存在的明显漏洞:
可以看到在echo_back(sub_B80)函数中存在着明显的格式化字符串漏洞
通过它我们可以获得相关libcbase, elfbase, 以及进行部分地址上数据的修改
3.获得偏移
在call printf初下断点查看其RDI寄存器获得指向栈上的地址, 然后通过pwngdb的: fmtarg addr可以快速获得其格式化的偏移(pwngdb可以直接和pwndbg一起用, 自行百度咯)
注:我也不知道为啥, 明明正确的应该是%10$p, 这玩意每次括号里都是自带减1
之后再继续查看栈上的内容, 可以看到距离RDI所指的后9*0x8处的地址记录的是函数__libc_start_main+0xF0的地址, 所以理所应当的想到通过%19$p打印出其地址, 然后打印值减去0xF0得到__libc_start_main的地址, 而后获得libc的偏移
echo_back('%19$p')
sh.recvuntil('say:')
libc_start_main_addr=int(sh.recvuntil('-').split('-')[0],16)-0xf0
libcbase=libc_start_main_addr-libc.sym['__libc_start_main']#获得libc
有了libcbase就可以在libc中找到相关所需要的地址了
system_addr=libc.sym['system']+libcbase
bin_sh_addr=libc.search('/bin/sh').next()+libcbase
我们再进行思考, 如何获得elf文件的偏移呢? 没错, 通过程序运行时的地址减去IDA中给出的地址就能获得elfbase了
依旧看call printf处的栈上信息, 在RBP之下记录的是RIP的返回地址, 而当前运行的是echo_back函数, 所以我们猜想这个返回地址是属于RIP的
在IDA查看调用echo_back函数时的代码
0XD08确实符合0x555555554d08的后三位, 所以我们猜想成立, 这样可以通过0x555555554d08-0xd08获得elfbase
(可能因为调试方便, gdb直接打开echo_back文件其elfbase一直是相同的, 可这不代表实际情况是这样的, 脚本调试中gdb.attach一下可以明显的看见elfbase的变化)
有了elfbase我们就可以获得程序运行中ROPgadgaet的实际地址了, 因为我们的ROPgadgaet参数是–binary, 所以要的偏移就算elfbase, 若是–binary libc.so.6的话应该是要加上libcbase(这里我没去尝试,读者可以自行尝试如何留言告诉我是不是这样)
言归正传, 如何获得这个地址呢? 通过算距离, 晓得格式化字符串漏洞用%13$p就可以打印出地址了(这里我是用main函数开始的地址算的, 其实可以直接用打印的地址进行计算的)
echo_back('%13$p')
sh.recvuntil('say:')
main_addr=int(sh.recvuntil('-').split('-')[0],16