Results 1 to 5 of 5
  1. #1
    TrollerCoaster's Avatar
    Join Date
    Sep 2010
    Gender
    male
    Location
    I am a fish
    Posts
    633
    Reputation
    61
    Thanks
    800

    Calling function pointers without definitions

    I've had this huge bug on me for the longest time in C++/C in that you cannot call abstract function pointers without defining the arguments like so:
    Code:
    int (*func)(int arg1,char* fedup,int keeptypingmyarguments);
    Now you should know that good practice is expecting your arguments to always be 4 bytes, since standard x86 architecture pushes 4 bytes at a time on to the stack. The return value should always be 4 bytes too since it is passed in a register that can only hold up to 4 bytes; So why can't C call a function without needing to define all the arguments? We know every argument is going to be 4 bytes!

    Well we're going to break this good practice of 4 byte arguments so we can call abstract function pointers without needing to make a definition.

    I thought about it: You can pass entire structures on the stack in C!
    Entire arrays cannot be passed on the stack (they are converted to a 4 byte pointer), but we can pass structs

    Code:
    struct Passer {
        int args[13]; //52 bytes of argument stack space
        int pos; //Stack position (0 is 1st arg, 1 is 2nd arg, etc.) *Can be a char to save space
    };
    You don't need pos, but I use it when the user is deciding which arguments to pass without having to input the number of arguments or making a definition.

    You can also replace int args[x] with char args[x*4]. I do this so I have access to each byte in the member. If you need to pass an entire integer, just cast it or use memcpy.

    We can now define an abstract function type.
    Code:
    typedef int (*FUNC)(Passer pass);
    FUNC func = ptr_to_func;
    I think any experienced C programmer would know what to do from there.

    Code:
    #include <windows.h>
    struct Passer {
        int args[13];
        int pos;
    };
    typedef int (*FUNC)(Passer pass);
    FUNC func;
    int main() {
        Passer pass;
        func = (FUNC)GetProcAddress(LoadLibrary("kernel32.dll"),"Beep");
        pass.args[0] = 1500;
        pass.args[1] = 500;
        func(pass);
        Sleep(100);
        func({{1500,500}}); //You don't even need to declare a Passer variable, just note the two pairs of {}s
    }
    The reason this works is because C puts the entire structure on the stack in order.

    I hope this helps!

    This trick goes great with my Importing library procedures without any IATs tutorial

  2. #2
    giniyat101's Avatar
    Join Date
    Sep 2011
    Gender
    male
    Location
    Not telling.
    Posts
    1,935
    Reputation
    130
    Thanks
    1,380
    My Mood
    Dead
    @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

    Code:
    1500
    500
    uninitialized 
    uninitialized 
    uninitialized 
    uninitialized 
    uninitialized 
    uninitialized 
    uninitialized 
    uninitialized 
    uninitialized 
    uninitialized 
    uninitialized 
    uninitialized
    when it returns, it pops only first two, leaving those uninitialized ints on stack, which would cause errors.

    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!
    Code:
    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;
    }
    compile it in visual studio

    example:
    Code:
    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);
    }
    hope comments explained everything


     



    [img]https://i43.photobucke*****m/albums/e367/DeteSting/Steam-update.gif[/img]

  3. #3
    TrollerCoaster's Avatar
    Join Date
    Sep 2010
    Gender
    male
    Location
    I am a fish
    Posts
    633
    Reputation
    61
    Thanks
    800
    @giniyat101
    I actually found a much better way in pure C. I might be posting it here
    And it's okay, ASM used to be the only real programming language I knew.

  4. #4
    giniyat101's Avatar
    Join Date
    Sep 2011
    Gender
    male
    Location
    Not telling.
    Posts
    1,935
    Reputation
    130
    Thanks
    1,380
    My Mood
    Dead
    Quote Originally Posted by TrollerCoaster View Post
    @giniyat101
    I actually found a much better way in pure C. I might be posting it here
    And it's okay, ASM used to be the only real programming language I knew.
    it would be cool if you can do it in c
    hope you succeed


     



    [img]https://i43.photobucke*****m/albums/e367/DeteSting/Steam-update.gif[/img]

  5. #5
    egycnq's Avatar
    Join Date
    Sep 2018
    Gender
    male
    Posts
    203
    Reputation
    84
    Thanks
    34
    My Mood
    Amazed
    good info It helps me

Similar Threads

  1. [Solved] Calling Functions With In Classes From Address
    By hwfhwhfwf in forum C++/C Programming
    Replies: 14
    Last Post: 02-14-2012, 11:28 AM
  2. [Help] Function pointer to data?
    By t7ancients in forum C++/C Programming
    Replies: 8
    Last Post: 01-29-2012, 10:37 AM
  3. Call Signs hack~(without using EAM)
    By UnknownHacking in forum Call of Duty Modern Warfare 2 Help
    Replies: 9
    Last Post: 05-04-2010, 02:18 AM
  4. Calling functions?
    By Void in forum C++/C Programming
    Replies: 6
    Last Post: 11-29-2009, 09:34 AM
  5. [Tutorial(C++)]How to call functions within another process
    By radnomguywfq3 in forum Programming Tutorials
    Replies: 4
    Last Post: 07-08-2008, 07:33 PM