diff --git a/CodeVirtualizer/CodeVirtualizer.vcxproj b/CodeVirtualizer/CodeVirtualizer.vcxproj index 9976509..7307d50 100644 --- a/CodeVirtualizer/CodeVirtualizer.vcxproj +++ b/CodeVirtualizer/CodeVirtualizer.vcxproj @@ -151,7 +151,7 @@ - + @@ -160,7 +160,7 @@ - + diff --git a/CodeVirtualizer/CodeVirtualizer.vcxproj.filters b/CodeVirtualizer/CodeVirtualizer.vcxproj.filters index 2dcec48..10fbd2c 100644 --- a/CodeVirtualizer/CodeVirtualizer.vcxproj.filters +++ b/CodeVirtualizer/CodeVirtualizer.vcxproj.filters @@ -20,8 +20,8 @@ VirtualMachine - - Obfuscator + + Obfuscator\XorInstructions @@ -41,8 +41,8 @@ VirtualMachine - - Obfuscator + + Obfuscator\XorInstructions @@ -64,5 +64,8 @@ {cc5b78db-cdf7-4b83-9652-2722cbdec89e} + + {51b7ca69-a7e9-4634-9eb2-d70f211fe2d2} + \ No newline at end of file diff --git a/CodeVirtualizer/CryptedCode.cpp b/CodeVirtualizer/CryptedCode.cpp deleted file mode 100644 index e9132fc..0000000 --- a/CodeVirtualizer/CryptedCode.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "CryptedCode.h" - -PNATIVE_CODE_BLOCK RxEmitXorForInstruction(PNATIVE_CODE_LINK Link); \ No newline at end of file diff --git a/CodeVirtualizer/CryptedCode.h b/CodeVirtualizer/CryptedCode.h deleted file mode 100644 index d586418..0000000 --- a/CodeVirtualizer/CryptedCode.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __CRYPTED_CODE_H -#define __CRYPTED_CODE_H - -#include "Windas.h" -#include "XedWrap.h" -#include "NativeCode.h" - -PNATIVE_CODE_BLOCK RxEmitXorForInstruction(PNATIVE_CODE_LINK Link); - - -#endif diff --git a/CodeVirtualizer/Main.cpp b/CodeVirtualizer/Main.cpp index 80a0967..03ad7fb 100644 --- a/CodeVirtualizer/Main.cpp +++ b/CodeVirtualizer/Main.cpp @@ -4,6 +4,7 @@ #include "NativeCode.h" +#include "XorInstructions.h" UCHAR TestBuffer[]{ 0x48, 0x33, 0xC0, @@ -32,6 +33,18 @@ int main() NcFromBuffer(&Block, TestBuffer, TestBufferSize); NcDebugPrint(&Block); + NATIVE_CODE_LINK T; + T.RawDataSize = 7; + XOR_INST_DATA Data; + RtlSecureZeroMemory(&Data, sizeof(XOR_INST_DATA)); + PNATIVE_CODE_BLOCK NewBlock = ObfEmitPostXorForInst(&T, &Data, TRUE); + if (NewBlock) + { + printf("\n"); + NcDebugPrint(NewBlock); + printf("\n"); + NcPrintBlockCode(NewBlock); + } //PNATIVE_CODE_LINK temp = new NATIVE_CODE_LINK("Hello"); system("pause"); diff --git a/CodeVirtualizer/NativeCode.cpp b/CodeVirtualizer/NativeCode.cpp index 17b6aaf..435c94a 100644 --- a/CodeVirtualizer/NativeCode.cpp +++ b/CodeVirtualizer/NativeCode.cpp @@ -20,6 +20,18 @@ _NATIVE_CODE_LINK::_NATIVE_CODE_LINK(ULONG LabelId, _NATIVE_CODE_BLOCK* B) Flags = CODE_FLAG_IS_LABEL; } +_NATIVE_CODE_LINK::~_NATIVE_CODE_LINK() +{ + if (RawData) + delete RawData; +} + +_NATIVE_CODE_BLOCK::_NATIVE_CODE_BLOCK() +{ + Start = End = NULL; + HasRelativeJumps = FALSE; +} + VOID NcInsertLinkAfter(PNATIVE_CODE_LINK Link1, PNATIVE_CODE_LINK Link2) { if (Link1) @@ -63,7 +75,7 @@ VOID NcConcat(PNATIVE_CODE_BLOCK Block1, PNATIVE_CODE_BLOCK Block2) BOOL NcInsertBlockAfter(PNATIVE_CODE_LINK Link, PNATIVE_CODE_BLOCK Block) { - + return FALSE; } BOOL NcInsertBlockBefore(PNATIVE_CODE_LINK Link, PNATIVE_CODE_BLOCK Block) @@ -203,16 +215,21 @@ BOOL NcFromBuffer(PNATIVE_CODE_BLOCK Block, PVOID Buffer, ULONG BufferSize) delete Link; return FALSE; } + Link->RawDataSize = XedDecodedInstGetLength(&Link->XedInst); + Link->RawData = new UCHAR[Link->RawDataSize]; + Link->Block = Block; Link->Prev = Block->End; Block->End->Next = Link; Block->End = Link; - Offset += XedDecodedInstGetLength(&Link->XedInst); + Offset += Link->RawDataSize; } PNATIVE_CODE_LINK StartLink = Block->Start; Block->Start = Block->Start->Next; + if (Block->Start) + Block->Start->Prev = NULL; delete StartLink; NcCreateLabels(Block); @@ -260,3 +277,16 @@ VOID NcDebugPrint(PNATIVE_CODE_BLOCK Block) } } +VOID NcPrintBlockCode(PNATIVE_CODE_BLOCK Block) +{ + for (PNATIVE_CODE_LINK T = Block->Start; T; T = T->Next) + { + if (!(T->Flags & CODE_FLAG_IS_LABEL)) + { + for (uint32_t i = 0; i < T->RawDataSize; i++) + { + std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)T->RawData[i] << ' '; + } + } + } +} \ No newline at end of file diff --git a/CodeVirtualizer/NativeCode.h b/CodeVirtualizer/NativeCode.h index 820f276..4078202 100644 --- a/CodeVirtualizer/NativeCode.h +++ b/CodeVirtualizer/NativeCode.h @@ -19,6 +19,7 @@ typedef struct _NATIVE_CODE_LINK XED_DECODED_INST XedInst; _NATIVE_CODE_LINK(); _NATIVE_CODE_LINK(ULONG LabelId, _NATIVE_CODE_BLOCK* B); + ~_NATIVE_CODE_LINK(); }NATIVE_CODE_LINK, *PNATIVE_CODE_LINK; typedef struct _NATIVE_CODE_BLOCK @@ -26,6 +27,7 @@ typedef struct _NATIVE_CODE_BLOCK PNATIVE_CODE_LINK Start; PNATIVE_CODE_LINK End; BOOL HasRelativeJumps; + _NATIVE_CODE_BLOCK(); }NATIVE_CODE_BLOCK, *PNATIVE_CODE_BLOCK; VOID NcInsertLinkAfter(PNATIVE_CODE_LINK Link1, PNATIVE_CODE_LINK Link2); @@ -50,6 +52,6 @@ VOID NcDelete(PNATIVE_CODE_BLOCK Block); VOID NcDebugPrint(PNATIVE_CODE_BLOCK Block); - +VOID NcPrintBlockCode(PNATIVE_CODE_BLOCK Block); #endif \ No newline at end of file diff --git a/CodeVirtualizer/Windas.h b/CodeVirtualizer/Windas.h index ce53263..a03d179 100644 --- a/CodeVirtualizer/Windas.h +++ b/CodeVirtualizer/Windas.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include #define INLINE inline #define STDSTRING std::string diff --git a/CodeVirtualizer/XorInstructions.cpp b/CodeVirtualizer/XorInstructions.cpp new file mode 100644 index 0000000..2fe26da --- /dev/null +++ b/CodeVirtualizer/XorInstructions.cpp @@ -0,0 +1,303 @@ +#include "XorInstructions.h" + + +BOOL ObfEmitPushfqInst(PNATIVE_CODE_BLOCK Block) +{ + PNATIVE_CODE_LINK Link = new NATIVE_CODE_LINK; + Link->Flags = CODE_FLAG_IS_INST; + Link->RawData = new UCHAR[1]; + *(PUCHAR)(Link->RawData) = 0x9C; + Link->RawDataSize = 1; + XED_ERROR_ENUM DecodeError = XedDecode(&Link->XedInst, Link->RawData, 1); + if (DecodeError != XED_ERROR_NONE) + { + printf("Pushfq decode failed with error %s\n", XedErrorEnumToString(DecodeError)); + delete Link; + return FALSE; + } + Link->Block = Block; + Link->Prev = Block->End; + Block->End->Next = Link; + Block->End = Link; + return TRUE; +} + +BOOL ObfEmitPopfqInst(PNATIVE_CODE_BLOCK Block) +{ + PNATIVE_CODE_LINK Link = new NATIVE_CODE_LINK; + Link->Flags = CODE_FLAG_IS_INST; + Link->RawData = new UCHAR[1]; + *(PUCHAR)(Link->RawData) = 0x9D; + Link->RawDataSize = 1; + XED_ERROR_ENUM DecodeError = XedDecode(&Link->XedInst, Link->RawData, 1); + if (DecodeError != XED_ERROR_NONE) + { + printf("Popfq decode failed with error %s\n", XedErrorEnumToString(DecodeError)); + delete Link; + return FALSE; + } + Link->Block = Block; + Link->Prev = Block->End; + Block->End->Next = Link; + Block->End = Link; + return TRUE; +} + +BOOL ObfEmitRipRelativeXorD(PNATIVE_CODE_BLOCK Block, INT32 RipDelta, ULONG Value) +{ + UCHAR Bytes[] = { 0x81, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + PNATIVE_CODE_LINK Link = new NATIVE_CODE_LINK; + Link->Flags = CODE_FLAG_IS_INST; + Link->RawData = new UCHAR[DWORD_XOR_INST_LENGTH]; + Link->RawDataSize = DWORD_XOR_INST_LENGTH; + memcpy(Link->RawData, Bytes, DWORD_XOR_INST_LENGTH); + + *(PINT32)&Link->RawData[DWORD_XOR_INST_RIP_OFFSET] = RipDelta; + *(PULONG)&Link->RawData[DWORD_XOR_INST_XOR_OFFSET] = Value; + + XED_ERROR_ENUM DecodeError = XedDecode(&Link->XedInst, Link->RawData, Link->RawDataSize); + if (DecodeError != XED_ERROR_NONE) + { + printf("XedDecode failed with error %s\n", XedErrorEnumToString(DecodeError)); + delete Link; + return FALSE; + } + Link->Block = Block; + Link->Prev = Block->End; + Block->End->Next = Link; + Block->End = Link; + return TRUE; +} + +BOOL ObfEmitRipRelativeXorW(PNATIVE_CODE_BLOCK Block, INT32 RipDelta, ULONG Value) +{ + UCHAR Bytes[] = { 0x66, 0x81, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + PNATIVE_CODE_LINK Link = new NATIVE_CODE_LINK; + Link->Flags = CODE_FLAG_IS_INST; + Link->RawData = new UCHAR[WORD_XOR_INST_LENGTH]; + Link->RawDataSize = WORD_XOR_INST_LENGTH; + memcpy(Link->RawData, Bytes, WORD_XOR_INST_LENGTH); + + *(PINT32)&Link->RawData[WORD_XOR_INST_RIP_OFFSET] = RipDelta; + *(PUSHORT)&Link->RawData[WORD_XOR_INST_XOR_OFFSET] = (USHORT)Value; + + XED_ERROR_ENUM DecodeError = XedDecode(&Link->XedInst, Link->RawData, Link->RawDataSize); + if (DecodeError != XED_ERROR_NONE) + { + printf("XedDecode failed with error %s\n", XedErrorEnumToString(DecodeError)); + delete Link; + return FALSE; + } + Link->Block = Block; + Link->Prev = Block->End; + Block->End->Next = Link; + Block->End = Link; + return TRUE; +} + +BOOL ObfEmitRipRelativeXorB(PNATIVE_CODE_BLOCK Block, INT32 RipDelta, ULONG Value) +{ + UCHAR Bytes[] = { 0x80, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + PNATIVE_CODE_LINK Link = new NATIVE_CODE_LINK; + Link->Flags = CODE_FLAG_IS_INST; + Link->RawData = new UCHAR[BYTE_XOR_INST_LENGTH]; + Link->RawDataSize = BYTE_XOR_INST_LENGTH; + memcpy(Link->RawData, Bytes, BYTE_XOR_INST_LENGTH); + + *(PINT32)&Link->RawData[BYTE_XOR_INST_RIP_OFFSET] = RipDelta; + *(PUCHAR)&Link->RawData[BYTE_XOR_INST_XOR_OFFSET] = (UCHAR)Value; + + XED_ERROR_ENUM DecodeError = XedDecode(&Link->XedInst, Link->RawData, Link->RawDataSize); + if (DecodeError != XED_ERROR_NONE) + { + printf("XedDecode failed with error %s\n", XedErrorEnumToString(DecodeError)); + delete Link; + return FALSE; + } + Link->Block = Block; + Link->Prev = Block->End; + Block->End->Next = Link; + Block->End = Link; + return TRUE; +} + +PNATIVE_CODE_BLOCK ObfEmitPreXorForInst(PNATIVE_CODE_LINK Link, PXOR_INST_DATA XorData, BOOL SaveFlags) +{ + ULONG FourByte = Link->RawDataSize / 4; + ULONG TwoByte = (Link->RawDataSize - (FourByte * 4)) / 2; + ULONG OneByte = (Link->RawDataSize - (FourByte * 4) - (TwoByte * 2)); + + PNATIVE_CODE_BLOCK Block = new NATIVE_CODE_BLOCK; + + Block->Start = Block->End = new NATIVE_CODE_LINK; + + if (SaveFlags && !ObfEmitPushfqInst(Block)) + { + NcDelete(Block); + delete Block; + return NULL; + } + + ULONG Count = FourByte; + while (Count) + { + //Account for remaining XORs + INT32 RipDelta = (((Count - 1) * DWORD_XOR_INST_LENGTH) + (TwoByte * WORD_XOR_INST_LENGTH) + (OneByte * BYTE_XOR_INST_LENGTH)); + //Account for POPFQ + if (SaveFlags) + RipDelta += 1; + //Account for already XORd instructions + RipDelta += ((FourByte - Count) * 4); + //Add the actual instruction + if (!ObfEmitRipRelativeXorD(Block, RipDelta, XorData->Data[FourByte-Count])) + { + NcDelete(Block); + delete Block; + return NULL; + } + --Count; + } + + if (TwoByte) + { + INT32 RipDelta = (OneByte * BYTE_XOR_INST_LENGTH); + if (SaveFlags) + RipDelta += 1; + RipDelta += (FourByte * 4); + if (!ObfEmitRipRelativeXorW(Block, RipDelta, XorData->Data[3])) + { + NcDelete(Block); + delete Block; + return NULL; + } + } + + if (OneByte) + { + INT32 RipDelta = 0; + if (SaveFlags) + RipDelta += 1; + RipDelta += (FourByte * 4) + (TwoByte * 2); + if (!ObfEmitRipRelativeXorB(Block, RipDelta, XorData->Data[4])) + { + NcDelete(Block); + delete Block; + return NULL; + } + } + + if (SaveFlags && !ObfEmitPopfqInst(Block)) + { + NcDelete(Block); + delete Block; + return NULL; + } + + PNATIVE_CODE_LINK StartLink = Block->Start; + Block->Start = Block->Start->Next; + if (Block->Start) + Block->Start->Prev = NULL; + delete StartLink; + + return Block; +} + +PNATIVE_CODE_BLOCK ObfEmitPostXorForInst(PNATIVE_CODE_LINK Link, PXOR_INST_DATA XorData, BOOL SaveFlags) +{ + ULONG FourByte = Link->RawDataSize / 4; + ULONG TwoByte = (Link->RawDataSize - (FourByte * 4)) / 2; + ULONG OneByte = (Link->RawDataSize - (FourByte * 4) - (TwoByte * 2)); + + PNATIVE_CODE_BLOCK Block = new NATIVE_CODE_BLOCK; + + Block->Start = Block->End = new NATIVE_CODE_LINK; + + if (SaveFlags && !ObfEmitPushfqInst(Block)) + { + NcDelete(Block); + delete Block; + return NULL; + } + + ULONG Count = FourByte; + while (Count) + { + + INT32 RipDelta = Link->RawDataSize - ((FourByte - Count) * 4); + if (SaveFlags) + RipDelta += 1; + + RipDelta += (FourByte - (Count - 1)) * DWORD_XOR_INST_LENGTH; + + RipDelta *= (-1); + + if (!ObfEmitRipRelativeXorD(Block, RipDelta, XorData->Data[FourByte - Count])) + { + NcDelete(Block); + delete Block; + return NULL; + } + + --Count; + } + + if (TwoByte) + { + INT32 RipDelta = Link->RawDataSize - (FourByte * 4); + if (SaveFlags) + RipDelta += 1; + + RipDelta += (FourByte * DWORD_XOR_INST_LENGTH); + + RipDelta += WORD_XOR_INST_LENGTH; + + RipDelta *= (-1); + + if (!ObfEmitRipRelativeXorW(Block, RipDelta, XorData->Data[3])) + { + NcDelete(Block); + delete Block; + return NULL; + } + } + + if (OneByte) + { + INT32 RipDelta = Link->RawDataSize - (FourByte * 4) - (TwoByte * 2); + if (SaveFlags) + RipDelta += 1; + + RipDelta += (FourByte * DWORD_XOR_INST_LENGTH); + + RipDelta += WORD_XOR_INST_LENGTH; + + RipDelta += BYTE_XOR_INST_LENGTH; + + RipDelta *= (-1); + + if (!ObfEmitRipRelativeXorB(Block, RipDelta, XorData->Data[4])) + { + NcDelete(Block); + delete Block; + return NULL; + } + } + + if (SaveFlags && !ObfEmitPopfqInst(Block)) + { + NcDelete(Block); + delete Block; + return NULL; + } + + PNATIVE_CODE_LINK StartLink = Block->Start; + Block->Start = Block->Start->Next; + if (Block->Start) + Block->Start->Prev = NULL; + delete StartLink; + + return Block; +} \ No newline at end of file diff --git a/CodeVirtualizer/XorInstructions.h b/CodeVirtualizer/XorInstructions.h new file mode 100644 index 0000000..ab3476a --- /dev/null +++ b/CodeVirtualizer/XorInstructions.h @@ -0,0 +1,34 @@ +#ifndef __CRYPTED_CODE_H +#define __CRYPTED_CODE_H + +#include "Windas.h" +#include "XedWrap.h" +#include "NativeCode.h" + +#define DWORD_XOR_INST_LENGTH 10 +#define DWORD_XOR_INST_RIP_OFFSET 2 +#define DWORD_XOR_INST_XOR_OFFSET 6 + +#define WORD_XOR_INST_LENGTH 9 +#define WORD_XOR_INST_RIP_OFFSET 3 +#define WORD_XOR_INST_XOR_OFFSET 7 + +#define BYTE_XOR_INST_LENGTH 7 +#define BYTE_XOR_INST_RIP_OFFSET 2 +#define BYTE_XOR_INST_XOR_OFFSET 6 + + +typedef struct _XOR_INST_DATA +{ + ULONG Data[5]; +}XOR_INST_DATA, *PXOR_INST_DATA; + +BOOL ObfEmitPushfqInst(PNATIVE_CODE_BLOCK Block); +BOOL ObfEmitPopfqInst(PNATIVE_CODE_BLOCK Block); +BOOL ObfEmitRipRelativeXorD(PNATIVE_CODE_BLOCK Block, INT32 RipDelta, ULONG Value); +BOOL ObfEmitRipRelativeXorW(PNATIVE_CODE_BLOCK Block, INT32 RipDelta, ULONG Value); +BOOL ObfEmitRipRelativeXorB(PNATIVE_CODE_BLOCK Block, INT32 RipDelta, ULONG Value); +PNATIVE_CODE_BLOCK ObfEmitPreXorForInst(PNATIVE_CODE_LINK Link, PXOR_INST_DATA XorData, BOOL SaveFlags); +PNATIVE_CODE_BLOCK ObfEmitPostXorForInst(PNATIVE_CODE_LINK Link, PXOR_INST_DATA XorData, BOOL SaveFlags); + +#endif diff --git a/x64/Debug/CodeVirtualizer.ilk b/x64/Debug/CodeVirtualizer.ilk index c334703..3a5073e 100644 Binary files a/x64/Debug/CodeVirtualizer.ilk and b/x64/Debug/CodeVirtualizer.ilk differ