chroot("/home/hibari")

備忘録とかに使えそうなノート

seccamp15 応募用紙 選択2

セキュリティキャンプの応募の時期であることを人伝に聞いたので書くことにした

結果、セキュリティキャンプ2015に参加することが出来たということもあり応募用紙を載せてみようと思う

その前にグダグダと前置きだけ

応募用紙の問題を見た第一印象、

 

「いや自分には厳しすぎるでしょ」

 

自分はWeb力は皆無なのでそれ関連の物はスルーとなった結果必然的にバイナリに焦点を向けることになった

バイナリとはいえ自分が出来ることはあまりなく...

今回の応募用紙を作成するにあたり、「某gle先生には極力尋ねない」という考えの下で問題に向き合った(今思うとほぼ何もできないのにおかしな話である)

 

後日ほかの参加者等の応募用紙をざっと見て、素晴らしい解答がたくさんあって「自分の解答はなんて低レベルなんだ!!!!」とさらに自分の弱さが身に染みた

後で時間が出来たときに今度はざっとではなく資料だと思って丁寧に読ませていただきます、そして勉強させていただきます

 

長すぎる前置きはここまでとして実際に提出した応募用紙の選択問題2を「そのまま」載せる

そのほかの問題はまた近いうちに載せる予定

 

 

■選択問題2 (左側の□について、回答した問題は■にしてください)

ある機械語をobjdumpにより逆アセンブルしたところ、以下の結果が得られました。このダンプに見られる問題点を指摘してください。

 

 

00000000 <.text>:

   0:       b8 de 07 00 00       mov   $0x7de,%eax

   5:       3d df 07 00 00       cmp   $0x7df,%eax

   a:       75 06                  jne   0x12

   c:       89 c0                  mov   %eax,%eax

   e:       ff e3                   jmp   *%ebx

10:       75 01                 jne   0x13

12:       e9 5b ba 0e 00       jmp   0xeba72

17:       00 00               add   %al,(%eax)

19:       b9 00 00 00 00       mov   $0x0,%ecx

1e:       bb 01 00 00 00       mov   $0x1,%ebx

23:       b8 04 00 00 00       mov   $0x4,%eax

28:       cd 80               int   $0x80

2a:       b8 01 00 00 00       mov   $0x1,%eax

2f:       cd 80               int   $0x80

 

【以下に回答してください(行は適宜追加してください)】

 

(I)上からの流れで見ていく場合

読み進めていくと、0xa → 0x12にジャンプして0xeba72にジャンプしてから返ってきてそのまま1つ目のint 0x80命令を実行した後で2つ目のint 0x80命令に到達して終了すると予想

int 0x80はシステムコールを表しているので、各々のレジスタの状態を確認すると1回目eax = 0x4、2回目eax = 0x1なのでそれぞれwrite()関数、exit()関数であると断定。

exit()関数に関してはプログラムを終了させる働きをしていると考えることが出来る。

write()関数を見てみると、この時のebx = 0x1, ecx = 0x0しかなく、出力するバイト数を示す引数であるedxが見当たらない。

また、ecxの値が0x0であることからバッファ元がmov命令をしている0x0アドレスである。

以上の2点が気になったので以下の方法で実験をしてみた。

 

まず必要箇所を抜き出して以下のアセンブリコードを書いた。

test.s

main:

     mov $0x7de,%eax

     cmp $0x7df,%eax

     mov $0x0,%ecx

     mov $0x1,%ebx

     mov $0x4,%eax

     int $0x80

     mov $0x1,eax

     int $0x80

 

これを作成した後コンパイルして、このままでは”mov $0x7de,%eax”に相当するアドレスがずれてしまうのでobjdumpでアドレスの確認。

$ gcc –nostdlib –m32 test.s

$ objdump -d a.out

a.out:     ファイル形式 elf32-i386


セクション .text の逆アセンブル:

