字符串格式化所导致的漏洞
1 HelloWorld
就个人来说,所学的c,第一个成功运行的程序既是HelloWorld了:
1 |
|
当时觉得很简单、很理所当然。然而,如此简单的程序之下,调用的printf
,却是一个非常难理解的”变参函数”。
普通的参数遵守调用规则,从右到左参数依次压栈。而变参函数呢?堆栈又由谁恢复呢?
2 变参函数导致的问题
就printf
来说,该函数的函数原型是
1 | int printf(const char *format,...); |
简单来说,该变参函数,使用format
所指向的字符串来解析后面不定长(以...
表示)的参数。
那么,若format
中所声明的参数,多于实际传入的变量又该如何呢?这就导致了所谓的fmt
漏洞:printf
函数会输出堆栈上传入参数之后的数据。
对于%s
来说,会输出传入值所指向的字符串;对于%p
来说,会输出传入的值。当然,也可以使用%c/%x/%d
等方式输出堆栈上的数据。
3 任意位置
3.1 使用$说明参数编号
此处参数编号从format
之后开始,从1数起。
1 | int main() |
看wiki上说不是c99标准,但是感觉遇到的都实现了这玩意吧。
3.2 使用传入的参数作为地址
因为传入的参数也是在堆栈上,所以很随意就可以用$
来指出来,再搭配$s
一波美滋滋。
4 写数据
甚至你还可以用printf
来写内存, 参数%i
会统计当前已输出的字符个数,并赋值到传入值所指向的位置。
1 |
|
5 其他
突然、就水了一波。
最近在看CS的那些玩意,cna真乃神器。现在就差个beacon的源码搞一搞了,虽然看片子、看代码好像没有像那些exe能直接插的地方,但是说不定那些正版大佬的Arsenal就会附赠一份beacon源码呢。所以还是只能用那屎一样的ruby写的msf了么……