Skip to content
MPGHThe Dark Arts
/
RegisterLog in
Forum
Community
What's NewLatest posts across the boardTrendingHottest threads right nowSubscribedThreads you follow
Discussion
GeneralIntroductionsEntertainmentDebate FortFlaming & Rage
Board
News & AnnouncementsMPGH TimesSuggestions & HelpGiveaways
More Sections
Art & Graphic DesignProgrammingHackingCryptocurrency
Hacks & Cheats
Games
ValorantCS2 / CS:GOCall of Duty / WarzoneFortniteApex LegendsEscape From Tarkov
+14 moreLeague of LegendsGTA VMinecraftRustROTMGBattlefieldTroveBattleOnCombat ArmsCrossFireBlackshotRuneScapeDayZDead by Daylight
Resources
Game Hacking TutorialsReverse EngineeringGeneral Game HackingAnti-CheatConsole Game Hacking
Tools
Game Hacking ToolsTrainers & CheatsHack/Release NewsNew
Submit a release →Share your cheat, tool, or config with the community.
AINEW
AI Tools
General & DiscussionPrompt EngineeringLLM JailbreaksHotAI Agents & AutomationLocal / Open Models
AI × Gaming
AI Aimbots & VisionML Anti-CheatGame Bots & Automation
Create
AI Coding / Vibe CodingAI Art & MediaAI Voice & TTS
The AI frontier →Where game hacking meets modern machine learning. Jump in.
Marketplace
Buy & Sell
SellingBuyingTradingUser Services
Trust & Safety
Middleman LoungeMarketplace TalkVouch Copy Profiles
Money
Cryptocurrency TalkCurrency ExchangeWork & Job Offers
Start selling →List accounts, services, and goods. Use the middleman to trade safe.
MPGH The Dark Arts

A community for offensive security research, reverse engineering, and AI.

Community

ForumMarketplaceSearch

Account

RegisterLog in

Legal

Privacy PolicyForum RulesHelp & FAQ
© 2026 MPGH · All rights reserved.Built by the community, for the community. For educational purposes onlyContent is shared for security research and education — we don't condone illegal use. You're responsible for complying with applicable laws. Use at your own risk.
Home › Forum › Programming › Programming Tutorials › Calling function pointers without definitions

Calling function pointers without definitions

Posts 1–5 of 5 · Page 1 of 1
TR
TrollerCoaster
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
#1 · edited 13y ago · 13y ago
giniyat101
giniyat101
@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
#2 · 13y ago
TR
TrollerCoaster
@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.
#3 · 13y ago
giniyat101
giniyat101
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
#4 · 13y ago
egycnq
egycnq
good info It helps me
#5 · 5y ago
Posts 1–5 of 5 · Page 1 of 1

Post a Reply

Similar Threads

  • [Tutorial(C++)]How to call functions within another processBy radnomguywfq3 in Programming Tutorials
    4Last post 18y ago
  • Function pointer to data?By t7ancients in C++/C Programming
    8Last post 14y ago
  • Calling Functions With In Classes From AddressBy hwfhwhfwf in C++/C Programming
    14Last post 14y ago
  • Calling functions?By Void in C++/C Programming
    6Last post 16y ago
  • Call Signs hack~(without using EAM)By UnknownHacking in Call of Duty Modern Warfare 2 Help
    9Last post 16y ago

Tags for this Thread

None