Tutorial Junk Code Generator and Polymorphic Code Engine Guide

Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat

Rake

Cesspool Admin
Administrator
Jan 21, 2014
12,380
78,998
2,414
Game Name
N/A
Anticheat
N/A
How long you been coding/hacking?
N/A
Coding Language
N/A
Junk code and Polymorphic code are both methods used to bypass hash based and signature based detection of your hacks by anticheats.

There are 2 important posts directly below this one from @mambda and @Liduen which contain actual source code for polymorpism



This is a guide to help you understand junk code / polymorphic engines. I do not know how to make one, but here is everything I know about the topic to get you started. At the bottom you will find from mambda c5 and Liduen who have provided source code on this topic. If you're not an experienced coder/hacker, read the tutorial but don't expect that you'll be able to actually do this anytime soon.

Adding junk code will not bypass signature detection

Prerequisites:
Please learn how pattern scanning / signature based detection works by doing this tutorial:

Please learn about anticheat by reading our AntiCheat Guide
and our Valve Anticheat Guide for more general anticheat info

What is junk code?
Junk code is when you add code to your project that has no effect on the functionality of your project but will result in new assembly code in the binary after you compile.

Why would I want to add junk code?
Adding junk code to a project will change the file hash and hash of the code sections of the binary. Anticheats can make hashes of code sections to identify your hacks.

What is a hash?
Hashing algorithms take data and make unique hashes to identify this data, that is substantially smaller than the actual data size making identifying the data faster. For simple file hashes in the past CRC and mad5 have been used but SHA2 is the standard right now. To make a SHA256 hash is very simple you can just do

C++:
#include "sha256.h"
std::string input = "data";
std::string hash = sha256(input);
You can easily modify this to hash a section of memory.

How to add junk code to my project?
You add code that essentially does nothing important. You must disable optimization as the compiler will know the code isn't important and remove it.

Limitations of junk code
Junk code essentially changes the file hash and the hash of the code sections that contain it. It does not defeat signature detection, which utilizes pattern scanning to compare every byte in memory against the signature you have built to identify that binary.

Note that if an anticheat is detecting you based on file hash and section hash, you can add junk code and your hack may no longer be detected. But they then can hash your new hack and detect it again. It's only a temporary solution.

Adding a few pieces of junk code will not bypass signature detection

The solution to these limitations is to use polymorphic code.

What is polymorphic code?
Polymorphic code changes the assembly of your binary every time it's loaded into memory. Or perhaps it only needs to be done on a per-user basis, for example if you're distributing a pay hack. Or perhaps you only want to polymorph it every couple of days/weeks to keep anticheat off your ass.

High tech malware often uses polymorphic code to bypass antivirus but more often you see the usage of Crypters that obfuscate the assembly on disk, but when it is loaded into memory it's usually the same. That is why antivirus scans memory and files on disk.

Polymorphic code defeats signature based detection of your CODE. Things like strings, PDB location or other parts of DATA sections can still be used in signature scanning.
Your poly implementation must change almost every byte of code, I would say every 5 bytes at a minimum. When you make hacks using pattern scanning you will see the average pattern size is maybe 10 bytes and some of them are wildcards. You do not know what bytes the anticheat is using to identify your hacks so you must over do it.

Who needs to use polymorphic code?
Pay cheat providers. No one else needs to use this. Anticheat developers do not have time to build signatures for every single cheat out there but they do build signatures for paid cheats that do not have protection. They'd have to flag your code as suspicious and send it to their team for analysis. Obviously they build sigs for all the public hacks you can download, if you wrote a polymorphic loader you could technically polymorph a detected hack and make it undetected as long as code signature was the only method they use for identification.

There are much easier ways to bypass anticheat, you can simply patch or hide from most.

Examples of Polymorphing code as could be created with a Junk Code Generator

Let's say the anticheat built a signature for this assembly:
C++:
mov ecx, 5
sub  ecx, 5
add ecx, 5
Here are some examples of what a polymorphed version might look like

