this指针的本质
- 隐式参数:所有非静态成员函数都隐式接收
this
指针作为第一个参数,指向调用该函数的对象实例 - 编译器实现:不同编译器对
this
的处理方式不同:- MSVC:使用
thiscall
约定,通过ECX
寄存器传递(可能该文件使用Visual C++编译 或者该函数是一个成员函数 ) - GCC:作为第一个参数压栈(x86)或通过
RDI
寄存器传递(x64)
- MSVC:使用
逆向识别特征
-
MSVC特征:
- 函数调用前
ECX
被设置为对象地址 - 构造函数会将
this
存入EAX
返回
- 函数调用前
-
类关系推断:
// 正向代码示例 class MyClass { public: void func1() { /*...*/ } void func2() { /*...*/ } };
; 逆向特征 mov ecx, [ebp+obj] ; 设置this指针 call MyClass_func1 mov ecx, [ebp+obj] ; 相同的对象地址 call MyClass_func2
当多个函数使用相同的对象地址作为
this
时,可判定它们属于同一个类
如果同一个地址被传递给两个或更多函数,这些函数全都属于同一个类层次结构。
构造函数的特殊处理
- 构造函数会隐式返回
this
指针(MSVC通过EAX
返回) - 析构函数同样会接收
this
指针作为隐式参数
示例:
class A {
public:
int fun(){return 1;}
int Lk(){return fun();}
};
int _tmain(int argc, _TCHAR* argv[]) {
A a;
a.Lk();
return 0;
}
对应IDA反汇编如下:
附:
构造函数并未指定返回类型,但由Visual C++生成的构造函数实际上把this指针存在EAX寄存器中并返回
应用场景
- 逆向工程中识别类成员函数
- 分析面向对象程序的二进制结构
- 破解商业软件的类层次关系
通过识别this
指针的传递方式,可以有效地还原C++程序的面向对象结构,是逆向分析中的重要技术点。