#include "Jit.h" #include "RipXorInst.h" #include "RipAndInst.h" #include "RipOrInst.h" #include "RipMovInst.h" BOOL JitEmitPushfqInst(PNATIVE_CODE_BLOCK Block) { UCHAR RawData[] = { 0x9C }; PNATIVE_CODE_LINK Link = new NATIVE_CODE_LINK(CODE_FLAG_IS_INST, RawData, 1); XedDecode(&Link->XedInstruction, Link->RawData, 1); NcAppendToBlock(Block, Link); return TRUE; } BOOL JitEmitPopfqInst(PNATIVE_CODE_BLOCK Block) { UCHAR RawData[] = { 0x9D }; PNATIVE_CODE_LINK Link = new NATIVE_CODE_LINK(CODE_FLAG_IS_INST, RawData, 1); XedDecode(&Link->XedInstruction, Link->RawData, 1); NcAppendToBlock(Block, Link); return TRUE; } BOOL JitCheckFlagCollisions(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 JitUpdateConFlagsLedger(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 JitDoesInstOverriteConditionFlags(PNATIVE_CODE_LINK Link) { CONST XED_SIMPLE_FLAG* SimpleFlags = XedDecodedInstGetRflagsInfo(&Link->XedInstruction); 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 JitAreFlagsClobberedBeforeUse(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->XedInstruction); CONST XED_FLAG_SET* FlagsRead = XedSimpleFlagGetReadFlagSet(SimpleFlags); CONST XED_FLAG_SET* FlagsWritten = XedSimpleFlagGetWrittenFlagSet(SimpleFlags); if (JitCheckFlagCollisions(FlagsRead, Ledger)) return FALSE; JitUpdateConFlagsLedger(FlagsWritten, &Ledger); if (Ledger.flat == 0) return TRUE; } return FALSE; } VOID JitMutateInstForXor(PNATIVE_CODE_LINK Link, PJIT_BITWISE_DATA JitData) { 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 ^= JitData->Data[2 - FourByte]; Buffer += 4; FourByte--; } if (TwoByte) { *(PUSHORT)Buffer ^= (USHORT)JitData->Data[3]; Buffer += 2; } if (OneByte) *(PUCHAR)Buffer ^= (UCHAR)JitData->Data[3]; } VOID JitMutateInstForOr(PNATIVE_CODE_LINK Link, PJIT_BITWISE_DATA JitData) { } VOID JitMutateInstForAnd(PNATIVE_CODE_LINK Link, PJIT_BITWISE_DATA JitData) { } PNATIVE_CODE_BLOCK JitEmitPreRipMov(PNATIVE_CODE_LINK Link, INT32 Delta) { 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; PUCHAR DataOffset = Link->RawData; ULONG Count = FourByte; while (Count) { //Account for remaining MOVs INT32 RipDelta = (((Count - 1) * DWORD_MOV_INST_LENGTH) + (TwoByte * WORD_MOV_INST_LENGTH) + (OneByte * BYTE_MOV_INST_LENGTH)); //Account for already MOVd instructions RipDelta += ((FourByte - Count) * 4); RipDelta += Delta; //Add the actual instruction if (!JitEmitRipRelativeMovD(Block, RipDelta, DataOffset)) { NcDeleteBlock(Block); delete Block; return NULL; } DataOffset += 4; --Count; } if (TwoByte) { INT32 RipDelta = (OneByte * BYTE_MOV_INST_LENGTH); RipDelta += (FourByte * 4); RipDelta += Delta; if (!JitEmitRipRelativeMovW(Block, RipDelta, DataOffset)) { NcDeleteBlock(Block); delete Block; return NULL; } DataOffset += 2; } if (OneByte) { INT32 RipDelta = 0; RipDelta += (FourByte * 4) + (TwoByte * 2); RipDelta += Delta; if (!JitEmitRipRelativeMovB(Block, RipDelta, DataOffset)) { NcDeleteBlock(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 JitEmitPostRipMov(PNATIVE_CODE_LINK Link, INT32 Delta) { 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; ULONG ZeroValue = 0; ULONG Count = FourByte; while (Count) { INT32 RipDelta = Link->RawDataSize - ((FourByte - Count) * 4); RipDelta += (FourByte - (Count - 1)) * DWORD_MOV_INST_LENGTH; RipDelta *= (-1); RipDelta += Delta; ZeroValue = rand(); if (!JitEmitRipRelativeMovD(Block, RipDelta, (PUCHAR)&ZeroValue)) { NcDeleteBlock(Block); delete Block; return NULL; } --Count; } if (TwoByte) { INT32 RipDelta = Link->RawDataSize - (FourByte * 4); RipDelta += (FourByte * DWORD_MOV_INST_LENGTH); RipDelta += WORD_MOV_INST_LENGTH; RipDelta *= (-1); RipDelta += Delta; ZeroValue = rand(); if (!JitEmitRipRelativeMovW(Block, RipDelta, (PUCHAR)&ZeroValue)) { NcDeleteBlock(Block); delete Block; return NULL; } } if (OneByte) { INT32 RipDelta = Link->RawDataSize - (FourByte * 4) - (TwoByte * 2); RipDelta += (FourByte * DWORD_MOV_INST_LENGTH); RipDelta += (TwoByte * WORD_MOV_INST_LENGTH); RipDelta += BYTE_MOV_INST_LENGTH; RipDelta *= (-1); RipDelta += Delta; ZeroValue = rand(); if (!JitEmitRipRelativeMovB(Block, RipDelta, (PUCHAR)&ZeroValue)) { NcDeleteBlock(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; } INLINE BOOL JitiEmitWrapperD(ULONG OpType, PNATIVE_CODE_BLOCK Block, INT32 RipDelta, ULONG Value) { switch (OpType) { case JIT_BITWISE_XOR: return JitEmitRipRelativeXorD(Block, RipDelta, Value); case JIT_BITWISE_AND: return JitEmitRipRelativeAndD(Block, RipDelta, Value); case JIT_BITWISE_OR: return JitEmitRipRelativeOrD(Block, RipDelta, Value); } } INLINE BOOL JitiEmitWrapperW(ULONG OpType, PNATIVE_CODE_BLOCK Block, INT32 RipDelta, ULONG Value) { switch (OpType) { case JIT_BITWISE_XOR: return JitEmitRipRelativeXorW(Block, RipDelta, Value); case JIT_BITWISE_AND: return JitEmitRipRelativeAndW(Block, RipDelta, Value); case JIT_BITWISE_OR: return JitEmitRipRelativeOrW(Block, RipDelta, Value); } } INLINE BOOL JitiEmitWrapperB(ULONG OpType, PNATIVE_CODE_BLOCK Block, INT32 RipDelta, ULONG Value) { switch (OpType) { case JIT_BITWISE_XOR: return JitEmitRipRelativeXorB(Block, RipDelta, Value); case JIT_BITWISE_AND: return JitEmitRipRelativeAndB(Block, RipDelta, Value); case JIT_BITWISE_OR: return JitEmitRipRelativeOrB(Block, RipDelta, Value); } } PNATIVE_CODE_BLOCK JitEmitPreRipBitwiseOp(PNATIVE_CODE_LINK Link, PJIT_BITWISE_DATA JitData, ULONG OpType, BOOL SaveFlags, INT32 Delta) { 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; if (!Block) return NULL; if (SaveFlags && !JitEmitPushfqInst(Block)) { NcDeleteBlock(Block); delete Block; return NULL; } ULONG Count = FourByte; while (Count) { INT32 RipDelta = (((Count - 1) * DWORD_RIP_INST_LENGTH) + (TwoByte * WORD_RIP_INST_LENGTH) + (OneByte * BYTE_RIP_INST_LENGTH)); if (SaveFlags) RipDelta += 1; RipDelta += ((FourByte - Count) * 4); RipDelta += Delta; if (!JitiEmitWrapperD(OpType, Block, RipDelta, JitData->Data[FourByte - Count])) { NcDeleteBlock(Block); delete Block; return NULL; } --Count; } if (TwoByte) { INT32 RipDelta = (OneByte * BYTE_RIP_INST_LENGTH); if (SaveFlags) RipDelta += 1; RipDelta += (FourByte * 4); RipDelta += Delta; if (!JitiEmitWrapperW(OpType, Block, RipDelta, JitData->Data[3])) { NcDeleteBlock(Block); delete Block; return NULL; } } if (OneByte) { INT32 RipDelta = 0; if (SaveFlags) RipDelta += 1; RipDelta += (FourByte * 4) + (TwoByte * 2); RipDelta += Delta; if (!JitiEmitWrapperB(OpType, Block, RipDelta, JitData->Data[4])) { NcDeleteBlock(Block); delete Block; return NULL; } } if (SaveFlags && !JitEmitPopfqInst(Block)) { NcDeleteBlock(Block); delete Block; return NULL; } return Block; } PNATIVE_CODE_BLOCK JitEmitPostRipBitwiseOp(PNATIVE_CODE_LINK Link, PJIT_BITWISE_DATA JitData, ULONG OpType, BOOL SaveFlags, INT32 Delta) { 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; if (!Block) return NULL; if (SaveFlags && !JitEmitPushfqInst(Block)) { NcDeleteBlock(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_RIP_INST_LENGTH; RipDelta *= (-1); RipDelta += Delta; if (!JitiEmitWrapperD(OpType, Block, RipDelta, JitData->Data[FourByte - Count])) { NcDeleteBlock(Block); delete Block; return NULL; } --Count; } if (TwoByte) { INT32 RipDelta = Link->RawDataSize - (FourByte * 4); if (SaveFlags) RipDelta += 1; RipDelta += (FourByte * DWORD_RIP_INST_LENGTH); RipDelta += WORD_RIP_INST_LENGTH; RipDelta *= (-1); RipDelta += Delta; if (!JitiEmitWrapperW(OpType, Block, RipDelta, JitData->Data[3])) { NcDeleteBlock(Block); delete Block; return NULL; } } if (OneByte) { INT32 RipDelta = Link->RawDataSize - (FourByte * 4) - (TwoByte * 2); if (SaveFlags) RipDelta += 1; RipDelta += (FourByte * DWORD_RIP_INST_LENGTH); RipDelta += WORD_RIP_INST_LENGTH; RipDelta += BYTE_RIP_INST_LENGTH; RipDelta *= (-1); RipDelta += Delta; if (!JitiEmitWrapperB(OpType, Block, RipDelta, JitData->Data[4])) { NcDeleteBlock(Block); delete Block; return NULL; } } if (SaveFlags && !JitEmitPopfqInst(Block)) { NcDeleteBlock(Block); delete Block; return NULL; } return Block; }