C++:
mov ecx, 5
push eax
pop eax
sub  ecx, 5
add eax, 5
sub eax, 5
add ecx, 5
C++:
nop
mov ecx, 5
nop
sub  ecx, 5
nop
add ecx, 5
nop
C++:
push edx
mov edx, 5
mov ecx, edx
pop edx
sub  ecx, 2
sub ecx, 3
push edx
mov edx, 5
add ecx, edx
pop edx
Notice the outcome of the instructions is identical, but the signatures won't match. The only thing limiting methods of polymorphism is your imagination, the secret is to do it with the least number of additional instructions, so your code is still efficient. My personal favorite is the NOP in between every byte, would be simple to implement and funny. Ideally you would not modify the number of instructions. If your polymorph engine adds bytes rather than replacing bytes, you must resolve all relative and hard coded addresses. It is much easier to modify the assembly without adding additional bytes.

Also if you make a payhack you would want to use several different algorithms, as heuristics could easily detect just one variant. Again tho, there are much easier ways to bypass anticheat then polymorphism.

So how do you polymorph your hack? Here are some techniques

At compile time using a modified compiler
Like Chris Domas who wrote his own compiler that only uses the MOV instruction

When you compile your project a bunch of .obj object files are made, you could use some method to polymorph them during the linking stage of compilation

At runtime or Before injection
Make your hack.exe read hack.exe from disk, polymorph it, write it to disk and then run it
Make your injector.exe polymorph hack.dll, write it to disk then inject it

During Manual Mapping
modify the assembly during your manual mapping routine, if you don't know what that is, here is our guide on manual mapping:

There are 2 more polymorphic posts below this one:
mambda's and Liduen's

Attached is a PDF which contains some "equivalent assembly instructions"
 

Attachments

Last edited:

mambda

headass
Escobar Tier VIP
Trump Tier Donator
Jun 25, 2014
2,305
37,938
270
Sup, decided I might as well release something, this is an old release i've done on UC so some of you may have seen it.
It's a small polymorphic engine base i wrote with a friend, this was when it was in its early development so quite a few things weren't done, feel free to upgrade the code, change the code, or just learn from it.

I won't really provide too much support for it because this is like some months old, and its only a few source files so it should be tooooo hard to understand.

I don't think i need to virus scan source files but here you go
https://www.virustotal.com/en/file/...528547aa9518ba202bf786aecb253d1c355/analysis/

Pic :


Download: attached.

Thought i might add some more information: At this stage it mutates MOVs and PUSHs to some variants, i.e. mov eax, reg can become xor eax, eax; or eax, reg.

Stuff like that.

The updated ( and private, sorry dewds ) version does some more advanced things to get the actual opcode length instead of hardcoding it like this, for more information about x86 opcode encoding you can go here: https://www.intel.com/content/dam/w...r-instruction-set-reference-manual-325383.pdf

or somewhere like that.

Enjoy
 

Attachments

Last edited:

Liduen

Hacker
Dank Tier VIP
May 19, 2013
702
8,478
33
Hi guys,
it's been a while since my last contribution so here is what I've been working on!


Module protection using a polymorphic Junk Code Generator




First of all the algorythm used in this example was written down pretty quickly and only stands as a proof of concept.
Certainly it can be improved and it would be cool if you share your thoughts about it.
But now it's time for me to give something back to the community. If you spot any mistakes tell me! :)



General information

AntiCheat software often uses pattern scanning in order to detect hacks.
When you inject your dll into the target process, the module gets loaded into memory and pretty much anybody can access it now.
Most likely the AntiCheat system will do so.
Without any protection concepts your compiled code/module can get identified easily.
A single byte pattern would suffice in order to identify your hack as a unique module.
And if the AntiCheat system figures out that you're cheating, boom you get banned.

This post isn't about making your hack "undetectable", it isn't even about preventing a ban due to what you are doing. It's about preventing a ban due to what your hack looks like in memory.
This concept even enables you to make detected hacks / public sources undetected again.
So what can we do about protecting our module from being identified?
A part of the answer might be a protection based on polymorphic junk code.



How its done

The principle itself should be really easy to understand.
You define a specific inline assembler macro which emits a unique sequence of bytes into your code at compiletime.
Later on during runtime you can scan your own module for that unique byte pattern and substitute it with something random.
That is where we need a junk code generator. The generated code shouldn't do anything or will never be executed.
It'll just be sitting there in memory, living a lonely life and protecting your module. :(
The inline assembler macro can look something like the following:
C++:
// Thanks to till0sch for the syntax
#define $$$ __asm      \
{                      \
    __asm pushfd      \
    __asm pushad      \
    __asm xor eax, eax\
    __asm xor eax, eax\
    __asm xor ebx, ebx\
    __asm xor eax, eax\
    __asm xor eax, eax\
    __asm popad          \
    __asm popfd          \
}
It has to be long enough to create a byte pattern which is unique and won't cause false positives when scanning for it, but it shouldn't be too long because this protection method causes your module to heavily grow in size.
It is also important that this inline macro doesn't modify the values stored in the registers or flags otherwise it would cause your program to crash.
Of course you can avoid that by morphing your module right at the beginning without calling anything else first, but that way you won't be able to morph the code which handles the morphing. More on that in the conclusion.
So be creative! :)



