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 › C++/C Programming › C/C++ Polymorphic Code (Encrypt/Decrypt Functions & Memory At Runtime)

C/C++ Polymorphic Code (Encrypt/Decrypt Functions & Memory At Runtime)

Posts 1–15 of 31 · Page 1 of 3
nullptr_t
nullptr_t
C/C++ Polymorphic Code (Encrypt/Decrypt Functions & Memory At Runtime)
In this Tutorial/Source Code Release I attempt to give you an introduction to self modifying / polymorphic code.
 
Will It Help To Prevent VAC From Detecting My Hacks?
There is no guarantee that this prevent anti-cheats from detecting your hacks, but nevertheless it can help.
Tested on MSVC 2015.

Our Dummy Function For Testing:
Code:
// Our testfunction that we are going to encrypt
void TestFunction()
{
	MessageBox(0, L"Hello From Testfunction!", L"Test", 0);
}
// Marks the end of testfunction()
void FunctionStub() { return; }
There is no official way of getting a size of a function in memory, but it can be done by subtracting the size of a stub function
from the original one. This requires the functions to be placed next to each other (as in code) by the compiler in the object
file when the program is built.

In order to achieve this, first do not place any code in between the two procedures, next disable all compiler optimizations
and last disable DEP (Data Execution Prevention) from advanced linker options (/NXCOMPAT:NO).



Now let's write our XOR Function (in inline asm)
Code:
void XorBlock(DWORD dwStartAddress, DWORD dwSize)
{
    __asm
	{
        push eax
        push ecx
        mov ecx, dwStartAddress          // Move Start Address to ECX
        add ecx, dwSize                  // Add the size of the function to ECX
        mov eax, dwStartAddress          // Copy the Start Address to EAX

        crypt_loop:                         // Start of the loop
            xor byte ptr ds:[eax], 0x4D     // XOR The current byte with 0x4D
            inc eax                         // Increment EAX with dwStartAddress++
            cmp eax,ecx                     // Check if every byte is XORed
        jl crypt_loop;                      // Else jump back to the start label

        pop ecx // pop ECX from stack
        pop eax // pop EAX from stack
    }
}
Next we'll write our function to get the size of a certain function:
Code:
DWORD GetFuncSize(DWORD* Function, DWORD* StubFunction)
{
	DWORD dwFunctionSize = 0, dwOldProtect;
	DWORD *fnA = NULL, *fnB = NULL;

	fnA = (DWORD *)Function;
	fnB = (DWORD *)StubFunction;
	dwFunctionSize = (fnB - fnA);
	VirtualProtect(fnA, dwFunctionSize, PAGE_EXECUTE_READWRITE, &dwOldProtect); // Need to modify our privileges to the memory
	return dwFunctionSize;
}
Memory Hex Dumper (just to see the differences):
(credits to domnikl for: C function to dump memory)

Code:
void HexDumpMemory(void *addr, int len)
{
	int i;
	unsigned char buff[17];
	unsigned char *pc = (unsigned char*)addr;

	// Process every byte in the data.
	for (i = 0; i < len; i++) {
		// Multiple of 16 means new line (with line offset).

		if ((i % 16) == 0) {
			// Just don't print ASCII for the zeroth line.
			if (i != 0)
				printf("  %s\n", buff);

			// Output the offset.
			printf("  %04X ", i);
		}

		// Now the hex code for the specific character.
		printf(" %02X", pc[i]);
		// And store a printable ASCII character for later.
		if ((pc[i] < 0x20) || (pc[i] > 0x7e)) {
			buff[i % 16] = '.';
		}
		else {
			buff[i % 16] = pc[i];
		}

		buff[(i % 16) + 1] = '\0';
	}

	// Pad out last line if not exactly 16 characters.
	while ((i % 16) != 0) {
		printf("   ");
		i++;
	}

	// And print the final ASCII bit.
	printf("  %s\n", buff);
}
And lastly a little test:
Code:
int main()
{
	DWORD dwFuncSize = GetFuncSize((DWORD*)&TestFunction, (DWORD*)&FunctionStub);
	
	printf("\n\nEncrypted:\n");
	XorBlock((DWORD)&TestFunction, dwFuncSize); // XOR encrypt the function
	HexDumpMemory(&TestFunction, dwFuncSize);

	//TestFunction(); // If you try to run the encrypted function you will get Access Violation Exception.

	printf("\n\nDecrypted:\n");
	XorBlock((DWORD)&TestFunction, dwFuncSize); // XOR decrypt the function   
	HexDumpMemory(&TestFunction, dwFuncSize);

	TestFunction(); // Fine here

	getchar();
    return 0;
}

Q: How to use this to (potentially) prevent from VAC detecting my cheats?
A: Encrypt each function of your cheat at main() and when needed, just decrypt the function
and after used just encrypt it again.
#1 · 10y ago
Hitokiri~
Hitokiri~
This by definition, isn't actually polymorphic code.
Basically you're encrypting/decrypting your function block as needed.
Polymorphic code would mutate the entire program's binary on the hard disk, thus changing the entire signature each time it's run.

