从赋值都从第二个地址开始赋值来看应该是个类的实例(对象),this指着的地方是指向虚表的指针,至于其它成员都是干什么的,什么结构,你得参照不同位置的引用慢慢猜,所以我建议你定义好structures然后慢慢分析
我写了一个简单的例子:
.text:00000000004008FF mov edi, 18h ; unsigned __int64
.text:0000000000400904 call __Znwm ; operator new(ulong)
.text:0000000000400909 mov rbx, rax
.text:000000000040090C mov rdi, rbx
.text:000000000040090F call sub_400A50
这里new了0x18大小,先把结构体大小设好0x18:
00000000 class struc ; (sizeof=0x18)
00000000 p_vtbl dq ?
00000008 db ? ; undefined
00000009 db ? ; undefined
0000000A db ? ; undefined
0000000B db ? ; undefined
0000000C db ? ; undefined
0000000D db ? ; undefined
0000000E db ? ; undefined
0000000F db ? ; undefined
00000010 db ? ; undefined
00000011 db ? ; undefined
00000012 db ? ; undefined
00000013 db ? ; undefined
00000014 db ? ; undefined
00000015 db ? ; undefined
00000016 db ? ; undefined
00000017 field_8 db ?
00000018 class ends
接下来找找赋值的地方,推算各个成员的大小,像这样的:
__int64 __fastcall sub_4009B4(__int64 a1)
{
__int64 result; // rax@1
std::operator<<<std::char_traits<char>>(6295808LL, 4197131LL);
*(_DWORD *)(a1 + 8) = 1;
*(_BYTE *)(a1 + 12) = 99;
result = a1;
*(_QWORD *)(a1 + 16) = -81985529216486896LL;
return result;
}
推算出成员大小:
00000000 class struc ; (sizeof=0x18)
00000000 p_vtbl dq ?
00000008 member1 dd ?
0000000C member2 dd ?
00000010 member3 dq ?
00000018 class ends
然后F5里面把变量转成结构体指针:
class *__fastcall sub_4009B4(class *pobj)
{
class *result; // rax@1
std::operator<<<std::char_traits<char>>(6295808LL, 4197131LL);
pobj->member1 = 1;
LOBYTE(pobj->member2) = 99;
result = pobj;
pobj->member3 = -81985529216486896LL;
return result;
}
class *__fastcall sub_400A50(class *a1)//这里是构造函数,给虚表赋值了
{
class *result; // rax@1
sub_400A3A();
result = a1;
a1->p_vtbl = (__int64)&off_400B30;
return result;
}
__int64 sub_4008F6()
{
class *pobj; // rbx@1
pobj = (class *)operator new(0x18uLL);
sub_400A50(pobj);
sub_4009B4(pobj);
(*(void (__fastcall **)(class *))pobj->p_vtbl)(pobj);//利用虚表调用虚函数
return 0LL;
}
int __fastcall sub_4009F6(class *a1)//可以追踪到调用的虚函数是这个
{
__int64 v1; // rbx@1
__int64 v2; // rax@1
__int64 v3; // rax@1
v1 = a1->member3;
LODWORD(v2) = std::operator<<<std::char_traits<char>>(0x601100LL, 0x400B0FLL);
LODWORD(v3) = std::ostream::operator<<(v2, v1);
return std::operator<<<std::char_traits<char>>(v3, 0x400B15LL);
}
基本上结构就很接近原程序了……原源码:
#include <iostream>
using std::cout;
using std::operator <<;
class base
{
virtual void vfunc(){cout<<"base!\n";}
};
class classA : base
{
public:
void func1(){cout<<"f1\n";a = 1;b = 'c';c = 0xfedcba9876543210;}
virtual void vfunc(){cout<<"f2\nc="<<c<<"\n";}
private:
int a;
char b;
unsigned long long c;
};
int main()
{
classA *pobjA = new classA;
pobjA -> func1();
pobjA -> vfunc();
}