質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.06%

シェルコードの実行に失敗してしまう

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 105

t4gforce

score 4

前提・実現したいこと

「たのしいバイナリの歩き方」という本を参考に勉強をしています。
C言語で配列に入れたシェルコードを実行しようとしているのですが、実行に失敗します。
具体的には、システムコールを呼び出す部分 int 0x80が実行がスキップされてしまいます。
どなたかご教授お願いいたします。

発生している問題・エラーメッセージ

Program received signal SIGSEGV, Segmentation fault.
0x0804a061 in ?? ()

該当のソースコード

コンパイル前のc言語でのソースコードはこちらです。
ファイル名はsample7.cです。

unsigned char shellcode[] = {
    0x31, 0xc0,                   // xor %eax, %eax
    0x50,                         // push %eax
    0x89, 0xe0,                   // mov %esp, %eax
    0x83, 0xe8, 0x0c,             // sub $0x0c, %eax
    0x50,                         // push %eax
    0x89, 0xe3,                   // mov %esp, %ebx
    0x68, 0x2f, 0x73, 0x68, 0x00, // push $0x68732f
    0x68, 0x2f, 0x62, 0x69, 0x6e, // push $0x6e69622f
    0x89, 0xe2,                   // mov %esp, %edx
    0x31, 0xc0,                   // xor %eax, %eax
    0x50,                         // push %eax
    0x53,                         // push %ebx
    0x52,                         // push %edx
    0x50,                         // push %eax
    0xb0, 0x3b,                   // mov $0x3b, %al
    0xcd, 0x80,                   // int $0x80
};

int main(void)
{
    void (*p)(void);
    p = (void(*)())shellcode;
    p();
    return 0;
}

以下のコマンドでコンパイルしました。

#gcc -Wall -m32 -fno-stack-protector -fno-asynchronous-unwind-tables -z execstack -g sample7.c -o sample7

試したこと

まず、実行権限を与えて実行した結果は以下になります。

$ ./sample7
Segmentation fault

fileコマンドでバイナリを調べました

$ file sample7
sample7: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), 
dynamically linked (uses shared libs), for GNU/Linux 2.6.24, 
BuildID[sha1]=0xf5a9899dfa70c47141d86c76067829a81ab73fab, not stripped

次にgdbで処理を1行ずつ確認しました。

$ gdb sample7
GNU gdb (Ubuntu/Linaro 7.4-2012.02-0ubuntu2) 7.4-2012.02
Copyright (C) 2012 Free Software Foundation, Inc.
...省略...
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/tk/target/sample7...done.
(gdb) disas main
Dump of assembler code for function main:
   0x080483b4 <+0>:    push   %ebp
   0x080483b5 <+1>:    mov    %esp,%ebp
   0x080483b7 <+3>:    and    $0xfffffff0,%esp
   0x080483ba <+6>:    sub    $0x10,%esp
   0x080483bd <+9>:    movl   $0x804a040,0xc(%esp)
   0x080483c5 <+17>:    mov    0xc(%esp),%eax
   0x080483c9 <+21>:    call   *%eax
   0x080483cb <+23>:    mov    $0x0,%eax
   0x080483d0 <+28>:    leave  
   0x080483d1 <+29>:    ret    
End of assembler dump.
(gdb) b *0x080483c9 ; call *%eax の部分にブレークポイントをセット
Breakpoint 1 at 0x80483c9: file sample7.c, line 24.
(gdb) b *0x080483cb ; mov $0x0,%eax の部分にブレークポイントをセット
Breakpoint 2 at 0x80483cb: file sample7.c, line 25.
(gdb) run
Starting program: /home/tk/target/sample7 

Breakpoint 1, 0x080483c9 in main () at sample7.c:24 ; call *%eaxの部分で止まる
24        p();
(gdb) si ; shellcode内部に入る
0x0804a040 in shellcode ()
(gdb) disas shellcode 
Dump of assembler code for function shellcode:
=> 0x0804a040 <+0>:    xor    %eax,%eax
   0x0804a042 <+2>:    push   %eax
   0x0804a043 <+3>:    mov    %esp,%eax
   0x0804a045 <+5>:    sub    $0xc,%eax
   0x0804a048 <+8>:    push   %eax
   0x0804a049 <+9>:    mov    %esp,%ebx
   0x0804a04b <+11>:    push   $0x68732f
   0x0804a050 <+16>:    push   $0x6e69622f
   0x0804a055 <+21>:    mov    %esp,%edx
   0x0804a057 <+23>:    xor    %eax,%eax
   0x0804a059 <+25>:    push   %eax
   0x0804a05a <+26>:    push   %ebx
   0x0804a05b <+27>:    push   %edx
   0x0804a05c <+28>:    push   %eax
   0x0804a05d <+29>:    mov    $0x3b,%al
   0x0804a05f <+31>:    int    $0x80
