Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
ExecASLR-ekoparty — ブランチターゲットバッファと投機的実行を悪用し、サイドチャネルを介してランダム化されたアドレスを漏洩させることで、Intel CPU上のASLRをバイパスする概念実証エクスプロイト。 | Kitploit
ツール/GitHubGitHub/es0j/execaslr-ekoparty
脆弱性分析エクスプロイトハードウェアセキュリティ学習と教育レッドチーミング敵対的攻撃バイナリエクスプロイト
GitHubes0j/execaslr-ekoparty

ExecASLR-ekoparty

ブランチターゲットバッファと投機的実行を悪用し、サイドチャネルを介してランダム化されたアドレスを漏洩させることで、Intel CPU上のASLRをバイパスする概念実証エクスプロイト。

リポジトリを見る
7293年前Kitploit レビュー済み

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

ExecASLR - Intelの分岐予測子を悪用してASLRをバイパスする

ASLRとは

ASLR(Address Space Layout Randomization)は、メモリ破壊攻撃の悪用を困難にするために使われる緩和策です。例えば、バッファオーバーフローの脆弱性があるシナリオでは、Return Oriented Programming(ROP)攻撃を行おうとする攻撃者は、チェーン内のガジェットのアドレスを知る必要があります。悪用対象のバイナリのコードセグメントがランダム化されていれば、攻撃者が正しいアドレスを選ぶことははるかに困難になり、悪用は実行不可能になります。

次の例は、アドレスがどのようにランダム化されるかを示しています:

root@kitploit:~
#include <stdio.h>
void DoNothing();
void (*codePtr)() = DoNothing;

void DoNothing(){}

int main(int argc,char **argv){

    printf("Destination %p\n",codePtr);
    DoNothing();
}


実行のたびに値がランダム化されます:

root@kitploit:~
Destination 0x563714256149
Destination 0x556d8e2f1149
Destination 0x5618c8bdd149
Destination 0x55ee623b0149

最後の12ビット149は常に同じですが、関数の位置はおおよそ0x550000000000から0x570000000000の間のどこにでもなり得ます。つまり、29ビットがランダム化され、0x200 0000 0000(2.2 TB)のアドレス空間を占有することになります。

CPUパイプライン

各命令の処理は困難なタスクです。単一の命令の処理には以下のような段階があります:

  • 命令のフェッチ;
  • 命令のデコード;
  • 算術論理演算装置(ALU)での演算の実行

CPUの命令スループットを向上させるために、命令の各タスクはプロセッサの特定のユニットによって実行されます。すべてのユニットが並行して動作することで、CPUはより高いクロック速度で実行できます。これがパイプラインの考え方です。

命令A、B、Cがサイクル1〜5で実行される様子。例えばサイクル3では、フェッチ、デコード、実行の各ユニットが同時にアクティブになります

しかし、命令は互いに完全に独立しているわけではありません。例えば、次のようなシーケンスを考えます:

root@kitploit:~
A. add ax,[bx]
B. jz $+1
C. mov dl,[rsi]  
D. nop

この場合、命令Aは最良でもサイクル3の実行段階でしか完了しません。しかし、フェッチユニットは次にメモリからフェッチする命令を決定する必要があり、命令C(mov dl,[rsi])をスキップすべきかどうかを判断しなければなりません。

このシナリオでは、CPUは命令Aの完了を待つという選択肢があります。例えばadd演算が0を返す場合、命令Aの完了は3クロックサイクル目にしか起こらないため、その後でメモリ上の正しい命令をフェッチすることになります:

これはパイプラインに遅延をもたらします。CPUは命令の実行が完了するまで待たなければならないからです。この例では遅延は1クロックサイクルですが、add ax,[bx]命令はメモリ操作を必要とし、前述のように完了までに数百サイクルかかることがあり、プロセッサに大きな性能コストをもたらします。

より高速な選択肢は、正しい実行経路を「推測」することです。CPUは分岐が取られるかどうかを投機的に実行できます。その時点以降、実行は投機された経路から続行され、A命令の完了後に経路が正しいと証明された場合にのみ値がコミットされます。経路が間違っていると証明された場合は、結果は破棄され、投機実行前の状態に戻されます。

実行経路を元に戻す際の唯一の問題は、CPUのマイクロアーキテクチャ状態は元に戻せないことです。そのため、CPUが命令C(mov dl,[rsi])の実行を投機すると、rsiが指すデータがキャッシュに移動されます。この影響は、後でサイドチャネル攻撃を用いて測定できます。

2ビット条件分岐予測子。 https://en.wikipedia.org/wiki/Branch_predictor

Spectre V2(分岐ターゲット注入)

予測しなければならないのは条件分岐命令だけではなく、間接分岐も同様です。CPUはcall [rdi]のような命令の分岐先を推測するメカニズムを持たなければなりません。

Spectre v2の脆弱性は、間接分岐予測子を悪用して他のプロセスで一時的実行(transient execution)を達成できることを示しています: https://spectreattack.com/spectre.pdf から引用

コンテキストAのコール命令を、コンテキストBの別のコールと同じ仮想アドレスに配置することで、攻撃者はCPUを訓練して、コンテキストB上で攻撃者が選んだ位置のコードを実行させることができます。これはReturn Oriented Programming(ROP)に似たコード再利用攻撃です。

標的となる被害者には、サイドチャネル攻撃を使って秘密情報を漏洩できる「Spectreガジェット」と呼ばれるコードが存在しなければなりません。Spectre攻撃を成功させるには、攻撃者もSpectreガジェットの位置を知っている必要があります。したがって、ユーザー対ユーザーの攻撃では、被害者をASLRで保護することがこの種の攻撃に対する緩和策として使われていました。しかし、Jump Over ASLRのようなマイクロアーキテクチャ攻撃を用いてASLRを抽出する手法もあります。ただし、この手法は直接分岐予測子の衝突に依存してASLRをバイパスするため、漏洩できるビット数に制限があります。

この予測子の内部メカニズムを以下に示します:

https://spectreattack.com/spectre.pdf から引用

これらのコンポーネントには以下のものがあります:

  • 分岐ターゲットバッファ(BTB);
    • BTBは予測先を格納するキャッシュのようなコンポーネントです。BTBは分岐先の完全な64ビットアドレスを格納し、BTBで利用可能なエントリ数はアーキテクチャに依存します。
  • 分岐履歴バッファ(BHB);
    • BHBは最近の実行フローの「ハッシュ」を格納します。各分岐命令はBHBに書き込みを行います。Skylake以前のCPUでは、BHBは直前の29分岐のコンテキストを格納できます。IcelakeではBHBは最大約100分岐を格納します。BHBはハッシュを作成するために分岐の20LSBのみを使用することに注意してください。そのうち12ビットはランダム化されていません。
  • 間接分岐予測子;
    • 間接分岐命令の12 LSBのみを使用して、完全な64ビットの分岐先を決定します。Exec ASLRはBTBから64ビットポインタを漏洩させ、ASLRアドレスを完全に復元します。
  • 直接分岐予測子
    • ソースアドレスの30 LSBを使用して32ビット値を予測します。アドレスの残りの半分はソースから再利用されます。Jump Over ASLR攻撃はこの予測子の衝突を悪用して、別のコンテキストと衝突するソースアドレスを見つけます。そのため、被害者コンテキストから30 LSBのみを漏洩させることに制限されます。

古典的なSpectre v2攻撃の構成は次のようになります:

  • 攻撃者は、被害者の分岐と同じ位置に間接分岐を配置しますが、その分岐先は被害者コンテキスト上のSpectreガジェットに一致させます。
  • 被害者が分岐を実行すると予測が外れ、Spectreガジェットが秘密情報をロードし、ライブラリなどの共有メモリ領域に対して条件付きアクセスを行います。例えば、getenv + secret[0]*4096を実行するSpectreガジェットは、libcを共有メモリとして使用することで位置0のsecretの値を漏洩させることができます。
  • 攻撃者はその後、flush+reload攻撃を使用して共有メモリのどの部分がキャッシュに移動されたかを検出し、漏洩した秘密情報を取得します。

Exec ASLR

Exec ASLR(別名Reverse Branch Target Buffer Poisoning)は、Spectre-BTI脆弱性を使用してASLRをバイパスする新しい手法です。この攻撃は、古典的なSpectre-BTIシナリオでは攻撃者だけがBTBを汚染できるのではなく、被害者も攻撃者プロセス内で分岐予測ミスを引き起こし、攻撃者をASLRで保護されたアドレスへの投機的ジャンプに導くことができるという事実を悪用します。そして、実行中のアドレスを漏洩させるサイドチャネルを使用することで、攻撃者は完全な分岐先アドレスを取得し、標的プロセスのASLRをバイパスできます。

Exec ASLR攻撃の構成は次のようになります:

  • 被害者が間接分岐を実行すると、ランダム化された分岐先ポインタ(0x55aabbeef456)がBTBに書き込まれます。
  • 攻撃者は12LSBがアラインされたアドレスに間接分岐を配置します。12LSBはランダム化されていないため、この部分は簡単です。
  • 攻撃者はメモリの可能なすべての場所を、probeArrayをサイドチャネルとして使って「私はこのアドレスで実行中です!」と攻撃者に伝える「リークガジェット」で埋めます。
  • 攻撃者が間接分岐を実行すると、予測が外れてメモリ内の多数のリークガジェットのいずれかに誤ってジャンプします。
  • 攻撃者はflush+reload攻撃を使用して、投機実行中にProbeArrayがアクセスされたかどうかを復元します。