Writing the code

In order to write a class out of this it is also handy to note down the opcodes for a relative jump, a no operation opcode and their length in bytes. We'll need these later on when generating our junk code.
What we'll also need is the size of our unique pattern in bytes, the byte pattern itself and its mask.
C++:
// assembler opcode defines for inline asm
#define ASM_OPCODE_JMP_REL        0xEB
#define ASM_OPCODE_NOP            0x90
// size of the full assembler instruction in bytes
#define ASM_INSTR_SIZE_JMP_REL    0x2
#define ASM_INSTR_SIZE_PUSH        0x1
#define ASM_INSTR_SIZE_NOP        0x1
// length of your pattern in bytes
#define MARKER_SIZE 14
// the pattern of the marker and its mask
#define MARKER_BYTES "\x9C\x60\x33\xC0\x33\xC0\x33\xDB\x33\xC0\x33\xC0\x61\x9D"
// I know the mask is pretty useless in this case but I like to use a generic findPattern method which can handle every mask
#define MARKER_MASK "xxxxxxxxxxxxxx"
Now it gets a little bit more interesting. The procedure morphModule() will be a public method in our class which can get called from the outside.
This function is the only "interface" for the user.
I removed the calls to my logger class but I'm sure you can replace them. Same with the findPattern method. ;)
It looks like this:
C++:
void morphModule()
{
    // all the vars we need for the GetModuleInformation call
    MODULEINFO modInfo;
    HANDLE hProcess = GetCurrentProcess();
    HMODULE hModule = GetModuleHandleA(NULL);
   
    if (GetModuleInformation(hProcess, hModule, &modInfo, sizeof(MODULEINFO)))
    {
        // you can log the base of your module here by using modInfo.lpBaseOfDll
        // you can also log the size of your module by using modInfo.SizeOfImage
       
        if (modInfo.SizeOfImage < MAXDWORD)
        {
            // where the pattern was found last
            byte* pbyLastMatch;
            // the offset from the module base to pbyLastMatch -> used as: module size - dwMatchOffset = range of bytes we still need to scan
            DWORD dwMatchOffset = 0;
            // are we done yet?
            bool bMorphingFinished = false;
            // good to know how many regions we morphed in total
            DWORD dwRegionCount = 0;
           
            while (!bMorphingFinished)
            {
                // search for the marker we will place in our code later on
                pbyLastMatch = Memory::get()->findPattern((byte*)modInfo.lpBaseOfDll + dwMatchOffset, modInfo.SizeOfImage - dwMatchOffset, (byte*)MARKER_BYTES, MARKER_MASK, MARKER_SIZE);

                // if marker found
                if (pbyLastMatch != NULL)
                {
                    // call morphMemory which generates the junk code and writes it to memory
                    morphMemory(pbyLastMatch, MARKER_SIZE);
                    dwRegionCount++;
                   
                    // this should be redundant if you think about it, better save than sorry though
                    pbyLastMatch++;
                    dwMatchOffset = (DWORD)pbyLastMatch - (DWORD)modInfo.lpBaseOfDll;
                }
                // if we found all markers
                else
                {
                    bMorphingFinished = true;
                    // here you can log how many regions got morphed by using dwRegionCount
                }
            }
        }
        else // log module too large
    }
    else // log unable to obtain module information
   
    // clean up
    CloseHandle(hProcess);
}
So the function above searches for all the markers we placed in our code and calls morphMemory everytime which does the actual junk code generating.
That's the algorythm I thought of first, maybe it's a stupid attempt maybe not idk. Give me a better one! :D
C++:
void morphMemory(byte* pbyDst, byte byLength)
{
    /*
    what kind of junk code this algorythm can produce (rdm = random opcode, jmp = jump past junk code)
    jmp        or        0x90
    rdm                jmp
    rdm                rdm
    rdm                rdm
    */
   
    // nullptr checking would be a good idea at this point
    // init random number generator only once
    static bool bSetSeed = true;
    if (bSetSeed)
    {
        srand((UINT)time(NULL));
        bSetSeed = false;
    }
   
    // get a place for our brand new random opcodes
    byte* morphedOpcodes = new byte[byLength];
    byte byOpcodeIt = 0;
   
    // first calculate if we wanna place a 0x90 at the beginning or not
    bool bPlaceNop = (rand() % 2) ? true : false;
    if (bPlaceNop)
    {
        morphedOpcodes[byOpcodeIt] = ASM_OPCODE_NOP;
        byOpcodeIt++;
    }
   
    // now place the jmp instruction
    morphedOpcodes[byOpcodeIt] = ASM_OPCODE_JMP_REL;
    byOpcodeIt++;

    // adjust the relative jmp based on wether we placed a nop before or not
    // keep in mind: we only want to jump past the junk code not any further
    morphedOpcodes[byOpcodeIt] = byLength - ASM_INSTR_SIZE_JMP_REL - ((bPlaceNop) ? ASM_INSTR_SIZE_NOP : 0);
    byOpcodeIt++;
   
    // now fill the rest with random opcodes
    for (; byOpcodeIt < byLength; byOpcodeIt++)
        morphedOpcodes[byOpcodeIt] = rand() % MAXBYTE; // 0xFF
   
    // write the new opcodes to memory
    DWORD dwOldProtect;
    VirtualProtect(pbyDst, byLength, PAGE_EXECUTE_READWRITE, &dwOldProtect);
    memcpy(pbyDst, morphedOpcodes, byLength);
    VirtualProtect(pbyDst, byLength, dwOldProtect, &dwOldProtect);
   
    // free the used memory again
    delete morphedOpcodes;
}

