Solved Function wiping

Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat

Liduen

Hacker
Dank Tier VIP
May 19, 2013
702
8,478
33
So I got inspired by all of these crypt classes which where posted here some days ago.
I wrote a dummy function which I want to wipe after using it once.
Now look at the picture below...



How is it possible that the function still works even if the opcodes completely changed? (I checked it with olly- the bytes really changed to some nonsense)
Does the compiler know that the function will get erased and therefore backs it up somewhere else or how does this sorcery work? :D


EDIT Solution: Make sure the function doesn't get inlined!
C++:
__declspec(noinline) void func(params)
:facepalm:
 
Last edited:

Solaire

Respected Hacker
Dank Tier VIP
Dec 15, 2013
1,051
16,353
62
The dummy function does nothing interesting:
C++:
int dummyFunction(int h)
{
    printf("%s \n", "Dummy function called");
    // some random calculations
    int b = 12;
    b -= h; 
    b *= 4;
    if (h == 2) wipe((BYTE*)dummyFunction);
    return b;
}

I changed all the opcodes to 0xC3 and 0xCC and still the function keeps working :/

C++:
void wipe(BYTE* cryptFunctionStart)
{
    DWORD oldProtection, newProtection;
    BYTE rdm = static_cast<BYTE>(rand() % 0xFF);
    size_t sizeOfWipedMemory = ((BYTE*)_ReturnAddress()) - cryptFunctionStart - 0x4;

    VirtualProtect((LPVOID)cryptFunctionStart, sizeOfWipedMemory, PAGE_EXECUTE_READWRITE, &oldProtection);
    for (unsigned int i = 0; i < sizeOfWipedMemory; i++)
    {
        //*(cryptFunctionStart + i) = 0xCC;
        *(cryptFunctionStart + i) ^= rdm;
    }    
    VirtualProtect((LPVOID)cryptFunctionStart, sizeOfWipedMemory, oldProtection, &newProtection);
}

C++:
int main()
{
    int returnValue = 0;

    printf("\n%s \n", "First 0xF bytes of dummy function before wiping:");
    printOpcodes((DWORD*)dummyFunction, (DWORD*)dummyFunction + 0xF);

    returnValue = dummyFunction(2); // should return 40
    printf("Return value: %d\n", returnValue);
    if (returnValue == 40) printf("%s\n", "Return value correct! -> function works");
    else printf("%s\n", "Return value incorrect! -> function doesn't work anymore");

    printf("\n%s \n", "First 0xF bytes of dummy function after wiping:");
    printOpcodes((DWORD*)dummyFunction, (DWORD*)dummyFunction + 0xF);

    returnValue = dummyFunction(1); // should return 44
    printf("Return value: %d\n", returnValue);
    if (returnValue == 44) printf("%s\n", "Return value correct! -> function works");
    else printf("%s\n", "Return value incorrect! -> function doesn't work anymore");


    printf("\n", "");
    system("pause");
    return EXIT_SUCCESS;
}
I'm using my own container class for this, you can use a vector or just a simple array if you want to.


C++:
int grabBytes(DWORD funct, Container<BYTE>& lst)
{
    for (int i = 0;; i++)
    {
        if ((*(BYTE*)(funct + i)) == 0xCC && (*(BYTE*)(funct + i - 1)) == 0xC3)
        {
            return i;
        }

        lst.push_back(*(BYTE*)(funct + i));
    }
}

void grabBytes(DWORD funct, Container<BYTE>& lst, int len)
{
    for (int i = 0; i < len; i++)
    {
        lst.push_back(*(BYTE*)(funct + i));
    }
}

void wipeFunction(DWORD funct, int lengthOfFunct)
{
    DWORD oldProtect;
    VirtualProtect((LPVOID)funct, lengthOfFunct, PAGE_EXECUTE_READWRITE, &oldProtect);

    for (int i = 0; i < lengthOfFunct; i++)
    {
        //You can use a different byte if you want to, or replace the first byte with 0xC3 for a return
        (*(BYTE*)(funct + i)) = 0xCC;
    }

    VirtualProtect((LPVOID)funct, lengthOfFunct, oldProtect, NULL);
}

void restoreFunction(DWORD funct, int lengthOfFunct, Container<BYTE> bytes)
{
    for (int i = 0; i < lengthOfFunct; i++)
    {
        (*(BYTE*)(funct + i)) = bytes[i];
    }
}
In main
C++:
Container<BYTE> byteList, afterWipe;
int lengthOfFunct = grabBytes((DWORD)dummyFunction, byteList);
dummyFunction(7);

