libc 2.32のSafe-Linkについて

7156 ワード

学習システムのハッカーにとって、heapに関連する弱点は非常に魅力的です.代表的なのは、スプレーの山だけを見てもそうです.また、fastbinやlibc 2.26から追加されたtcacheが安全面から迂回しやすいのも有名な話です.
もちろん、開発者がそれを知らないわけではありません.彼らはそれがだめだと思っているのか、Safe-Linkというメモリ暗号化プロセスを実行しています.従って、heap漏れやlibc漏れがなければ、heapオーバーフローが発生した場合にメモリ調整を行うことは非常に困難である.
まずはlibc 2.32のmalloccではsafe-linkngについて以下に説明した.
Use randomness from ASLR (mmap_base) to protect single-linked lists
of Fast-Bins and TCache. That is, mask the "next"pointers of the
lists' chunks, and also perform allocation alignment checks on them.
This mechanism reduces the risk of pointer hijacking, as was done with
Safe-Unlinking in the double-linked lists of Small-Bins.
It assumes a minimum page size of 4096 bytes (12 bits). Systems with
larger pages provide less entropy, although the pointer mangling
still works.
どういう意味か分かりませんが、ポインタハイジャック防止の手段としてASLRのランダム性が使われているようです.コードを見てみましょう次はsafe-linkngに関連するマクロ関数です.
#define PROTECT_PTR(pos, ptr) \
  ((__typeof (ptr)) ((((size_t) pos) >> 12) ^ ((size_t) ptr)))
#define REVEAL_PTR(ptr)  PROTECT_PTR (&ptr, ptr)
PROTECT_PTRマクロは、posパラメータを3バイト右シフト演算し、ptrおよびXORを行う.REVEAL_PTRマクロptrのアドレスと値をパラメータとしてPROTECT_PTRマクロに入れる.
これらのマクロが実際に使用する関数は、tcache_getおよびtcache_put、およびint_mallocint_freeの関数である.
/* Caller must ensure that we know tc_idx is valid and there's room
   for more chunks.  */
static __always_inline void
tcache_put (mchunkptr chunk, size_t tc_idx)
{
  tcache_entry *e = (tcache_entry *) chunk2mem (chunk);
  e->key = tcache;
  e->next = PROTECT_PTR (&e->next, tcache->entries[tc_idx]); //추가된 부분
  tcache->entries[tc_idx] = e;
  ++(tcache->counts[tc_idx]);
}


static __always_inline void *
tcache_get (size_t tc_idx)
{
  tcache_entry *e = tcache->entries[tc_idx];
  if (__glibc_unlikely (!aligned_OK (e)))
    malloc_printerr ("malloc(): unaligned tcache chunk detected");
  tcache->entries[tc_idx] = REVEAL_PTR (e->next); //추가된 부분 
  --(tcache->counts[tc_idx]);
  e->key = NULL;
  return (void *) e;
}
ソースコードから、fastbin、tcacheにブロックを追加する場合はPROTECT_PTRマクロを使用する必要があり、ブロックをインポートする場合はREVEAL_PTRマクロを使用する必要があることがわかる.
この2つのマクロは、XORの簡単な原理(A^B=Cの場合、A^C=B)を用いて暗号化、復号化される.PROTECT_PTR (&e->next, tcache->entries[tc_idx])の第1因子、第2因子、結果をそれぞれA、B、Cとした場合、REVEAL_PTR (e->next)の結果はA>>12^Cとなるので、従来のnextにおける正常ポインタBを得ることができる.
コードを見ればわかりますが、Safe-linkingはbinに1つのブロックしか効果がありません.ただし、空きブロックが2つ以上存在する場合はnextに有効なポインタがないため、heapのアドレスが分からない場合はXOR演算が行われ、値も乱されるため、誤ったポインタが参照され、競合が発生する可能性があっても剥削を阻止できます.
最初はheaplibcのアドレスでしたが、fastbinにとってfastbinはlibcのmain_arenaに存在するので、hipもlibcのアドレスもわかるでしょう?
そして派会法が現れ始めた.hip風水とtcache stashing Unlink攻撃の名前は壮大ですが、最終的には小さなbinを悪用してtcacheに入る過程の攻撃方法を使い、漏れがないことからstdoutの漏れを使ってRCEを行うことができます.
https://github.com/c4ebt/House-of-Rust
https://smallkirby.hatenablog.com/entry/safeunlinking
+大変だ!pwndbgパスワードを解いてくれ!!