i've been working lately on making different algorithms for calling C++ methods using pointers and all manner of things, dealing with normal methods and virtual methods..
just wanna post some of my examples here, and see if anybody likes them (though they are inline assembler examples that can easily be modified to call in memory C++ objects from ASM code in the same process, also maybe people might be able to point out some errors in my logic or understanding. b.t.w these are MSVC++ specific as other compilers probably implement things differently.. one thing to note is i haven't tested/made allowances for classes that use multiple inheritence

first issue is getting a pointer to the method. The folowing inline assembly will do it for virtual and non virtual methods, however it won't do it if you only have an empty "shell interface" definiton of the class (i.e virtual BOOL Shutdown() = 0;


_asm
{
mov eax,Test::DoIt;
}


If you just have a 'shell interface' though, that won't compile, and maybe you want to rather get that address from C/C++, or actually maybe you know its a virtual method, and you want to rather get it from the pointer to the instance of the class. well first lets try getting it with C++ code..
first thing you need to do is use a method pointer..



//here is what the method actually looks like for reference
virtual long DoIt(long x);
...
// and now we need to declare a pointer to a method
long (Test::*pfn2)(long x); //method pointer
// and now set the method pointer.
pfn2 = &Test::DoIt;
// now do the impossible, cast a method pointer as a function pointer
void * ptr = *((void **)&pfn2 );

now we have a pointer to a method (but we can't actually just use that as a function pointer because of difference in calling convention. b.t.w if the function pointer is pointing to a nonvirtual method the address is the actual address of the method , however if its a virtual method.. its a pointer to a stub, that looks up the instance, and calls an entry in the virtual table (calling either this address of the actual address will both work.)
that stub always (as far as i've seen) looks like this


//00401EF0 8B 01 mov eax,dword ptr [ecx]
//00401EF2 FF 60 04 jmp dword ptr [eax+4]

the only difference between each time, is the +4 or the 5th byte which is an index into the virtual table..
so i've this routine here that call be called on the address we got from the method pointer to see if it points to a virtual or non virtual method


static BOOL ismethodptrvirtual(void * methodptr)
{
BOOL returnval;
_asm
{
mov eax,methodptr;
mov ebx,[eax]
mov eax,TRUE
cmp ebx,60FF018Bh
je skip
mov eax,FALSE
skip:
mov returnval,eax
}
return returnval;
}

the next thing is maybe we already know the virtual table index (quite easy to calculate by looking at the class definition since msvc++ puts everything in the order it was declared, also you can altneratively do
myobj->doit(1); in a test app, and see the Assembly that msvc++ produces (or debug the app to see it).also the offset is goign to be DWORD aligned so first method be at offset 4, 2nd at offset 8 etc..
anyhow i made this function to go inside the virtual table and get the adddress of a virtual method based on the instance and offset.


static PVOID virtualaddress(void* thisptr,int methodoffset)
{
PVOID returnval;
_asm
{
mov eax,thisptr;
mov eax,[eax] ; //point to the start of virtualtable
mov ebx,methodoffset;
mov eax,[eax+ebx*4]
mov returnval,eax
}
return returnval;
}

now that we can get the address of a method in many different ways.. How about calling this method..
nonstaTIC C++ methods use the THISCALL calling convention which is basically the STDCALL (called method cleans up the stack) with the hidden 'this' instance pointer also being sent, with MSVC++ the 'this' pointer is passed in ECX register.. and all the parameters like STDCALL are pushed on the the stack in right to left order. (but since the stack goes downwards, basically in memory in left to right order ) so if you want to call
this particular method manually you could do.. the return value is normally returned in eax, but 8 bit structures are returned in eax:edx, and floats are returned in ST0 - so will have to be accessed seperately, not covered in this article


// to do the equivilant of the following
// int mine = obj1.doIt(43);
//where you allready have the pointer to doIt in PVOID doitptr;
_asm
{
push43
mov ecx,obj1
call [doitptr]
mov mine,eax
}

however we want to make a more generic technique to call functions.. so this is the solution..
first this is how it is called.


//here is the definition of the method used in this example

virtual BOOL Startup(HWND hPrimaryWnd, DWORD modeFlags);

// and i know that it is the first method in the virtual table,
//and we have an instance of this class called
//m_pEngine
//here is the structure containing the parameters to pass to the function
struct
{
HWND wndhandle;
DWORD c;
} mystruct = {tmphwnd,VJEMODE_PRESENTATION};

//use the virtualaddress method we have already
//covered to get the address from the instance.

address = (DWORD) thiscall::virtualaddress(m_pEngine,1);

//use the my callmethod passing in the instance of the object,
//the adress, the structure containing
//the arguments for the function and the size of the arugments (structure)

thiscall::callmethod(m_pEngine,address,(const void*)&mystruct,sizeof(mystruct));


and that is all. now here the actual code for callmethod. basically we copy the structure to the stack (as if we had pushed the parmeters backwards), put the instance of the object into ECX and call the address. and return what is returned in EAX


static DWORD callmethod(void* thisptr, DWORD address,const void* arguments,size_t argsize)
{
DWORD returnval;
_asm
{
mov ecx, argsize // get size of arguments for the function
sub esp, ecx // adjust the stack pointer to give room to copy these arguments there
shr ecx, 2 // divide by 4 (because we'll copy DWORDS over at a time)
mov esi, arguments // get the pointer to the start of the arguments buffer (Source)
mov edi, esp // start of destination stack frame (destination)
rep movsd // copy arugments to stack frame
mov ecx, thisptr // THISCALL passes "this" in ecx
call [address] // call the function
mov returnval, eax // return value returns in eax, so we better save it
}
return returnval;
}

also if we are just calling a virtual method, and we know the offset, i combined my getvirtualaddress method with the one here to produce this


static DWORD callvirtualmethod(void *thisptr,int methodoffset,const void* arguments,size_t argsize)
{
DWORD returnval;
_asm
{
mov ecx, argsize // get size of arguments for the function
sub esp, ecx // adjust the stack pointer to give room to copy these arguments there
shr ecx,2 // divide by 4 (because we'll copy DWORDS over at a time)
mov esi, arguments // get the pointer to the start of the arguments buffer (Source)
mov edi, esp // start of destination stack frame (destination)
rep movsd // copy arugments to stack frame
mov eax, thisptr // get the "this" pointer
mov eax, [eax] // point to the start of virtualtable
mov ebx, methodoffset // offset into the virtualtable
mov ecx, thisptr // THISCALL passes "this" in ecx
call [eax+ebx*4] // call the function (the address of virtualtable+offset*4)
mov returnval, eax // return value returns in eax, so we better save it
}
return returnval;

}


which enables you do do the following


//instead of the following used in the last example

address = (DWORD) thiscall::virtualaddress(m_pEngine,1);
thiscall::callmethod(m_pEngine,address,(const void*)&mystruct,sizeof(mystruct));

//you can just do this directly

thiscall::callvirtualmethod(m_pEngine,1,(const void*)&mystruct,sizeof(mystruct));


which is really useful, but often you might get the pointer directly using other methods so "callmethod" itself is useful. There is one more technique i have done so far.. ussually it wouldn't be of use to anybody, but in my case of HOOK methods, it is absolutely essential. Early on in the article i showed getting an address to a method pointer. I also pointed out that if that method pointer points to a virtual method, it doesn't point directly to it, but rather to some stub code that looks up the actual address from the virtual table based on an offset specified in the stub code as below


//00401EF0 8B 01 mov eax,dword ptr [ecx]
//00401EF2 FF 60 04 jmp dword ptr [eax+4]

for hooking purposes there isn't enough bytes (6) for me to install a safe hook, and also if i hooked this function then it would only hook calls to the method that were called through a method pointer rather that any other way. so i made a function that checks the address, and if it starts with the faith bytes 60FF018B as above it knows its this stub, and then it grabs the 5th byte as the offset, and then manually looks up the vtable itself and gets the actual address of the function. that code is below. (it has alot of comments in this one)


static PVOID dereferencemethodptr(void* thisptr,void * methodptr)
{
PVOID returnval;
//issues if size of pointer is more than 4 bytes (multiple inheritance it might be different)
//if a method pointer points to a nonstatic (but not virtual) function, then it points directly
//to that function
//if it points to a nonstatic VIRTUAL function, then it points to a stub that C++ creates that looks
//the the following
//00401EF0 8B 01 mov eax,dword ptr [ecx]
//00401EF2 FF 60 04 jmp dword ptr [eax+4]
//as far as i've seen , irregardless of anything i've seen so far , or compiler optomisation options
//it seems to be exactly the same as above, other than the last byte (the +4)
//which is actually the information
//we need to be able to look up the function in the vtable.. so we can read it directly from this code.
//so first we check to see if the first 4 bytes are 8b01FF60 (or is it 60FF018B?) and if it is grab the
//address + 4.. otherwise just treat the address as what it is.
_asm
{
mov eax,methodptr;
mov ebx,[eax]
cmp ebx,60FF018Bh
jne skip
//if its a virtual method
xor ebx,ebx
mov bl,byte ptr [eax + 4]; //grab the 5th byte which is the +4 (or +whatever) offset in the virtual table
mov eax,thisptr; //ptr to the instance of the class
mov eax,[eax] ;//start of virtual table
mov eax,[eax+ebx];//get the address of the method from getting it from the virtual table with offset
skip:
mov returnval,eax
}
return returnval;
}


end of article..
------------------
feedback from people in this community is sought after desperately, maybe i've made some wrong assumptions , or overlooked some important things.. so if you find this interesting, or find any errors in my logic.
i know that it may not faithfully always work (though alot of it still will) for classes with multiple inheritence, or with other compilers than MSVC++, but maybe in the future i'll look into both of those issues.
Posted on 2004-08-09 19:33:34 by klumsy
nice and correct :alright:
Classes with more than 31 virtuals are not rare, so the 5 bytes (60FF018Bh) will change to A0FF018Bh, and the next 4 bytes are the offset in vtable.
Also, it should be accented on where the constructor and destructor are: constructor is always static, the destructor can be marked as virtual, and if so - it's at offset 0 of the vtable.
Multiple inheritance is actually a really easy matter - the new class just has a copy of its parent's vtable, modified a little.

The approach of tutoring with inline asm is a little confusing - the purpose of the article gets really lost - but anyway it's ok as long as the reader can think of a (the) way to use it in asm :)
Maybe at this point I should remind that here on this board there is a whole macro base for interfacing of C++ code, named "ATC" :) Of course the basics should be learnt but it gets really annoying to be hardcoding calls to C++ functions if some good software is about to be made.
And again, nice article :alright:

ah, and don't care about other compilers than MSVC - because this is the actual standard everyone works with.
Posted on 2004-08-10 07:29:24 by Ultrano
yeah thanks for the extra info, my destructor is virtual thus the zero 0, you have given alot of good info.. i had also wonder about the case when the vtable offset would be more than 32.. i'll have to adjust my library.

the prob with multiple inheritance i have is not necciarily the vtable, but non virtual (and maybe virtual function) that are being referenced by a METHOD pointer, as the method pointer's size can change (not just 4 bytes) but actually 8 or 12 and contain offset and other information as per
http://weblogs.asp.net/oldnewthing/archive/2004/02/09/70002.aspx

as for tutoring in inline assembly being a bit confusing..
do you mean thast i put comments describing it inside the comments with the code (which i probably should change to make it more readible. or using inline assembler alltogether (which is purposeful because i'm trying to build a library of functions so that C programmers can use it without having to do any inline assembly at all (other than the ocassional mov eax, ThisClass::thisMethod, mov myptr,eax) sort of thing. and my intended audience is mostly programmers who willl need to understand a little under the hood , but be able to use the techniques - either to make some callback methodology from C, to implement and link together a scripting language, manual RPC technique, or to use madCHook to hook functions (my main intention of doing this all)

thanks again for all the insights though.
Posted on 2004-08-10 18:22:47 by klumsy