2013年4月23日火曜日

HACKING: 美しき策謀(第2版) がたまらなく面白い

正しいHACKINGを学びましょう

前から欲しかった本がタマタマ本屋さんにあったので、思わず買ってしまいました。ほぼバイナリー的なお話が多いです。そちらに興味がある方には必読の本でしょう。



昨今、セキュリティーや脆弱性をついた攻撃などが多いデスよね、最近も色々あったばかりで、やはり自社システムなどを正常、安定に保にはいろいろな攻撃方法、クラッキング方法などを知っていた方が為になるとは思います。

偉いことをいってるようですが、さほど知っている理由ではありません 笑...

単純なコードでもこんなことになってる! 

 

日頃、仕事上LWな言語で仕事をするので、Lowレベルなところを意識する事が少なくなったような感じがします。
バイナリーの世界ではこんなことになってるって事が多いのです(タマタマ発見したのですが...)


普通のCのコード、見れば分かりますが5回「I'm tired today」を表示する
#include <stdio.h>

int main(void)
{
  int i;
  for(i = 0; i < 5; i++) {
    printf("Ah, I'm tired today\n");                                                     
  }
  return 0;
}

これをコンパイルして実行
cuomo@karky7 ~/sample $ gcc print.c -o print
cuomo@karky7 ~/sample $ ./print 
Ah, I'm tired today
Ah, I'm tired today
Ah, I'm tired today
Ah, I'm tired today
Ah, I'm tired today
cuomo@karky7 ~/sample $

これをobjdumpで見てみると、こうなってます。 アセンブラのコードはx86系の64bitCPUならこうなると思います。

レジスタはrsp(64bitスタックポインタレジスタ)、rbp(64bitスタックベースポインタ)、eax(32bitアキュムレータレジスタ)など色々ありますが割愛させて下さい。

cuomo@karky7 ~/sample $ objdump -D print | grep -A14 '<main>'
0000000000400534 <main>:
  400534:       55                      push   %rbp
  400535:       48 89 e5                mov    %rsp,%rbp
  400538:       48 83 ec 10             sub    $0x10,%rsp
  40053c:       c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%rbp)
  400543:       eb 0e                   jmp    400553 <main+0x1f>
  400545:       bf 4c 06 40 00          mov    $0x40064c,%edi
  40054a:       e8 e1 fe ff ff          callq  400430 <puts@plt>
  40054f:       83 45 fc 01             addl   $0x1,-0x4(%rbp)
  400553:       83 7d fc 04             cmpl   $0x4,-0x4(%rbp)
  400557:       7e ec                   jle    400545 <main+0x11>
  400559:       b8 00 00 00 00          mov    $0x0,%eax
  40055e:       c9                      leaveq 
  40055f:       c3                      retq 

ちなみに知らなかったのですがobjdumpがIntelシンタックスでも出力できる
cuomo@karky7 ~/sample $ objdump -M intel -D print | grep -A14 '<main>'
0000000000400534 <main>:
  400534:       55                      push   rbp
  400535:       48 89 e5                mov    rbp,rsp
  400538:       48 83 ec 10             sub    rsp,0x10
  40053c:       c7 45 fc 00 00 00 00    mov    DWORD PTR [rbp-0x4],0x0 ーー> i=0
  400543:       eb 0e                   jmp    400553 <main+0x1f> ーー> 400553のアドレスへジャンプ
  400545:       bf 4c 06 40 00          mov    edi,0x40064c ーー> I'm tired todaiのIの保存されているアドレスをediへ入れる
  40054a:       e8 e1 fe ff ff          call   400430 <puts@plt> ーー> printfのcall(コンパイラがputsに修正)
  40054f:       83 45 fc 01             add    DWORD PTR [rbp-0x4],0x1 ーー> i++
  400553:       83 7d fc 04             cmp    DWORD PTR [rbp-0x4],0x4 ーー> i < 5
  400557:       7e ec                   jle    400545 <main+0x11>
  400559:       b8 00 00 00 00          mov    eax,0x0 ーー> return 0(関数の戻り値はeaxレジスタに入れて返す)
  40055e:       c9                      leave  
  40055f:       c3                      ret  
MS-DOSとかでアセンブラを書いていた自分にとってはこちらの方が読みやすいのデスが、今となってはもうどちらでもいいです。コード中に説明を書いてしまいましたが、こんな感じでプログラムが動くって分かります。printfでコード中に書いているのデスが、可変長引数が無いので、gccがputsへ最適化してくれたりと色々「ふーん」っていうことがたくさんあります。 さらにgccのオプションをちょっと変えると....
cuomo@karky7 ~/sample $ gcc -O3 print.c -o print
cuomo@karky7 ~/sample $ objdump -M intel -D print | grep -A14 '<main>'
0000000000400540 <main>:
  400540:       48 83 ec 08             sub    rsp,0x8
  400544:       bf 6c 06 40 00          mov    edi,0x40066c
  400549:       e8 e2 fe ff ff          call   400430 <puts@plt>
  40054e:       bf 6c 06 40 00          mov    edi,0x40066c
  400553:       e8 d8 fe ff ff          call   400430 <puts@plt>
  400558:       bf 6c 06 40 00          mov    edi,0x40066c
  40055d:       e8 ce fe ff ff          call   400430 <puts@plt>
  400562:       bf 6c 06 40 00          mov    edi,0x40066c
  400567:       e8 c4 fe ff ff          call   400430 <puts@plt>
  40056c:       bf 6c 06 40 00          mov    edi,0x40066c
  400571:       e8 ba fe ff ff          call   400430 <puts@plt>
  400576:       31 c0                   xor    eax,eax ーー> return 0
  400578:       48 83 c4 08             add    rsp,0x8
  40057c:       c3                      ret

初め見たときは、これなんだ?って思いますがよく見てみると、forが単純にそのまま5回分展開されてprintf(puts)がcallされてるアセンブラコードの展開されているのですね。xor eax,eaxなんてmov eax,0ってやるよりオペコードのバイト数が少なく済むようにちゃんと変わってるところが凄い。オペコードが少なければCPUクロック数が少なく済むからね、 

エコじゃないか!!!!!!

まぁそんなことはどうでもいいのですが、こんな感じで色々バイナリ感を楽しむ事ができます、タイトルと内容がかなりかけ離れてしまいましたが、とにかくバイナリは楽しいです。
みなさんも是非.....



0 件のコメント:

コメントを投稿