刻在栈里的秘密
本题考查格式化字符串漏洞利用及 x86-64 函数调用约定的理解。
这题没有附件,只有远程靶机,连接之后你会看到一些这样的输出

需要我们去泄露存放在栈上的密码以及它对应的地址。本题的目标是“泄露”,所以我们重点关注两个指示符:
$: 位置指示符,允许我们指定要访问第几个参数,例如%7$p就是以指针形式打印第 7 个参数。%p(或%lx): 以十六进制形式打印一个指针或长整型。%s: 将对应参数视为一个char*指针,并打印出它所指向的字符串内容。
要准确定位泄露目标,我们必须了解 x86-64 架构下函数是如何传递参数的。
- 前 6 个参数: 通过寄存器传递。依次是
RDI,RSI,RDX,RCX,R8,R9。 - 第 7 个及以后的参数: 通过栈传递。
printf的第 7 个参数就位于RSP(栈顶)所指向的位置,第 8 个在RSP+8,以此类推。
这也是出题人想通过题目描述想表达的事情。在 printf(your_input) 调用中,我们的输入(格式化字符串)位于 RDI,但是由于 printf 的错误使用,没有给出第二个参数,printf 会遵循调用约定,当它需要第一个格式化参数时,它会去 RSI 里找;需要第二个时,去 RDX 里找,以此类推。
所以只要计算出指向密码的指针所在位置所对应的参数位置,就可以用 %n$s 进行泄露,这里用 %s 是不行的,栈上难免会有一些不合法的地址,使用 %s 会导致程序直接崩溃。
稍微数一数就知道我们需要的 %24$s 来泄露密码,用 %24$p 来泄露指针即可。
