Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Emulating Windows __thiscall in C

Name: Anonymous 2010-09-26 3:48

Does anyone know to call a __thiscall function from C code? It's not a problem of garbled symbols (I have its address), it's a problem of passing this pointer in ecx. I thought declaring function as __stdcall and storing stuff in ecx with assembly magic would work, like this:
    __asm { mov ecx,self }
    res=sub(a2,a3,a4,a5,a6,a7);


But code generated by visual studio overwrites ecx:
dinput8.dll:66551153 mov     ecx, [esp+10h] # my code
dinput8.dll:66551157 mov     ecx, [esp+120h] # automatically generated by msvcs, thanks a lot
dinput8.dll:6655115E mov     edx, [esp+11Ch]
dinput8.dll:66551165 push    esi
dinput8.dll:66551166 push    edi
dinput8.dll:66551167 push    ebx
dinput8.dll:66551168 push    ebp
dinput8.dll:66551169 push    ecx
dinput8.dll:6655116A push    edx
dinput8.dll:6655116B call    off_66553344


Any ideas? I'd even be fine with writing some fake C++ class and calling its method, but unfortunately you can't specify an address of method of class when calling it...

Name: Anonymous 2010-09-26 3:56

Probably not doable properly without compiler support. __usercall(eax) would be nice to have (a certain decompiler has support for custom calling conventions like that). fastcall also works by putting things in registers, but that's not exactly what you need. If hacking the compiler or using some other compiler or frontend for it is not acceptable, you can probably do with some nasty C macros and more detailed __asm code.

Name: Anonymous 2010-09-26 4:44

Heh, I figured it out. Instead of setting ecx before the call to __thiscall function, I'm just calling some proxy function, setting ecx in it, eliminating changes it made to stack, and jumping to desired address. This still needs a bit more work (not storing this in global variables for thread safety, restoring stack properly instead of just pop ebx), but it's working and with almost no hacking. Here's working code for your enjoyment and enlightenment:

int globalself;
#define CAT2(a,b) a##b
#define CAT(a,b) CAT2(a,b)
#define DECLARE_THISCALL_CALLER(type,func,args) \
    type (__stdcall *func) args; \
    type __stdcall CAT(func,_caller) args { \
        __asm{ pop ebp }; \
        __asm{ mov ecx,globalself }; \
        __asm{ jmp func }; \
    } \

#define THISCALL(res,self,func,args) do{ \
    __asm { mov eax,self } \
    __asm { mov globalself,eax } \
    res=CAT(func,_caller) args; \
} while(0);

DECLARE_THISCALL_CALLER(signed int,subGylphsOriginal,(int,int,int,int,int,int));
signed int __stdcall subGylphs(int a2, int a3, int a4, int a5, int a6, int a7){
    char s[0x100];
    int self,res;

    __asm { mov self,ecx }

    sprintf(s,"%d %d %d %d %d %d",a2,a3,a4,a5,a6,a7);
    MessageBox(NULL,s,"",0);

    THISCALL(res,self,subGylphsOriginal,(a2,a3,a4,a5,a6,a7));

    return res;
}


Doing this low-level tinkering with programs is so self-fulfilling. I never felt so good in some long time.

Name: Anonymous 2010-09-26 5:12

It took you less then an hour.  I admire your quickness of thought.

Name: Anonymous 2010-09-26 5:28

>>4
Er, is this supposed to be an insult? Maybe I was doing something else at this time, or didn't post immediately after discovering this method and just went about using it for my greasy purposes instead?

Anyway, I'm struggling to eliminate that pop ebp now. From what I understand, what I popping from stack is a frame pointer (compiler generates push ebp; mov ebp, esp), so if someone enables the eliminate frame pointer optimization, it will all break, since I'll be popping something important off stack. What's strange though, is that neither __pragma(optimize( "y", off )), nor disabling frame pointer globally are removing this push ebp.

Name: 4さん 2010-09-26 5:52

>>5
No, I was completely honest, though it surprised myself that I had to be.  I wish you success in your noble quest to conjure the spirits of the x86 stack machine.

Name: 2 2010-09-26 6:34

>>5
So you just want to make a stdcall or  cdecl(but not fastcall) convertor to thiscall?

Here's my quick attempt at it:

push ...
push ...
call thiscall_func
->
push ...
push ...
call your_stub_for_thiscall_func


your_stub_for_thiscall_func:
add esp,4
pop ecx
push dword ptr ss:[esp-8]
jmp thiscall_func

My stdcall/cdecl->thiscall convertor approach is clean in that it doesn't really use any extra registers or extra stack space.

Name: Anonymous 2010-09-26 8:57

>>7
It's not clean in a way that you have to write a lot of boilerplate code pushing your args onto stack, while my solution allows you to use argument lists and compiler will generate all the pushing for you. Since I'm planning to use this a lot to aid myself in researching/debugging programs I didn't write, ease of use is top priority for me.

Name: Anonymous 2010-09-26 10:56

It's fun implementing stuff like this yourself (I've written something similar before), but I'm pretty sure it's been done before.

http://www.haible.de/bruno/packages-ffcall-README.html
http://sourceware.org/libffi/

Name: Anonymous 2010-09-26 14:14

int globalself;
Kill yourself.

Name: Anonymous 2010-09-26 20:53

__asm
{
mov ecx,dword ptr ds:[some_class_ptr_on_the_heap]
call niggers
}

Name: Anonymous 2010-09-27 7:56

>>11
Fascinating. I wanted compiler to generate code that will push args to stack for mew though.

>>10
Are you from SICP/haskell, C, or HMA spammers camp?

Name: Representative of the C Camp 2010-09-27 18:48

>>12
What wrong with us, yo?

Name: Anonymous 2010-10-01 1:58

>>13
I just wanted to know who sent this asshole.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List