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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
how-to-bypass-aslr-on-linux-x86_64 — ASLRバイパス(情報漏洩なし) | Kitploit
ツール/GitHubGitHub/nick0ve/how-to-bypass-aslr-on-linux-x86_64
エクスプロイトCTF学習と教育バイナリエクスプロイト
GitHubnick0ve/how-to-bypass-aslr-on-linux-x86_64

how-to-bypass-aslr-on-linux-x86_64

ASLRバイパス(情報漏洩なし)

リポジトリを見る

人気

すべて見る →

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

すべてのツールを探索

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

すべてのツールを見る →
共有
16717164年前Kitploit レビュー済み

Linux x86-64 における 64 ビット aslr の突破

この記事では、Samuel Groß が自身の Remote iPhone Exploitation Part 2: Bringing Light into the Darkness -- a Remote ASLR Bypass で説明した手法を、Linux x86_64 上の ASLR をバイパスするために適用することについて説明します。

これを示すために、Buckeye CTF の pwnable チャレンジである guess_god を解いてみます。

このコンテンツはできるだけ初心者向けにしようと思います。十分に自信がある方は、任意のセクションをスキップして、エクスプロイトだけを見たい場合は遠慮なく飛ばしてください。

0. はじめに


私はその CTF には参加しませんでしたが、CTF 終了の約2時間前に、fibonhack の Discord で暗号関連のゴタゴタについて助けを求めていた Guray00 のおかげで、このチャレンジに興味を持ちました。

彼を助けることはできませんでしたが、pwnable チャレンジを調べてみて、P0 のブログ記事を理解し、うまくいけば報奨金を得るのに良いだろうと考えました。

1. ASLR とそのバイパス方法

1.1 ASLR とは?

Address Space Layout Randomization(ASLR)は、プロセスのアドレス空間内にある実行ファイルのベースアドレスや、ライブラリ、ヒープ、スタックの位置をランダムに配置するコンピュータセキュリティ技術です。

1.2 Linux における ASLR

Linux では、/proc/<pid>/maps ファイルを読むことで、procfs を介して、pid に基づくプロセスのマッピングを調べることができます。

自分自身のメモリマッピングを知りたい場合は、/proc/self/maps を読むことができます。