Another note:
That method of determining the function size only works with optimizations disabled. A compiler wouldn't necessary put two consecutive functions right next to each other. A better and more reliable method I've found was:

- Using an opcode disassembler to determine the length of each instruction.
- Iterate over each instruction of the function till you encounter an interrupt ( 0xCC ) as functions are almost always aligned using these.

So:
Code:
std::int32_t GetFunctionLength( void* addr ){
    auto _addr = PCHAR( addr );
    auto sz = 0ul;

    // Make sure this is actually a valid address
    while( _addr && *PWORD( _addr ) != 0xCCCC ){
        // Calculate the size of the instruction
        auto tmp = OpDisassemble( _addr ).GetLength();

        // Size of INT3 is 1 byte. If the following byte is also 0xCC with a size of 1 also, chances are, we've reached the end of the function.
        if( tmp == 1 && OpDisassemble( _addr + 1 ).GetLength() == 1 && *PWORD( _addr ) = 0xCCCC )
            break;

        // Iterate past
        sz += tmp;
        _addr += tmp;
    }
    return sz;
}
While this is not a perfect method, it's better than simply "hoping" the compiler would align your stub right next to your target function.
#2 · 10y ago
UC
UCantCMe
Very cool.
#3 · 10y ago
nullptr_t
nullptr_t
Quote Originally Posted by Hitokiri~ View Post
This by definition, isn't actually polymorphic code.
Basically you're encrypting/decrypting your function block as needed.
Polymorphic code would mutate the entire program's binary on the hard disk, thus changing the entire signature each time it's run.

Another note:
That method of determining the function size only works with optimizations disabled. A compiler wouldn't necessary put two consecutive functions right next to each other. A better and more reliable method I've found was:

- Using an opcode disassembler to determine the length of each instruction.
- Iterate over each instruction of the function till you encounter an interrupt ( 0xCC ) as functions are almost always aligned using these.

So:
Code:
std::int32_t GetFunctionLength( void* addr ){
    auto _addr = PCHAR( addr );
    auto sz = 0ul;

    // Make sure this is actually a valid address
    while( _addr && *PWORD( _addr ) != 0xCCCC ){
        // Calculate the size of the instruction
        auto tmp = OpDisassemble( _addr ).GetLength();

        // Size of INT3 is 1 byte. If the following byte is also 0xCC with a size of 1 also, chances are, we've reached the end of the function.
        if( tmp == 1 && OpDisassemble( _addr + 1 ).GetLength() == 1 && *PWORD( _addr ) = 0xCCCC )
            break;

        // Iterate past
        sz += tmp;
        _addr += tmp;
    }
    return sz;
}
While this is not a perfect method, it's better than simply "hoping" the compiler would align your stub right next to your target function.
Thanks for the alternative method! You left out the disassembler function though.
#4 · edited 10y ago · 10y ago
Hitokiri~
Hitokiri~
Quote Originally Posted by nullptr_t View Post
Thanks for the alternative method! You left out the disassembler function though.
Check out BeaEngine. It has the ability to decode both x86 and x64 instructions.
#5 · 10y ago
__
__readgsqword
@nullptr_t

As Hitokiri~ pointed out, this is not polymorphic code, it's just encryption and decryption. As for your method of receiving the function size , you could write the target function in assembly yourself, so you know every instruction you placed. Then if you wanted to calculate the length of that specific function you could just write another function to do it, like search for the ret instruction. It would only be useful for your own function that you wrote, but honestly most functions are gaurunteed to have a single ret instruction at the bottom.

The other thing you should note is because of ASLR if you tried to move the code elsewhere, the address to messagebox would be invalid and potentially crash. This is the case with all shellcode. You can solve this by resolving addresses at runtime or writing strictly Position Independent Code.
@Hitokiri~

Your method of receiving the function size is just as undefined as nullptr_t's. Yes most of the time the compiler will align functions by using int3, but the chances of that happening is just as likely as the compiler place functions together. As long as the stub function is inlined assembly with a single ret or nop, nullptr_t can ensure the compiler will not emit or omit any extra instructions.

Regardless this is always undefined behavior and using a length disassembler engine is the best way to go.

Still I would avoid any encryption or decryption functions, a real polymorphic engine would be more suitable to evade code signatures.
#6 · 10y ago
nullptr_t
nullptr_t
Quote Originally Posted by Hitokiri~ View Post

Check out BeaEngine. It has the ability to decode both x86 and x64 instructions.
Alright, thanks for that aswell!
#7 · 10y ago
LY
LyanR
I appreciate that you are trying to teach people something, but I have to be honest:

1) The title is wrong
Like Hitokiri~ said, it has nothing to do with polymorphism!

2) Everything you did is completely over-complicated.
We are in C/C++ section. Even though the inline-asm function is very easy and even beginners could write it, for someone who never programmed in asm not completely understandable. You could write the same function easily in C and since there are no differences I call it overcomplicated in the matter of this tutorial.


Sorry, but this looks so much like someone who just learned something and feels OP and needs to post it to get some attention - especially with that misplaced title.
#8 · edited 10y ago · 10y ago
FA
FatAssHacker123
Quote Originally Posted by LyanR View Post
I appreciate that you are trying to teach people something, but I have to be honest:

