今天在学fmt,觉得自己会忘记,写下这个
格式化字符串对应的转义
%d :十进制,输出十进制整数
%s : 字符串,从内存中读取字符串
%x : 十六进制,输出十六进制数
%c : 字符串,输出字符串
%n : 到目前为止缩写的字符串数
%p :输出指针所指的值(常用)
64位的大整数覆盖地址
我们直接从题目开始做
fmt_64
这个文件夹里已经有我的脚本了
做题之前记得将libc指定为里面给的
我们从这个题目将栈上的fmt彻底讲完
该题目为2024Newstar的EZ_fmt
我们先checksec一下
我们发现他没有开PIE,(我们可以直接调用里面的地址)
RELRO也没绿 (我们可以修改got表以调用我们需要的函数)
IDA逆向查看(由于是NewStar的题,main里另外一个是纯艺术字)
我们Shift+F12再看,发现没有/bin/sh字符串
所以我们需要自己造/bin/sh
题目的主函数是3次printf的fmt漏洞所以思路大概如下
1、第一个fmt泄露libc地址
2、第二个用fmt修改printf的got表,改为system的地址
3、输入/bin/sh,执行system(“/bin/sh”)
1. 泄露libc地址
这是ret2libc也常用到的方法,我们调用gdb来断点在call printf上。来确定我们要泄露的地方。
1 | from pwn import * |
这时运行,程序会停在pause()。等待gdb运行,然后我们再输入c继续运行至下一个断点
(其实就是第一个printf的断点),“%p”只是单纯为了跳过第一个read
这个时候stack 30,展开栈
我们需要泄露的libc地址在0d的位置,由于是64的程序,所以还要加上6(6个寄存器),最后的偏移是19
这个地址对应的函数我们需要在libc.so.6中找(但我们其实不需要知道)
vmmap查看libc的基址
差值在最后5位,地址长度为12位
1 | p.send("%19$p") |
这样的base就是每次程序运行时的libc基址
我们动调得到的libc
即可得到system的地址
system = base + 0x50d70
2. 构造payload修改got表
1 | low = system & 0xff |
%hhn改动0xff的长度对应的got地址要继续写的时候是+1,如果第一个写的是%hn,那就得+2
至于%12$是一样的,只要ljust的时候是8的整数倍即可(因为p64)(这里由于泄露0x30,而且前面的payload为0x19)
如果是32位,那就应该是%6$
我们只修改got地址的后6位,(因为printf跟system的地址只差了5个,6是为了凑偶)
这个方式不只可以更改got,也可以改其他地方的地址
3. 最后
因为我们已经更改printf为system,我们直接传入/bin/sh即可打通
github上的附件是根据原题作者的wp改的,做法不同之处在于用elf直接对libc文件读取偏移,而不用单独用gdb去查看,会快一点吧
小整数
直接在前面加入相应个数的字符就好了