读任意地址
printf("%x")
只给格式化字符串,而不给参数,会导致内存泄漏从而读到内存中其他地址的数据。
%N$x
参数可以以16进制方式打印第N个参数的内容,通过修改N,我们可以遍历栈上的所有内容。
通过%N$s
参数,我们可以将第N个参数对应的内容作为字符串的地址从而获得内存中任意位置的内容。方法如下
- 如果我们使用的打印语句为:
printf("AAAA%x")
那么栈的内容如下:
栈底 |
---|
… |
x |
% |
A |
A |
A |
A |
… |
栈顶 |
- 使用
printf("AAAA%N$x")
,并令N=1,2,3,… 假设,当N=6时得到如下输出内容:
AAAA41414141#
其中41是‘A’的ASCII码,‘41414141#’正好是4个字节,即int的大小,这说明偏移量为6时正好读到格式化字符串在栈中的位置。 - 使用
printf("%7$sAAAA")
,则栈内容如下:
栈底 |
---|
… |
A |
A |
A |
A |
s |
$ |
7 |
% |
… |
栈顶 |
我们知道偏移量为6时正好能读到‘%’的位置,那么偏移量为7的时候会往栈底方向再走4个字节,于是得到的内容为‘AAAA’,而由于这次我们使用的是%s
打印符,因此会打印地址‘AAAA’处的内容,通过修改‘AAAA’的内容,就可以打印任意内存位置的内容。
4. 可以用pwntool实现该功能如下:
from pwn import *
context.log_level='debug'
conn=process('./test')
conn.sendline("%7$s"<