Android SO逆-オブジェクトの継承と虚関数

16083 ワード

0x00
この節では,オブジェクトの継承と虚関数のアセンブリ実装について論じる.
    0x01
まずアセンブリコードを直接見てみましょう.
#include "com_example_ndkreverse6_Lesson6.h"
#include <android/log.h>
#define LOG_TAG "lesson6"
#define ALOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))

class Base {
public:
	virtual void display() { //   ,virtual     ,                    
		ALOGD("Base:%d, BaseChar:%d", base_, baseChar_);
	}

	Base(int base) {
		base_ = base;
		baseChar_ = 8;
		ALOGD("Base ...");
	}

	virtual ~Base() { //     ,     virtual,                 ,          
		ALOGD("~Base ...");
	}
private:
	int base_;
	char baseChar_;
};
class Derived: public Base {
public:
	virtual void display() { //       
		ALOGD("Derived:%d, DerivedChar:%d", derived_,  derivedChar_);
		Base::display(); //       ,     ,    ,         
	}

	Derived(int derived) :
			Base(derived) {
		derived_ = derived;
		derivedChar_ = 10;
		ALOGD("Derived ...");
	}

	~Derived() {
		ALOGD("~Derived ...");
	}
private:
	int derived_;
	char derivedChar_;
};

JNIEXPORT void JNICALL Java_com_example_ndkreverse6_Lesson6_main
(JNIEnv * env, jobject jobject) {
	Base* d = new Derived(18);
	d->display();
	delete d;
}
では、実行後に実行された結果は次のようになります.
D/lesson6 (28959): Base ...
D/lesson6 (28959): Derived ...
D/lesson6 (28959): Derived:18, DerivedChar:10
D/lesson6 (28959): Base:18, BaseChar:8
D/lesson6 (28959): ~Derived ...
D/lesson6 (28959): ~Base ...

    0x02