Using the code

Now after you wrote your ub3r codenz you can place the defined macro all over your code. This can also be automated with a text editor but you can do it whichever way you prefer.
I highly suggest you doing this after debugging when you're sure your code won't change anymore.
It can look like this:
C++:
// init random number generator only once
$$$;
static bool bSetSeed = true;
$$$;
if (bSetSeed)
{
    $$$;
    srand((UINT)time(NULL));
    $$$;   
    bSetSeed = false;
    $$$;
}
$$$;
You don't really want to debug this anymore now do you? :D
One thing which you should keep in mind though is, complex highlevel expressions undermine this protection concept!
That's because an expression like
C++:
morphedOpcodes[byOpcodeIt] = byLength - ASM_INSTR_SIZE_JMP_REL - ((bPlaceNop) ? ASM_INSTR_SIZE_NOP : 0);
will get compiled as a whole bunch of assembler instructions.
Such an expression will generate a nearly unique byte pattern in your module. And because of its high level complexity you can't place your marker directly in the middle of it.
The worst case scenario would be getting your module detected by a pattern scan, due to an expression like this one.
Therefore you'll have to split up these kind of lines and write more "low level" code. :/
Also it isn't really a good style either. ^^
The call from our main function should look as simple as this:
C++:
// we don't need anything more than this line to randomize our module in the end
morphModule();

Conclusion

Now compile it and take a look at it with OllyDbg, x32Dbg or some other debugger...
Most part of the opcodes should change eveytime you run your code.
Another advantage of this technique is the ability to also morph the code sections which actually handle the code morphing like the methods morphModule() and morphMemory() from above.
You can place the macro all over this code too. It will then polymorph itself, so to say.
That's because neither the marker opcodes nor the junk code changes the functionality of the surrounding code.
Btw something interesting to know is that this concept of protection also sometimes screws up disassemblers and their interpretation of your code.
To conclude, one can say that using the technique of polymorhic junk code can successfully protect your module against pattern scanning.

Have fun ;)
Liduen
 
Last edited by a moderator:

keto

Dank Tier Donator
Nobleman
May 25, 2013
151
1,648
1
I waited for something like this a long time! Very well written, incredible technique and god damn it way too advanced for me. Just the name "Polymorphism" causes butterflies flying around my stomach.

Please do more 10/10.
 

Rake

Cesspool Admin
Administrator
Jan 21, 2014
12,380
78,998
2,414
Great tutorial! I stickied it in the anti-cheat section
 

