c++で書かれたコードのアセンブリの読み方めも

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()の呼び出しになります。

ちなみに、問題のほうは無事にクリアしてます(∩´∀`)∩ワーイ

f:id:masami256:20161225214740p:plain

レガシーコード改善ガイド

レガシーコード改善ガイド