解决之前在格式化字符串的学习过程中的遗留和遗忘的问题
通过格式化字符串漏洞修改函数的返回地址
我将通过例题来说明,话不多说直接上题
https://pan.baidu.com/s/1bWKL-y2KVU1Iob5XODRshw (tcm:chen)
这个是第二届陇剑杯线下的题算是比较入门的格式化字符串的题了。
先查看其保护(我用的虚拟机版本是18.04)
在ida中打开分析
可以看到只有一个输入和输出,并且该程序循环只进行一次,执行完printf函数后,程序便exit退出,最重要的一点是该程序存在格式化字符串漏洞。
一开始我想的是,通过修改printf函数的got表来进行操作,可是该程序执行完后便退出了,根本不会再次执行printf函数,
后面我才看到原来此程序是有后门的,我们可以修改printf函数的返回地址为后门,便可以getshell。
说干就干,首先我们先在gdb中找到printf的返回地址
我们可以看到printf的返回地址是<__libc_start_main+231>,我们的目的就是将这个函数的地址修改为后门函数的地址(4006F8)。
我们通过命令查看修改该字段的偏移
对应写出其exp:
from pwn import* |
注:%n表示将0x64写入偏移10处保存的指针所指向的地址(4字节)
%hn表示写入的地址空间为2字节
%h h n 表 示 写 入 的 地 址 空 间 为 1 字 节
%lln表示写入的地址空间为8字节
可是却没有成功getshell
原因很显而易见栈没对齐,一般情况下加个retn补齐那8个字节就行了,但是咱们这个直接修改返回地址的,添加retn是很麻烦的(貌似就行不通)。这里还有一个办法,后门函数的地址+1,这样就打通了,那么为什么呢?
我们查看后门函数的汇编
首先我们知道 retnde作用就相当于pop rip ,使地址增加8个字节,达到补齐的目的而push命令刚好与之相反,我们这里不后门函数的地址(0x4006f8),而是用(0x4006f9)的原因就是略过push从而达到添加retn的目的。
所以正确的exp:
from pwn import* |
通过格式化字符串漏洞篡改函数的got表
并且我只会修改一次两个字节函数的got表,并且还不是太理解。
这里也是通过例题来说明
链接:https://pan.baidu.com/s/1QSIcCEj96SwL0XEJxIvc3g (tcm:chen)
这个也是第二届陇剑杯线下的格式化字符串的题,但是比刚才的稍微难一点,难就难在了篡改got表。
同样的先查看保护(养成习惯)
再查看ida
可以看到这个程序首先会先输出一段英文,然后能“一直”输入和输出,当你输入“exit”时程序会直接退出,但是这个程序并没有后门,所以上面的那个方法自然不能使用,但是这个程序能“无限”循环,所以可以将printf的got表改为system,这样便可以getshell。
我们来说一下大致解题思路:
1 利用printf和格式化字符串漏洞来泄露printf函数的got表(注意偏移来正确泄露);
2 对比system got表地址和printf再次利用格式化字符串漏洞,按字节进行修改;
3 修改正确后输入“/bin/sh”得到shell。
接下来我重点讲讲第2个的方法
可以发现只有后3个字节不一样我们再次查看
%n表示将0x64写入偏移10处保存的指针所指向的地址(4字节)
%hn表示写入的地址空间为2字节
%h h n 表 示 写 入 的 地 址 空 间 为 1 字 节
%lln表示写入的地址空间为8字节
我们可以用%hn和%hhn两个搭配,通过一次写两个来进行修改
举个例子,我们可以把69改为67,1e40改为c420,这样printf就改为了system。
payload2 = "%" + str(high_sys) + "c%10$hhn" + "%" + str(low_sys-high_sys) + "c%11$hn" |
上面的代码 我们就是把printf_got + 2的最后一个字节改为了high_sys
printf的地址最后两个字节改为low_sys
那么现在就有3个问题
1:为什么要printf_got + 2?
因为我们修改字节的时候只能从后面的字节往前面修改,当我们用printf_got + 2的时候,我们就可以把倒数第三个字节弄到最后面,然后进行修改。
2:为什么要第二个修改要用str(low_sys-high_sys)?
因为我们之前输入的是%str(high_sys) c%个数据,当我们再次输入%str(low_sys)时数据就会多算进去%str(high_sys) c%,因此我们把它减掉就行啦。
3:payload2.ljust(32,”A”)是干嘛的
为了补齐,方便后面的修改。
修改之前:
修改之后:
完整exp:
from pwn import* |
最后在输入/bin/sh就行啦。
后续新增:
DASCTF X HDCTF 2024 公开赛
下载地址
https://pan.baidu.com/share/init?surl=C7c3wrjyPTVf-mTlWvfgoQ?pwd=chen
一次输入篡改不在栈上的一个地址
exp: |