1

I've a binary opened in IDA. It uses a function pointer from a COM vtable. I found that the COM method has 13 parameters (including this). But IDA shows only 4 parameters as shown in this pseudocode:

v93 = 0i64;
v79 = &hObject;
v78 = &v93;
v77 = 0xFFFFFFFF;
v76 = (signed int)NtCurrentPeb()->ProcessParameters->Reserved2[0];
v75 = a6;
LODWORD(v74) = v130;
v73 = v129;
HIDWORD(v72) = HIDWORD(v118);
v71 = Dst;
v14 = (*(__int64 (__fastcall **)(__int64, __int64, _QWORD, __int64))(*(_QWORD *)v10 + 48i64))(v10, v117, v91, v116);

The corresponding disassembly looks like this:

loc_1400055B6:
mov     [rsp+2A8h+var_1E0], rsi
mov     rax, gs:60h
mov     rcx, [rax+20h]
mov     rdx, [rcx+10h]
mov     rax, [r12]
mov     r10, [rax+30h]
lea     rax, [rsp+2A8h+hObject]
mov     [rsp+2A8h+var_248], rax
lea     rax, [rsp+2A8h+var_1E0]
mov     [rsp+2A8h+var_250], rax
or      [rsp+2A8h+var_258], 0FFFFFFFFh
mov     [rsp+2A8h+var_260], edx
mov     [rsp+2A8h+var_268], r15
mov     eax, dword ptr [rsp+2A8h+var_90]
mov     dword ptr [rsp+2A8h+var_270], eax
mov     rax, [rsp+2A8h+var_98]
mov     [rsp+2A8h+var_278], rax
mov     rax, [rsp+2A8h+var_110]
mov     [rsp+2A8h+var_280], rax
mov     rax, [rsp+2A8h+Dst]
mov     [rsp+2A8h+var_288], rax
mov     r9, [rsp+2A8h+var_120]
mov     r8d, [rsp+2A8h+var_1EC]
mov     rdx, [rsp+2A8h+var_118]
mov     rcx, r12
mov     rax, r10
call    cs:__guard_dispatch_icall_fptr
mov     rcx, [rsp+2A8h]
test    eax, eax
js      loc_140005FF4

Question: The function pointer i.e. v10 + 48i64 shows only four parameter. How can I add or find the remaining parameters?


Update: I add a header file mentioning the total 13 probable parameters in that method. Though IDA changes the data type of four parameters (v10, v117, v91, v116) it doesn't add remaining ones. I thought that if v71 to v79 are the other parameter of that COM method. That'll make all 13 parameters. And the execution starts with v79. May be like __stdcall.

  • To modify the function declaration, select its name in the IDA View-A and press Y. That should bring up a dialog that lets you edit the function declaration in C. – 0xC0000022L Jul 10 '18 at 8:27
  • There is ... in the vtable. Of course in this case it has no name initially. But of course you can tack a function declaration on it once you have defined a struct corresponding to the vtable layout. – 0xC0000022L Jul 10 '18 at 8:33
  • I've never used a header file to achieve this. So I'm probably not qualified to comment further. Whenever I do this, I use the method with Y outlined above. The least you can achieve with it, would be to see if your header file actually took effect. – 0xC0000022L Jul 10 '18 at 8:39
1

You need to define the virtual method table structure, then for the method at offset 48 (0x30) you need to specify the correct function definition, and then set v10 type to your structure.

  • Is calling conventions important in COM methods? – Biswapriyo Jun 30 '18 at 16:14
  • 1
    In x32 - yes, in x64 - no – Anton Kukoba Jul 2 '18 at 7:30
0
  • Simplification: All the memory offsets are in decimal.
loc_1400055B6:
mov     [rsp+200], rsi
mov     rax, gs:60h
mov     rcx, [rax+32]
mov     rdx, [rcx+16]
mov     rax, [r12]              ;IUnknown::QueryInterface
mov     r10, [rax+48]           ;sixth function after QueryInterface
lea     rax, [rsp+168]
mov     [rsp+96], rax           ;13th parameter
lea     rax, [rsp+200]
mov     [rsp+88], rax           ;12th parameter
mov     [rsp+80], rsi           ;11th parameter
mov     [rsp+72], edx           ;10th parameter
mov     [rsp+64], r15           ;9th parameter
mov     eax, [rsp+744]
mov     [rsp+56], eax           ;8th parameter
mov     rax, [rsp+736]
mov     [rsp+48], rax           ;7th parameter
mov     rax, [rsp+616]
mov     [rsp+40], rax           ;6th parameter
mov     rax, [rsp+592]
mov     [rsp+32], rax           ;5th parameter
mov     r9, [rsp+600]           ;4th parameter
mov     r8d, [rsp+196]          ;3rd parameter
mov     rdx, [rsp+608]          ;2nd parameter
mov     rcx, r12                ;1st parameter aka. 'this' pointer 
mov     rax, r10                ;sixth function after QueryInterface
call    cs:__guard_dispatch_icall_fptr
mov     rcx, [rsp+378h]
test    eax, eax
js      loc_140005FF4
  • Explanation: The binary is a Windows 64bit executable. It is not easily possible to get details of function parameters with pseudo-code only. The assembly code defines more than that.

The function follows __fastcall convention. Quote from this article: "Integer arguments are passed in registers RCX, RDX, R8, and R9". As you can see the assembly follows same rule from 1st to 4th parameter. Then the rest of parameters are stored in stack with increment of [RSP+32] to [RSP+96]. For example:

func1(int a, int b, int c, int d, int e);
// a in RCX, b in RDX, c in R8, d in R9, e pushed on stack 

Hence IDA only takes the four general 64bit registers as parameters only, not the stack variables and it shows only four parameters instead of thirteen parameters. At last, ignore the calling of __guard_dispatch_icall_fptr function, it's just a Control Flow Guard added by M$ Visual Studio compiler.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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