@TrollerCoaster
that was a nice try, but unfortunately, it will fail.
let me explain why.
you tried it on a __stdcall function, where stack is fixed by the callee
now, the ordinary function expects 2 parameters, but you passed 14 of them!
so the stack would look like
when it returns, it pops only first two, leaving those uninitialized ints on stack, which would cause errors.Code:1500 500 uninitialized uninitialized uninitialized uninitialized uninitialized uninitialized uninitialized uninitialized uninitialized uninitialized uninitialized uninitialized
also, if you call a __cdecl function, it will leave everything except one parameter!
and if you try to call __thiscall or __fastcall, you wont be able to modify ecx and edx registers!
anyway i wrote a function that will do the job for you, hope you are good at asm!
compile it in visual studioCode:enum CALLINGCONV { CALLINGONV_STDCALL, CALLINGCONV_CDECL, CALLINGCONV_THISCALL, CALLINGCONV_FASTCALL, }; int callsomething(void* func, CALLINGCONV cc, int* args, unsigned int count) { int retval; if (cc == CALLINGCONV_THISCALL && count < 1) return 0; //__thiscall function must have at least one parameter (this pointer) __asm { push ecx; //save original values push esi; push edi; push eax; //calculate stack size mov eax, 4; mov ecx, count; mul ecx; mov ecx, eax; pop eax; sub esp, ecx; //put parameters on stack mov esi, args; mov edi, esp; rep movs [edi], byte ptr [esi]; cmp cc, CALLINGCONV_THISCALL; //check if calling convention was __thiscall jne not_thiscall; pop ecx; //remove first parameter from stack and put it on ecx not_thiscall: cmp cc, CALLINGCONV_FASTCALL; //check if calling convention was __fastcall jne neither; mov esi, count; //check parameter count cmp esi, 1; //make sure we have 1 parameters or more jl neither; pop ecx; //remove first parameter from stack and put it on ecx mov esi, count; //check parameter count cmp esi, 2; //make sure we have 1 parameters or more jl neither; pop edx; //remove second parameter from stack and put it on edx neither: call func; //lets call the function mov retval, eax; //save return value cmp cc, CALLINGCONV_CDECL; //if calling convention was __cdecl, perform a stack clean up jne not_cdecl; push eax; mov eax, 4; mov ecx, count; mul ecx; mov ecx, eax; pop eax; add esp, ecx; not_cdecl: pop edi; //restore original values pop esi; pop ecx; } return retval; }
example:
hope comments explained everythingCode:void hey(int arg1, int arg2, int arg3, int arg4) //default calling convention is __cdecl { cout << arg1 << ", " << arg2 << ", " << arg3 << ", " << arg4 << endl; } void __fastcall hey2(int arg1, int arg2, int arg3, int arg4) { cout << arg1 << ", " << arg2 << ", " << arg3 << ", " << arg4 << endl; } class myclass { public: int arg1; void hey3(int arg2, int arg3, int arg4) //this one should be __thiscall { cout << arg1 << ", " << arg2 << ", " << arg3 << ", " << arg4 << endl; } }; //you cant convert &myclass::hey3 to void*, so i came up with this trick.. struct hack { typedef void (myclass::*myfunc)(int,int,int); myfunc pp; }; int main() { FARPROC func = GetProcAddress(LoadLibraryA("kernel32.dll"), "Beep"); myclass my; my.arg1 = 5; hack hk; hk.pp = &myclass::hey3; int beeparg[2] = {1500, 500}; int myargs[4] = {5, 10, 51, 11}; int thisargs[4] = {(int)&my, 10, 51, 11}; callsomething((void*)func, CALLINGONV_STDCALL, beeparg, 2); callsomething((void*)hey, CALLINGCONV_CDECL, myargs, 4); callsomething((void*)hey2, CALLINGCONV_FASTCALL, myargs, 4); callsomething((void*)(*(int*)(&hk)), CALLINGCONV_THISCALL, thisargs, 4); }![]()


General





Reply With Quote