printf("\n\nAll %d bytes of \"dummyFunction\"\n", lengthOfFunct);

for (int i = byteList.begin(); i != byteList.end(); i++)
{
    printf("\\x%02X", byteList[i]);
}

wipeFunction((DWORD)dummyFunction, lengthOfFunct);
grabBytes((DWORD)dummyFunction, afterWipe, lengthOfFunct);

printf("\n\nAll %d bytes of \"dummyFunction\"\n", lengthOfFunct);

for (int i = afterWipe.begin(); i != afterWipe.end(); i++)
{
    printf("\\x%02X", afterWipe[i]);
}

getchar();
 

Solaire

Respected Hacker
Dank Tier VIP
Dec 15, 2013
1,051
16,353
62
So I got inspired by all of these crypt classes which where posted here some days ago.
I wrote a dummy function which I want to wipe after using it once.
Now look at the picture below...



How is it possible that the function still works even if the opcodes completely changed?
Hm. Try replacing the first byte with a return, or changing all bytes to CC. What exactly does the function do? :)
 

Liduen

Hacker
Dank Tier VIP
May 19, 2013
702
8,478
33
Hm. Try replacing the first byte with a return, or changing all bytes to CC. What exactly does the function do? :)
The dummy function does nothing interesting:
C++:
int dummyFunction(int h)
{
	printf("%s \n", "Dummy function called");
	// some random calculations
	int b = 12;
	b -= h; 
	b *= 4;
	if (h == 2) wipe((BYTE*)dummyFunction);
	return b;
}

I changed all the opcodes to 0xC3 and 0xCC and still the function keeps working :/

C++:
void wipe(BYTE* cryptFunctionStart)
{
	DWORD oldProtection, newProtection;
	BYTE rdm = static_cast<BYTE>(rand() % 0xFF);
	size_t sizeOfWipedMemory = ((BYTE*)_ReturnAddress()) - cryptFunctionStart - 0x4;

	VirtualProtect((LPVOID)cryptFunctionStart, sizeOfWipedMemory, PAGE_EXECUTE_READWRITE, &oldProtection);
	for (unsigned int i = 0; i < sizeOfWipedMemory; i++)
	{
		//*(cryptFunctionStart + i) = 0xCC;
		*(cryptFunctionStart + i) ^= rdm;
	}	
	VirtualProtect((LPVOID)cryptFunctionStart, sizeOfWipedMemory, oldProtection, &newProtection);
}

C++:
int main()
{
	int returnValue = 0;

	printf("\n%s \n", "First 0xF bytes of dummy function before wiping:");
	printOpcodes((DWORD*)dummyFunction, (DWORD*)dummyFunction + 0xF);

	returnValue = dummyFunction(2); // should return 40
	printf("Return value: %d\n", returnValue);
	if (returnValue == 40) printf("%s\n", "Return value correct! -> function works");
	else printf("%s\n", "Return value incorrect! -> function doesn't work anymore");

	printf("\n%s \n", "First 0xF bytes of dummy function after wiping:");
	printOpcodes((DWORD*)dummyFunction, (DWORD*)dummyFunction + 0xF);

	returnValue = dummyFunction(1); // should return 44
	printf("Return value: %d\n", returnValue);
	if (returnValue == 44) printf("%s\n", "Return value correct! -> function works");
	else printf("%s\n", "Return value incorrect! -> function doesn't work anymore");


	printf("\n", "");
	system("pause");
	return EXIT_SUCCESS;
}
 
Last edited:

Solaire

Respected Hacker
Dank Tier VIP
Dec 15, 2013
1,051
16,353
62
The dummy function does nothing interesting:
C++:
int dummyFunction(int h)
{
    printf("%s \n", "Dummy function called");
    // some random calculations
    int b = 12;
    b -= h; 
    b *= 4;
    if (h == 2) wipe((BYTE*)dummyFunction);
    return b;
}
I changed all the opcodes to 0xC3 and 0xCC and still the function keeps working :/
I'll check it out :)
 

Liduen

Hacker
Dank Tier VIP
May 19, 2013
702
8,478
33
I'm using my own container class for this, you can use a vector or just a simple array if you want to.


C++:
int grabBytes(DWORD funct, Container<BYTE>& lst)
{
    for (int i = 0;; i++)
    {
        if ((*(BYTE*)(funct + i)) == 0xCC && (*(BYTE*)(funct + i - 1)) == 0xC3)
        {
            return i;
        }

        lst.push_back(*(BYTE*)(funct + i));
    }
}

