FunctionInterception icon indicating copy to clipboard operation
FunctionInterception copied to clipboard

Overwrite C/C++ functions in memory for x86-32/64 on Linux, Mac & Windows

Function interception and detours that work on Windows, Linux, and MacOS.

Hook into method calls and change what they do, re-call the original function, all at runtime.
No modifyig of the binary, overwrites the code-segment directly in RAM.
This way, the MD5-checksum of the file stays the same.

There are the preprocessor-functions HOTPATCH, UNPATCH and NATURALIZE.

Hotpatch is just a convenience function for TemplateFuncInterceptFunction which calls InterceptFunction. Hotpatch requires you have a backup function pointer with name original_##FUNCTION_NAME defined and a function modified_##FUNCTION_NAME, which is the function you are overwriting ##FUNCTION_NAME with.

UNPATCH is just a convenience preprocessor-function-definition for unpatchfunc.

NATURALIZE is a preprocessor defined function which assigns a function in the code segment to a function pointer based on the function's address.

The target function RE_RenderScene, and the backup and naturalization pointers:

extern "C" 
{

	

	//void __cdecl RE_RenderScene()
	void RE_RenderScene()
	{
		printf("This is the original RE_RenderScene\n");
	}


	// void(__cdecl  *original_RE_RenderScene)(); // = &RE_RenderScene;
	void(*original_RE_RenderScene)(); // = &RE_RenderScene;


	// void(__cdecl  *Naturalized_RE_RenderScene)(); // = &RE_RenderScene;
	void(*Naturalized_RE_RenderScene)(); // = &RE_RenderScene;
	

	//void __cdecl modified_RE_RenderScene()
	void __cdecl modified_RE_RenderScene()
	{
		printf("Entering the modified RenderScene\n");

		printf("Calling the original RenderScene in the modified RenderScene\n");
		printf("Address of RE_RenderScene: %p\n", &RE_RenderScene);
		printf("Address of original_RE_RenderScene: %p\n", *original_RE_RenderScene);
		printf("Address of original_RE_RenderScene: %p\n", original_RE_RenderScene);
		// (*original_RE_RenderScene)();
		
		printf("Finished calling the original RenderScene in the modified RenderScene\n");

		printf("Exiting modified RenderScene\n");
	}

	
}

Then you can call it in code:

//#define RE_RenderScene_COPY 9 // Visual Studio 2015
#define RE_RenderScene_COPY 9 // Visual Studio 2013
// #define RE_RenderScene_COPY 6 // g++

// int _tmain(int argc, _TCHAR* argv[])
int main(int argc, char* argv[])
{
	printf("Sizeof address: %d bit\n", sizeof(void*) * 8);
	printf("Address of %s: 0x%08p\n", "RE_RenderScene", &RE_RenderScene);
	printf("Address of %s: 0x%08x\n", "RE_RenderScene", &RE_RenderScene);
	printf("===================================================\n");
	

	unsigned char* memoryDumpPointer = (unsigned char*)&RE_RenderScene;
	int i;
	for (i = 0; i < 100; ++i)
	{
		printf("0x%02X\n", memoryDumpPointer[i]);
	}


	if (true)
	{
		RE_RenderScene(); // Calling original version
		
		printf("\n\n====================== Naturalizing =============================\n");
		NATURALIZE(RE_RenderScene);
		// Expands to 
		// Naturalized_RE_RenderScene = FuncConvertAddress(Naturalized_RE_RenderScene, reinterpret_cast<unsigned long>  (&RE_RenderScene));
		printf("====================== Naturalized ==============================\n\n");
		
		(*Naturalized_RE_RenderScene)();


		printf("\n\n====================== Hotpatching =============================\n");
		// HOTPATCH(RE_RenderScene);
		/////// Expands to
		/////// InterceptFunction(&RE_RenderScene, RE_RenderScene_COPY, &modified_RE_RenderScene);
		/////// original_RE_RenderScene = FuncInterceptFunction(RE_RenderScene, modified_RE_RenderScene);

		// Overwriting the RE_RenderScene function (JMP REL32 = 0xE9)
		original_RE_RenderScene = TemplateFuncInterceptFunction(
			original_RE_RenderScene,
			reinterpret_cast<unsigned long> (&RE_RenderScene),
			reinterpret_cast<unsigned long> (&modified_RE_RenderScene),
			static_cast<unsigned long> (RE_RenderScene_COPY)
		);

		printf("====================== Hotpatched ==============================\n\n");
		
		RE_RenderScene(); // Calling the modified version
		// Second time works as well
		RE_RenderScene();


		printf("\n\n====================== Unpatching =============================\n");
		UNPATCH(RE_RenderScene); // Undoing modification
		printf("====================== Unpatched ==============================\n");
		// BUG shows here
		RE_RenderScene();
	}


	printf("\n\n\n--- Press any key to continue --- \n");
	WaitChar();
	return EXIT_SUCCESS;
}