この種の攻撃では、Spectreガジェットを見つける必要も、サイドチャネルのための共有メモリを持つ必要もありません。唯一の要件は悪用する間接分岐が存在することであり、Spectre v2に必要なすべてのガジェットは攻撃者プロセス内に配置されます。この攻撃の唯一の新しい要件は、被害者の分岐先アドレスを自分のプロセスにマップできることです。そのため、この攻撃は例えばKASLRに対しては機能しません。

これはブルートフォース攻撃でもありません。1回の試行で複数のアドレスを同時にテストできますが、メモリが同時に保持できる「リークガジェット」の数には制限があります。これにより、Jump Over ASLRと比較して攻撃にかかる時間が大幅に短縮され、毎秒約100アドレスから毎秒数千億アドレスまで向上します。

リークガジェット

リークガジェットはprobeArrayを使用して、ガジェット自身がどこで実行されたかを攻撃者に通知します。probeArrayと漏洩させたいRIPのインデックスを引数として受け取り、probeArray[0]とprobeArray[4096]のどちらにアクセスすべきかを決定する分岐のないプログラミング手法を実行します。

root@kitploit:~
lea rax,[rip - 7]      ;load current address
shr rax,cl             ;selects the bit using cl arg
and rax,1
shl rax,12             ;loads probearray
mov dl,[rsi+rax]       ;or probearray+4096

BHBと標的の被害者コードの制御

前述のとおり、BHBはBTBエントリを選択するために使用されます。BTBの衝突を見つけてこの脆弱性を悪用するには、攻撃者は最後に実行されたN個(<skylakeの場合は29個)の分岐を知っている必要があります。私たちのテストでは、間接呼び出しの前にBHBの状態を既知の値に設定するためにforループを使用しました。以下は脆弱な被害者コードの例です:

root@kitploit:~
#include <stdio.h>

void DoNothing();
void (*codePtr)() = DoNothing;

void DoNothing(){
    return;
}

int main(){
    printf("Destination = %p\n",codePtr);
    while(1){
	for(int i=0;i<200;i++){}
    	codePtr();
    }
}

両方のコンテキストでBHBの状態が同じになるようにするため、攻撃者は被害者のforループとcallに対応するバイトをシェルコードの形式でコピーします。シェルコードは、BHBの状態を同じにするために必要な20LSBのアライメントに一致し得るすべての256ポジションにコピーされます。

root@kitploit:~
Victim Code

0x5594c566a152 <+28>:    mov    eax,0xc8
0x5594c566a157 <+33>:    dec    eax
0x5594c566a159 <+35>:    jne    0x1157 <main+33>
0x5594c566a15b <+37>:    nop
0x5594c566a15c <+38>:    nop
0x5594c566a15d <+39>:    nop
0x5594c566a15e <+40>:    lea    rdi,[rip+0x2ecb]
0x5594c566a165 <+47>:    call   QWORD PTR [rdi]

--> Executes to
0x5594c5669135:    ret

root@kitploit:~
Attacker Code

… //eax=200 rsi=probeArray, cl=0 
0x6a157    dec    eax
0x6a159    jne    0x455555500157
…
0x6a165    jmp    QWORD PTR [rdi]

--> Misspredicts to
0x5594c566a135:    lea rax,[rip - 7]
0x5594c566a13c:    shr rax,cl
0x5594c566a13f:    and rax,1
0x5594c566a133:    shl rax,12
0x5594c566a137:    mov dl,[rsi+rax]

課題

すべての可能な位置に同時にガジェットを配置しようとすると、問題があります。私たちのテストでは、ASLRは分岐先を0x550000000000から0x570000000000の間のどこかに配置します。つまり、マップすべき仮想アドレス空間は2.2TB、すなわち5億3700万個のリークガジェットに相当します。しかし、システムのRAMはわずか8GBです。

COWを使用して2TBのRAMをマップすることも可能ですが、このアプローチではあまり成功しませんでした。おそらく、Translation Lookaside Buffer(TLB)に過度のプレッシャーがかかり、未変換アドレスへの投機が遅すぎるのだと思います。

テストでは、1GBのメモリ内ページを作成し、リークガジェットで満たしました。その後、remapシステムコールを使用してページを2TBの範囲全体にシフトしました。

観察されたもう1つの問題は、投機されたアドレスは実際に実行されたことがないため、おそらくTLBに存在しないという事実でした。しかし、Intelのマニュアルには次のように記載されています:

  • 「プロセッサは、プリフェッチに必要な変換や、実行されたコードパスでは実際には発生しない投機実行の結果としてのアクセスに必要な変換をキャッシュする場合があります」 - ISA

