format_string
介绍什么是格式化字符串函数
众所周知,在初学c语言的时候,有一个不是太离谱的函数叫做printf(),主要就是用来格式化输出一些string,并且可以传一些变量作为参数,动态的输出这些string并且保持格式不变,所以这个函数也叫格式化字符串函数。同时,在c语言中有许多这样类似的格式化字符串函数。众所也周知,c语言是一个漏洞很多的语言,有无限制读入的gets函数,所以,格式化函数当然也有漏洞,今天就来讲讲格式化字符串漏洞。
格式化字符串函数示例
1 |
|
这个是我从ctf-wiki上扒下来的,如果讲的不好可以去看原文。可以看到printf函数中总共有五个参数,第一个是格式化字符串,后面几个就是动态传参的参数,通过gcc编译一下,把保护关一下
1 |
|
试运行
很简单的一段c语言代码,这是正常输入的时候会是正常的输出,但是当不正常的输入参数%s就会有特别的事情发生
可以看到有一些不属于我输入,或者缓冲区变量的东西出现了,这么一看,也许是一个地址
接下来,就通过gdb来动态调试一下,看一下到底是啥。在printf出打一个断点,然后运行程序,输入%8x.%8x.%8x 就可以看到程序运行到printf函数就停下了
可以通过stack指令来查看栈上的具体情况
可以看到,栈顶第一个参数,就是main函数的返回地址,往后面四个,就是刚刚的格式化字符串参数
可以看到,已经停在了第二个输出s的printf处,再看一下栈的情况
继续c
可以看到输出的地址,就是栈上依次往后的几位,从0xffffc554开始作为第一个参数,往后两位作为第二,第三位参数输出。
在这插一条关于c语言的小tips:
我们可以通过%n$p来输出格式化字符串函数的第n+1位参数,
例如,输入的是%3$x,
理论是就应该输出第四个参数的地址,继续运行
可以看出,这样的函数,非常容易导致内存泄露,所以漏洞利用点主要就在这,当然在ctf中一般不会单独考察格式化字符串漏洞,主要和别的绕过手段一块考察,例如canary保护开启时,我们可以通过格式化字符串漏洞,读取canary的值,然后添加在payload中,从而绕过canary保护
攻防世界 Mary_Morton
先测试一下
‘
可以看到,第二个函数有循环的功能,并且开启了canary保护,初步猜测应该是利用第二个函数获取canary的地址,然后继续利用第二个或者第一个,或者第三个函数,来进行获取shell操作,那就来看一下ida里面把吧。
function1 存在栈溢出漏洞
funtion2 存在格式化字符串漏洞
和分析不太一样的是,并不是第二个函数有循环功能,而是第三个选项直接退出,否则就一直循环执行。那就选择输入一些数据来测试。选择输入aaaaaaaa-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p
可以看到aaaaaaaa这个参数偏移量是6,也就是第六个参数,在ida中可以看到buf距离rbp是0x90,但是开了canary保护,栈就会有一点变化
应该好理解了哈!所以canary的偏移量应该是aaaaaaaa的偏移量加上0x88/8 也就是6+17 =
23 所以读取canary 也就是%23$p
最后直接给exp了
1 |
|