web-dev-qa-db-ja.com

RSPは実行間で大きく異なるため、ASLRを無効にした状態でスタックベースのバッファオーバーフローを利用することはできませんか?

ALSRを無効にしてコンパイルした小さなおもちゃのプログラムを作成しましたが、スタックベースのバッファオーバーフローを使用して悪用したいと思います。

// gcc stackexec0x1.c -Wl,-z,execstack -no-pie -fno-stack-protector -o stackexec0x1

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define SBUFSZ 0x100
#define LBUFSZ 0x800

int main(int argc, char* argv[]) {
    char buf[SBUFSZ];
    printf("# ");
    fgets(buf, LBUFSZ, stdin); // exploit this!
    printf("%s", buf);
    return 0;
}

スタックに保存されているリターンアドレスをカスタムアドレスで簡単に上書きできます。ただし、プログラムの連続実行間で、rspレジスタ(retの直前)は異なります。

0x7ffdc114dc88
0x7ffeb97d5668
0x7ffd48027798
0x7ffdbf2e9ea8
0x7ffe036a5d78
0x7fff40595998

Above rspレジスタ値の違いを計算すると、それらが大きいことがわかります。それらのほとんどをカバーするNOPそりをスタックに置くことは現実的ではないでしょうか?

スタックのNOP-sledge +ペイロードに戻りアドレスを選択して、関数が戻るときに(高い確率で)実行されるようにするにはどうすればよいですか?

checksec

checksec stackexec0x1
[*] '/home/nlykkei/exploit-dev/stackexec0x1/stackexec0x1'
    Arch:     AMD64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x400000)
    RWX:      Has RWX segments
2
Shuzheng

GCC -no-pieオプションはASLRを部分的に無効にします。バイナリは固定ベースアドレスにロードされます(つまり、0x400000);ただし、他のメモリセグメント(スタックなど)は、ランダムなベースアドレスにロードされる可能性があります。

ASLRを完全に無効にするには、システム全体でASLRを無効にする必要があります。

echo 0 | Sudo tee /proc/sys/kernel/randomize_va_space

これで、スタックは固定ベースアドレスにロードされます。以下のアドレスは、rspretの直前のmainの値です(r2 -d):

0x7fffffffdfb8
0x7fffffffdfb8
0x7fffffffdfb8
0x7fffffffdfb8
0x7fffffffdfb8
0x7fffffffdfb8

これを踏まえると、NOP-sledgeにターゲットアドレスを選択するのは簡単です。