したがって、「投機誘発」ページウォークの可能性を高めるために、正しいアドレスが解決されるのを可能な限り困難にしました。これは分岐先アドレスにポインタチェーンを使用することで実現されます。アイデアは、CPUのフロントエンドが分岐先を投機し、リオーダーユニットがポインタチェーンの読み取りを完了する前にリークガジェットを実行するというものです。

root@kitploit:~
Improved Caller - Frontend fetched instructions
mov rcx,%1       ;mask arg for gadget
lea rsi,[%2]     ;probe array ptr arg
lea rdx,[%0]
mov rdx,[rdx]    ;pointer chain
mov rdx,[rdx]
mov rdx,[rdx]
...
mov rdx,[rdx]
mov rdx,[rdx]
check [rdx]      ;mispredicts to gadget

lea rax,[rip - 7];speculative execution
shr rax,cl
and rax,1
shl rax,12
mov dl,[rsi+rax]

root@kitploit:~
Improved Caller - Reorder unit scheduled instructions
mov rcx,%1    ;mask arg for gadget
lea rsi,[%2]  ;probe array ptr arg
lea rdx,[%0]
mov rdx,[rdx] ;pointer chain
mov rdx,[rdx]
; <pagewalk occurs some where here>
... ;Out of order + speculation
lea rax,[rip - 7]
shr rax,cl
and rax,1
shl rax,12
mov dl,[rsi+rax]
...
mov rdx,[rdx]
mov rdx,[rdx]
check [rdx] ;the execution path reverted

このアウト・オブ・オーダー+投機実行の手法により、攻撃における望ましい予測ミス率が改善されました。

スケジューリングとSTIBP

Spectre V2攻撃を実行するには、攻撃者は被害者と同じコアでコードを実行し、同じ分岐予測ユニット(BPU)を共有する必要があります。<= SkylakeのCPUでは、ハイパースレッディングを使用してコアの同一配置(コア・コレジデンシー)を達成できることを確認しました。

IcelakeおよびCascade Lake CPUは、スレッド間でBPUを分離するSingle Thread Indirect Branch Predictor(STIBP)と呼ばれる緩和策を実装しています。そのため、被害者と攻撃者を同じスレッドで実行し、usleepを使用して被害者プロセスと攻撃者プロセスを交互に切り替える必要があります。これらの世代のキャッシュ(おそらくTLBも)が非常に優れており、同時にはるかに多くのガジェットをキャッシュできるため、攻撃者はこのCPUでは遅くなります。

結果

この手法は、Google Cloudで利用可能なすべてのIntel CPU(N1世代とN2世代の両方)でテストされました。

  • Sandy Bridge
  • Ivy Bridge
  • Haswell
  • Broadwell
  • Skylake
  • Cascadelake
  • Icelake

Cascade LakeとIce Lakeではエクスプロイトにいくつかの違いがありますが、すべてのテストで10秒未満に99%を超える精度でアドレスを復元できました。

緩和策

緩和策は、ユーザー対ユーザー攻撃を防ぐためのSpectre V2と同じです。 Indirect Branch Prediction Barrier(IBPB)はBPUのフラッシュを可能にし、コンテキストスイッチ時に使用できます。Linuxでは、IBPBはprctlシステムコールをPR_SET_SPECULATION_CTRLオプション付きで使用することで利用できます。 Windowsでの同等の緩和策はまったくわかりません。教えてください。


論文:

https://cos.ufrj.br/uploadfile/publicacao/3061.pdf

Ekopartyトーク:

https://www.youtube.com/watch?v=Qj4z-KvnkxU

スライド:

https://docs.google.com/presentation/d/10t-oo-c26x9ydx1_FYgmhy204rxfmQ92eboPlCnA2y4/edit?usp=sharing

参考文献:

https://googleprojectzero.blogspot.com/2018/01/reading-privileged-memory-with-side.html https://eprint.iacr.org/2013/448.pdf https://spectreattack.com/spectre.pdf https://www.cs.ucr.edu/~nael/pubs/micro16.pdf http://download.vusec.net/papers/bhi-spectre-bhb_sec22.pdf https://www.kernel.org/doc/html/latest/userspace-api/spec_ctrl.html Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3. Santa Clara, USA: Intel Corporation, 2016, iSBN 325384-060US

ツールをダウンロード
操作 \ クロックサイクル12345
フェッチABC
デコードABC
実行ABC
操作 \ クロックサイクル123456
フェッチABD
デコードABD
実行ABD
操作 \ クロックサイクル123456
フェッチAB(S) C
デコードAB(S) C
実行AB(S) C