如何找到 *(_DWORD *)v2 + 24) 指向的真正函数?

逆向工程 艾达
2021-06-25 20:35:46

我怎样才能找到*(_DWORD *)v2 + 24)指向的真正函数

(*(void (__fastcall **)(int, int))(*(_DWORD *)v2 + 24))(v2, v4);

int __fastcall sub_1(int a1, int a2)
{
  int v2; // r4@1
  int v3; // r5@1
  int v4; // r6@1
  int v5; // r0@2
  int v6; // r0@2
  unsigned int v7; // r0@4
  int v8; // r5@8

  v2 = a2;
  v3 = a1;
  sub_2(a2);
  v4 = *(_BYTE *)(sub_3(*(_DWORD *)(v3 + 1684)) + 13);
  (*(void (__fastcall **)(int, int))(*(_DWORD *)v2 + 24))(v2, v4);
  if ( v4 )
  {
    (*(void (__fastcall **)(int, _DWORD))(*(_DWORD *)v2 + 56))(v2, *(_DWORD 
2个回答

关键是您可能正在处理 C++ 对象,这些对象的结构大致如下:

void* vtable;
void* param1;
...
etc

在 vtable 中,它看起来像这样:

void* func1;
void* func2;

所以你会想看看传入了什么a2,你可能会发现这样的东西:

v1 = operator new(0x60);
*v1 = offset XXXXX;

...

这是类被初始化的地方。找到这个,你就会发现传入的内容。

请记住,代码使用虚函数的原因可能是利用了继承,因此可能会有多个类传递给 this。如果你在二进制文件中有 RTTI 信息,你可以用它来给你提供线索——这些应该包括类名、函数名和函数签名。

__fastcall 函数在 ECX 和 EDX 中获取其前两个参数。 int __fastcall sub_1(int a1, int a2) { int v2; v2 = a2; //v2 = EDX ... 这一行可能会改变a2指向的地址,如果它恰好是一个指针,而不是a2本身的值但是,在此行之后 EDX 可能已更改:

sub_2(a2);

在这一行:

(*(void (__fastcall **)(int, int))(*(_DWORD *)v2 + 24))(v2, v4);

相关部分是:

(*(_DWORD *)v2 + 24))

v2 被视为 _DWORD 指针,这意味着它的大小是指针的大小,通常为 4 个字节。因此,将 v2+24 视为指针大小的变量是v2+24*4然后取消引用该值并将其视为函数指针。

函数地址是在以下位置找到的 _DWORD[v2+0x60]