次にidaを用いてsoを開き,アセンブリコードを説明する.このアセンブリコードは、デバッグ状態のアセンブリコードを使用します.
.text:00003088                 EXPORT Java_com_example_ndkreverse6_Lesson6_main
.text:00003088 Java_com_example_ndkreverse6_Lesson6_main
.text:00003088                 PUSH    {R4-R6,LR}
.text:0000308A                 MOVS    R0, #0x14       ; unsigned int R0    20,     20        
.text:0000308C                 BL      _Znwj           ; operator new(uint)    20          
.text:00003090                 LDR     R3, =(_ZTV4Base_ptr - 0x3098) ;    Base     
.text:00003092                 MOVS    R6, #0x12       ;R6     18
.text:00003094                 ADD     R3, PC ; _ZTV4Base_ptr
.text:00003096                 LDR     R3, [R3]        ; `vtable for'Base   Base     ,  .data.rel.ro, 0x70428960
.text:00003098                 MOVS    R4, R0          ;R0     20              ,     R4
.text:0000309A                 ADDS    R3, #8          ;R3+8    R3,R3   0x70428968
.text:0000309C                 STR     R3, [R0]        ; 0x70428968               (        )
.text:0000309E                 MOVS    R3, #8          ;R3    8
.text:000030A0                 LDR     R5, =(aLesson6 - 0x30AA)     
.text:000030A2                 LDR     R2, =(aBase____0 - 0x30B0)
.text:000030A4                 STR     R6, [R0,#4]     ; 18               +4
.text:000030A6                 ADD     R5, PC          ; "lesson6" R5     .rodata  lesson6
.text:000030A8                 MOVS    R1, R5          ; R5   R1    
.text:000030AA                 STRB    R3, [R0,#8]     ; 8               +8
.text:000030AC                 ADD     R2, PC          ; "Base ..." R2     .rodata  Base ...
.text:000030AE                 MOVS    R0, #3          ;R0     3
.text:000030B0                 BL      j_j___android_log_print ;  Base ...
.text:000030B4                 LDR     R3, =(_ZTV7Derived_ptr - 0x30BE) ;    Derived     
.text:000030B6                 LDR     R2, =(aDerived____0 - 0x30C2)
.text:000030B8                 MOVS    R1, R5          ;R1    R5,    .rodata   lesson6
.text:000030BA                 ADD     R3, PC ; _ZTV7Derived_ptr
.text:000030BC                 LDR     R3, [R3]        ; `vtable for'Derived   Derived     ,  .data.rel.ro, 0x70428978
.text:000030BE                 ADD     R2, PC          ; "Derived ..." R2    .rodata  Derived
.text:000030C0                 STR     R6, [R4,#0xC]   ; 18               +12
.text:000030C2                 ADDS    R3, #8          ;R3   Derived     +8, 0x70428980
.text:000030C4                 STR     R3, [R4]        ; 0x70428980               
.text:000030C6                 MOVS    R3, #0xA        ; R3   10
.text:000030C8                 MOVS    R0, #3          ; R0   3
.text:000030CA                 STRB    R3, [R4,#0x10]  ; 10               +16
.text:000030CC                 BL      j_j___android_log_print ;  R0,R1,R2           ,    j_j___android_log_print
.text:000030D0                 LDR     R3, [R4]        ;      ,   .data.rel.ro    0x70428980
.text:000030D2                 MOVS    R0, R4          ; R0   R4,       ,R4             , this  
.text:000030D4                 LDR     R3, [R3]        ;            , Derived Display     
.text:000030D6                 BLX     R3              ;   Derived Display  
.text:000030D8                 LDR     R3, [R4]        ;      ,   .data.rel.ro    0x70428980
.text:000030DA                 MOVS    R0, R4          ; R0   R4,       ,R4             , this  
.text:000030DC                 LDR     R3, [R3,#8]     ;      +8      , Derived ~Derived     
.text:000030DE                 BLX     R3              ;   Derived ~Derived  
.text:000030E0                 POP     {R4-R6,PC}
.text:704220E4 off_704220E4    DCD _ZTV4Base_ptr - 0x70422098
.text:704220E4                                         ; DATA XREF: Java_com_example_ndkreverse6_Lesson6_main+8r
.text:704220E8 off_704220E8    DCD aLesson6 - 0x704220AA
.text:704220E8                                         ; DATA XREF: Java_com_example_ndkreverse6_Lesson6_main+18r
.text:704220E8                                         ; "lesson6"
.text:704220EC off_704220EC    DCD aBase____0 - 0x704220B0
.text:704220EC                                         ; DATA XREF: Java_com_example_ndkreverse6_Lesson6_main+1Ar
.text:704220EC                                         ; "Base ..."
.text:704220F0 off_704220F0    DCD _ZTV7Derived_ptr - 0x704220BE
.text:704220F0                                         ; DATA XREF: Java_com_example_ndkreverse6_Lesson6_main+2Cr
.text:704220F4 off_704220F4    DCD aDerived____0 - 0x704220C2
.text:704220F4                                         ; DATA XREF: Java_com_example_ndkreverse6_Lesson6_main+2Er
.text:704220F4                                         ; "Derived ..."
.got:70428F24                 AREA .got, DATA
.got:70428F24                 ; ORG 0x70428F24
.got:70428F24 _ZTV4Base_ptr   DCD _ZTV4Base           ; DATA XREF: Base::~Base()+Ao
.got:70428F24                                         ; Base::~Base()+Cr ...
.got:70428F24                                         ; `vtable for'Base
.got:70428F28 _ZTV7Derived_ptr DCD _ZTV7Derived       ; DATA XREF: Derived::~Derived()+Ao
.got:70428F28                                         ; Derived::~Derived()+Cr ...
.got:70428F28                                         ; `vtable for'Derived
.data.rel.ro:70428960 ; `vtable for'Base
.data.rel.ro:70428960 _ZTV4Base       DCB    0                ; DATA XREF: Base::~Base()+Co
.data.rel.ro:70428960                                         ; Java_com_example_ndkreverse6_Lesson6_main+Eo ...
.data.rel.ro:70428961                 DCB    0
.data.rel.ro:70428962                 DCB    0
.data.rel.ro:70428963                 DCB    0
.data.rel.ro:70428964                 DCD _ZTI4Base           ; `typeinfo for'Base
.data.rel.ro:70428968                 DCD _ZN4Base7displayEv+1
.data.rel.ro:7042896C                 DCD _ZN4BaseD2Ev+1
.data.rel.ro:70428970                 DCD _ZN4BaseD0Ev+1
.data.rel.ro:70428974                 ALIGN 8
.data.rel.ro:70428978                 WEAK _ZTV7Derived
.data.rel.ro:70428978 ; `vtable for'Derived
.data.rel.ro:70428978 _ZTV7Derived    DCB    0                ; DATA XREF: Derived::~Derived()+Co
.data.rel.ro:70428978                                         ; Java_com_example_ndkreverse6_Lesson6_main+34o ...
.data.rel.ro:70428979                 DCB    0
.data.rel.ro:7042897A                 DCB    0
.data.rel.ro:7042897B                 DCB    0
.data.rel.ro:7042897C                 DCD _ZTI7Derived        ; `typeinfo for'Derived
.data.rel.ro:70428980                 DCD _ZN7Derived7displayEv+1
.data.rel.ro:70428984                 DCD _ZN7DerivedD2Ev+1
.data.rel.ro:70428988                 DCD _ZN7DerivedD0Ev+1
.rodata:704267B0 ; `typeinfo name for'Base
.rodata:704267B0 _ZTS4Base       DCB "4Base",0           ; DATA XREF: .data.rel.ro:_ZTI4Base+4o
.rodata:704267B6                 ALIGN 4
.rodata:704267B8                 WEAK _ZTS7Derived
.rodata:704267B8 ; `typeinfo name for'Derived
.rodata:704267B8 _ZTS7Derived    DCB "7Derived",0        ; DATA XREF: .data.rel.ro:_ZTI7Derived+4o
.rodata:704267C1                 ALIGN 4
.rodata:704267C4 aLesson6        DCB "lesson6",0         ; DATA XREF: Base::display(void)+Eo
.rodata:704267C4                                         ; .text:off_70421FD4o ...
.rodata:704267CC aBaseDBasecharD DCB "Base:%d, BaseChar:%d",0
.rodata:704267CC                                         ; DATA XREF: Base::display(void)+10o
.rodata:704267CC                                         ; .text:off_70421FD8o
.rodata:704267E1 aDerivedDDerive DCB "Derived:%d, DerivedChar:%d",0
.rodata:704267E1                                         ; DATA XREF: Derived::display(void)+Eo
.rodata:704267E1                                         ; .text:off_70422000o
.rodata:704267FC aBase___        DCB "~Base ...",0       ; DATA XREF: Base::~Base()+10o
.rodata:704267FC                                         ; .text:off_7042202Co
.rodata:70426806 aDerived___     DCB "~Derived ...",0    ; DATA XREF: Derived::~Derived()+10o
.rodata:70426806                                         ; .text:off_70422060o
.rodata:70426813 aBase____0      DCB "Base ...",0        ; DATA XREF: Java_com_example_ndkreverse6_Lesson6_main+24o
.rodata:70426813                                         ; .text:off_704220ECo
.rodata:7042681C aDerived____0   DCB "Derived ...",0     ; DATA XREF: Java_com_example_ndkreverse6_Lesson6_main+36o
.rodata:7042681C                                         ; .text:off_704220F4o
    
Displayメソッドを実行する場合,まずオブジェクトのヘッダアドレスから虚表ポインタを取り出し,その後虚表ポインタが指すメモリセルから具体的なDisplay命令のアドレスを取り出し,対応する命令実行にジャンプする.
.text:70421FDC ; _DWORD Derived::display(Derived *__hidden this)
.text:70421FDC                 WEAK _ZN7Derived7displayEv
.text:70421FDC _ZN7Derived7displayEv                   ; DATA XREF: .data.rel.ro:_ZTV7Derived+8o
.text:70421FDC
.text:70421FDC var_10          = -0x10
.text:70421FDC
.text:70421FDC                 PUSH    {R0,R1,R4,LR}
.text:70421FDE                 MOVS    R4, R0           ;R4    R0,             
.text:70421FE0                 LDRB    R3, [R0,#0x10]   ;                ,   DerivedChar  
.text:70421FE2                 LDR     R1, =(aLesson6 - 0x70421FEC)
.text:70421FE4                 LDR     R2, =(aDerivedDDerive - 0x70421FEE)
.text:70421FE6                 STR     R3, [SP,#0x10+var_10] ;               
.text:70421FE8                 ADD     R1, PC          ; "lesson6"
.text:70421FEA                 ADD     R2, PC          ; "Derived:%d, DerivedChar:%d"
.text:70421FEC                 LDR     R3, [R4,#0xC]   ;               ,   Derived  
.text:70421FEE                 MOVS    R0, #3
.text:70421FF0                 BL      j_j___android_log_print
.text:70421FF4                 MOVS    R0, R4          ; this ;  this  
.text:70421FF6                 BL      _ZN4Base7displayEv ; Base::display(void)
.text:70421FFA                 POP     {R0,R1,R4,PC}
    
次に、解析関数を続けます.考え方はDisplayと同じです.まず、オブジェクトの先頭アドレスから虚表ポインタを取り出し、虚表ポインタ+8が指すメモリユニットから具体的なDerivedクラスの解析関数のアドレスを取り出し、対応する命令実行にジャンプします. 
.text:70422064 ; _DWORD __fastcall Derived::~Derived(Derived *__hidden this)
.text:70422064                 WEAK _ZN7DerivedD0Ev
.text:70422064 _ZN7DerivedD0Ev                         ; DATA XREF: .data.rel.ro:_ZTV7Derived+10o
.text:70422064                 PUSH    {R4,LR}
.text:70422066                 MOVS    R4, R0          ;R4    R0,       
.text:70422068                 BL      _ZN7DerivedD2Ev ; Derived::~Derived()
.text:7042206C                 MOVS    R0, R4          ; void * R0          
.text:7042206E                 BL      _ZdlPv          ; operator delete(void *)         
.text:70422072                 MOVS    R0, R4
.text:70422030 ; _DWORD __fastcall Derived::~Derived(Derived *__hidden this)
.text:70422030                 WEAK _ZN7DerivedD2Ev
.text:70422030 _ZN7DerivedD2Ev                         ; CODE XREF: Derived::~Derived()+4p
.text:70422030                                         ; DATA XREF: .data.rel.ro:_ZTV7Derived+Co
.text:70422030                 PUSH    {R4,LR}         ; Alternative name is 'Derived::~Derived()'
.text:70422032                 MOVS    R4, R0          ;R4    R0,       
.text:70422034                 LDR     R3, =(_ZTV7Derived_ptr - 0x7042203E)
.text:70422036                 LDR     R1, =(aLesson6 - 0x70422042)
.text:70422038                 LDR     R2, =(aDerived___ - 0x70422044)
.text:7042203A                 ADD     R3, PC ; _ZTV7Derived_ptr
.text:7042203C                 LDR     R3, [R3]        ; `vtable for'Derived R3   Derived     ,  .data.rel.ro, 0x70428978
.text:7042203E                 ADD     R1, PC          ; "lesson6"
.text:70422040                 ADD     R2, PC          ; "~Derived ..."
.text:70422042                 ADDS    R3, #8          ;R3   Derived     +8, 0x70428980
.text:70422044                 STR     R3, [R0]        ; 0x70428980               
.text:70422046                 MOVS    R0, #3
.text:70422048                 BL      j_j___android_log_print
.text:7042204C                 MOVS    R0, R4          ; this R0          
.text:7042204E                 BL      _ZN4BaseD2Ev    ; Base::~Base()          
.text:70422052                 MOVS    R0, R4          ;        
.text:70422054                 POP     {R4,PC}
.text:70422004 ; _DWORD __fastcall Base::~Base(Base *__hidden this)
.text:70422004                 WEAK _ZN4BaseD2Ev
.text:70422004 _ZN4BaseD2Ev                            ; CODE XREF: Derived::~Derived()+1Ep
.text:70422004                                         ; Base::~Base()+4p
.text:70422004                                         ; DATA XREF: ...
.text:70422004                 PUSH    {R4,LR}         ; Alternative name is 'Base::~Base()'
.text:70422006                 MOVS    R4, R0          ;R4          
.text:70422008                 LDR     R3, =(_ZTV4Base_ptr - 0x70422012)
.text:7042200A                 LDR     R1, =(aLesson6 - 0x70422016)
.text:7042200C                 LDR     R2, =(aBase___ - 0x70422018)
.text:7042200E                 ADD     R3, PC ; _ZTV4Base_ptr
.text:70422010                 LDR     R3, [R3]        ; `vtable for'Base   Base     ,  .data.rel.ro, 0x70428960
.text:70422012                 ADD     R1, PC          ; "lesson6"
.text:70422014                 ADD     R2, PC          ; "~Base ..."
.text:70422016                 ADDS    R3, #8          ;R3+8    R3,R3   0x70428968
.text:70422018                 STR     R3, [R0]        ; 0x70428968               (        )
.text:7042201A                 MOVS    R0, #3          ;R0      ,   3
.text:7042201C                 BL      j_j___android_log_print
.text:70422020                 MOVS    R0, R4          ;        
.text:70422022                 POP     {R4,PC}

    0x03
まとめ:親クラスのメンバーは低アドレス、子クラスのメンバーは高アドレス、虚表ポインタはオブジェクトの最初のアドレスにあり、オブジェクトを構築するときは、まず親クラスを構築し、虚表ポインタは親クラスの虚表を指し、子クラスを構築し、虚表ポインタは子クラスの虚表を指す.オブジェクトを解析するときは、まずサブクラスを解析し、虚表ポインタはサブクラスの虚表を指し、さらに親クラスを解析し、虚表ポインタは親クラスの虚表を指す.