Skip to content

刻在栈里的秘密

本题考查格式化字符串漏洞利用及 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 进行泄露,这里用 n%s 是不行的,栈上难免会有一些不合法的地址,使用 %s 会导致程序直接崩溃。

稍微数一数就知道我们需要的 n 是 24,所以使用 %24$s 来泄露密码,用 %24$p 来泄露指针即可。

验证逻辑