08048098 <main>:
 8048098:    b8 de 07 00 00           mov    $0x7de,%eax
 804809d:    3d df 07 00 00           cmp    $0x7df,%eax
 80480a2:    b9 00 00 00 00           mov    $0x0,%ecx
 80480a7:    bb 01 00 00 00           mov    $0x1,%ebx
 80480ac:    b8 04 00 00 00           mov    $0x4,%eax
 80480b1:    cd 80                    int    $0x80
 80480b3:    b8 01 00 00 00           mov    $0x1,%eax
 80480b8:    cd 80                    int    $0x80

 

以上より設問の0x0に相当するアドレスは0x08048098であると分かったので、ecxに対して、

“mov $0x08048098,%ecx”に書き変えて、gdbで見ていった(必要箇所以外は適宜中略した)。

$ gdb -q a.out

Reading symbols from a.out...(no debugging symbols found)...done.

(gdb) set disassembly-flavor intel

(gdb) start

Temporary breakpoint 1 at 0x8048098

Starting program: /a.out

 

Temporary breakpoint 1, 0x08048098 in main ()

(gdb) info registers

eax           0x0   0

ecx           0x0   0

edx           0x0   0

ebx           0x0   0

esp           0xffffd180   0xffffd180

 

(gdb) b *main+25

Breakpoint 2 at 0x80480b1

(gdb) b *main+27

Breakpoint 3 at 0x80480b3

(gdb) c

Continuing.

 

Breakpoint 2, 0x080480b1 in main ()

(gdb) disas

Dump of assembler code for function main:

   0x08048098 <+0>:   mov     eax,0x7de

   0x0804809d <+5>:   cmp     eax,0x7df

   0x080480a2 <+10>:   mov     ecx,0x8048098

   0x080480a7 <+15>:   mov     ebx,0x1

   0x080480ac <+20>:   mov     eax,0x4

=> 0x080480b1 <+25>:   int   0x80

   0x080480b3 <+27>:   mov     eax,0x1

   0x080480b8 <+32>:   int     0x80

End of assembler dump.

(gdb) info registers

eax           0x4    4

ecx           0x8048098   134512792

edx           0x0   0

ebx           0x1   1

esp           0xffffd180   0xffffd180

 

(gdb) c

Continuing.

 

Breakpoint 3, 0x080480b3 in main ()

(gdb) disas

Dump of assembler code for function main:

   0x08048098 <+0>:   mov     eax,0x7de

   0x0804809d <+5>:   cmp     eax,0x7df

   0x080480a2 <+10>:   mov     ecx,0x8048098

   0x080480a7 <+15>:   mov     ebx,0x1

   0x080480ac <+20>:   mov     eax,0x4

   0x080480b1 <+25>:   int     0x80

=> 0x080480b3 <+27>:   mov   eax,0x1

   0x080480b8 <+32>:   int     0x80

End of assembler dump.

(gdb) info registers

eax           0x0   0

ecx           0x8048098   134512792

edx           0x0   0

ebx           0x1   1

esp           0xffffd180   0xffffd180

 

(gdb) c

Continuing.

[Inferior 1 (process 3845) exited with code 01]

(gdb) q

 

このことから、1回目のシステムコールの前後でedxの値は0を取り続けていたので出力するバイト数は0となるので何も出力しないと分かった。

その証拠に返り値としてint 0x80の後でeaxの値が0になっていることが確認できる。

 

また、ecxが0x0であったことも気になるので試しに、もし0x12のジャンプ先である0xeba72でedxを設定することが出来て文字を出力をすることが出来たとしたら、と仮定して5バイト出力してもらうため新たに”mov 0x5,%edx”を追加して同様にしてみた(適宜中略してある)。

(gdb) disas

Dump of assembler code for function main:

=> 0x08048098 <+0>:   mov   eax,0x7de

   0x0804809d <+5>:   cmp     eax,0x7df

   0x080480a2 <+10>:   mov     edx,0x5      …追加した行

   0x080480a7 <+15>:   mov     ecx,0x8048098

   0x080480ac <+20>:   mov     ebx,0x1

   0x080480b1 <+25>:   mov     eax,0x4

   0x080480b6 <+30>:   int     0x80

   0x080480b8 <+32>:   mov     eax,0x1

   0x080480bd <+37>:   mov     ebx,0x0

   0x080480c2 <+42>:   int     0x80

