セキュリティ コースの講義スライドから次のコードを取得しました。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
extern char shellcode;
#define VULN "./vuln"
int main(int argc, char **argv) {
void *addr = (char *) 0xc0000000 - 4
- (strlen(VULN) + 1)
- (strlen(&shellcode) + 1);
fprintf(stderr, "Using address: 0x%p\n", addr);
// some other stuff
char *params[] = { VULN, buf, NULL };
char *env[] = { &shellcode, NULL };
execve(VULN, params, env);
perror("execve");
}
このコードは、その環境でシェルコードを使用して脆弱なプログラムを呼び出します。シェルコードは、シェルを開く外部ファイル内のアセンブリ コードであり、VULN は脆弱なプログラムの名前を定義します。
私の質問: シェルコード アドレスはどのように計算されますか
addr 変数は、シェルコード (環境の一部) のアドレスを保持します。このアドレスがどのように決定されるかを誰かに説明してもらえますか? そう:
- 0xc0000000 - 4 はどこから来たのですか?
- シェルコードの長さとプログラム名が差し引かれるのはなぜですか?
このコードと脆弱なプログラムの両方が次のようにコンパイルされていることに注意してください。
$ CFLAGS="-m32 -fno-stack-protector -z execstack -mpreferred-stack-boundary=2"
$ cc $CFLAGS -o vuln vuln.c
$ cc $CFLAGS -o exploit exploit.c shellcode.s
$ echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
0
そのため、アドレス空間のランダム化はオフになっています。
スタックはプロセス内の最初のもの(最上位メモリアドレス)であることを理解しました。スタックには、次の順序で含まれます。
- 環境データ。
- argv
- argc
- メインのリターンアドレス
- フレームポインタ
- メインのローカル変数
- ...等...
定数とグローバル データはスタックに格納されないため、VULN 定数の長さがシェルコードが配置されるアドレスに影響する理由もわかりません。
あなたが私のためにこれを片付けてくれることを願っています:-)
Intel x86 アーキテクチャの UNIX システムで作業していることに注意してください。