End of assembler dump.
(gdb) b *0x0804a05f ; 最終行 int $0x80にブレークポイントをセット
Breakpoint 3 at 0x804a05f
(gdb) c
Continuing.

Breakpoint 3, 0x0804a05f in shellcode () ; int 0x80の前で処理が止まる
(gdb) disas shellcode 
Dump of assembler code for function shellcode:
   0x0804a040 <+0>:    xor    %eax,%eax
   0x0804a042 <+2>:    push   %eax
   0x0804a043 <+3>:    mov    %esp,%eax
   0x0804a045 <+5>:    sub    $0xc,%eax
   0x0804a048 <+8>:    push   %eax
   0x0804a049 <+9>:    mov    %esp,%ebx
   0x0804a04b <+11>:    push   $0x68732f
   0x0804a050 <+16>:    push   $0x6e69622f
   0x0804a055 <+21>:    mov    %esp,%edx
   0x0804a057 <+23>:    xor    %eax,%eax
   0x0804a059 <+25>:    push   %eax
   0x0804a05a <+26>:    push   %ebx
   0x0804a05b <+27>:    push   %edx
   0x0804a05c <+28>:    push   %eax
   0x0804a05d <+29>:    mov    $0x3b,%al
=> 0x0804a05f <+31>:    int    $0x80
End of assembler dump.
(gdb) si ; int $0x80でシステムコールが実行されるはず・・・
0x0804a061 in ?? () ; 実行されずプログラムカウンタが進んだ
(gdb) x/i *0x0804a061
   0x0:    Cannot access memory at address 0x0
(gdb) si

Program received signal SIGSEGV, Segmentation fault.
0x0804a061 in ?? ()

知識が足りず、どのようにして対処すればよいのかわからない状態です。
int $0x80のシステムコールが無視されてしまうので、なにか対処法を教えていただきたいです。

補足情報(FW/ツールのバージョンなど)

OS : Ubuntu 12.04 LTS 32bit
32bitであることは、コマンドでも確認しました。

$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=12.04
DISTRIB_CODENAME=precise
DISTRIB_DESCRIPTION="Ubuntu 12.04 LTS"
$ uname -a
Linux tk-VirtualBox 3.2.0-126-generic-pae #169-Ubuntu SMP Fri Mar 31 14:43:09 UTC 2017 i686 i686 i386 GNU/Linux

gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
GNU gdb (Ubuntu/Linaro 7.4-2012.02-0ubuntu2) 7.4-2012.02

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

それFreeBSD用では?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/08/02 15:40 編集

    回答していただきありがとうございます。
    そのソースコードはFreeBSD用ですが、FreeBSDの過去の(書籍で指定している)バージョンが見つからなかったので、Ubuntuで試しています。
    重ねて質問になってしまいますが、Ubuntu(カーネルは3.2.0)では、int 0x80でシステムコールをすることはできず、syscallやsysenterを使うしかないのでしょうか?
    いくつかのサイトでは、linuxカーネル2.6.xxでint 0x80でシステムコールを呼び出している例があったので、疑問に思いました。

    キャンセル

  • 2020/08/02 17:18

    FreeBSDのマニュアルですが
    https://www.freebsd.org/doc/en_US.ISO8859-1/books/developers-handbook/x86-system-calls.html
    FreeBSD(デフォルト)とLinux(Alternate Calling Convention)では呼び出し規約が違っていて
    FreeBSDではスタックに引数を渡しますが、Linuxではレジスタに渡しています。

    キャンセル

  • 2020/08/02 17:39

    呼び出し規約が違ったのですね。
    詳しく教えてくださりありがとうございました。とても参考になりました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.06%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る