Unlink原理和一些手法

CH13hh發表於2024-04-25

Unlink原理和一些手法

✅簡單介紹一下unlink相關的知識

unlink是利用glibc malloc 的記憶體回收機制造成攻擊的,核心就在於當兩個free的堆塊在物理上相鄰時,會將他們合併,並將原來free的堆塊在原來的連結串列中解鏈,加入新的連結串列中其目的是把一個雙向連結串列中的空閒塊拿出來(例如 free 時和目前物理相鄰的 free chunk 進行合併)比如說陣列這類的.........等等。

前提是我們可以進行溢位修改下一個chunk的fd和bk指標

當我們實現unlink的時候就可以任意地址寫,但是現實是殘酷的,現在的unlink加了很多保護,我們先看一下定義。

#define unlink(P, BK, FD) {                                            
  FD = P->fd;                                                          
  BK = P->bk;                                                          
  if (__builtin_expect (FD->bk != P || BK->fd != P, 0))                
    malloc_printerr (check_action, "corrupted double-linked list", P); 
  else {                                                              
    FD->bk = BK;                                                       
    BK->fd = FD;                                                       
    if (!in_smallbin_range (P->size)                       
    && __builtin_expect (P->fd_nextsize != NULL, 0)) {         
      assert (P->fd_nextsize->bk_nextsize == P);              
      assert (P->bk_nextsize->fd_nextsize == P);              
      if (FD->fd_nextsize == NULL) {                       
    if (P->fd_nextsize == P)                       
      FD->fd_nextsize = FD->bk_nextsize = FD;              
    else {                                 
      FD->fd_nextsize = P->fd_nextsize;                
      FD->bk_nextsize = P->bk_nextsize;                
      P->fd_nextsize->bk_nextsize = FD;                
      P->bk_nextsize->fd_nextsize = FD;                
    }                                  
      } else {                                 
    P->fd_nextsize->bk_nextsize = P->bk_nextsize;             
    P->bk_nextsize->fd_nextsize = P->fd_nextsize;              
      }                                    
    }                                      
  }                                                                    
}

大多是一些保護,其中最重要的是下面這個

//檢查p和其前後的chunk是否構成雙向連結串列
if (__builtin_expect (fd->bk != p || bk->fd != p, 0))
    malloc_printerr ("corrupted double-linked list");

這是一個關鍵 check ,那麼如何繞過檢查呢?

64位滿足以下式子32位依次類推:

P->fd->bk == P <=> *(P->fd + 0x18) == P 
p->bk->fd == P <=> *(p->bk + 0x10) == P

那麼我們可以將fd設定為*p-0x18 bk設定為*p-0x10,那麼我們就可以繞過檢查,那麼當我們free下一個chunk的時候就會進行合併,實現了unlink,那麼當我們再次修改該chunk的時候指標就會指向*p-0x18的位置進而實現任意地址寫。

我們透過題目看一下具體用法題目連結🔗https://pan.baidu.com/s/1lEba9fl8Yt56MvC6fj3xjQ?pwd=w6du提取碼:w6du

首先看保護

Unlink原理和一些手法

got表可修改,我們ida載入看一下

Unlink原理和一些手法

是一些選單什麼的,其中有一個隱藏選項,看一下

Unlink原理和一些手法

好傢伙是後門函式,但是他有條件,magic處地址的值必須大於等於114514才可以執行

Unlink原理和一些手法

值得注意的是edit函式沒有對我們輸入的修改長度進行檢查,那麼我們可以使用unlink修改magic地址的值

✅思路:

1.先申請4個較大的chunk(方便到時候我們進行偽造)4個chunk是因為*p-0x18可以指向第一個chunk,最後一個用來free

2.編輯chunk進行偽造修改bk和fd指標,實現unlink

3.修改magic處地址的值為理想的值,選擇隱藏選項得到flag

先貼一下wp我再詳細解釋

Unlink原理和一些手法

Unlink原理和一些手法

這裡採用下標為3的陣列是因為當設定完bk和fd之後會指向第一個下標(*p-0x18),那麼我們再次修改下標為0的chunk資料是理想資料下標為3的陣列為magic地址那麼

相當於magic的地址為我們理想的值(3->0->magic)中間把下標為3的chunk分割成了兩個chunk,偽造fd和bk以及下一個chunk的頭部使當前chunk為free狀態,那麼再free下一個chunk就可以完成unlink,最後再進行修改就好啦具體可以參考這個圖和這個連結https://blog.csdn.net/qq_35493457/article/details/105857572

Unlink原理和一些手法

相關文章