Looking at JNI C++ from a reverse perspective

Looking at the JNI C++ class structure from a reverse perspective

1. First look at multiple inheritance

code show as below

classTest.h


class Base1
{
public:
    virtual void vb1f() {printf("Base1 vb1f");}
    virtual void vf() {printf("Base1 vf");}
};

class Base2
{
public:
    virtual void vb2f() {printf("Base2 vb2f");}
    virtual void vf() {printf("Base2 vf");}
};

class Drive : public Base1, Base2
{
public:
    virtual void vdf() {printf("Driver vdf");}
    virtual void vf() {printf("Driver vf");}
    void f() {printf("Driver f");}
};

classTest.cpp

#include "ClassTest.h"
#include <jni.h>

extern "C"
JNIEXPORT jint JNICALL
Java_com_example_idareversecppclass_JniPerson_createClsssTest(JNIEnv *env, jobject thiz, jlong addr,
                                                              jint age) {
    jlong result;
    result =(jlong) new Drive();//创建了一个Drive对象
    return result;
}

Put the generated so into IDA for analysis

_DWORD *Java_com_example_idareversecppclass_JniPerson_createClsssTest()
{
  _DWORD *result; // r0

  result = (_DWORD *)operator new(8u);
  *result = &off_26840;                         // 虚表1
  result[1] = &off_26854;						//虚表2
  return result;
}

The content of the address pointed to by off_26840

.data.rel.ro:0002683C 6C 68 02 00  DCD _ZTI5Drive                   ; `typeinfo for'Drive
.data.rel.ro:00026840 D5 28 01 00  off_26840 DCD _ZN5Base14vb1fEv+1 ; Base1::vb1f(void)
.data.rel.ro:00026844 E1 28 01 00  DCD _ZN5Drive2vfEv+1             ; Drive::vf(void)
.data.rel.ro:00026848 ED 28 01 00  DCD _ZN5Drive3vdfEv+1            ; Drive::vdf(void)
.data.rel.ro:0002684C FC           DCB 0xFC
.data.rel.ro:0002684D FF           DCB 0xFF
.data.rel.ro:0002684E FF           DCB 0xFF
.data.rel.ro:0002684F FF           DCB 0xFF

The first function is Base1::vb1f(void)

The second function is Drive::vf(void)

The third function is Drive::vdf(void)

The content of the address pointed to by off_26854

.data.rel.ro:00026850 6C 68 02 00  DCD _ZTI5Drive                  ; `typeinfo for'Drive
.data.rel.ro:00026854 F9 28 01 00  off_26854 DCD _ZN5Base24vb2fEv+1; Base2::vb2f(void)
.data.rel.ro:00026858 05 29 01 00  DCD _ZThn4_N5Drive2vfEv+1       ; `non-virtual thunk to'Drive::vf(void)

The first function is Base2::vb2f(void)

The second function is `non-virtual thunk to' Drive::vf(void)

So create a structure for MyDrive as follows

struct MyDrive
{
  int driveVtable1;
  int driveVtable2;
};

struct DriveVtable1
{
  int field_0;
  int field_4;
  int field_8;
};

struct DriveVtable2
{
  int field_0;
  int field_4;
};

Modified code

MyDrive *Java_com_example_idareversecppclass_JniPerson_createClsssTest()
{
  MyDrive *result; // r0

  result = (MyDrive *)operator new(8u);
  result->driveVtable1 = &stru_26840;           // 虚表1
                                                // 
                                                // 
                                                // 虚表2
 
  result->driveVtable2 = &stru_26854;
  return result;
}
  1. It can be seen that because Base1 and Base2 are inherited, there are two virtual table pointers to manage the virtual function. There are as many virtual table pointers as there are parent classes inherited.
  2. The content of the first virtual table pointer off_26840 virtual table is the virtual function in the first inherited class Base1
  3. The first 4-byte address of off_26840 is stored in the Base1 class Base1::vb1f(void) and then the overloaded Drive::vf(void) and finally its own virtual function Drive::vdf(void). It can be seen that the order of the virtual functions is also from the base class first, and then its own functions

2. Look at diamond inheritance (virtual inheritance)

the code


class Base
{
public:
    virtual void vbbf() {printf("base vbbf");}
    virtual void vbf() {printf("base vbf");}
};

class Base1 : virtual public Base
{
public:
    virtual void vb1f() {printf("base1 vb1f");}
    virtual void vf() {printf("base1 vf");}
};

class Base2 : virtual public Base
{
public:
    virtual void vb2f() {printf("base2 vb2f");}
    virtual void vf() {printf("base2 vf");}
};

class Drive : virtual public Base1, virtual public Base2
{
public:
    virtual void vdf() {printf("drive vdf");}
    virtual void vf() {printf("drive vf");}
    void f() {}
};
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_idareversecppclass_JniPerson_createLxClsssTest(JNIEnv *env, jobject thiz) {
    jlong result;
    result =(jlong) new Drive();
    return result;
}

disassembled code

_DWORD *Java_com_example_idareversecppclass_JniPerson_createLxClsssTest()
{
  _DWORD *result; // r0

  result = (_DWORD *)operator new(8u);
  *result = &off_26BA0;
  result[1] = &unk_26BD0;
  return result;
}

The content of the address pointed to by off_26BA0

.data.rel.ro:00026BA0 C1 2B 01 00 off_26BA0 DCD _ZN4Base4vbbfEv+1   ; Base::vbbf(void)
.data.rel.ro:00026BA4 CD 2B 01 00 DCD _ZN4Base3vbfEv+1              ; Base::vbf(void)
.data.rel.ro:00026BA8 65 2B 01 00 DCD _ZN5Base14vb1fEv+1            ; Base1::vb1f(void)
.data.rel.ro:00026BAC D9 2B 01 00 DCD _ZN7Drive112vfEv+1            ; Drive11::vf(void)
.data.rel.ro:00026BB0 E5 2B 01 00 DCD _ZN7Drive113vdfEv+1           ; Drive11::vdf(void)

The first function Base::vbbf(void)

The second function Base::vbf(void)

The third function Base1::vb1f(void)

The fourth function Drive11::vf(void)

The fifth function Drive11::vdf(void)

The content of the address pointed to by unk_26BD0

.data.rel.ro:00026BD0 00 00 00 00 dword_26BD0 DCD 0
.data.rel.ro:00026BD4 00 00 00 00 DCD 0
.data.rel.ro:00026BD8 89 2B 01 00 DCD _ZN5Base24vb2fEv+1           ; Base2::vb2f(void)
.data.rel.ro:00026BDC F1 2B 01 00 DCD _ZTv0_n28_N7Drive112vfEv+1   ; `virtual thunk to'Drive11::vf(void)

first function 0

second function 0

The third function Base2::vb2f(void)

The fourth function `virtual thunk to'Drive11::vf(void)

  1. First of all, there are still only two virtual pointers
  2. off_26BA0 The first virtual table contains all the virtual functions of Base Base1Driver
  3. The first two addresses of unk_26BD0 are empty, and the virtual function of Base is not put into the virtual function that only stores Base2 and Drive

Guess you like

Origin blog.csdn.net/qq_36535153/article/details/131125876