シェルコードに挑戦

流れに流れて今回はシェルコードに挑戦してみようと思います。

まずシェルコードとは

ソフトウェアのセキュリティホールを利用するペイロードとして使われるコード断片である。
By Wikipedia

いわゆるfragmentだ。

とりあえず参考サイトのままに権限を取得するコードを試しでやってみた。
実行結果しか載せないけど、うまくいかずに結構時間はかかってる。
アセンブラむずかしい。

[takeken@32bittest]$ id                                                                                                           [/home/takeken/asm]
uid=500(takeken) gid=500(takeken)
[takeken@32bittest]$ ./shelltest.o
sh-4.1# zsh
[root@32bittest]$ id
uid=0(root) gid=500(takeken)
[root@32bittest]$

 

さくっとrootが取れちゃうような、こういうものらしいけど・・・、サンプルがこういうのしかなく試しただけであって、自分でアセンブラを使ってなにか作りたいのさ。

アセンブリに詳しくなりそうだし、まずはやっぱりHello Worldだわよね。

とりあえず前回作ったHello Worldのコードを修正する。
-nostdlibオプションを使うように、短いコードにする。

[takeken@32bittest]# cat hello2.s                                               [/home/takeken/asm]
.att_syntax noprefix
.global _start

_start:
        mov             $1, %ebx
        mov             $4, %eax
        mov        $msg, %ecx
        mov             $15,    %edx
        int        $0x80

        mov             $1,     %eax
        int               $0x80

.data
        msg:    .ascii "Hello, World!!\n"


[takeken@32bittest]# ./hello2                                                   [/home/takeken/as
Hello, World!!
[takeken@32bittest]#    

 

実行可能となりました。
だけどこのままではダメなようで、シェルコードはヌルバイトをなくさないといけないらしい。

レジスタのことはまだいまいち分かってないので、パズル式にやってみる。
pushとaddを使って、ヌルにならないようにしてみた。

[takeken@32bittest]# cat hello2.s                                               [/home/takeken/asm]
.att_syntax noprefix
.global _start

_start:
        mov             $1, %ebx
        mov             $4, %eax
        mov     $msg, %ecx
        mov             $15,    %edx
        int     $0x80

        mov             $1,     %eax
        int     $0x80

.data
        msg:    .ascii "Hello, World!!\n"

[takeken@32bittest]# objdump -d hello                                                        

hello:     file format elf32-i386


Disassembly of section .text:

080480b8 <_start>:
 80480b8:       31 d2                   xor    %edx,%edx
 80480ba:       6a 01                   push   $0x1
 80480bc:       53                      push   %ebx
 80480bd:       83 c0 04                add    $0x4,%eax
 80480c0:       b9 d0 90 04 08          mov    $0x80490d0,%ecx
 80480c5:       83 c2 0f                add    $0xf,%edx
 80480c8:       cd 80                   int    $0x80
 80480ca:       b0 01                   mov    $0x1,%al
 80480cc:       cd 80                   int    $0x80
[takeken@32bittest]# ./hello2                                                 
Hello, World!!

 

ご覧のようにヌルバイトがなくなり、実行も可能な状態となった。

だが

Cの形式にしてみて実行しても


objdump -M att -d hello2 | grep '^ ' | cut -f2 | perl -pe 's/(\w{2})\s+/\\x\1/g'
#include <stdio.h>

char shellcode[] = "\x31\xd2\x6a\x01\x53\x83\xc0\x04\xb9\xd0\x90\x04\x08\x83\xc2\x0f\xcd\x80\xb0\x01\xcd\x80";

int main()
{
    printf("sizeof(shellcode) == %d\n", sizeof(shellcode));
    (*(void (*)())shellcode)();
}
$ ./aa.o                                                                                                       [/home/takeken/asm]
sizeof(shellcode) == 23
zsh: segmentation fault  ./aa.o

 

 

だめらしい。

うーん・・・。

どうしたもんかなぁ。

普通にデバッグしてみたものの

(gdb) next
Single stepping until exit from function shellcode,
which has no line number information.

Program received signal SIGSEGV, Segmentation fault.
0x0804966c in shellcode ()
(gdb) next
Single stepping until exit from function shellcode,
which has no line number information.

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.

 

 

うーん、分からん。

nasm式というのがあるらしいので、そっちでやってみることにした。

[takeken@32bittest nasm]$ cat hello.asm
section .text
global _start

BITS 32

_start:
        xor     edx, edx
        mov     ebx, 1    ; stdout
                mov             eax, 4          ; write
        mov     ecx, msg    ; address
                mov             edx, len
                int 0x80

        mov     eax, 1      ; sys_exit
                int 0x80

section .data
        msg     db      'hello, world',0xa
        len     equ     $ - msg

[takeken@32bittest nasm]$ ./hello
hello, world

 

 

とりあえず実行できるようにはなったものの。

[takeken@32bittest nasm]$ objdump -d hello.o

hello.o:     file format elf32-i386


Disassembly of section .text:

00000000 <_start>:
   0:   31 d2                   xor    %edx,%edx
   2:   bb 01 00 00 00          mov    $0x1,%ebx
   7:   b8 04 00 00 00          mov    $0x4,%eax
   c:   b9 00 00 00 00          mov    $0x0,%ecx
  11:   ba 0d 00 00 00          mov    $0xd,%edx
  16:   cd 80                   int    $0x80
  18:   b8 01 00 00 00          mov    $0x1,%eax
  1d:   cd 80                   int    $0x80

そりゃそうなんだが、ヌルヌルなのであった。

さっきの要領でヌル除去を進めていくんだが、うまくいかないらしい。

もうダメかなーなんて思ってたらNASMは変数タイプを保存しないというのを発見して閃いた。

[takeken@32bittest nasm]$ cat hello.asm
section .text
global _start

BITS 32

foo equ 1
bar equ 4

_start:
        xor     edx, edx
        mov       bl,foo    ; stdout
                mov             al,bar          ; write
        mov     ecx, msg    ; address
                mov             dl, len
                int 0x80

        mov     al, 1      ; sys_exit
                mov             ah, 0
                int 0x80

section .data
        msg     db      'hello, world',0xa
        len     equ     $ - msg

[takeken@32bittest nasm]$ nasm -f elf hello.asm && ld -s -o hello hello.o
[takeken@32bittest nasm]$ ./hello
hello, world
[takeken@32bittest nasm]$ objdump -d hello

hello:     file format elf32-i386


Disassembly of section .text:

08048080 <.text>:
 8048080:       31 d2                   xor    %edx,%edx
 8048082:       b3 01                   mov    $0x1,%bl
 8048084:       b0 04                   mov    $0x4,%al
 8048086:       b9 98 90 04 08          mov    $0x8049098,%ecx
 804808b:       b2 0d                   mov    $0xd,%dl
 804808d:       cd 80                   int    $0x80
 804808f:       b0 01                   mov    $0x1,%al
 8048091:       b4 00                   mov    $0x0,%ah
 8048093:       cd 80                   int    $0x80

おおおー。

 

[takeken@32bittest nasm]$ ./mike
セグメンテーション違反です orz

ダメか。

なにか違うところに原因があるのかもしれない。

 

参考サイト

技術メモ帖 shellcode を書く

The Netwide Assembler: NASM

ももいろテクノロジー  Linux x86用のシェルコードを書いてみる

 

Related Posts


投稿者: Takeken

インターネット利用者のITリテラシーを向上したいという設定の2次元キャラです。 サーバー弄りからプログラミングまで手を付けた自称エッセイストなたけけんの物語。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です