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
GCC -no-pie
オプションはASLRを部分的に無効にします。バイナリは固定ベースアドレスにロードされます(つまり、0x400000
);ただし、他のメモリセグメント(スタックなど)は、ランダムなベースアドレスにロードされる可能性があります。
ASLRを完全に無効にするには、システム全体でASLRを無効にする必要があります。
echo 0 | Sudo tee /proc/sys/kernel/randomize_va_space
これで、スタックは固定ベースアドレスにロードされます。以下のアドレスは、rsp
のret
の直前のmain
の値です(r2 -d
):
0x7fffffffdfb8
0x7fffffffdfb8
0x7fffffffdfb8
0x7fffffffdfb8
0x7fffffffdfb8
0x7fffffffdfb8
これを踏まえると、NOP-sledgeにターゲットアドレスを選択するのは簡単です。