End of assembler dump.

(gdb) b *main+30

Breakpoint 2 at 0x80480b6

(gdb) b *main+32

Breakpoint 3 at 0x80480b8

(gdb) c

Continuing.

 

Breakpoint 2, 0x080480b6 in main ()

(gdb) disas

Dump of assembler code for function main:

   0x08048098 <+0>:   mov     eax,0x7de

   0x0804809d <+5>:   cmp     eax,0x7df

   0x080480a2 <+10>:   mov     edx,0x5

   0x080480a7 <+15>:   mov     ecx,0x8048098

   0x080480ac <+20>:   mov     ebx,0x1

   0x080480b1 <+25>:   mov     eax,0x4

=> 0x080480b6 <+30>:   int   0x80

   0x080480b8 <+32>:   mov     eax,0x1

   0x080480bd <+37>:   mov     ebx,0x0

   0x080480c2 <+42>:   int     0x80

End of assembler dump.

(gdb) info registers

eax           0x4   4

ecx           0x8048098   134512792

edx           0x5   5

ebx          0x1     1

esp           0xffffd180   0xffffd180

 

(gdb) c

Continuing.

??                                                          …(*)

Breakpoint 3, 0x080480b8 in main ()

(gdb) info registers

eax           0x5   5

ecx           0x8048098   134512792

edx           0x5   5

ebx           0x1  1

esp           0xffffd180   0xffffd180

 

(gdb) c

Continuing.

[Inferior 1 (process 3861) exited normally]

(gdb) q

 

結果、(*)の箇所で「??」が出力されていることが確認できた。

これはバッファのアドレスとして渡された0x08048098から5バイトの「b8 de 07 00 00」を出力させようとした結果であると考えられるので、仮にwrite関数が出力可能であったとしても設問でいうところの「0x0」アドレスから文字を出力しようとするのでよくわからない文字が出てきてしまう。

以上よりしたがって、write関数に出力させるバイト数が渡されていないので何も出力しない点と、仮に出力バイト数が1以上であっても出力させようとするアドレス元が命令している箇所なので文字化けしたものが出力されてしまう点が問題である。

 

 

(II)バイナリそのものを見ていった場合

アドレス0x10の”jne 0x13”が少し気になったので見てみる

0x13は5bを表していて、そのあとでba 0e 00 00 00 … と見て”ba 0e 00 00 00”の並びを見て下のmov命令と非常によく似ていることことに気が付いた

先ほどのtest.sを少し書き変えて本来はこのようになっていたのではないかと考えた(アドレス指定の都合で少しだけ違いが生じている)

$ objdump -d a.out

a.out:     ファイル形式 elf32-i386


セクション .text の逆アセンブル:

08048098 <main>:
 8048098:    b8 de 07 00 00           mov    $0x7de,%eax
 804809d:    3d df 07 00 00           cmp    $0x7df,%eax
 80480a2:    0f 85 6a 7f fb f7        jne    12 <main-0x8048086>
 80480a8:    89 c0                    mov    %eax,%eax
 80480aa:    ff e3                    jmp    *%ebx
 80480ac:    0f 85 61 7f fb f7        jne    13 <main-0x8048085>
 80480b2:    5b                       pop    %ebx
 80480b3:    ba 0e 00 00 00           mov    $0xe,%edx
 80480b8:    b9 98 80 04 08           mov    $0x8048098,%ecx
 80480bd:    bb 01 00 00 00           mov    $0x1,%ebx
 80480c2:    b8 04 00 00 00           mov    $0x4,%eax
 80480c7:    cd 80                    int    $0x80
 80480c9:    b8 01 00 00 00           mov    $0x1,%eax
 80480ce:    bb 00 00 00 00           mov    $0x0,%ebx
 80480d3:    cd 80                    int    $0x80

以上により、%edxに0xeをmovする命令が正しくダンプされていないことが問題点として考えられた

【回答ここまで】