http://pwnable.kr/play.phpのuafがc++で書かれていたので読む必要が有ったので今後のためにもメモ程度に覚書を。今回はgdbのdisasとかobjdumpでアセンブリを読む時にnewはどのように呼んでいるるのかとかのめもです。
読んでいるバイナリのタイプはLinuxのELF64です。 基本的にはcHumanというクラスが有って、このクラスを継承したManとWomanというクラスがあります。main関数では最初にManとWomanのクラスのインスタンスをnewして作成します。そして、virtual関数のintroduce()を呼びます。
やっている処理のc++のコードを単純に書くとこんな感じになります。
Human *m = new Man("hoge", 1); m->introduce();
Humanクラスはこのようなクラスです。
class Human{ private: virtual void give_shell(){ system("/bin/sh"); } protected: int age; string name; public: virtual void introduce(){ cout << "My name is " << name << endl; cout << "I am " << age << " years old" << endl; } };
main関数のディスアセンブル結果はこちらです。
0000000000400ec4 <main>: 400ec4: 55 push %rbp 400ec5: 48 89 e5 mov %rsp,%rbp 400ec8: 41 54 push %r12 400eca: 53 push %rbx 400ecb: 48 83 ec 50 sub $0x50,%rsp 400ecf: 89 7d ac mov %edi,-0x54(%rbp) 400ed2: 48 89 75 a0 mov %rsi,-0x60(%rbp) 400ed6: 48 8d 45 ee lea -0x12(%rbp),%rax 400eda: 48 89 c7 mov %rax,%rdi 400edd: e8 8e fe ff ff callq 400d70 <_ZNSaIcEC1Ev@plt> 400ee2: 48 8d 55 ee lea -0x12(%rbp),%rdx 400ee6: 48 8d 45 b0 lea -0x50(%rbp),%rax 400eea: be f0 14 40 00 mov $0x4014f0,%esi 400eef: 48 89 c7 mov %rax,%rdi 400ef2: e8 19 fe ff ff callq 400d10 <_ZNSsC1EPKcRKSaIcE@plt> 400ef7: 4c 8d 65 b0 lea -0x50(%rbp),%r12 400efb: bf 18 00 00 00 mov $0x18,%edi 400f00: e8 8b fe ff ff callq 400d90 <_Znwm@plt> 400f05: 48 89 c3 mov %rax,%rbx 400f08: ba 19 00 00 00 mov $0x19,%edx 400f0d: 4c 89 e6 mov %r12,%rsi 400f10: 48 89 df mov %rbx,%rdi 400f13: e8 4c 03 00 00 callq 401264 <_ZN3ManC1ESsi> 400f18: 48 89 5d c8 mov %rbx,-0x38(%rbp) 400f1c: 48 8d 45 b0 lea -0x50(%rbp),%rax 400f20: 48 89 c7 mov %rax,%rdi 400f23: e8 d8 fd ff ff callq 400d00 <_ZNSsD1Ev@plt> 400f28: 48 8d 45 ee lea -0x12(%rbp),%rax 400f2c: 48 89 c7 mov %rax,%rdi 400f2f: e8 0c fe ff ff callq 400d40 <_ZNSaIcED1Ev@plt> 400f34: 48 8d 45 ef lea -0x11(%rbp),%rax 400f38: 48 89 c7 mov %rax,%rdi 400f3b: e8 30 fe ff ff callq 400d70 <_ZNSaIcEC1Ev@plt> 400f40: 48 8d 55 ef lea -0x11(%rbp),%rdx 400f44: 48 8d 45 c0 lea -0x40(%rbp),%rax 400f48: be f5 14 40 00 mov $0x4014f5,%esi 400f4d: 48 89 c7 mov %rax,%rdi 400f50: e8 bb fd ff ff callq 400d10 <_ZNSsC1EPKcRKSaIcE@plt> 400f55: 4c 8d 65 c0 lea -0x40(%rbp),%r12 400f59: bf 18 00 00 00 mov $0x18,%edi 400f5e: e8 2d fe ff ff callq 400d90 <_Znwm@plt> 400f63: 48 89 c3 mov %rax,%rbx 400f66: ba 15 00 00 00 mov $0x15,%edx 400f6b: 4c 89 e6 mov %r12,%rsi 400f6e: 48 89 df mov %rbx,%rdi 400f71: e8 92 03 00 00 callq 401308 <_ZN5WomanC1ESsi> 400f76: 48 89 5d d0 mov %rbx,-0x30(%rbp) 400f7a: 48 8d 45 c0 lea -0x40(%rbp),%rax 400f7e: 48 89 c7 mov %rax,%rdi 400f81: e8 7a fd ff ff callq 400d00 <_ZNSsD1Ev@plt> 400f86: 48 8d 45 ef lea -0x11(%rbp),%rax 400f8a: 48 89 c7 mov %rax,%rdi 400f8d: e8 ae fd ff ff callq 400d40 <_ZNSaIcED1Ev@plt> 400f92: be fa 14 40 00 mov $0x4014fa,%esi 400f97: bf 60 22 60 00 mov $0x602260,%edi 400f9c: e8 4f fd ff ff callq 400cf0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt> 400fa1: 48 8d 45 e8 lea -0x18(%rbp),%rax 400fa5: 48 89 c6 mov %rax,%rsi 400fa8: bf e0 20 60 00 mov $0x6020e0,%edi 400fad: e8 1e fe ff ff callq 400dd0 <_ZNSirsERj@plt> 400fb2: 8b 45 e8 mov -0x18(%rbp),%eax 400fb5: 83 f8 02 cmp $0x2,%eax 400fb8: 74 46 je 401000 <main+0x13c> 400fba: 83 f8 03 cmp $0x3,%eax 400fbd: 0f 84 b3 00 00 00 je 401076 <main+0x1b2> 400fc3: 83 f8 01 cmp $0x1,%eax 400fc6: 74 05 je 400fcd <main+0x109> 400fc8: e9 dc 00 00 00 jmpq 4010a9 <main+0x1e5> 400fcd: 48 8b 45 c8 mov -0x38(%rbp),%rax 400fd1: 48 8b 00 mov (%rax),%rax 400fd4: 48 83 c0 08 add $0x8,%rax 400fd8: 48 8b 10 mov (%rax),%rdx 400fdb: 48 8b 45 c8 mov -0x38(%rbp),%rax 400fdf: 48 89 c7 mov %rax,%rdi 400fe2: ff d2 callq *%rdx 400fe4: 48 8b 45 d0 mov -0x30(%rbp),%rax 400fe8: 48 8b 00 mov (%rax),%rax 400feb: 48 83 c0 08 add $0x8,%rax 400fef: 48 8b 10 mov (%rax),%rdx 400ff2: 48 8b 45 d0 mov -0x30(%rbp),%rax 400ff6: 48 89 c7 mov %rax,%rdi 400ff9: ff d2 callq *%rdx 400ffb: e9 a9 00 00 00 jmpq 4010a9 <main+0x1e5> 401000: 48 8b 45 a0 mov -0x60(%rbp),%rax 401004: 48 83 c0 08 add $0x8,%rax 401008: 48 8b 00 mov (%rax),%rax 40100b: 48 89 c7 mov %rax,%rdi 40100e: e8 0d fd ff ff callq 400d20 <atoi@plt> 401013: 48 98 cltq 401015: 48 89 45 d8 mov %rax,-0x28(%rbp) 401019: 48 8b 45 d8 mov -0x28(%rbp),%rax 40101d: 48 89 c7 mov %rax,%rdi 401020: e8 4b fc ff ff callq 400c70 <_Znam@plt> 401025: 48 89 45 e0 mov %rax,-0x20(%rbp) 401029: 48 8b 45 a0 mov -0x60(%rbp),%rax 40102d: 48 83 c0 10 add $0x10,%rax 401031: 48 8b 00 mov (%rax),%rax 401034: be 00 00 00 00 mov $0x0,%esi 401039: 48 89 c7 mov %rax,%rdi 40103c: b8 00 00 00 00 mov $0x0,%eax 401041: e8 7a fd ff ff callq 400dc0 <open@plt> 401046: 48 8b 55 d8 mov -0x28(%rbp),%rdx 40104a: 48 8b 4d e0 mov -0x20(%rbp),%rcx 40104e: 48 89 ce mov %rcx,%rsi 401051: 89 c7 mov %eax,%edi 401053: e8 48 fc ff ff callq 400ca0 <read@plt> 401058: be 13 15 40 00 mov $0x401513,%esi 40105d: bf 60 22 60 00 mov $0x602260,%edi 401062: e8 89 fc ff ff callq 400cf0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt> 401067: be 60 0d 40 00 mov $0x400d60,%esi 40106c: 48 89 c7 mov %rax,%rdi 40106f: e8 dc fc ff ff callq 400d50 <_ZNSolsEPFRSoS_E@plt> 401074: eb 33 jmp 4010a9 <main+0x1e5> 401076: 48 8b 5d c8 mov -0x38(%rbp),%rbx 40107a: 48 85 db test %rbx,%rbx 40107d: 74 10 je 40108f <main+0x1cb> 40107f: 48 89 df mov %rbx,%rdi 401082: e8 b3 01 00 00 callq 40123a <_ZN5HumanD1Ev> 401087: 48 89 df mov %rbx,%rdi 40108a: e8 f1 fb ff ff callq 400c80 <_ZdlPv@plt> 40108f: 48 8b 5d d0 mov -0x30(%rbp),%rbx 401093: 48 85 db test %rbx,%rbx 401096: 74 10 je 4010a8 <main+0x1e4> 401098: 48 89 df mov %rbx,%rdi 40109b: e8 9a 01 00 00 callq 40123a <_ZN5HumanD1Ev> 4010a0: 48 89 df mov %rbx,%rdi 4010a3: e8 d8 fb ff ff callq 400c80 <_ZdlPv@plt> 4010a8: 90 nop 4010a9: e9 e4 fe ff ff jmpq 400f92 <main+0xce> 4010ae: 49 89 c4 mov %rax,%r12 4010b1: 48 89 df mov %rbx,%rdi 4010b4: e8 c7 fb ff ff callq 400c80 <_ZdlPv@plt> 4010b9: 4c 89 e3 mov %r12,%rbx 4010bc: eb 03 jmp 4010c1 <main+0x1fd> 4010be: 48 89 c3 mov %rax,%rbx 4010c1: 48 8d 45 b0 lea -0x50(%rbp),%rax 4010c5: 48 89 c7 mov %rax,%rdi 4010c8: e8 33 fc ff ff callq 400d00 <_ZNSsD1Ev@plt> 4010cd: eb 03 jmp 4010d2 <main+0x20e> 4010cf: 48 89 c3 mov %rax,%rbx 4010d2: 48 8d 45 ee lea -0x12(%rbp),%rax 4010d6: 48 89 c7 mov %rax,%rdi 4010d9: e8 62 fc ff ff callq 400d40 <_ZNSaIcED1Ev@plt> 4010de: 48 89 d8 mov %rbx,%rax 4010e1: 48 89 c7 mov %rax,%rdi 4010e4: e8 b7 fc ff ff callq 400da0 <_Unwind_Resume@plt> 4010e9: 49 89 c4 mov %rax,%r12 4010ec: 48 89 df mov %rbx,%rdi 4010ef: e8 8c fb ff ff callq 400c80 <_ZdlPv@plt> 4010f4: 4c 89 e3 mov %r12,%rbx 4010f7: eb 03 jmp 4010fc <main+0x238> 4010f9: 48 89 c3 mov %rax,%rbx 4010fc: 48 8d 45 c0 lea -0x40(%rbp),%rax 401100: 48 89 c7 mov %rax,%rdi 401103: e8 f8 fb ff ff callq 400d00 <_ZNSsD1Ev@plt> 401108: eb 03 jmp 40110d <main+0x249> 40110a: 48 89 c3 mov %rax,%rbx 40110d: 48 8d 45 ef lea -0x11(%rbp),%rax 401111: 48 89 c7 mov %rax,%rdi 401114: e8 27 fc ff ff callq 400d40 <_ZNSaIcED1Ev@plt> 401119: 48 89 d8 mov %rbx,%rax 40111c: 48 89 c7 mov %rax,%rdi 40111f: e8 7c fc ff ff callq 400da0 <_Unwind_Resume@plt>
c++のクラスのインスタン生成時の細かい挙動はわからないんですが(´・ω・`)、newしているのは↓の部分です。
400f59: bf 18 00 00 00 mov $0x18,%edi 400f5e: e8 2d fe ff ff callq 400d90 <_Znwm@plt>
stackoverflowによると、_Znwmがnewで、
operator new(unsigned long)
_Znamがnew[]のようです。
operator new[](unsigned long)
今回のコード以下のような処理なので、前者の方を使ってます。サイズとして0x18を渡しています。
400f59: bf 18 00 00 00 mov $0x18,%edi 400f5e: e8 2d fe ff ff callq 400d90 <_Znwm@plt>
newの呼び出しはこんな感じで、次にいって、virtual関数の呼び出し部分を見てみます。
m->introduce()をやっているのがこの部分です。
400fcd: 48 8b 45 c8 mov -0x38(%rbp),%rax 400fd1: 48 8b 00 mov (%rax),%rax 400fd4: 48 83 c0 08 add $0x8,%rax 400fd8: 48 8b 10 mov (%rax),%rdx 400fdb: 48 8b 45 c8 mov -0x38(%rbp),%rax 400fdf: 48 89 c7 mov %rax,%rdi 400fe2: ff d2 callq *%rdx
アドレス0x400fcdのところは変数mのアドレスををraxレジスタに入れます。 そして、0x400fd1でraxが指す先のアドレスがraxの値が入ります。0x400fd1を実行するとraxはgive_shell()のアドレスになります。そして、0x400fd4ではraxに8を足すのでintroduce()のアドレスを指すようになります。呼び出す関数の設定の最後にraxの指す先のアドレスをrdxにコピーします。 つぎに、再度mのアドレスをraxにコピーします。そして、それをそのままrdiに入れます。最後にrdxが指すアドレスにある関数を呼び出します。これでm->introduce()の呼び出しになります。
ちなみに、問題のほうは無事にクリアしてます(∩´∀`)∩ワーイ
- 作者: マイケル・C・フェザーズ
- 出版社/メーカー: 翔泳社
- 発売日: 2016/01/15
- メディア: Kindle版
- この商品を含むブログ (2件) を見る