1) The title is wrong
Like Hitokiri~ said, it has nothing to do with polymorphism!

2) Everything you did is completely over-complicated.
We are in C/C++ section. Even though the inline-asm function is very easy and even beginners could write it, for someone who never programmed in asm not completely understandable. You could write the same function easily in C and since there are no differences I call it overcomplicated in the matter of this tutorial.


Sorry, but this looks so much like someone who just learned something and feels OP and needs to post it to get some attention - especially with that misplaced title.
Do you know that using Asm is probably the simplest way to access memory directly? It works directly with hardware, no "middlemen" involved. It's not over complicating especially when even a beginner could write it, as you said.
#9 · edited 10y ago · 10y ago
WA
WasserEsser
Quote Originally Posted by FatAssHacker123 View Post


Do you know that using Asm is probably the simplest way to access memory directly? It works directly with hardware, no "middlemen" involved. It's not over complicating especially when even a beginner could write it, as you said.
C / C++ is not the place to post this in if he ain't using the language.

- - - Updated - - -

Quote Originally Posted by FatAssHacker123 View Post


Do you know that using Asm is probably the simplest way to access memory directly? It works directly with hardware, no "middlemen" involved. It's not over complicating especially when even a beginner could write it, as you said.
And how is a middlemen involved in C++ ? It's directly translated into assembly at compile time.
The generated assembly will access memory the exact same way.
#10 · edited 10y ago · 10y ago
_NightWare
_NightWare
Quote Originally Posted by WasserEsser View Post
And how is a middlemen involved in C++ ? It's directly translated into assembly at compile time.
The generated assembly will access memory the exact same way.
Or C?
C is known for being so 'close' to the hardware (thus why linux is made with it)
#11 · 10y ago
WA
WasserEsser
Quote Originally Posted by _NightWare View Post

Or C?
C is known for being so 'close' to the hardware (thus why linux is made with it)
C will access the memory the same way.
#12 · 10y ago
JA
javalover
Quote Originally Posted by _NightWare View Post
C is known for being so 'close' to the hardware (thus why linux is made with it)
This is wrong. C++ accesses your underlying machine memory/hardware as C, because the first one, C++, adds just some OO peculiarities/features, such as more abstractions (eg. cin/cout). The reason the creator chooses C instead of C++ is because Linux is affected/inspired to MINIX, another unix like operating system. Another prove of this is that Windows was created in C++.
#13 · 10y ago
_NightWare
_NightWare
Quote Originally Posted by javalover View Post
This is wrong. C++ accesses your underlying machine memory/hardware as C, because the first one, C++, adds just some OO peculiarities/features, such as more abstractions (eg. cin/cout). The reason the creator chooses C instead of C++ is because Linux is affected/inspired to MINIX, another unix like operating system. Another prove of this is that Windows was created in C++.
So, because someone made something using C, he did too?
That's like the story 'you wouldn't jump in the river because someone else does it?'
linux > windows, I don't see how that's related or proofs anything though.

I appreciate the thought, really I do. I like to learn things from different perspectives
And you're definitely right that c++ brings a lot of tools + supports ObjectOrientedProgramming
#14 · 10y ago
JA
javalover
@_NightWare the affermation of the proof Windows that is made in C++ obviously has a nexus -> if Windows uses C++, it must surely be able to access hardware directly as C.

So, because someone made something using C, he did too?
That's like the story 'you wouldn't jump in the river because someone else does it?'
Everyone should know Linux is heavily inspired from MINIX for its design principles and some functionalities. However, some functionalities are inherited from MINIX because Torvalds developed Linux when he was using MINIX. There are some posts of Torvalds where he says why he hates C++, so the reasons because he used C instead of C++ may be one of these:

1. he hates C++ and he is inspired to MINIX because...
2. he hates C++.
3. he is inspired to MINIX because...

Probably in part yes, in part no. We do not know and we can't determine for which preferences he used C, also if he states in his website C++ is crap. We can probably just try to guess as alternative of asking him what he was thinking about in that moment.

linux > windows
I completely disagree. Both Linux and Windows may be good and bad, depending on the user's workstation.

- - - Updated - - -

tanenbaum (minix creator) also accused torvalds to have copied some of his lines of code, which is probable.
#15 · 10y ago
Posts 1–15 of 31 · Page 1 of 3

Post a Reply

Similar Threads

  • C/C++ Encrypt/Decrypt Functions & Memory At RuntimeBy nullptr_t in Counter-Strike 2 Coding & Resources
    38Last post 9y ago
  • Encrypt/Decrypt FunctionsBy CodeDemon in Combat Arms Hack Coding / Programming / Source Code
    7Last post 16y ago
  • Mods Encrypt/Decrypt???By SPA777174 in Call of Duty Modern Warfare 2 Help
    0Last post 16y ago
  • [TUT]Basic Encrypter\DecrypterBy Bombsaway707 in Visual Basic Programming
    30Last post 16y ago
  • Encrypt/Decrypt vb.Net?By o0OpurezO0o in Visual Basic Programming
    24Last post 15y ago

Tags for this Thread

None