Created
December 31, 2021 00:51
-
-
Save mislavjakopovic/fde2724744d4087c6538790e701ac8d1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "stdafx.h" | |
void __fastcall Hotpatch(void* pOFunc, void* pHkFunc) | |
{ | |
DWORD dwOldProt = 0; | |
BYTE bPatch[5]; | |
bPatch[0] = 0xE9; | |
VirtualProtect((void*)pOFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProt); | |
DWORD dwRelativeAddr = ((DWORD)pHkFunc - (DWORD)pOFunc - 5); | |
memcpy(&bPatch[1], &dwRelativeAddr, 4); | |
memcpy(pOFunc, bPatch, 5); | |
VirtualProtect((void*)pOFunc, 5, dwOldProt, NULL); | |
} | |
uint32_t __fastcall uiGetOpCodeSize(BYTE btOpCode) | |
{ | |
switch (btOpCode) | |
{ | |
// Only care about opcodes with a size greater than 1 | |
case 0xD5: // AAD | |
return 2; | |
case 0xD4: // AAM | |
return 2; | |
#pragma region ADC | |
// ADC | |
case 0x14: | |
return 2; | |
case 0x15: | |
return 3; | |
case 0x12: | |
return 2; // Can be 4 | |
case 0x13: | |
return 2; // Can be 4 | |
case 0x80: | |
return 3; // Can be 5 | |
case 0x81: | |
return 4; // Can be 6 | |
case 0x83: | |
return 3; // Can be 5 | |
case 0x10: | |
return 2; // Can be 4 | |
case 0x11: | |
return 2; // Can be 4 | |
#pragma endregion | |
#pragma region ADD | |
// ADD | |
case 0x4: | |
return 2; | |
case 0x5: | |
return 3; | |
case 0x2: | |
return 2; // Can be 4 | |
case 0x3: | |
return 2; // Can be 4 | |
case 0x0: | |
return 2; // Can be 4 | |
case 0x1: | |
return 2; // Can be 4 | |
#pragma endregion | |
#pragma region AND | |
case 0x24: | |
return 2; | |
case 0x25: | |
return 3; | |
case 0x22: | |
return 2; // Can be 4 | |
case 0x23: | |
return 2; // Can be 4 | |
case 0x20: | |
return 2; // Can be 4 | |
case 0x21: | |
return 2; // Can be 4 | |
#pragma endregion | |
case 0x63: // ARPL | |
return 2; // Can be 4 | |
case 0x62: // BOUND | |
return 2; // Can be 4 | |
case 0xF: // BSF || BSR || BSWAP | |
return 4; // Can be 2, 3, 4, 5, or 6 | |
// MOST LIKELY TO BE 4 | |
#pragma region CALL | |
case 0xE8: | |
return 5; | |
case 0xFF: | |
return 2; // Can be 4 | |
case 0x9A: | |
return 5; | |
#pragma endregion | |
case 0x66: // CDQ | |
return 2; | |
case 0xF5: // CLTS | |
return 2; | |
#pragma region CMP | |
case 0x3C: | |
return 2; | |
case 0x3D: | |
return 3; | |
case 0x3A: | |
return 2; // Can be 4 | |
case 0x3B: | |
return 2; // Can be 4 | |
case 0x38: | |
return 2; // Can be 4 | |
case 0x39: | |
return 2; // Can be 4 | |
#pragma endregion | |
#pragma region DIV | |
case 0xF6: | |
return 2; // Can be 4 | |
case 0xF7: | |
return 2; // Can be 4 | |
#pragma endregion | |
case 0xC8: // ENTER | |
return 4; | |
#pragma region HolyFuckFloats | |
case 0xD9: | |
return 2; | |
case 0xDE: | |
return 2; | |
case 0xD8: | |
return 2; // Can be 4 | |
case 0xDC: | |
return 2; // Can be 4 | |
case 0x9B: | |
return 3; | |
case 0xDD: | |
return 2; | |
case 0xDA: | |
return 2; // Can be 4 | |
case 0xDF: | |
return 2; // Can be 4 | |
#pragma endregion | |
#pragma region IMUL | |
case 0x6B: // IMUL | |
return 3; // Can be 5 | |
case 0x69: | |
return 6; // Can be 8 | |
#pragma endregion | |
#pragma region IN_OPCODE | |
case 0xE4: | |
return 2; | |
case 0xE5: | |
return 2; | |
#pragma endregion | |
case 0xFE: // INC | |
return 2; // Can be 4 | |
case 0xCD: // INT | |
return 2; | |
case 0x77: // JA | |
return 2; | |
case 0x73: // JAE | |
return 2; | |
case 0x72: // JB | |
return 2; | |
case 0x76: // JBE | |
return 2; | |
case 0xE3: // JCXZ | |
return 2; | |
case 0x67: // JECXZ, wtf | |
return 3; | |
case 0x74: // JE | |
return 2; | |
case 0x7F: // JG | |
return 4; | |
case 0x7D: // JGE | |
return 4; | |
case 0x7C: // JL | |
return 2; | |
case 0x7E: // JLE | |
return 2; | |
#pragma region JMP | |
case 0xEB: | |
return 2; | |
case 0xE9: | |
return 3; | |
case 0xEA: | |
return 5; | |
#pragma endregion | |
case 0x75: // JNE | |
return 2; | |
case 0x71: // JNO | |
return 2; | |
case 0x79: // JNS | |
return 2; | |
case 0x7B: // JNP | |
return 2; | |
case 0x70: // JO | |
return 2; | |
case 0x7A: // JP | |
return 2; | |
case 0x78: // JS | |
return 2; | |
case 0xC5: // LDS | |
return 2; // Can be 4 | |
case 0x8D: // LEA | |
return 4; // Can be 2 | |
case 0xC4: // LES | |
return 4; // Can be 2 | |
case 0xE2: // LOOP | |
return 2; | |
case 0xE1: // LOOPE | |
return 2; | |
case 0xE0: // LOOPNZ | |
return 2; | |
#pragma region MOV | |
case 0xA0: | |
return 3; | |
case 0xA1: | |
return 3; | |
case 0xB0: | |
return 2; | |
case 0xB4: | |
return 2; | |
case 0xB8: | |
return 5; // ? wat john, these can be up to 5 bytes; this actually fucked shit up rofl | |
case 0xB1: | |
return 2; | |
case 0xB5: | |
return 2; | |
case 0xB9: | |
return 3; | |
case 0xB2: | |
return 2; | |
case 0xB6: | |
return 2; | |
case 0xBA: | |
return 3; | |
case 0xB3: | |
return 2; | |
case 0xB7: | |
return 2; | |
case 0xBB: | |
return 3; | |
case 0xBC: | |
return 3; | |
case 0xBD: | |
return 3; | |
case 0xBE: | |
return 3; | |
case 0xBF: | |
return 3; | |
case 0x8A: | |
return 4; // Can be 2 | |
case 0x8B: | |
return 3; // Can be 4 // FUCK ME; Or even 3 john, once again breaking code. (changed from 2 to 3) | |
case 0xA2: | |
return 3; | |
case 0xA3: | |
return 3; | |
case 0xC6: | |
return 5; // Can be 3 | |
case 0xC7: | |
return 7; // Can be 4, actually it can even be 7. (changed value from 6 to 7) | |
case 0x89: | |
return 4; // Can be 2 | |
case 0x8C: | |
return 4; // Can be 2 | |
case 0x8E: | |
return 4; // Can be 2 | |
#pragma endregion | |
#pragma region OR | |
case 0xC: | |
return 2; | |
case 0xD: | |
return 3; | |
case 0xA: | |
return 4; // Can be 2 | |
case 0xB: | |
return 4; // Can be 2 | |
case 0x8: | |
return 4; // Can be 2 | |
case 0x9: | |
return 4; // Can be 2 | |
#pragma endregion | |
#pragma region OUT_OPCODE | |
case 0xE6: | |
return 2; | |
case 0xE7: | |
return 2; | |
#pragma endregion | |
case 0x8F: // POP | |
return 4; // Can be 2 | |
case 0x6A: // PUSH | |
return 2; | |
case 0x68: | |
return 5; | |
#pragma region ROTATE_SHIFT_OPCODES | |
//RCR, RCL, ROR, ROL, SAL, SHL, SAR, SHR | |
case 0xD0: | |
return 4; // Can be 2 | |
case 0xD2: | |
return 4; // Can be 2 | |
case 0xC0: | |
return 5; // Can be 3 | |
case 0xD1: | |
return 4; // Can be 2 | |
case 0xD3: | |
return 4; // Can be 2 | |
case 0xC1: | |
return 5; // Can be 3 | |
#pragma endregion | |
#pragma region SBB | |
case 0x1C: | |
return 2; | |
case 0x1D: | |
return 3; | |
case 0x1A: | |
return 4; // Can be 2 | |
case 0x1B: | |
return 4; // Can be 2 | |
case 0x18: | |
return 4; // Can be 2 | |
case 0x19: | |
return 4; // Can be 2 | |
#pragma endregion | |
#pragma region SUB | |
case 0x2C: | |
return 2; | |
case 0x2D: | |
return 2; | |
case 0x2A: | |
return 2; // Can be 2 /*mambda note: set these from 4 to 2*/ | |
case 0x2B: | |
return 2; // Can be 2 | |
case 0x28: | |
return 2; // Can be 2 | |
case 0x29: | |
return 2; // Can be 2 | |
#pragma endregion | |
#pragma region TEST | |
case 0xA8: | |
return 2; | |
case 0xA9: | |
return 3; | |
case 0x84: | |
return 4; // Can be 2 | |
case 0x85: | |
return 4; // Can be 2 | |
#pragma endregion | |
#pragma region XCHG | |
case 0x86: | |
return 4; // Can be 2 | |
case 0x87: | |
return 4; // Can be 2 | |
#pragma endregion | |
#pragma region XOR | |
case 0x34: | |
return 2; | |
case 0x35: | |
return 2; | |
case 0x32: | |
return 2; // Can be 2 /*mambda: changed all these 3s to 2s*/ | |
case 0x33: | |
return 2; // Can be 2 | |
case 0x30: | |
return 2; // Can be 2 | |
case 0x31: | |
return 2; // Can be 2 | |
#pragma endregion | |
default: | |
return 1; | |
} | |
} | |
bool __fastcall bIsRelativeOpCode(BYTE btOpCode) | |
{ | |
switch (btOpCode) | |
{ | |
case 0xE8: | |
return true; | |
// TODO: Finish this function | |
default: | |
return false; | |
} | |
} | |
/* | |
PVOID __fastcall pFindCodeCave(PVOID pStartingAddr, uint32_t uiSize) | |
{ | |
uiSize += 2; | |
PVOID pCodeCode = nullptr | |
while (pCodeCode == nullptr) | |
{ | |
if( | |
} | |
return pCodeCode; | |
} | |
*/ | |
struct OPCODE | |
{ | |
unsigned short usSize; | |
PBYTE pbOpCode; | |
bool bRelative; | |
bool bMutated; | |
}; | |
#pragma region MOV / POP / XOR / OR Register Byte definitions | |
namespace MOVRegisters | |
{ | |
enum MovRegisters | |
{ | |
EAX = 0xB8, | |
ECX, | |
EDX, | |
EBX, | |
ESP, | |
EBP, | |
ESI, | |
EDI | |
}; | |
} | |
namespace SUBRegisters | |
{ | |
enum SUBRegisters | |
{ | |
EAX = 0xC0, | |
ECX = EAX + 0x9, | |
EDX = ECX + 0x9, | |
EBX = EDX + 0x9, | |
ESP = EBX + 0x9, | |
EBP = ESP + 0x9, | |
ESI = EBP + 0x9, | |
EDI = ESI + 0x9 | |
}; | |
} | |
namespace ADDRegisters | |
{ | |
enum ADDRegisters | |
{ | |
EAX = 0x5, | |
ECX = 0xC1, | |
EDX, | |
EBX, | |
ESP, | |
EBP, | |
ESI, | |
EDI | |
}; | |
} | |
namespace ORRegisters | |
{ | |
enum ORRegisters | |
{ | |
EAX = 0xD, | |
ECX = 0xC9, | |
EDX, | |
EBX, | |
ESP, | |
EBP, | |
ESI, | |
EDI | |
}; | |
} | |
namespace XORRegisters | |
{ | |
enum XorRegisters | |
{ | |
EAX = 0xC0, | |
ECX = EAX + 0x9, | |
EDX = ECX + 0x9, | |
EBX = EDX + 0x9, | |
ESP = EBX + 0x9, | |
EBP = ESP + 0x9, | |
ESI = EBP + 0x9, | |
EDI = ESI + 0x9 | |
}; | |
} | |
namespace POPRegisters | |
{ | |
enum POPRegister | |
{ | |
EAX = 0x58, | |
ECX, | |
EDX, | |
EBX, | |
ESP, | |
EBP, | |
ESI, | |
EDI | |
}; | |
} | |
#pragma endregion | |
bool __fastcall bIsMOV(PBYTE pInstruction) | |
{ | |
if (*pInstruction == MOVRegisters::EAX || *pInstruction == MOVRegisters::ECX || *pInstruction == MOVRegisters::EDX || *pInstruction == MOVRegisters::EBX || | |
*pInstruction == MOVRegisters::ESP || *pInstruction == MOVRegisters::EBP || *pInstruction == MOVRegisters::ESI || *pInstruction == MOVRegisters::EDI) | |
return true; | |
else | |
return false; | |
} | |
bool __fastcall bIsPUSH(PBYTE pInstruction) | |
{ | |
return *pInstruction == 0x68; | |
} | |
//outAdd = value to add to uiOpCodeSize | |
void __fastcall MutatePUSH(OPCODE * pOpCodeIn, OPCODE * pOpCodeOut) | |
{ | |
pOpCodeOut->pbOpCode[0] = 0x83; | |
pOpCodeOut->pbOpCode[1] = 0xEC; | |
pOpCodeOut->pbOpCode[2] = 0x4; // 3 | |
pOpCodeOut->pbOpCode[3] = 0xC7; | |
pOpCodeOut->pbOpCode[4] = 0x04; | |
pOpCodeOut->pbOpCode[5] = 0x24; // 3 | |
memcpy(&pOpCodeOut->pbOpCode[6], &pOpCodeIn->pbOpCode[1], 4); // 4 | |
//5 bytes to 10 bytes, haha. | |
} | |
void __fastcall MutateMOV(OPCODE * pOpCode, OPCODE * pOutOpCode, int &outAdd) | |
{ | |
srand(GetTickCount()); | |
int chosenMorph = rand() % 9; | |
if (chosenMorph % 2 == 0) | |
{ | |
pOutOpCode->pbOpCode = new BYTE[6]; | |
switch (pOpCode->pbOpCode[0]) | |
{ | |
case MOVRegisters::EAX: | |
pOutOpCode->pbOpCode[0] = 0x68; | |
memcpy(&pOutOpCode->pbOpCode[1], &pOpCode->pbOpCode[1], 4); | |
pOutOpCode->pbOpCode[5] = POPRegisters::EAX; // 0 -> 4 = 0x68 VALUE | |
break; | |
case MOVRegisters::ECX: | |
pOutOpCode->pbOpCode[0] = 0x68; | |
memcpy(&pOutOpCode->pbOpCode[1], &pOpCode->pbOpCode[1], 4); | |
pOutOpCode->pbOpCode[5] = POPRegisters::ECX; | |
break; | |
case MOVRegisters::EDX: | |
pOutOpCode->pbOpCode[0] = 0x68; | |
memcpy(&pOutOpCode->pbOpCode[1], &pOpCode->pbOpCode[1], 4); | |
pOutOpCode->pbOpCode[5] = POPRegisters::EDX; | |
break; | |
case MOVRegisters::EBX: | |
pOutOpCode->pbOpCode[0] = 0x68; | |
memcpy(&pOutOpCode->pbOpCode[1], &pOpCode->pbOpCode[1], 4); | |
pOutOpCode->pbOpCode[5] = POPRegisters::EBX; | |
break; | |
case MOVRegisters::ESP: | |
pOutOpCode->pbOpCode[0] = 0x68; | |
memcpy(&pOutOpCode->pbOpCode[1], &pOpCode->pbOpCode[1], 4); | |
pOutOpCode->pbOpCode[5] = POPRegisters::ESP; | |
break; | |
case MOVRegisters::EBP: | |
pOutOpCode->pbOpCode[0] = 0x68; | |
memcpy(&pOutOpCode->pbOpCode[1], &pOpCode->pbOpCode[1], 4); | |
pOutOpCode->pbOpCode[5] = POPRegisters::EBP; | |
break; | |
case MOVRegisters::ESI: | |
pOutOpCode->pbOpCode[0] = 0x68; | |
memcpy(&pOutOpCode->pbOpCode[1], &pOpCode->pbOpCode[1], 4); | |
pOutOpCode->pbOpCode[5] = POPRegisters::ESI; | |
break; | |
case MOVRegisters::EDI: | |
pOutOpCode->pbOpCode[0] = 0x68; | |
memcpy(&pOutOpCode->pbOpCode[1], &pOpCode->pbOpCode[1], 4); | |
pOutOpCode->pbOpCode[5] = POPRegisters::EDI; | |
break; | |
} | |
outAdd = 1; | |
} | |
else if (chosenMorph % 3 == 0) | |
{ | |
if (pOpCode->pbOpCode[0] == MOVRegisters::EAX) | |
pOutOpCode->pbOpCode = new BYTE[7]; // initialize it in here because the size is variable | |
else | |
pOutOpCode->pbOpCode = new BYTE[8]; // initialize it in here because the size is variable | |
switch (pOpCode->pbOpCode[0]) | |
{ | |
case MOVRegisters::EAX: | |
pOutOpCode->pbOpCode[0] = 0x31; | |
pOutOpCode->pbOpCode[1] = XORRegisters::EAX; | |
pOutOpCode->pbOpCode[2] = ORRegisters::EAX; | |
memcpy(&pOutOpCode->pbOpCode[3], &pOpCode->pbOpCode[1], 4); | |
outAdd = 5; | |
return; | |
case MOVRegisters::ECX: | |
pOutOpCode->pbOpCode[0] = 0x31; | |
pOutOpCode->pbOpCode[1] = XORRegisters::ECX; | |
pOutOpCode->pbOpCode[2] = 0x81; | |
pOutOpCode->pbOpCode[3] = ORRegisters::ECX; | |
memcpy(&pOutOpCode->pbOpCode[4], &pOpCode->pbOpCode[1], 4); // get that value. | |
break; | |
case MOVRegisters::EDX: | |
pOutOpCode->pbOpCode[0] = 0x31; | |
pOutOpCode->pbOpCode[1] = XORRegisters::EDX; | |
pOutOpCode->pbOpCode[2] = 0x81; | |
pOutOpCode->pbOpCode[3] = ORRegisters::EDX; | |
memcpy(&pOutOpCode->pbOpCode[4], &pOpCode->pbOpCode[1], 4); // get that value. | |
break; | |
case MOVRegisters::EBX: | |
pOutOpCode->pbOpCode[0] = 0x31; | |
pOutOpCode->pbOpCode[1] = XORRegisters::EBX; | |
pOutOpCode->pbOpCode[2] = 0x81; | |
pOutOpCode->pbOpCode[3] = ORRegisters::EBX; | |
memcpy(&pOutOpCode->pbOpCode[4], &pOpCode->pbOpCode[1], 4); // get that value. | |
break; | |
case MOVRegisters::ESP: | |
pOutOpCode->pbOpCode[0] = 0x31; | |
pOutOpCode->pbOpCode[1] = XORRegisters::ESP; | |
pOutOpCode->pbOpCode[2] = 0x81; | |
pOutOpCode->pbOpCode[3] = ORRegisters::ESP; | |
memcpy(&pOutOpCode->pbOpCode[4], &pOpCode->pbOpCode[1], 4); // get that value. | |
break; | |
case MOVRegisters::EBP: | |
pOutOpCode->pbOpCode[0] = 0x31; | |
pOutOpCode->pbOpCode[1] = XORRegisters::EBP; | |
pOutOpCode->pbOpCode[2] = 0x81; | |
pOutOpCode->pbOpCode[3] = ORRegisters::EBP; | |
memcpy(&pOutOpCode->pbOpCode[4], &pOpCode->pbOpCode[1], 4); // get that value. | |
break; | |
case MOVRegisters::ESI: | |
pOutOpCode->pbOpCode[0] = 0x31; | |
pOutOpCode->pbOpCode[1] = XORRegisters::ESI; | |
pOutOpCode->pbOpCode[2] = 0x81; | |
pOutOpCode->pbOpCode[3] = ORRegisters::ESI; | |
memcpy(&pOutOpCode->pbOpCode[4], &pOpCode->pbOpCode[1], 4); // get that value. | |
break; | |
case MOVRegisters::EDI: | |
pOutOpCode->pbOpCode[0] = 0x31; | |
pOutOpCode->pbOpCode[1] = XORRegisters::EDI; | |
pOutOpCode->pbOpCode[2] = 0x81; | |
pOutOpCode->pbOpCode[3] = ORRegisters::EDI; | |
memcpy(&pOutOpCode->pbOpCode[4], &pOpCode->pbOpCode[1], 4); // get that value. | |
break; | |
} | |
outAdd = 6; | |
} | |
else | |
{ | |
if (pOpCode->pbOpCode[0] == MOVRegisters::EAX) | |
pOutOpCode->pbOpCode = new BYTE[7]; // initialize it in here because the size is variable | |
else | |
pOutOpCode->pbOpCode = new BYTE[8]; // initialize it in here because the size is variable | |
switch (pOpCode->pbOpCode[0]) | |
{ | |
case MOVRegisters::EAX: | |
pOutOpCode->pbOpCode[0] = 0xC0; | |
pOutOpCode->pbOpCode[1] = SUBRegisters::EAX; | |
pOutOpCode->pbOpCode[2] = ADDRegisters::EAX; | |
memcpy(&pOutOpCode->pbOpCode[3], &pOpCode->pbOpCode[1], 4); // get that value. | |
outAdd = 5; | |
return; | |
case MOVRegisters::ECX: | |
pOutOpCode->pbOpCode[0] = 0x29; | |
pOutOpCode->pbOpCode[1] = SUBRegisters::ECX; | |
pOutOpCode->pbOpCode[2] = 0x81; | |
pOutOpCode->pbOpCode[3] = ADDRegisters::ECX; | |
memcpy(&pOutOpCode->pbOpCode[4], &pOpCode->pbOpCode[1], 4); // get that value. | |
break; | |
case MOVRegisters::EDX: | |
pOutOpCode->pbOpCode[0] = 0x29; | |
pOutOpCode->pbOpCode[1] = SUBRegisters::EDX; | |
pOutOpCode->pbOpCode[2] = 0x81; | |
pOutOpCode->pbOpCode[3] = ADDRegisters::EDX; | |
memcpy(&pOutOpCode->pbOpCode[4], &pOpCode->pbOpCode[1], 4); // get that value. | |
break; | |
case MOVRegisters::EBX: | |
pOutOpCode->pbOpCode[0] = 0x29; | |
pOutOpCode->pbOpCode[1] = SUBRegisters::EBX; | |
pOutOpCode->pbOpCode[2] = 0x81; | |
pOutOpCode->pbOpCode[3] = ADDRegisters::EBX; | |
memcpy(&pOutOpCode->pbOpCode[4], &pOpCode->pbOpCode[1], 4); // get that value. | |
break; | |
case MOVRegisters::ESP: | |
pOutOpCode->pbOpCode[0] = 0x29; | |
pOutOpCode->pbOpCode[1] = SUBRegisters::ESP; | |
pOutOpCode->pbOpCode[2] = 0x81; | |
pOutOpCode->pbOpCode[3] = ADDRegisters::ESP; | |
memcpy(&pOutOpCode->pbOpCode[4], &pOpCode->pbOpCode[1], 4); // get that value. | |
break; | |
case MOVRegisters::EBP: | |
pOutOpCode->pbOpCode[0] = 0x29; | |
pOutOpCode->pbOpCode[1] = SUBRegisters::EBP; | |
pOutOpCode->pbOpCode[2] = 0x81; | |
pOutOpCode->pbOpCode[3] = ADDRegisters::EBP; | |
memcpy(&pOutOpCode->pbOpCode[4], &pOpCode->pbOpCode[1], 4); // get that value. | |
break; | |
case MOVRegisters::ESI: | |
pOutOpCode->pbOpCode[0] = 0x29; | |
pOutOpCode->pbOpCode[1] = SUBRegisters::ESI; | |
pOutOpCode->pbOpCode[2] = 0x81; | |
pOutOpCode->pbOpCode[3] = ADDRegisters::ESI; | |
memcpy(&pOutOpCode->pbOpCode[4], &pOpCode->pbOpCode[1], 4); // get that value. | |
break; | |
case MOVRegisters::EDI: | |
pOutOpCode->pbOpCode[0] = 0x29; | |
pOutOpCode->pbOpCode[1] = SUBRegisters::EDI; | |
pOutOpCode->pbOpCode[2] = 0x81; | |
pOutOpCode->pbOpCode[3] = ADDRegisters::EDI; | |
memcpy(&pOutOpCode->pbOpCode[4], &pOpCode->pbOpCode[1], 4); // get that value. | |
break; | |
} | |
outAdd = 6; | |
} | |
} | |
PVOID __fastcall pMorphFunction(PVOID pFunction, PBYTE pFirstFive, DWORD& dwSize, PVOID pLastFunc = nullptr) | |
{ | |
if (*pFirstFive == 0x0) | |
memcpy(pFirstFive, pFunction, 5); | |
else | |
memcpy(pFunction, pFirstFive, 5); | |
std::vector<OPCODE*> vOpCodes = std::vector<OPCODE*>(); | |
uint32_t uiSize = 0; | |
PBYTE pCurrentByte = (PBYTE)pFunction; | |
while (*pCurrentByte != 0xC3 && *pCurrentByte != 0xC2 && *pCurrentByte != 0xCB && *pCurrentByte != 0xCA) | |
{ | |
OPCODE* pNewOp = new OPCODE(); | |
pNewOp->pbOpCode = pCurrentByte; | |
#pragma region MOV Mutation | |
if (bIsMOV(pNewOp->pbOpCode)) | |
{ | |
OPCODE * pMovOP = new OPCODE(); | |
int outAdd; | |
MutateMOV(pNewOp, pMovOP, outAdd); | |
uint32_t uiOpCodeSize = uiGetOpCodeSize(*pMovOP->pbOpCode) + outAdd; | |
pMovOP->usSize = uiOpCodeSize; | |
pMovOP->bRelative = bIsRelativeOpCode(*pMovOP->pbOpCode); | |
pMovOP->bMutated = true; | |
delete pNewOp; | |
vOpCodes.push_back(pMovOP); | |
pCurrentByte += uiOpCodeSize - (uiOpCodeSize - 5); | |
uiSize += uiOpCodeSize; | |
continue; | |
} | |
#pragma endregion | |
#pragma region PUSH Mutation | |
else if (bIsPUSH(pCurrentByte)) | |
{ | |
OPCODE * pPushOP = new OPCODE(); | |
pPushOP->pbOpCode = new BYTE[9]; | |
MutatePUSH(pNewOp, pPushOP); | |
uint32_t uiOpCodeSize = uiGetOpCodeSize(*pPushOP->pbOpCode) + 7; | |
pPushOP->usSize = uiOpCodeSize; | |
pPushOP->bRelative = bIsRelativeOpCode(*pPushOP->pbOpCode); | |
pPushOP->bMutated = true; | |
delete pNewOp; | |
vOpCodes.push_back(pPushOP); | |
pCurrentByte += uiOpCodeSize - 5; | |
uiSize += uiOpCodeSize; | |
continue; | |
} | |
#pragma endregion | |
uint32_t uiOpCodeSize = uiGetOpCodeSize(*pCurrentByte); | |
pNewOp->usSize = uiOpCodeSize; | |
pNewOp->bRelative = bIsRelativeOpCode(*pCurrentByte); | |
pNewOp->bMutated = false; | |
vOpCodes.push_back(pNewOp); | |
pCurrentByte += uiOpCodeSize; | |
uiSize += uiOpCodeSize; | |
} | |
if (*pCurrentByte == 0xC2 || *pCurrentByte == 0xCA) | |
{ | |
OPCODE* pNewOp = new OPCODE(); | |
pNewOp->pbOpCode = pCurrentByte; | |
pNewOp->usSize = 3; | |
pNewOp->bRelative = false; | |
vOpCodes.push_back(pNewOp); | |
uiSize += 3; | |
} | |
else | |
{ | |
OPCODE* pNewOp = new OPCODE(); | |
pNewOp->pbOpCode = pCurrentByte; | |
pNewOp->usSize = 1; | |
pNewOp->bRelative = false; | |
vOpCodes.push_back(pNewOp); | |
++uiSize; | |
} | |
uint32_t uiOpCodesSize = vOpCodes.size(); | |
PVOID pNewFunction = VirtualAlloc(pLastFunc != nullptr ? pLastFunc : NULL, uiOpCodesSize + uiSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); | |
memset(pNewFunction, 0x90, uiOpCodesSize + uiSize); | |
uint32_t uiCurrentOffset = 0; | |
for (unsigned int i = 0; i < uiOpCodesSize; ++i) | |
{ | |
OPCODE* pOpCode = vOpCodes.at(i); | |
memcpy((PVOID)((uint32_t)pNewFunction + uiCurrentOffset), pOpCode->pbOpCode, pOpCode->usSize); | |
if (pOpCode->bRelative) | |
{ | |
DWORD dwNewRelative = ((DWORD)pOpCode->pbOpCode + *(DWORD*)(pOpCode->pbOpCode + 1)) - ((DWORD)pNewFunction + uiCurrentOffset); | |
memcpy((PVOID)((uint32_t)pNewFunction + uiCurrentOffset + 1), &dwNewRelative, sizeof(DWORD)); | |
} | |
uiCurrentOffset += pOpCode->usSize; | |
++uiCurrentOffset; | |
if (pOpCode->bMutated) | |
delete[pOpCode->usSize] pOpCode->pbOpCode; | |
delete pOpCode; | |
int holdMeHereThanksBreakpoint = 0; | |
} | |
Hotpatch(pFunction, pNewFunction); | |
dwSize = uiOpCodesSize + uiSize; | |
return pNewFunction; | |
} | |
void __cdecl TestFunc() | |
{ | |
int eaxVal = 0; | |
_asm | |
{ | |
push ecx | |
mov ecx, 5 | |
mov eaxVal, ecx | |
pop ecx | |
} | |
printf("Testing %d\n", eaxVal); | |
} | |
int _tmain(int argc, _TCHAR* argv[]) | |
{ | |
PBYTE pFirstFive = (PBYTE)malloc(5); | |
RtlZeroMemory(pFirstFive, 5); | |
TestFunc(); | |
PVOID pLastFunc = nullptr; | |
DWORD dwLastSize = NULL; | |
while (true) | |
{ | |
if (pLastFunc != nullptr) | |
{ | |
VirtualFree(pLastFunc, dwLastSize, MEM_DECOMMIT); | |
VirtualFree(pLastFunc, 0, MEM_RELEASE);//dwLastSize needs to be 0 for this to work best jumbooo | |
} | |
pLastFunc = pMorphFunction(TestFunc, pFirstFive, dwLastSize); | |
TestFunc(); | |
system("pause"); | |
} | |
TestFunc(); | |
system("pause"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment