mvwhyatt
mvwhyatt

Reputation: 465

Is decompiled __thiscall expression a pointer to a function?

I am doing static analysis on a Win32 .dll using IDA Pro 6.3 and am using the Hex-Rays decompiler in tandem with the IDA disassembler. I'd like to understand what this line does.

v4 = (*(int (__thiscall **)(int, int))(*(_DWORD *)dword_10087418 + 4))(dword_10087418, v11);

It is formatted like a function call. Is this what decompiled code looks like when a pointer to a function is used in a subroutine call?

Thanks.

Upvotes: 2

Views: 4340

Answers (2)

user1233508
user1233508

Reputation:

This is most likely C++, not plain C. That is exactly what Visual C++-generated virtual method calls look like. I would say that:

  • dword_10087418 is a pointer to an object. It is either a global or static variable, not a local one.
  • That object has a virtual method table, and the code is calling the second function in that table.
  • Assuming Hex-Rays has identified the function arguments correctly, the function being called takes one 32-bit argument. The return type is not clear.
  • The C++ call was most likely very simple, similar to SomeClass::Instance->func(arg).

If you are not familiar with the C++ object layout, you should read C++ Under the Hood , Reversing: Secrets of Reverse Engineering or Inside the C++ Object Model. The IDA Pro Book also has a brief section on the topic.


If you want a brief summary, read on. Keep in mind that all of this is an implementation detail of MSVC, other compilers do it differently and they can freely change it as they please. (Also, I'm simplifying things by not mentioning virtual/multiple inheritance). When a class uses virtual functions, the compiler builds a table of all such functions in that class and puts a pointer to that table as the first hidden member of each object of that class. Then, calling the virtual function from the table is as simple as:

mov ecx, esi   ; pretend that esi contains a pointer 
               ; to the object whose method is being called
               ; also known as "this"
               ; __thiscall functions expect to find this pointer in ecx
               ;  and all later arguments on the stack
mov edx, [ecx] ; get the vtable address
push edi       ; set up some integer-sized argument
call [edx + 4] ; call the second function in the vtable

And that is basically what that line of code is doing:

(*(int (__thiscall **)(int, int))(*(_DWORD *)dword_10087418 + 4))(dword_10087418, v11)
                                  ^-----------------------^
                                  dereference pointer to get the address of the vtable
                                  (it's the first piece of data in the object)
                                 ^-----------------------------^
                                 add 4 bytes to get address of the second function
^------------------------------------------------------------------------------------^
cast that pointer to a particular function pointer and call it
(cast is invisible in assembler code, so it's just a call)

Note that since the member function needs access to this, the compiler has to pass it as well. It's a detail that's not visible in C++, but this is treated like an additional argument for the function - hence you see two arguments but the function only takes one (MSVC's thiscall convention mandates that this pointer is passed in ecx). IDA doesn't bother hiding that pointer because that would get confusing.


More advice: Get the ms_rtti script for IDA and run it to find the virtual method tables in the DLL, then search for other references to dword_10087418 to see what values are written to it - you should be able to determine which vtable is associated with that object and then figure out which function is being called.

You can make Hex-Rays show the code in a more readable fashion if you define stub struct types for the class and the vtable in question, then tell IDA that the pointer uses that struct type.

Upvotes: 3

fortenbt
fortenbt

Reputation: 76

This is casting the address at *dword_10087418 + 4 to a function and calling it.

So it's casting dword_10087418 to a dword pointer and then dereferencing it, and then adding 4 to that result. The resulting address is cast to a function whose declaration looks like:

int __thiscall foo(int, int)

The int (__thiscall **)(int, int) makes a double pointer to a function with __thiscall calling convention that takes two integer arguments. Then the *() around all that dereferences it to a single function pointer. So in the end you're casting some resulting address to a function pointer.

dword_10087418 and v11 are the integers passed to this function. The result of the function call is saved in v4. The C code would look like this:

int v4 = foo(dword_10087418, v11);

Upvotes: 0

Related Questions