5

Consider the following code:

In C++:

SomeClass* globalPointer; // we don't know what it points to, but it's not null a pointer, it's initialized

void someFunction()
{
  globalPointer->someVirtualFunction();
}

In IDA (inside someFunction):

mov     ecx, dword_XXXX ; ecx = globalPointer
mov     eax, [ecx] ; eax = vtable
jmp     dword ptr [eax+30h] ; call vtable[0x30]

The meaning of dword_XXXX is just a pointer value. I tried to check it this way:

printf("Address of pointer = %p, pointer's value = %p\n", &otherPointer, otherPointer);

And I got:

push dword_XXXX ; otherPointer
push offset dword_XXXX ; &otherPointer
push offset format ; "Address of pointer = %p, pointer's value = %p\n"

call printf

Thus dword_XXXX seems to be a pointer's value and offset dword_XXXX seems to be an address of the pointer.

However, I noticed another code (which can be expressed the same as the c++ function I provided above):

SomeClass2* globalPointer2;

void someFunction2()
{
  globalPointer2->someVirtualFunction2();
}

And IDA surprisingly gave me (inside someFunction2):

mov eax, dword_XXXX ; eax = globalPointer2
mov ecx, offset dword_XXXX ; ecx = &globalPointer2
jmp dword ptr [eax+5Ch] ; call [globalPointer2+0x5C] with &globalPointer2 as this?? It should be call vtable[0x5C]

I checked the values and found out that IDA somehow "changes" the meaning of dword_XXXX, in this case it actually was:

mov eax, dword_XXXX ; eax = vtable
mov ecx, offset dword_XXXX ; ecx = globalPointer2
jmp dword ptr [eax+5Ch] ; call vtable[0x5C]

Why the meaning of dword_XXXX was different in the second case? In the first case it was just pointer, but in the second case it was *pointer.

And the meaning of offset dword_XXXX in the first case was &pointer and in the second case was pointer.

I'm sorry if something is unclear, I really tried to simplify that as much as possible.

anx199
  • 175
  • 10
  • 1
    Remove your answer from the question and add it as an answer. You can post answers to your own questions – Avery3R Jul 31 '18 at 17:51

1 Answers1

5

I think I figured out what's going on.

The opcodes for the printing were (assuming dword_AAAAAAAA instead of general dword_XXXX):

FF 35 AA AA AA AA    push dword_AAAAAAAA; otherPointer
68 AA AA AA AA       push offset dword_AAAAAAAA; &otherPointer

Thanks to this site, I know that the above instructions are equal to:

push [0xAAAAAAAA]; push otherPointer
push 0xAAAAAAAA;   push &otherPointer

So, in this case, dword_XXXX is equal to value of a pointer. However, in the second case (again assuming dword_AAAAAAAA instead of general dword_XXXX):

A1 AA AA AA AA    mov eax, dword_AAAAAAAA ; eax = vtable
B9 AA AA AA AA    mov ecx, offset dword_AAAAAAAA ; ecx = globalPointer2

And it's equal to:

mov eax, [0xAAAAAAAA] ; eax = vtable
mov ecx, 0xAAAAAAAA ; ecx = globalPointer2

Thus in this case dword_XXXX is equal to *pointer rather than pointer.

Therefore I think the answer is: it depends. We need to understand what dword_XXXX means - it can be a pointer, an address of the pointer, or even pointer to pointer to pointer, and so on. But IDA gives us a hint: offset dword_XXXX means a raw value of whatever dword_XXXX is and dword_XXXX gives a dereferenced value of it.

anx199
  • 175
  • 10