0.格式化字符串漏洞
0-1.起因
我们知道,一般情况下,在C语言中格式化输出函数printf()的用法如下:
1 | printf("%d",a); |
可以发现,对于printf()这种函数而言,它的参数数量是不定的。而对于可变参数的函数而言,如printf(),它本身并不知道需要传入的参数的数量,也不清楚在该函数调用前有多少参数被压栈。因此,它需要传入一个format来告诉它究竟有多少参数被传入。因此,有几个格式化字符串,函数就认为传入了几个参数。
那么,如果没有format会发生什么呢?
例如:
1 | printf(a); |
答案是如果a是个正常的数据,那么程序也会正常输出a的值。
那么假如我们稍加利用,传入一个格式化字符串又会发生什么呢?
那么则有可能会泄露出内存中的一些数据。
0-2.泄露任意参数
假如我们知道在函数调用的过程中某参数是第k个传入的,那么要输出该参数的值,则可利用如下方式:
1 | printf("%k$p"); |
按照这种道理,假如我们知道了canary在函数中的是第几个被传入的,则可以通过上述方法泄露canary。
1.例子
本题用到的ELF:点击下载
查看IDA:
发现明显的格式化字符串漏洞。利用此处泄露canary。
用gdb进行动态调试,在func_a()处下断点:
按r运行,再按n直到运行到call read处:
输入canary查看其值,再输入stack查看栈。
可以看出在栈中偏移量为0008、0024、0056处都存有canary的值。这里考虑泄露0008处。
我们知道,64位Linux中函数前6个参数靠寄存器传值,之后的参数才会压入栈中。因此我们需要泄露的是第6+8/8=7个参数。
因此exp可以这样写:
1 | from pwn import * |
执行完的效果如下图:
可以看出成功泄露了canary。