|
|
@ -3,125 +3,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
BOOL ObfEmitPushfqInst(PNATIVE_CODE_BLOCK Block)
|
|
|
|
BOOL ObfEmitPushfqInst(PNATIVE_CODE_BLOCK Block)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
PNATIVE_CODE_LINK Link = new NATIVE_CODE_LINK;
|
|
|
|
UCHAR RawData[] = { 0x9C };
|
|
|
|
Link->Flags = CODE_FLAG_IS_INST;
|
|
|
|
PNATIVE_CODE_LINK Link = new NATIVE_CODE_LINK(CODE_FLAG_IS_INST, RawData, 1);
|
|
|
|
Link->RawData = new UCHAR[1];
|
|
|
|
XedDecode(&Link->XedInst, Link->RawData, 1);
|
|
|
|
*(PUCHAR)(Link->RawData) = 0x9C;
|
|
|
|
NcAppendToBlock(Block, Link);
|
|
|
|
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;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL ObfEmitPopfqInst(PNATIVE_CODE_BLOCK Block)
|
|
|
|
BOOL ObfEmitPopfqInst(PNATIVE_CODE_BLOCK Block)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
PNATIVE_CODE_LINK Link = new NATIVE_CODE_LINK;
|
|
|
|
UCHAR RawData[] = { 0x9D };
|
|
|
|
Link->Flags = CODE_FLAG_IS_INST;
|
|
|
|
PNATIVE_CODE_LINK Link = new NATIVE_CODE_LINK(CODE_FLAG_IS_INST, RawData, 1);
|
|
|
|
Link->RawData = new UCHAR[1];
|
|
|
|
XedDecode(&Link->XedInst, Link->RawData, 1);
|
|
|
|
*(PUCHAR)(Link->RawData) = 0x9D;
|
|
|
|
NcAppendToBlock(Block, Link);
|
|
|
|
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;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL ObfEmitRipRelativeXorD(PNATIVE_CODE_BLOCK Block, INT32 RipDelta, ULONG Value)
|
|
|
|
BOOL ObfEmitRipRelativeXorD(PNATIVE_CODE_BLOCK Block, INT32 RipDelta, ULONG Value)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
UCHAR Bytes[] = { 0x81, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
|
|
|
UCHAR RawData[] = { 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);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PNATIVE_CODE_LINK Link = new NATIVE_CODE_LINK(CODE_FLAG_IS_INST, RawData, sizeof(RawData));
|
|
|
|
*(PINT32)&Link->RawData[DWORD_XOR_INST_RIP_OFFSET] = RipDelta;
|
|
|
|
*(PINT32)&Link->RawData[DWORD_XOR_INST_RIP_OFFSET] = RipDelta;
|
|
|
|
*(PULONG)&Link->RawData[DWORD_XOR_INST_XOR_OFFSET] = Value;
|
|
|
|
*(PULONG)&Link->RawData[DWORD_XOR_INST_XOR_OFFSET] = Value;
|
|
|
|
|
|
|
|
XedDecode(&Link->XedInst, Link->RawData, Link->RawDataSize);
|
|
|
|
XED_ERROR_ENUM DecodeError = XedDecode(&Link->XedInst, Link->RawData, Link->RawDataSize);
|
|
|
|
NcAppendToBlock(Block, Link);
|
|
|
|
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;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL ObfEmitRipRelativeXorW(PNATIVE_CODE_BLOCK Block, INT32 RipDelta, ULONG Value)
|
|
|
|
BOOL ObfEmitRipRelativeXorW(PNATIVE_CODE_BLOCK Block, INT32 RipDelta, ULONG Value)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
UCHAR Bytes[] = { 0x66, 0x81, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
|
|
|
UCHAR RawData[] = { 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);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PNATIVE_CODE_LINK Link = new NATIVE_CODE_LINK(CODE_FLAG_IS_INST, RawData, sizeof(RawData));
|
|
|
|
*(PINT32)&Link->RawData[WORD_XOR_INST_RIP_OFFSET] = RipDelta;
|
|
|
|
*(PINT32)&Link->RawData[WORD_XOR_INST_RIP_OFFSET] = RipDelta;
|
|
|
|
*(PUSHORT)&Link->RawData[WORD_XOR_INST_XOR_OFFSET] = (USHORT)Value;
|
|
|
|
*(PUSHORT)&Link->RawData[WORD_XOR_INST_XOR_OFFSET] = (USHORT)Value;
|
|
|
|
|
|
|
|
XedDecode(&Link->XedInst, Link->RawData, Link->RawDataSize);
|
|
|
|
XED_ERROR_ENUM DecodeError = XedDecode(&Link->XedInst, Link->RawData, Link->RawDataSize);
|
|
|
|
NcAppendToBlock(Block, Link);
|
|
|
|
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;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL ObfEmitRipRelativeXorB(PNATIVE_CODE_BLOCK Block, INT32 RipDelta, ULONG Value)
|
|
|
|
BOOL ObfEmitRipRelativeXorB(PNATIVE_CODE_BLOCK Block, INT32 RipDelta, ULONG Value)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
UCHAR Bytes[] = { 0x80, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
|
|
|
UCHAR RawData[] = { 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);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PNATIVE_CODE_LINK Link = new NATIVE_CODE_LINK(CODE_FLAG_IS_INST, RawData, sizeof(RawData));
|
|
|
|
*(PINT32)&Link->RawData[BYTE_XOR_INST_RIP_OFFSET] = RipDelta;
|
|
|
|
*(PINT32)&Link->RawData[BYTE_XOR_INST_RIP_OFFSET] = RipDelta;
|
|
|
|
*(PUCHAR)&Link->RawData[BYTE_XOR_INST_XOR_OFFSET] = (UCHAR)Value;
|
|
|
|
*(PUCHAR)&Link->RawData[BYTE_XOR_INST_XOR_OFFSET] = (UCHAR)Value;
|
|
|
|
|
|
|
|
XedDecode(&Link->XedInst, Link->RawData, Link->RawDataSize);
|
|
|
|
XED_ERROR_ENUM DecodeError = XedDecode(&Link->XedInst, Link->RawData, Link->RawDataSize);
|
|
|
|
NcAppendToBlock(Block, Link);
|
|
|
|
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;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -150,6 +80,78 @@ VOID ObfXorInstBytes(PNATIVE_CODE_LINK Link, PXOR_INST_DATA XorData)
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL ObfiCheckXorFlagCollisions(CONST XED_FLAG_SET* FlagsRead, XED_FLAG_SET Ledger)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return ((FlagsRead->s.zf && FlagsRead->s.zf == Ledger.s.zf) ||
|
|
|
|
|
|
|
|
(FlagsRead->s.sf && FlagsRead->s.sf == Ledger.s.sf) ||
|
|
|
|
|
|
|
|
(FlagsRead->s.pf && FlagsRead->s.pf == Ledger.s.pf) ||
|
|
|
|
|
|
|
|
(FlagsRead->s.of && FlagsRead->s.of == Ledger.s.of) ||
|
|
|
|
|
|
|
|
(FlagsRead->s.cf && FlagsRead->s.cf == Ledger.s.cf) ||
|
|
|
|
|
|
|
|
(FlagsRead->s.af && FlagsRead->s.af == Ledger.s.af)
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VOID ObfiUpdateXorLedger(CONST XED_FLAG_SET* FlagsWritten, XED_FLAG_SET* Ledger)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (FlagsWritten->s.zf)
|
|
|
|
|
|
|
|
Ledger->s.zf = FALSE;
|
|
|
|
|
|
|
|
if (FlagsWritten->s.sf)
|
|
|
|
|
|
|
|
Ledger->s.sf = FALSE;
|
|
|
|
|
|
|
|
if (FlagsWritten->s.pf)
|
|
|
|
|
|
|
|
Ledger->s.pf = FALSE;
|
|
|
|
|
|
|
|
if (FlagsWritten->s.of)
|
|
|
|
|
|
|
|
Ledger->s.of = FALSE;
|
|
|
|
|
|
|
|
if (FlagsWritten->s.cf)
|
|
|
|
|
|
|
|
Ledger->s.cf = FALSE;
|
|
|
|
|
|
|
|
if (FlagsWritten->s.af)
|
|
|
|
|
|
|
|
Ledger->s.af = FALSE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL ObfDoesInstWriteToAllXorFlags(PNATIVE_CODE_LINK Link)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
CONST XED_SIMPLE_FLAG* SimpleFlags = XedDecodedInstGetRflagsInfo(&Link->XedInst);
|
|
|
|
|
|
|
|
CONST XED_FLAG_SET* FlagsWritten = XedSimpleFlagGetWrittenFlagSet(SimpleFlags);
|
|
|
|
|
|
|
|
CONST XED_FLAG_SET* FlagsUndefined = XedSimpleFlagGetUndefinedFlagSet(SimpleFlags);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (FlagsWritten->s.zf &&
|
|
|
|
|
|
|
|
FlagsWritten->s.sf &&
|
|
|
|
|
|
|
|
FlagsWritten->s.pf &&
|
|
|
|
|
|
|
|
FlagsWritten->s.of &&
|
|
|
|
|
|
|
|
FlagsWritten->s.cf &&
|
|
|
|
|
|
|
|
FlagsUndefined->s.af
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL ObfAreXorFlagsClobberedBeforeUse(PNATIVE_CODE_LINK Link)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
XED_FLAG_SET Ledger;
|
|
|
|
|
|
|
|
Ledger.s.zf = TRUE;
|
|
|
|
|
|
|
|
Ledger.s.sf = TRUE;
|
|
|
|
|
|
|
|
Ledger.s.pf = TRUE;
|
|
|
|
|
|
|
|
Ledger.s.of = TRUE;
|
|
|
|
|
|
|
|
Ledger.s.cf = TRUE;
|
|
|
|
|
|
|
|
Ledger.s.af = TRUE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (PNATIVE_CODE_LINK T = Link->Next; T; T = T->Next)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (T->Flags & CODE_FLAG_IS_LABEL)
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CONST XED_SIMPLE_FLAG* SimpleFlags = XedDecodedInstGetRflagsInfo(&T->XedInst);
|
|
|
|
|
|
|
|
CONST XED_FLAG_SET* FlagsRead = XedSimpleFlagGetReadFlagSet(SimpleFlags);
|
|
|
|
|
|
|
|
CONST XED_FLAG_SET* FlagsWritten = XedSimpleFlagGetWrittenFlagSet(SimpleFlags);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ObfiCheckXorFlagCollisions(FlagsRead, Ledger))
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ObfiUpdateXorLedger(FlagsWritten, &Ledger);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (Ledger.flat == 0)
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PNATIVE_CODE_BLOCK ObfEmitPreXorForInst(PNATIVE_CODE_LINK Link, PXOR_INST_DATA XorData, BOOL SaveFlags, INT32 DeltaToInst)
|
|
|
|
PNATIVE_CODE_BLOCK ObfEmitPreXorForInst(PNATIVE_CODE_LINK Link, PXOR_INST_DATA XorData, BOOL SaveFlags, INT32 DeltaToInst)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ULONG FourByte = Link->RawDataSize / 4;
|
|
|
|
ULONG FourByte = Link->RawDataSize / 4;
|
|
|
@ -157,8 +159,8 @@ PNATIVE_CODE_BLOCK ObfEmitPreXorForInst(PNATIVE_CODE_LINK Link, PXOR_INST_DATA X
|
|
|
|
ULONG OneByte = (Link->RawDataSize - (FourByte * 4) - (TwoByte * 2));
|
|
|
|
ULONG OneByte = (Link->RawDataSize - (FourByte * 4) - (TwoByte * 2));
|
|
|
|
|
|
|
|
|
|
|
|
PNATIVE_CODE_BLOCK Block = new NATIVE_CODE_BLOCK;
|
|
|
|
PNATIVE_CODE_BLOCK Block = new NATIVE_CODE_BLOCK;
|
|
|
|
|
|
|
|
if (!Block)
|
|
|
|
Block->Start = Block->End = new NATIVE_CODE_LINK;
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
|
|
if (SaveFlags && !ObfEmitPushfqInst(Block))
|
|
|
|
if (SaveFlags && !ObfEmitPushfqInst(Block))
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -225,12 +227,6 @@ PNATIVE_CODE_BLOCK ObfEmitPreXorForInst(PNATIVE_CODE_LINK Link, PXOR_INST_DATA X
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PNATIVE_CODE_LINK StartLink = Block->Start;
|
|
|
|
|
|
|
|
Block->Start = Block->Start->Next;
|
|
|
|
|
|
|
|
if (Block->Start)
|
|
|
|
|
|
|
|
Block->Start->Prev = NULL;
|
|
|
|
|
|
|
|
delete StartLink;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Block;
|
|
|
|
return Block;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -241,8 +237,8 @@ PNATIVE_CODE_BLOCK ObfEmitPostXorForInst(PNATIVE_CODE_LINK Link, PXOR_INST_DATA
|
|
|
|
ULONG OneByte = (Link->RawDataSize - (FourByte * 4) - (TwoByte * 2));
|
|
|
|
ULONG OneByte = (Link->RawDataSize - (FourByte * 4) - (TwoByte * 2));
|
|
|
|
|
|
|
|
|
|
|
|
PNATIVE_CODE_BLOCK Block = new NATIVE_CODE_BLOCK;
|
|
|
|
PNATIVE_CODE_BLOCK Block = new NATIVE_CODE_BLOCK;
|
|
|
|
|
|
|
|
if (!Block)
|
|
|
|
Block->Start = Block->End = new NATIVE_CODE_LINK;
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
|
|
if (SaveFlags && !ObfEmitPushfqInst(Block))
|
|
|
|
if (SaveFlags && !ObfEmitPushfqInst(Block))
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -311,11 +307,5 @@ PNATIVE_CODE_BLOCK ObfEmitPostXorForInst(PNATIVE_CODE_LINK Link, PXOR_INST_DATA
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PNATIVE_CODE_LINK StartLink = Block->Start;
|
|
|
|
|
|
|
|
Block->Start = Block->Start->Next;
|
|
|
|
|
|
|
|
if (Block->Start)
|
|
|
|
|
|
|
|
Block->Start->Prev = NULL;
|
|
|
|
|
|
|
|
delete StartLink;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Block;
|
|
|
|
return Block;
|
|
|
|
}
|
|
|
|
}
|
|
|
|