#include "RipXorInst.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; } VOID ObfXorInstBytes(PNATIVE_CODE_LINK Link, PXOR_INST_DATA XorData) { ULONG FourByte = Link->RawDataSize / 4; ULONG TwoByte = (Link->RawDataSize - (FourByte * 4)) / 2; ULONG OneByte = (Link->RawDataSize - (FourByte * 4) - (TwoByte * 2)); PUCHAR Buffer = Link->RawData; while (FourByte) { *(PULONG)Buffer ^= XorData->Data[2 - FourByte]; Buffer += 4; FourByte--; } if (TwoByte) { *(PUSHORT)Buffer ^= (USHORT)XorData->Data[3]; Buffer += 2; } if (OneByte) *(PUCHAR)Buffer ^= (UCHAR)XorData->Data[3]; } 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; }