Liduen

Hacker
Dank Tier VIP
May 19, 2013
702
8,478
33
Fixed a few typos.
I also commented the code a bit more so it's easier to read / understand.
 

Liduen

Hacker
Dank Tier VIP
May 19, 2013
702
8,478
33
I waited for something like this a long time! Very well written, incredible technique and god damn it way too advanced for me. Just the name "Polymorphism" causes butterflies flying around my stomach.

Please do more 10/10.
To be accurate polymorphism is something different ^^
Polymorphic code - Not to be confused with Polymorphism

It was fun writing this and I'll definitely write more :)
I really appreciate your feedback!
 

darknessxk

Newbie
Dank Tier Donator
Jul 25, 2015
10
673
1
Hi. thanks for the code i am reading it and absorving and learning much new things about Poly Code
I am trying to make a similar code but you can share with me you memory find pattern code ?
Because i am not sure how did you make it. or if it a header from the c++.

*using vs 2015 enterprise*
 

Liduen

Hacker
Dank Tier VIP
May 19, 2013
702
8,478
33
Hi. thanks for the code i am reading it and absorving and learning much new things about Poly Code
I am trying to make a similar code but you can share with me you memory find pattern code ?
Because i am not sure how did you make it. or if it a header from the c++.

*using vs 2015 enterprise*
Check out this wiki page.
It provides a few other links, source code and examples regarding pattern scanning.
For more interesting links check out this collecion.
 

Liduen

Hacker
Dank Tier VIP
May 19, 2013
702
8,478
33
Nice, interesting code!
I really enjoy reading your posts. They're always worth a read.

Keep it up!
 

mambda

headass
Escobar Tier VIP
Trump Tier Donator
Jun 25, 2014
2,305
37,938
270
Thanks man!

I might do reversal threads on games that i find fun since im all out of codenz my friend will allow me to give away, heh, so if i ever get into the Overwatch beta ill try to start one up of that, because im too lazy to write any kind of full-fledged tutorial :p .

Also edit:

There are a plethora of things you can do to make this more advanced/suited for your needs , for example, the route we took was some heavy modification of this to also mutate MOVSS ( floating point, SSE stuff ) , MOV DWORD PTR ( different instruction that just regular old mov ), JMP/CALLs .

We also decided to encrypt the function we want to protect and store it in memory, then destroy the original function and replace it with a JMP to our mutated stuff ( not sure if its in this older source ) , the mutated stuff is then copied to another place in memory whenever we want to morph it, its then decrypted and morphed simultaneously, fun stuff, just some examples of where you could go should you want to make this baby your own
 
Last edited:

Rake

Cesspool Admin
Administrator
Jan 21, 2014
12,380
78,998
2,414
Lots of google searching on this topic leads to this page, I just updated this thread with a guide

I am focusing on making guides on topics of interest so it is easier to find the good content in the sea of shit that is our forum :brokeback:
 

Traxin

Escobar Tier VIP
Dank Tier Donator
Aug 3, 2015
1,041
25,378
154

Traxin

Escobar Tier VIP
Dank Tier Donator
Aug 3, 2015
1,041
25,378
154
I've already got the function that returns DWORD but I actually need that byte*
How could I possibly get that?
Oh, if you're getting mixed up by something like that then you might want to start off at Learn C++
To answer your question, you need to modify the function so that it returns a pointer instead of an unsigned integer.
I don't know your exact situation so I'm not saying to simply just cast the result, but that might also be a possibility.

Again, maybe try to brush up on the basics...
 
  • Like
Reactions: Sajed

Traxin

Escobar Tier VIP
Dank Tier Donator
Aug 3, 2015
1,041
25,378
154
  • Like
Reactions: Sajed
Mar 18, 2019
1
12
0
Attention! Before you post:

Read the How to Ask Questions Guide
99% of questions are answered in the Beginner's Guide, do it before asking a question.

No Hack Requests. Post in the correct section.  Search the forum first. Read the rules.

How to make a good post:

  • Fill out the form correctly
  • Tell us the game name & coding language
  • Post everything we need to know to help you
  • Ask specific questions, be descriptive
  • Post errors, line numbers & screenshots
  • Post code snippets using code tags
  • If it's a large project, zip it up and attach it

If you do not comply, your post may be deleted.  We want to help, please make a good post and we will do our best to help you.

Community Mods