我试图了解格式字符串漏洞如何工作以及我们如何读取任何地址。
我可以实时检查在 printf 中输入“%x %x %x”如何将元素从字符串地址上方的堆栈中弹出。
这是该堆栈在 printf 中的外观:
(...)
0x7fffffffe018: 0x000000000040052c
0x7fffffffe020: 0x00007fffffffe180
0x7fffffffe028: 0x00007fffffffe168
0x7fffffffe030: *0x00007fffffffe48d* << address of argument
0x7fffffffe038: 0x00007ffff7dd4e80
0x7fffffffe040: 0x00007ffff7de9d60
0x7fffffffe048: 0x00007ffff7ffe268
0x7fffffffe050: 0x0000000000000000
0x7fffffffe058: 0x0000000000400563 <</ return address after printf
0x7fffffffe060: 0x00007fffffffe168
0x7fffffffe068: 0x0000000200400440
(...)
并且0x7ffffffffe48d是内存中“%x %x %x”字符串的地址:
0x7fffffffe469: "/home/.../C/format_string/test"
*0x7fffffffe48d*: "%x %x %x"
0x7fffffffe4ac: "SSH_AGENT_PID=..."
所以从逻辑上讲,这将在此之上输出 3 个元素,即:
ffffe168 ffffe180 40052c
现在,我不明白的是,如果我在参数中放一个随机地址,比如: "\x15\xff\x0A\x23 %x %x %x %x %s",为什么会是"\x15\ xff\x0A\x23"是否实际存储在堆栈中并由 "%s" 读取?
从我在上面看到的内容来看,只有整个字符串的地址被放入堆栈(0x00007ffffffffe48d),而不是字符(实际上是我打算读取的地址)本身。
换句话说,无论我在字符串中放入什么,我都只能控制地址的内容:
0x7fffffffe48d: "blablabla %x %x %x"
但不是从堆栈中弹出的内容。