void grabBytes(DWORD funct, Container<BYTE>& lst, int len)
{
    for (int i = 0; i < len; i++)
    {
        lst.push_back(*(BYTE*)(funct + i));
    }
}

void wipeFunction(DWORD funct, int lengthOfFunct)
{
    DWORD oldProtect;
    VirtualProtect((LPVOID)funct, lengthOfFunct, PAGE_EXECUTE_READWRITE, &oldProtect);

    for (int i = 0; i < lengthOfFunct; i++)
    {
        //You can use a different byte if you want to, or replace the first byte with 0xC3 for a return
        (*(BYTE*)(funct + i)) = 0xCC;
    }

    VirtualProtect((LPVOID)funct, lengthOfFunct, oldProtect, NULL);
}

void restoreFunction(DWORD funct, int lengthOfFunct, Container<BYTE> bytes)
{
    for (int i = 0; i < lengthOfFunct; i++)
    {
        (*(BYTE*)(funct + i)) = bytes[i];
    }
}
In main
C++:
Container<BYTE> byteList, afterWipe;
int lengthOfFunct = grabBytes((DWORD)dummyFunction, byteList);
dummyFunction(7);

printf("\n\nAll %d bytes of \"dummyFunction\"\n", lengthOfFunct);

for (int i = byteList.begin(); i != byteList.end(); i++)
{
    printf("\\x%02X", byteList[i]);
}

wipeFunction((DWORD)dummyFunction, lengthOfFunct);
grabBytes((DWORD)dummyFunction, afterWipe, lengthOfFunct);

printf("\n\nAll %d bytes of \"dummyFunction\"\n", lengthOfFunct);

for (int i = afterWipe.begin(); i != afterWipe.end(); i++)
{
    printf("\\x%02X", afterWipe[i]);
}

getchar();
Does the function still work afterwards?
 

Solaire

Respected Hacker
Dank Tier VIP
Dec 15, 2013
1,051
16,353
62
Does the function still work afterwards?
I can tell you with 100% certainty that once it's wiped, it will not work :p. The second byte list there is the literal bytes read from that section of memory. If I were to call the function it would crash since there is nothing there to continue the program flow.

I've been running this for the past 10-15 minutes to make sure it works fine, and it does :)
C++:
for (int i = 0;; i++)
{
    wipeFunction((DWORD)dummyFunction, lengthOfFunct);
    restoreFunction((DWORD)dummyFunction, lengthOfFunct, byteList);
    dummyFunction(7);
}
Liduen, video of the dummyFunction being cleared and returned :)
https://youtu.be/woyQOGZuM5g
 
Last edited:

Liduen

Hacker
Dank Tier VIP
May 19, 2013
702
8,478
33
I know why it didn't work.
There was nothing wrong with writing the bytes of the function.

When testing stuff like this make sure the test function you want to wipe doesn't get inlined by the compiler!

This will help:
C++:
__declspec(noinline) void testFunctionToWipeAfterwards(params)
{
	// body
}
 

HalfWayToHell333

Jr.Coder
Silenced
Full Member
Nobleman
Jun 23, 2014
80
783
3
And what if the Function you want to wipe is inline ? , wouldn´t that be interesting too?
Cool stuff btw.
 

Liduen

Hacker
Dank Tier VIP
May 19, 2013
702
8,478
33
And what if the Function you want to wipe is inline ? , wouldn´t that be interesting too?
Cool stuff btw.
It would be an unbelievable mess to wipe a function which got inlined especially if it got inlined several times.
We're talking about functions you wrote yourself so it's your decision to make them inline or not.
If you want to wipe them later you should probably make them noinline because it makes things much easier. ;)
 

c5

Kim Kong Trasher
Dank Tier VIP
Dank Tier Donator
Jul 19, 2012
1,187
12,638
76
And what if the Function you want to wipe is inline ? , wouldn´t that be interesting too?
Cool stuff btw.
Compilers optimization would probably make it impossible for you to wipe it with such approach then.
 

HalfWayToHell333

Jr.Coder
Silenced
Full Member
Nobleman
Jun 23, 2014
80
783
3
Liduen said:
We're talking about functions you wrote yourself so it's your decision to make them inline or not.
Ok understood so far , but why wipe a function that was written by myself ? :confused:
 

Solaire

