2

How can I find the real function that *(_DWORD *)v2 + 24) points to?

(*(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
  • Inside the function, the address of the function you are looking for is v2 + sizeof(*_DWORD)*24. This typically means: v2+0x60 on a 32-bit program where a pointer size is 4 bytes, and double that in a 64-bit system. v2 = a2, which is the second int passed to sub_1, probably in register EDX, because it is a __fastcall type func. The first line of your code also calls a function pointer, but I cannot see which scope it belongs to.
    – Yotamz
    Mar 25, 2020 at 13:31
  • its address is in the a2 variable
    – SSpoke
    Mar 25, 2020 at 22:53

2 Answers 2

3

The key thing is that you're likely dealing with a C++ object and these are roughly structured as follows:

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

Inside the vtable it'll look like this:

void* func1;
void* func2;

So you'll want to see what gets passed into a2, you'll probably find something like this:

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

...

This is where the class gets initialized. Find this and you find what's getting passed in.

Keep in mind the reason the code is using virtual functions is likely to take advantage of inheritance, so there could be multiple classes that get passed to this. If you have RTTI information in the binary you can use this to give you clues – these should include the class name, function names and function signatures.

1
  • RTTI rarely includes function names as it is only needed for telling apart classes, so at most you'll get class names (but this may be compiler dependent).
    – Igor Skochinsky
    Dec 20, 2021 at 21:37
1

A __fastcall function gets its first two arguments in ECX and EDX. int __fastcall sub_1(int a1, int a2) { int v2; v2 = a2; //v2 = EDX ... This line may change the address pointed to by a2, if it happens to be a pointer, but not the value of a2 itself. However, after this line EDX may have changed:

sub_2(a2);

In this line:

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

the relevant part is:

(*(_DWORD *)v2 + 24))

v2 is treated as a _DWORD pointer, which means its size is that of a pointer, typically 4 bytes. So, v2+24, treated as a pointer-sized variable is v2+24*4. This value is then dereferenced and treated as function pointer.

The function address is the _DWORD value found at [v2+0x60]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.