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.

  • 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
4

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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