Respected Hacker
Dank Tier VIP
Dec 15, 2013
1,051
16,353
62
Say you have a function that initialises your hack, if you wipe it, no more sig for an anti cheat to find
Another really great reason for it is that it's super freaking cool! (At least to me :p)
 

Liduen

Hacker
Dank Tier VIP
May 19, 2013
702
8,478
33
Another really great reason for it is that it's super freaking cool! (At least to me :p)
Haha yep that's reason enough on its own :D

-----------------------

But there's still one thing I've been thinking about.
You can encrypt and hide everything perfectly fine except the class / bit of code / whatever, which handles these operations...
So it could be very easy to find this class / function / bit of code and make a sig out of that.
That sig would work just fine in a sig scanner and all hiding / encryption / wiping was useless in the end. (Only if the goal is to detect your hack ofc...)

I mean where is the advantage of having a "hiding" or "encryption" class which can be sigged instead of your normal functions getting sigged?
Is there a way to let a class hide itself?

If I got this right there has to be atleast one function which isn't encrypted so it can get called and decrypt the bit of code which was originally called.
So in the end there has to be atleast one "static" / "constant" bit of code handling the others...

----------------------

I was inspired by the post of c5 in which he posted a code like the following:

C++:
// pseudo code
function
{
  decryptTheFollowing(); // call 0x12345
  // function code
  encryptTheFunctionAgain(); // call 0x67890
}
Wouldn't it be extremely easy for a reverser to notice all these weird calls (call 0x12345 / call 0x67890) to the same structure again and again in every important function of our code?
This way we would literally present the reverser the solution for the problem of having messed up code in memory.
That's because the call to decrypt the function can't be crypted itself in order to be readable...

Does somebody know a bit more about this kind of stuff?
It really got me interested in it :)

Thanks 4 reading I hoped that made sense ^^

:wat:
 

c5

Kim Kong Trasher
Dank Tier VIP
Dank Tier Donator
Jul 19, 2012
1,187
12,638
76
Haha yep that's reason enough on its own :D

-----------------------

But there's still one thing I've been thinking about.
You can encrypt and hide everything perfectly fine except the class / bit of code / whatever, which handles these operations...
So it could be very easy to find this class / function / bit of code and make a sig out of that.
That sig would work just fine in a sig scanner and all hiding / encryption / wiping was useless in the end. (Only if the goal is to detect your hack ofc...)

I mean where is the advantage of having a "hiding" or "encryption" class which can be sigged instead of your normal functions getting sigged?
Is there a way to let a class hide itself?

If I got this right there has to be atleast one function which isn't encrypted so it can get called and decrypt the bit of code which was originally called.
So in the end there has to be atleast one "static" / "constant" bit of code handling the others...

----------------------

I was inspired by the post of c5 in which he posted a code like the following:

C++:
// pseudo code
function
{
  decryptTheFollowing(); // call 0x12345
  // function code
  encryptTheFunctionAgain(); // call 0x67890
}
Wouldn't it be extremely easy for a reverser to notice all these weird calls (call 0x12345 / call 0x67890) to the same structure again and again in every important function of our code?
This way we would literally present the reverser the solution for the problem of having messed up code in memory.
That's because the call to decrypt the function can't be crypted itself in order to be readable...

Does somebody know a bit more about this kind of stuff?
It really got me interested in it :)

Thanks 4 reading I hoped that made sense ^^

:wat:
I don't think you realized I had defined markers (YUNO_FAST) between each operation/line in code. They emit a sequence of bytes with a signature my post-compile tool recognizes and replaces with crap that either gets jumped over or doesnt too anything (junk code). This makes it harder to build a signature for your core, especially if your junk code generator is good enough.

Edit: another benefit is that it can be a good anti-reversing addition. Say your module is mapped and someone dumps it after you have wiped your shit, the reverser would have to put a lot more effort in to reversing it in that case.
 
Last edited:

Liduen

Hacker
Dank Tier VIP
May 19, 2013
702
8,478
33
I don't think you realized I had defined markers (YUNO_FAST) between each operation/line in code. They emit a sequence of bytes with a signature my post-compile tool recognizes and replaces with crap that either gets jumped over or doesnt too anything (junk code). This makes it harder to build a signature for your core, especially if your junk code generator is good enough.

Edit: another benefit is that it can be a good anti-reversing addition. Say your module is mapped and someone dumps it after you have wiped your shit, the reverser would have to put a lot more effort in to reversing it in that case.
Ah okay that makes sense. I thought these YUNO_FAST's where anti c+p stuff. :D
 
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