灰帽黑客进阶秘籍之二——Linux格式化字符串漏洞实战篇

 

前言

hello,大家好,我又来更新文章了,这次写的文章是Linux下的格式化字符漏洞实现,希望通过这篇文章的5个不同难度的实验我们都能了解掌握该漏洞的原理/调试,如果有写的不对,烦请各位大佬联系我斧正!

 

下载/环境搭建

实验Linux版本:deepin 15.11 最新发行版本

bug程序下载地址: https://pan.baidu.com/s/1a_Odm2g1tRDPWGp20KP9JA 提取码: vtb9

辅助工具:pwntools、peda 下载地址:https://github.com/longld/peda

(Linux 4.15的内核最近出了个洞是可以被提权的。。。 哈哈哈)

 

实验前简单介绍

本次实验环境分别为 level0-level4 均提供了源码和编译好的程序,格式化字符串主要源于程序员对用户输入未进行过滤,这些输入数据都作为数据传递给某些执行格式化操作的函数,如printf,sprintf,vprintf,vprintf。恶意用户/攻击者可以使用”%s”,”%x”来得到堆栈的数据,甚至可以通过”%n”来对任意地址进行读写,导致任意代码读写。

format0

我们先看一下源码:

通过源码可以看到在13行代码处,是最典型的导致格式化漏洞的写法。

下面我自己用gdb调试

如上图,我直接在“ret”处下了个断点,下面直接输入62个“A”、2个“B”、2个“D”

如上图中看到的,在输入上面66个字符后的,程序直接报错了,EAX刚刚好是我们输入的在65、66的“DD”刚刚好对应了上上图中的“cmp eax;0xdeadbeef”比较偏移64位后的输入字符是否为“0xdeadbeef”,比较简单那下面解题的exp就可以这样写:

run python -c "print '%64xxefxbexadxde

成功!

format1

查看源码:

我们直接运行吧,输入“AAAA”

可以看到,程序也直接显示了我们的输入,下面我们输入调试格式化字符串常用的“%x”来试一下

如上图,当我们输入一个“%x”时,程序给出了一个内存地址,当我输入5个“%x”时,程序也给出了5个内存地址,这就对了,下面我们看一下,这些地址是啥,

下面我们来算一下偏移位(小弟写文章过程中电脑没电虚拟机重启了一次,所以地址变了)

按照上图操作我们算出了地址“0xa4”,转化成十进制位“164”,下一步我们找出我们需要跳转到的“target”地址,如图:

得到地址“0x08049638”,经过简单反复调试后,exp为:

python -c 'print "x38x96x04x08BBBB%162$n"'

成功!

format2

查看源码:

我们一样,直接运行调试吧

如图当我们输入一个“%x”时,

当我们输入“%x%x%x%x”时,然后就出现了“41414141”… 这说明该程序的偏移位为4,下面我们使用pwntools来验证一下,代码如下:

运行

至于这个是不是正确的,大家可以使用上个level的算偏移的值来算一下,小弟算过。其实是对的,所以这里就不浪费大家时间了,下面我们跟上面一样还是找到“target”的地址,这里大家也可以拉到IDA里完成,我就不演示了,如图:

得到地址“0x080496e4”,

下面我们搭配组合起来试一下poc,

如图,可以看到我们已经成功加入源代码中第15行的“if”判断中了,只需要数值=64即可,我们继续试一下

如上图,当我们在后面加入4个“A”时,数值变成了“8”,当我们在后面加入8个“A”时,数值变成了“12”,相信看到这里,聪明的你应该知道后面怎么弄了。。。废话不多说,我们直接写exp

成功!

format3

查看源码:

我们运行一下看看

输入“%x”也是一样,存在格式化漏洞,下面我们还是找偏移量,还是使用上篇文章的python程序完成,但是需要修改一下,

需要修改的地址就几个,第一个就是几个载入文件,下面需要修改的就是“exit_got”和”vuln_addr”2个函数,地址为,如图:

比较简单,跑起来吧

还是跟上面一样,我们查找“target”地址

我们试一下构造poc看看结果

可以看到target的值随着我们的输入而变化,这说明这些构造都是对的,那我们继续

我们用gdb载入调试该程序,查看“vuln”,在如上图中可以发现,程序有个比较操作,地址“0x1025544”。那我们继续逐一构造吧,如图:

这里我们可以使用最笨的方法来解题,比如16进制的“0x1025544”=十进制的值为“16930116”然后减去刚刚上图中12位偏移地址的“4”,就是“16930112”。最后的exp为:python -c 'print "xf4x96x04x08%16930112x%12$n"' | ./format3

如图,成功控制指针完成工作

当然你也可以通过另外一种方法来完成,先查看target函数地址

上图中可以看到“target”的起始地址到“_end”的值,中间还有4个位的空白地址,这些其实都是可以直接写入的

那么另外一个exp就可以这样写

效果一样,成功!

format4

查看源码:

一样,还是运行一下看看

可以看到,跟上一个level一样,偏移还是4位,我们继续使用上一个python程序验证一下吧

可以看到,的确是“4”,

下面我们继续,可以通过源码看到我们需要“hello”的地址,如图:

“hello” = 0x080484b4

下一步我们继续,找一下“exit”

“exit” = 0x08049724

那我们简单构造一下poc,测试一下

下面我们使用gdb,运行调试一下

可以看到还是跟上面一样可以控制内存地址,下一步我们来算一下值

如上图十进制位:164

因为84减去b4为负数,我们需要在最高位加上1

如上图十进制位:208

如上图十进制位:128

如上图十进制位:260

最后我们直接得到exp,

如图成功!

本章完结

(完)