Last active
November 3, 2023 17:20
-
-
Save jackullrich/ce3b5263e05c88548b175f4f21909384 to your computer and use it in GitHub Desktop.
Single Step Encryption/Decryption
This file contains 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 <Windows.h> | |
LONG SingleStepEncryptDecrypt(EXCEPTION_POINTERS* ExceptionInfo); | |
typedef VOID(__stdcall* Shellcode)(); | |
LPBYTE ShellcodeBuffer; | |
ULONG_PTR PreviousOffset; | |
ULONG_PTR CurrentOffset; | |
ULONGLONG InstructionCount; | |
DWORD dwOld; | |
// Hello World! shellcode encrypted with single byte xor (0xff) | |
unsigned char Shellcode_XOR_FF[400] = | |
{ | |
0x16, 0xF4, 0xFE, 0xFF, 0xFF, 0x33, 0x33, 0x33, 0xB7, 0x74, 0x3B, 0xB7, 0x76, 0xA7, 0xF7, 0xB7, | |
0x76, 0x97, 0xEF, 0xB7, 0x76, 0x8F, 0xE7, 0xB7, 0x76, 0x87, 0xDF, 0xBE, 0xA9, 0xBE, 0xA8, 0x9A, | |
0xB7, 0x74, 0xFB, 0xDA, 0x9F, 0xFF, 0xFF, 0xFF, 0xBB, 0x74, 0x06, 0xB7, 0x74, 0xAF, 0xE7, 0xB3, | |
0x74, 0x8D, 0xDF, 0xB2, 0x74, 0x39, 0xB2, 0x74, 0xB7, 0xDF, 0xB2, 0x74, 0xFF, 0xB2, 0x7A, 0x36, | |
0xF0, 0x7B, 0x76, 0xFF, 0xFF, 0xFF, 0xB6, 0x9C, 0xBE, 0xC3, 0xBD, 0x74, 0x73, 0xF7, 0x77, 0xFF, | |
0xFF, 0xFF, 0x7A, 0x36, 0x8B, 0x86, 0xB2, 0x72, 0xEB, 0xF6, 0xBE, 0x74, 0xAD, 0xF3, 0xB6, 0xFC, | |
0x2E, 0xCC, 0x00, 0x14, 0xE9, 0x3E, 0x30, 0xF2, 0xBE, 0xF0, 0x41, 0x34, 0xBE, 0x7F, 0x04, 0x9E, | |
0x72, 0xBE, 0x1F, 0xF0, 0xB3, 0x3E, 0xFC, 0x07, 0xB7, 0x00, 0x3D, 0xBB, 0x75, 0xE5, 0xBA, 0x7B, | |
0x24, 0x8A, 0x1D, 0xBE, 0x74, 0xAD, 0xDF, 0xBA, 0xCC, 0x24, 0xB6, 0xFC, 0x2E, 0xBA, 0xC6, 0xA5, | |
0xE7, 0x89, 0xC3, 0x74, 0xE5, 0xB6, 0xFC, 0x26, 0xCC, 0x09, 0x14, 0xE9, 0x3E, 0x31, 0xF2, 0xBF, | |
0xF0, 0x41, 0x32, 0xBF, 0x7F, 0x02, 0x9E, 0x72, 0xBE, 0x1F, 0xF0, 0xB3, 0x3E, 0xFC, 0x0F, 0xB7, | |
0x00, 0x3C, 0xBF, 0x75, 0xD4, 0xBF, 0x7B, 0x12, 0x8A, 0x1D, 0x72, 0xFB, 0xC1, 0xBB, 0xC4, 0x07, | |
0x8B, 0xCE, 0xBE, 0x00, 0x3C, 0xB7, 0x7C, 0x3D, 0xFB, 0xBA, 0xC4, 0xA5, 0xE7, 0x8D, 0x3B, 0xB2, | |
0xC4, 0x39, 0xF0, 0x7A, 0xA1, 0x00, 0x00, 0x00, 0xCC, 0x3F, 0xB7, 0x74, 0xA3, 0xDB, 0xE7, 0xB7, | |
0x74, 0x93, 0xDB, 0xDF, 0xB7, 0x74, 0x8B, 0xDB, 0xD7, 0xB7, 0x74, 0x83, 0xDB, 0xCF, 0xBE, 0xA0, | |
0xBE, 0xA1, 0x3C, 0xBE, 0x74, 0xB5, 0xDB, 0xB6, 0xFC, 0x36, 0xB9, 0xF0, 0x48, 0xFB, 0xA6, 0xBE, | |
0x74, 0xB5, 0xE3, 0xB6, 0xFC, 0x36, 0xBD, 0x74, 0xFB, 0x7E, 0xB6, 0xFC, 0x3E, 0x14, 0x34, 0x33, | |
0xBF, 0xAA, 0xB7, 0x74, 0x13, 0xB7, 0x7C, 0x13, 0xAF, 0xCC, 0x3F, 0x38, 0xBA, 0x2F, 0x8A, 0x8C, | |
0x9A, 0x8D, 0x46, 0x72, 0xEF, 0x48, 0x07, 0x77, 0xBA, 0x25, 0x77, 0xBA, 0x15, 0x77, 0xBA, 0x03, | |
0x38, 0xBA, 0x2B, 0xCC, 0xCD, 0xD1, 0x9B, 0x99, 0x38, 0xBA, 0x27, 0x93, 0x93, 0x38, 0xBA, 0x1F, | |
0xAC, 0x97, 0x9A, 0x93, 0x38, 0xBA, 0x1B, 0x93, 0xAC, 0x8B, 0x9B, 0x99, 0x38, 0xBA, 0x17, 0x96, | |
0x90, 0x38, 0xBA, 0x0F, 0xB7, 0x9A, 0x93, 0x93, 0x38, 0xBA, 0x0B, 0x90, 0xDF, 0xA8, 0x90, 0x38, | |
0xBA, 0x07, 0x8D, 0x93, 0x9B, 0xDE, 0x17, 0x62, 0x01, 0x00, 0x00, 0xB7, 0x72, 0xB2, 0x2F, 0x00, | |
0x2F, 0x46, 0x61, 0x87, 0x87, 0x32, 0x17, 0x72, 0x01, 0x00, 0x00, 0xBA, 0xCC, 0x36, 0xB3, 0x72, | |
0xBA, 0x1F, 0xB7, 0x72, 0xAA, 0x0F, 0xCC, 0x36, 0x00, 0x2F, 0xB7, 0x7C, 0x3B, 0xAF, 0xA2, 0x3C | |
}; | |
LONG SingleStepEncryptDecrypt(EXCEPTION_POINTERS* ExceptionInfo) | |
{ | |
BYTE* currentBlock128 = NULL; | |
CurrentOffset = (ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress - (ULONG_PTR)ShellcodeBuffer; | |
if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_GUARD_PAGE) | |
{ | |
// This is a naive disassembler | |
// Hopefully no instruction is longer than 16 bytes | |
currentBlock128 = (BYTE*)((ULONG_PTR)ShellcodeBuffer + CurrentOffset); | |
PreviousOffset = CurrentOffset; | |
// Decrypt next 16-byte block | |
VirtualProtect(ShellcodeBuffer, 0x1000, PAGE_READWRITE, &dwOld); | |
for (size_t i = 0; i < 0x10; i++) | |
*(BYTE*)(currentBlock128 + i) ^= 0xff; | |
VirtualProtect(ShellcodeBuffer, 0x1000, PAGE_EXECUTE_READ, &dwOld); | |
// Single step | |
ExceptionInfo->ContextRecord->EFlags |= 0x100; | |
InstructionCount++; | |
// Execute next instruction | |
// Triggers EXCEPTION_SINGLE_STEP | |
return EXCEPTION_CONTINUE_EXECUTION; | |
} | |
else if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP) | |
{ | |
currentBlock128 = (BYTE*)((ULONG_PTR)ShellcodeBuffer + PreviousOffset); | |
// Re-encrypt the 16-byte block | |
VirtualProtect(ShellcodeBuffer, 0x1000, PAGE_READWRITE, &dwOld); | |
for (size_t i = 0; i < 0x10; i++) | |
*(BYTE*)(currentBlock128 + i) ^= 0xff; | |
VirtualProtect(ShellcodeBuffer, 0x1000, PAGE_EXECUTE_READ | PAGE_GUARD, &dwOld); | |
// Continue execution at next instruction | |
// Triggers EXCEPTION_GUARD_PAGE | |
return EXCEPTION_CONTINUE_EXECUTION; | |
} | |
else | |
{ | |
return EXCEPTION_CONTINUE_SEARCH; | |
} | |
} | |
int main(void) | |
{ | |
AddVectoredExceptionHandler(TRUE, (PVECTORED_EXCEPTION_HANDLER)SingleStepEncryptDecrypt); | |
ShellcodeBuffer = (LPBYTE)VirtualAlloc(NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); | |
InstructionCount = 0; | |
if (ShellcodeBuffer) | |
{ | |
RtlCopyMemory(ShellcodeBuffer, Shellcode_XOR_FF, sizeof(Shellcode_XOR_FF)); | |
if (VirtualProtect(ShellcodeBuffer, 0x1000, PAGE_EXECUTE_READ | PAGE_GUARD, &dwOld)) | |
{ | |
Shellcode AntiMem = (Shellcode)ShellcodeBuffer; | |
AntiMem(); | |
} | |
} | |
RemoveVectoredExceptionHandler((PVECTORED_EXCEPTION_HANDLER)SingleStepEncryptDecrypt); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment