user12023629
user12023629

Reputation:

How to read this decompiled statement?

When I decompiled a function I got the following code

((void(__thiscall**)(int))(*v4 + 4))(v4);

*v4 in this context is a virtual table. I can't really break it down (who is resolved first and the exact meaning of it).

I'd kindly ask you to help me resolving this step by step so I can understand how this works.

Upvotes: 0

Views: 338

Answers (3)

Erik Eidt
Erik Eidt

Reputation: 26656

(
    (   // these parens around the type declaration are a cast
        void (__thiscall**)(int) // this type declaration:
                                 // a pointer to pointer to function taking int parameter
    )
    (*v4 + 4) // this is a pointer expression
              // this pointer is being cast to a function
) // this is a function pointer
( // these paren's invoke the function
    v4     // this is the parameter being passed to the function 
);

The only thing that is strange is that v4, passed as parameter, is not an int as the cast says — it is a pointer.

It looks like v4 is an object, and the vtable is the first member of the object, so *v4 refers to the vtable. *v4+4 refers to the 5th vtable entry.

Upvotes: 2

Phantomas
Phantomas

Reputation: 206

This statement use some weird calling convention specification from Microsoft, but what it basically is, is just a cast, followed by a call.

(void(**)(int)) this type is a pointer to a pointer to a function taking int as parameter, and returning void.

__thiscall is a calling convention specifier only supported by Microsoft compiler as you can see here

(*v4 + 4) This part is just dereferencing v4, then adding 4, so I'd guess that *v4 is a pointer, and the type of v4 is something like void **

Wrapping all up, this statement de-reference v4, add 4 to this value, cast this new pointer as a pointer to a pointer to function, then invoke this by passing v4.

As pointed out by others, it's weird that v4 is passed as an int. However, as the architecture seems to be x86, this should not break anything, as int and pointer should have the same size of 32bits.

Upvotes: 0

((void(__thiscall**)(int))(*v4 + 4))(v4);
                            ^^ pointer
                           ^^^ dereference it
                           ^^^^^^^ add 4
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cast to void (__thiscall**)(int)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Call with v4 as the parameter

void (__thiscall**)(int) is a pointer to a pointer to a function, which has an int parameter.

Presumably:

  • v4 is the address of an object.
  • *v4 reads the vtable pointer from the object.
  • *v4 + 4 is the slot in the vtable where the function pointer we want to call is. It's a pointer to that function pointer.
  • The first parameter is this

Note that we're calling a pointer to a function pointer. Function pointers are automatically dereferenced in C(++), but I wasn't aware that that also applied to pointers to function pointers. Evidently, it does.

Upvotes: 2

Related Questions