例えば、cat を使って /proc/self/maps を読んでみることができます:``` root@088ec31b2ce9:/home/ctf/challenge# cat /proc/self/maps 55faeb01c000-55faeb01e000 r--p 00000000 fe:01 2497233 /usr/bin/cat 55faeb01e000-55faeb023000 r-xp 00002000 fe:01 2497233 /usr/bin/cat 55faeb023000-55faeb026000 r--p 00007000 fe:01 2497233 /usr/bin/cat 55faeb026000-55faeb027000 r--p 00009000 fe:01 2497233 /usr/bin/cat 55faeb027000-55faeb028000 rw-p 0000a000 fe:01 2497233 /usr/bin/cat 55faeb115000-55faeb136000 rw-p 00000000 00:00 0 [heap] 7fe15dfb1000-7fe15dfd5000 rw-p 00000000 00:00 0 7fe15dfd5000-7fe15dffb000 r--p 00000000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7fe15dffb000-7fe15e166000 r-xp 00026000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7fe15e166000-7fe15e1b2000 r--p 00191000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7fe15e1b2000-7fe15e1b5000 r--p 001dc000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7fe15e1b5000-7fe15e1b8000 rw-p 001df000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7fe15e1b8000-7fe15e1c3000 rw-p 00000000 00:00 0 7fe15e1c7000-7fe15e1c8000 r--p 00000000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7fe15e1c8000-7fe15e1ef000 r-xp 00001000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7fe15e1ef000-7fe15e1f9000 r--p 00028000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7fe15e1f9000-7fe15e1fb000 r--p 00031000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7fe15e1fb000-7fe15e1fd000 rw-p 00033000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7fff4388f000-7fff438b0000 rw-p 00000000 00:00 0 [stack] 7fff43989000-7fff4398d000 r--p 00000000 00:00 0 [vvar] 7fff4398d000-7fff4398f000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]

root@088ec31b2ce9:/home/ctf/challenge# cat /proc/self/maps 55ffc0b1b000-55ffc0b1d000 r--p 00000000 fe:01 2497233 /usr/bin/cat 55ffc0b1d000-55ffc0b22000 r-xp 00002000 fe:01 2497233 /usr/bin/cat 55ffc0b22000-55ffc0b25000 r--p 00007000 fe:01 2497233 /usr/bin/cat 55ffc0b25000-55ffc0b26000 r--p 00009000 fe:01 2497233 /usr/bin/cat 55ffc0b26000-55ffc0b27000 rw-p 0000a000 fe:01 2497233 /usr/bin/cat 55ffc2108000-55ffc2129000 rw-p 00000000 00:00 0 [heap] 7f1ec6e0f000-7f1ec6e33000 rw-p 00000000 00:00 0 7f1ec6e33000-7f1ec6e59000 r--p 00000000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7f1ec6e59000-7f1ec6fc4000 r-xp 00026000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7f1ec6fc4000-7f1ec7010000 r--p 00191000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7f1ec7010000-7f1ec7013000 r--p 001dc000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7f1ec7013000-7f1ec7016000 rw-p 001df000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7f1ec7016000-7f1ec7021000 rw-p 00000000 00:00 0 7f1ec7025000-7f1ec7026000 r--p 00000000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7f1ec7026000-7f1ec704d000 r-xp 00001000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7f1ec704d000-7f1ec7057000 r--p 00028000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7f1ec7057000-7f1ec7059000 r--p 00031000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7f1ec7059000-7f1ec705b000 rw-p 00033000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7ffc72fa4000-7ffc72fc5000 rw-p 00000000 00:00 0 [stack] 7ffc72fe7000-7ffc72feb000 r--p 00000000 00:00 0 [vvar] 7ffc72feb000-7ffc72fed000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]

### メモリマッピングのパターン

これを数回行うと、次のことが推測できるでしょう:
* バイナリのPIEベースは0x00005500_00000000〜0x00005700_00000000の範囲にあるはずです。つまり、2TBの候補アドレスがあります。
* ヒープはバイナリの近くにあります。
* ライブラリは0x00007f00_00000000〜0x00007fff_ffffffffの範囲にあり、1TBの候補アドレスがあります。
* スタックは(ほとんどの場合)0x00007ffc_00000000〜0x00007fff_ffffffffの範囲にあり、16GBの候補アドレスがあります。
* 範囲0xffffffffff600000〜0xffffffffff601000は常にマップされています。それが何か気になる場合は、[この記事](http://terenceli.github.io/%E6%8A%80%E6%9C%AF/2019/02/13/vsyscall-and-vdso)を読んでください。

## 1.3 情報漏えい(infoleak)なしでASLRを回避する方法

情報漏えいが不可能な場合に、ASLRを回避するためにできることについて説明します。

これは、Saeloのブログ記事を読んで得た内容を要約しようという試みです。

ASLRを回避するには、次のものが必要です:
* メモリスプレー技術。指定したサイズの連続メモリを、指定したアドレス範囲にマップすることができます。
  
  彼が言うように、これには2つの方法があります:
  1. メモリリーク(情報漏えいではない!)を悪用する方法。メモリのチャンクが「忘れられ」て解放されないバグを、目的の量のメモリがリークするまで複数回トリガーします。
  2. 「増幅ガジェット」を見つけて悪用する方法。既存のデータチャンクを取得してそれをコピーするコード(潜在的に複数回コピーする)で、攻撃者が比較的少数のバイトを送信するだけで大量のメモリをスプレーできるようにします。
* アドレスがマップされているかどうかを教えてくれる `isAddressMapped` オラクル。

### LinuxでのASLR回避のPoC

LinuxでASLRを完全に破壊するために、saeloのPoCを再現してみましょう。

<p align="center"> <img src="https://assets.kitploit.com/production/public/readmes/48660/93fcc6aff8ffd2e8395f34b35bc2f5d244e74a53b2fac39c3dae35c802227339.png" > <i> saeloのPoC</i> <p/> <br/>

Linuxではそれほど簡単ではありません。16TBのメモリを割り当てることができる場合にのみ、ASLRを完全に破壊することが可能です。```C
#include <stdio.h>
#include <stdlib.h>

int main()
{
    // 64gb
    size_t size = 0x1000000000;

    // 16TB allocations
    for (int i = 0; i < 256; i++) {
        void *mem = malloc(size); // this ends up calling mmap
        if (!mem) {
            puts("Failed");
            return 1;
        }
        printf("%p\n", mem);
    }

    unsigned int *mem = (void*)0x7f0000000000ULL;
    *mem = 0x41414141;
    printf("R/W to %p: %x\n", mem, *mem);

    return 0;
}

glibcメモリ割り当てに関する注意

man malloc の注意書きより:

  • 通常、malloc() はヒープからメモリを割り当て、必要に応じて sbrk(2) を使ってヒープのサイズを調整する。MMAP_THRESHOLD バイトより大きいメモリブロックを割り当てる場合、glibc の malloc() 実装は mmap(2) を使用してプライベート匿名マッピングとしてメモリを割り当てる。MMAP_THRESHOLD はデフォルトで 128 kB だが、mallopt(3) で調整可能である。mmap(2) を使用して行われた割り当ては、RLIMIT_DATA リソース制限の影響を受けない(getrlimit(2) を参照)。

したがって、void *mem = malloc(size) は最終的に mmap(size + malloc_metadata_size, ...) を呼び出すことになる。

ライブラリは ld によって mmap 経由でプロセスにマッピングされるため、それらの割り当てはライブラリの近くに配置されることになる。

境界クロストリック

malloc が返すアドレスを見れば、何が起きているのかをよりよく理解できる。プロのヒント: 最上位バイトに注目しよう。

ツールをダウンロード