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()の呼び出しになります。
ちなみに、問題のほうは無事にクリアしてます(∩´∀`)∩ワーイ