正しい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 retMS-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 件のコメント:
コメントを投稿