Files
2023-11-07 08:18:50 +08:00

888 lines
28 KiB
C++

#include "pch.h"
#include "reflector.h"
static ZydisDecoder s_Decoder;
static SIZE_T s_TotalSize = 0;
static SIZE_T s_EncodeSize = 0;
PVOID NTAPI Reflector(_In_ PUCHAR Address,
_In_ ULONG Length,
_In_opt_ REPAIR_CALLBACK Callback){
ULONG count = 0;
PANALYZER pAnalyzers = NULL;
PUCHAR procedure = NULL;
NTSTATUS status = STATUS_SUCCESS;
SIZE_T size = max(Length * 4, PAGE_SIZE);
do
{
if (!ZYAN_SUCCESS(ZydisDecoderInit(&s_Decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64)))
break;
procedure = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, size, 'corp');
if (NULL == procedure) {
break;
}
RtlFillMemory(procedure, size, 0xCC);
// 获取重构指令的数量
count = GetAnalyzerCount(Address, Length);
pAnalyzers = BuildAnalyzer(Address, count);
if (NULL == pAnalyzers){
break;
}
BuildAllRepairInfo(pAnalyzers, count);
status = BuildFirstProcedure(procedure, pAnalyzers, count, Callback);
if (!NT_SUCCESS(status)) {
break;
}
status = BuildSecondProcedure(pAnalyzers, count);
if (!NT_SUCCESS(status)) {
break;
}
} while (FALSE);
NT_ASSERT(s_TotalSize < size);
if (NULL != pAnalyzers) {
ExFreePool(pAnalyzers);
pAnalyzers = NULL;
}
if (!NT_SUCCESS(status)) {
if (NULL != procedure)
ExFreePool(procedure);
procedure = NULL;
}
return procedure;
}
PUCHAR ReflectCode(_In_ PUCHAR Address, _In_ ULONG Length,
_In_ PUCHAR pTrampoline, _In_ ULONG Size) {
ULONG count = 0;
PANALYZER pAnalyzers = NULL;
NTSTATUS status = STATUS_SUCCESS;
s_TotalSize = 0;
do
{
if (!ZYAN_SUCCESS(ZydisDecoderInit(&s_Decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64)))
break;
// 获取重构指令的数量
count = GetAnalyzerCount(Address, Length);
pAnalyzers = BuildAnalyzer(Address, count);
if (NULL == pAnalyzers) {
break;
}
BuildAllRepairInfo(pAnalyzers, count);
status = BuildFirstProcedure(pTrampoline, pAnalyzers, count, NULL);
if (!NT_SUCCESS(status)) {
break;
}
status = BuildSecondProcedure(pAnalyzers, count);
if (!NT_SUCCESS(status)) {
break;
}
} while (FALSE);
NT_ASSERT(s_TotalSize < Size);
if (NULL != pAnalyzers) {
ExFreePool(pAnalyzers);
pAnalyzers = NULL;
}
if (!NT_SUCCESS(status)) {
return pTrampoline;
}
return pTrampoline + s_TotalSize;
}
ULONG GetAnalyzerCount(_In_ PUCHAR Address, _In_ ULONG Length) {
ZyanStatus status = ZYAN_STATUS_SUCCESS;
ZydisDecodedInstruction instruction;
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT] = { 0 };
ZyanUSize offset = 0;
ULONG count = 0;
do
{
status = ZydisDecoderDecodeFull(&s_Decoder,
Address + offset,
Length - offset, &instruction,
operands);
if (!ZYAN_SUCCESS(status))
{
break;
}
count += 1;
offset += instruction.length;
} while (FALSE != ZYAN_SUCCESS(status));
return count;
}
PANALYZER BuildAnalyzer(_In_ PUCHAR Address, _In_ ULONG Count) {
ZyanStatus status = ZYAN_STATUS_SUCCESS;
ZyanUSize offset = 0;
PANALYZER pAnalyzers = NULL;
ULONG idx = 0;
if (Count <= 0) {
return NULL;
}
pAnalyzers = (PANALYZER)ExAllocatePoolWithTag(PagedPool, sizeof(ANALYZER) * Count, 'oted');
if (NULL != pAnalyzers) {
RtlZeroMemory(pAnalyzers, sizeof(ANALYZER) * Count);
for (idx = 0; idx < Count; idx++) {
status = ZydisDecoderDecodeFull(&s_Decoder,
Address + offset,
ZYDIS_MAX_INSTRUCTION_LENGTH,
&pAnalyzers[idx].Decoded.Instruction,
pAnalyzers[idx].Decoded.Operands);
if (!ZYAN_SUCCESS(status))
{
break;
}
status = ZydisEncoderDecodedInstructionToEncoderRequest(
&pAnalyzers[idx].Decoded.Instruction,
pAnalyzers[idx].Decoded.Operands,
pAnalyzers[idx].Decoded.Instruction.operand_count_visible,
&pAnalyzers[idx].Encoder.Request);
if (!ZYAN_SUCCESS(status)) {
break;
}
pAnalyzers[idx].Decoded.Address= Address + offset;
pAnalyzers[idx].Decoded.Length= pAnalyzers[idx].Decoded.Instruction.length;
offset += pAnalyzers[idx].Decoded.Length;
}
if (idx != Count) {
ExFreePool(pAnalyzers);
pAnalyzers = NULL;
}
}
return pAnalyzers;
}
VOID BuildAllRepairInfo(_In_ PANALYZER pAnalyzers, _In_ ULONG Count) {
ULONG idx = 0;
PANALYZER pAnalyzer = NULL;
for (idx = 0; idx < Count; idx++) {
pAnalyzer = &pAnalyzers[idx];
NTSTATUS status = BuildBranchType(pAnalyzer);
if (NT_SUCCESS(status)) {
if (ZYDIS_ATTRIB_HAS_MODRM & pAnalyzer->Decoded.Instruction.attributes) {
if (0 == pAnalyzer->Decoded.Instruction.raw.modrm.mod
&& 5 == pAnalyzer->Decoded.Instruction.raw.modrm.rm) {
pAnalyzer->Repair.Address =
pAnalyzer->Decoded.Address +
pAnalyzer->Decoded.Length +
pAnalyzer->Decoded.Instruction.raw.disp.value;
pAnalyzer->Repair.Flags |= BRANCH_IMP;
}
else {
pAnalyzer->Repair.Flags = REPAIR_NONE;
}
}
else {
status = BuildBranchAnalyzerId(pAnalyzers, Count, pAnalyzer);
if (NT_SUCCESS(status)) {
pAnalyzer->Repair.Flags |= BRANCH_LOCAL;
}
else {
pAnalyzer->Repair.Address =
pAnalyzer->Decoded.Address +
pAnalyzer->Decoded.Length +
pAnalyzer->Decoded.Instruction.raw.imm->value.s;
pAnalyzer->Repair.Flags |= BRANCH_REMOTE;
}
}
}
else {
if (ZYDIS_ATTRIB_HAS_MODRM & pAnalyzer->Decoded.Instruction.attributes) {
if (0 == pAnalyzer->Decoded.Instruction.raw.modrm.mod &&
5 == pAnalyzer->Decoded.Instruction.raw.modrm.rm) {
pAnalyzer->Repair.Address =
pAnalyzer->Decoded.Address +
pAnalyzer->Decoded.Length +
pAnalyzer->Decoded.Instruction.raw.disp.value;
pAnalyzer->Repair.Flags = REPAIR_REL;
}
else {
pAnalyzer->Repair.Flags = REPAIR_NONE;
}
}
else {
pAnalyzer->Repair.Flags = REPAIR_NONE;
}
}
}
}
NTSTATUS BuildBranchType(_In_ PANALYZER Analyzer) {
switch (Analyzer->Decoded.Instruction.mnemonic)
{
case ZYDIS_MNEMONIC_JB:
case ZYDIS_MNEMONIC_JBE:
case ZYDIS_MNEMONIC_JCXZ:
case ZYDIS_MNEMONIC_JECXZ:
case ZYDIS_MNEMONIC_JKNZD:
case ZYDIS_MNEMONIC_JKZD:
case ZYDIS_MNEMONIC_JL:
case ZYDIS_MNEMONIC_JLE:
case ZYDIS_MNEMONIC_JNB:
case ZYDIS_MNEMONIC_JNBE:
case ZYDIS_MNEMONIC_JNL:
case ZYDIS_MNEMONIC_JNLE:
case ZYDIS_MNEMONIC_JNO:
case ZYDIS_MNEMONIC_JNP:
case ZYDIS_MNEMONIC_JNS:
case ZYDIS_MNEMONIC_JNZ:
case ZYDIS_MNEMONIC_JO:
case ZYDIS_MNEMONIC_JP:
case ZYDIS_MNEMONIC_JRCXZ:
case ZYDIS_MNEMONIC_JS:
case ZYDIS_MNEMONIC_JZ:
Analyzer->Repair.Flags = REPAIR_JCC;
break;
case ZYDIS_MNEMONIC_JMP:
Analyzer->Repair.Flags = REPAIR_JMP;
break;
case ZYDIS_MNEMONIC_CALL:
Analyzer->Repair.Flags = REPAIR_CALL;
break;
default:
Analyzer->Repair.Flags = REPAIR_NONE;
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
NTSTATUS BuildBranchAnalyzerId(_In_ PANALYZER pAnalyzers,
_In_ ULONG Count, _In_ PANALYZER pAnalyzer) {
ULONG idx = 0;
for (idx = 0; idx < Count; idx++) {
if (pAnalyzers[idx].Decoded.Address ==
pAnalyzer->Decoded.Address +
pAnalyzer->Decoded.Length +
pAnalyzer->Decoded.Instruction.raw.imm->value.s) {
return STATUS_SUCCESS;
}
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS BuildFirstProcedure(_In_ PUCHAR Procedure, _In_ PANALYZER pAnalyzers,
_In_ ULONG Count, _In_opt_ REPAIR_CALLBACK Callback) {
ULONG idx = 0;
PANALYZER pAnalyzer = NULL;
PUCHAR pPointer = NULL;
pPointer = Procedure;
for (idx = 0; idx < Count; idx++) {
pAnalyzer = &pAnalyzers[idx];
if (NULL != Callback) {
if (0 != (BRANCH_REMOTE & pAnalyzer->Repair.Flags) ||
0 != (BRANCH_IMP & pAnalyzer->Repair.Flags) ||
0 != (REPAIR_REL & pAnalyzer->Repair.Flags)) {
Callback(
pAnalyzer->Repair.Flags,
pAnalyzer->Repair.Address);
}
}
switch (pAnalyzer->Repair.Flags)
{
case REPAIR_NONE:
// 拷贝原始指令
pPointer = BuildNormalInstruction(pPointer, pAnalyzer);
break;
case REPAIR_REL:
pPointer = BuildRelativeInstruction(pPointer, pAnalyzer);
break;
case REPAIR_JCC | BRANCH_LOCAL:
pAnalyzer->Encoder.Length = 6;
pAnalyzer->Encoder.Address = pPointer;
pPointer += pAnalyzer->Encoder.Length;
break;
case REPAIR_JCC | BRANCH_REMOTE:
pAnalyzer->Encoder.Length = 20;
pAnalyzer->Encoder.Address = pPointer;
pPointer += pAnalyzer->Encoder.Length;
break;
case REPAIR_JMP | BRANCH_LOCAL:
pAnalyzer->Encoder.Length = 5;
pAnalyzer->Encoder.Address = pPointer;
pPointer += pAnalyzer->Encoder.Length;
break;
case REPAIR_JMP | BRANCH_REMOTE:
pAnalyzer->Encoder.Length = 16;
pAnalyzer->Encoder.Address = pPointer;
pPointer += pAnalyzer->Encoder.Length;
break;
case REPAIR_JMP | BRANCH_IMP:
pAnalyzer->Encoder.Length = 19;
pAnalyzer->Encoder.Address = pPointer;
pPointer += pAnalyzer->Encoder.Length;
break;
case REPAIR_CALL | BRANCH_LOCAL:
pAnalyzer->Encoder.Length = 5;
pAnalyzer->Encoder.Address = pPointer;
pPointer += pAnalyzer->Encoder.Length;
break;
case REPAIR_CALL | BRANCH_REMOTE:
pAnalyzer->Encoder.Length = 23;
pAnalyzer->Encoder.Address = pPointer;
pPointer += pAnalyzer->Encoder.Length;
break;
case REPAIR_CALL | BRANCH_IMP:
pAnalyzer->Encoder.Length = 26;
pAnalyzer->Encoder.Address = pPointer;
pPointer += pAnalyzer->Encoder.Length;
break;
default:
break;
}
if (NULL == pPointer) {
return STATUS_UNSUCCESSFUL;
}
}
if (NULL != pAnalyzer) {
// 构建跳转回去的代码
PUCHAR pInsn = BuildTruncationInstruction(pAnalyzer);
if (NULL == pInsn)
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
PUCHAR BuildTruncationInstruction(_In_ PANALYZER pAnalyzer) {
UCHAR code[] ={
// push rax
0x50,
// mov rax,0x8877665544332211
0x48, 0xB8, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
// xchg qword ptr ss:[rsp],rax
0x48, 0x87, 0x04, 0x24,
// ret
0xC3,
};
*(PUCHAR*)&code[3] = pAnalyzer->Decoded.Address + pAnalyzer->Decoded.Length;
RtlCopyMemory(pAnalyzer->Encoder.Address + pAnalyzer->Encoder.Length,
code,
sizeof(code));
s_TotalSize += sizeof(code) + pAnalyzer->Encoder.Length;
return pAnalyzer->Encoder.Address;
}
PUCHAR BuildNormalInstruction(_In_ PUCHAR pPointer, _In_ PANALYZER pAnalyzer) {
RtlCopyMemory(pPointer, pAnalyzer->Decoded.Address,
pAnalyzer->Decoded.Length);
s_TotalSize += pAnalyzer->Decoded.Length;
pAnalyzer->Encoder.Address = pPointer;
pAnalyzer->Encoder.Length = pAnalyzer->Decoded.Length;
return pPointer + pAnalyzer->Encoder.Length;
}
PUCHAR BuildRelativeInstruction(_In_ PUCHAR pPointer, _In_ PANALYZER pAnalyzer) {
ZydisRegister idleRegister = ZYDIS_REGISTER_NONE;
SIZE_T size = sizeof(ZydisEncoderRequest) * 4;
ZydisEncoderRequest* pRequests = (ZydisEncoderRequest*)ExAllocatePoolWithTag(NonPagedPool,
size, 'tqer');
if (NULL == pRequests) {
return NULL;
}
ZyanU32 idx = 0;
RtlZeroMemory(pRequests, size);
idleRegister = SelectIdleRegister(pAnalyzer);
if (ZYDIS_REGISTER_NONE != idleRegister) {
for (idx = 0; idx < pAnalyzer->Encoder.Request.operand_count; idx++) {
if (ZYDIS_OPERAND_TYPE_MEMORY == pAnalyzer->Encoder.Request.operands[idx].type) {
pAnalyzer->Encoder.Request.operands[idx].mem.base = idleRegister;
pAnalyzer->Encoder.Request.operands[idx].mem.displacement = 0;
}
}
pRequests[0].machine_mode = ZYDIS_MACHINE_MODE_LONG_64;
pRequests[0].allowed_encodings = ZYDIS_ENCODABLE_ENCODING_LEGACY;
pRequests[0].mnemonic = ZYDIS_MNEMONIC_PUSH;
pRequests[0].address_size_hint = ZYDIS_ADDRESS_SIZE_HINT_64;
pRequests[0].operand_size_hint = ZYDIS_OPERAND_SIZE_HINT_64;
pRequests[0].operand_count = 1;
pRequests[0].operands[0].type = ZYDIS_OPERAND_TYPE_REGISTER;
pRequests[0].operands[0].reg.value = idleRegister;
pRequests[1].machine_mode = ZYDIS_MACHINE_MODE_LONG_64;
pRequests[1].allowed_encodings = ZYDIS_ENCODABLE_ENCODING_LEGACY;
pRequests[1].mnemonic = ZYDIS_MNEMONIC_MOV;
pRequests[1].address_size_hint = ZYDIS_ADDRESS_SIZE_HINT_64;
pRequests[1].operand_size_hint = ZYDIS_OPERAND_SIZE_HINT_64;
pRequests[1].operand_count = 2;
pRequests[1].operands[0].type = ZYDIS_OPERAND_TYPE_REGISTER;
pRequests[1].operands[0].reg.value = idleRegister;
pRequests[1].operands[1].type = ZYDIS_OPERAND_TYPE_IMMEDIATE;
pRequests[1].operands[1].imm.u = (ZyanU64)pAnalyzer->Repair.Address;
RtlCopyMemory(&pRequests[2], &pAnalyzer->Encoder.Request,
sizeof(ZydisEncoderRequest));
pRequests[3].machine_mode = ZYDIS_MACHINE_MODE_LONG_64;
pRequests[3].allowed_encodings = ZYDIS_ENCODABLE_ENCODING_LEGACY;
pRequests[3].mnemonic = ZYDIS_MNEMONIC_POP;
pRequests[3].address_size_hint = ZYDIS_ADDRESS_SIZE_HINT_64;
pRequests[3].operand_size_hint = ZYDIS_OPERAND_SIZE_HINT_64;
pRequests[3].operand_count = 1;
pRequests[3].operands[0].type = ZYDIS_OPERAND_TYPE_REGISTER;
pRequests[3].operands[0].reg.value = idleRegister;
pAnalyzer->Encoder.Address = pPointer;
PUCHAR pInst = BuildInstructionFromRequest(
pAnalyzer->Encoder.Address,
size/ sizeof(ZydisEncoderRequest),
pRequests);
ExFreePool(pRequests);
return pInst;
}
return NULL;
}
ULONG CreateRegisterBitmap(_In_ PANALYZER pAnalyzer) {
ULONG idx = 0;
ULONG bitmap = 0;
for (idx = 0; idx < pAnalyzer->Decoded.Instruction.operand_count; idx++) {
if (ZYDIS_OPERAND_TYPE_REGISTER == pAnalyzer->Decoded.Operands[idx].type) {
switch (pAnalyzer->Decoded.Operands[idx].reg.value)
{
case ZYDIS_REGISTER_AL:
case ZYDIS_REGISTER_AH:
case ZYDIS_REGISTER_AX:
case ZYDIS_REGISTER_EAX:
case ZYDIS_REGISTER_RAX:
bitmap |= REGISTER_BITMAP_EAX;
break;
case ZYDIS_REGISTER_CL:
case ZYDIS_REGISTER_CH:
case ZYDIS_REGISTER_CX:
case ZYDIS_REGISTER_ECX:
case ZYDIS_REGISTER_RCX:
bitmap |= REGISTER_BITMAP_ECX;
break;
case ZYDIS_REGISTER_DL:
case ZYDIS_REGISTER_DH:
case ZYDIS_REGISTER_DX:
case ZYDIS_REGISTER_EDX:
case ZYDIS_REGISTER_RDX:
bitmap |= REGISTER_BITMAP_EDX;
break;
case ZYDIS_REGISTER_BL:
case ZYDIS_REGISTER_BH:
case ZYDIS_REGISTER_BX:
case ZYDIS_REGISTER_EBX:
case ZYDIS_REGISTER_RBX:
bitmap |= REGISTER_BITMAP_EBX;
break;
case ZYDIS_REGISTER_SIL:
case ZYDIS_REGISTER_SI:
case ZYDIS_REGISTER_ESI:
case ZYDIS_REGISTER_RSI:
bitmap |= REGISTER_BITMAP_ESI;
break;
case ZYDIS_REGISTER_DIL:
case ZYDIS_REGISTER_DI:
case ZYDIS_REGISTER_EDI:
case ZYDIS_REGISTER_RDI:
bitmap |= REGISTER_BITMAP_EDI;
break;
case ZYDIS_REGISTER_BPL:
case ZYDIS_REGISTER_BP:
case ZYDIS_REGISTER_EBP:
case ZYDIS_REGISTER_RBP:
bitmap |= REGISTER_BITMAP_EBP;
break;
default:
break;
}
}
}
return bitmap;
}
ZydisRegister SelectIdleRegister(_In_ PANALYZER pAnalyzer) {
ULONG idx = 0;
ULONG bitmap = 0;
bitmap = CreateRegisterBitmap(pAnalyzer);
for (idx = 0; idx < 7; idx++) {
if (0 == (REGISTER_BITMAP_EAX & bitmap)) {
return ZYDIS_REGISTER_RAX;
}
if (0 == (REGISTER_BITMAP_ECX & bitmap)) {
return ZYDIS_REGISTER_RCX;
}
if (0 == (REGISTER_BITMAP_EDX & bitmap)) {
return ZYDIS_REGISTER_RDX;
}
if (0 == (REGISTER_BITMAP_EBX & bitmap)) {
return ZYDIS_REGISTER_RBX;
}
if (0 == (REGISTER_BITMAP_ESI & bitmap)) {
return ZYDIS_REGISTER_RSI;
}
if (0 == (REGISTER_BITMAP_EDI & bitmap)) {
return ZYDIS_REGISTER_RDI;
}
if (0 == (REGISTER_BITMAP_EBP & bitmap)) {
return ZYDIS_REGISTER_RBP;
}
}
return ZYDIS_REGISTER_NONE;
}
PUCHAR BuildInstructionFromRequest(_In_ PUCHAR pPointer,
_In_ ULONG Count, _In_ ZydisEncoderRequest* pRequests) {
ZyanStatus status = ZYAN_STATUS_SUCCESS;
ZyanUSize length = 0;
ZyanUSize offset = 0;
ULONG idx = 0;
for (idx = 0; idx < Count; idx++) {
length = 15;
status = ZydisEncoderEncodeInstruction(&pRequests[idx],
pPointer + offset, &length);
if (!ZYAN_SUCCESS(status)) {
return NULL;
}
else {
offset += length;
}
}
s_TotalSize += offset;
return pPointer + offset;
}
NTSTATUS BuildSecondProcedure(_In_ PANALYZER pAnalyzers, _In_ ULONG Count) {
ULONG idx = 0;
PANALYZER pAnalyzer = NULL;
NTSTATUS status = STATUS_SUCCESS;
PUCHAR pInsn = NULL;
for (idx = 0; idx < Count; idx++) {
pAnalyzer = &pAnalyzers[idx];
switch (pAnalyzer->Repair.Flags)
{
case REPAIR_JCC | BRANCH_LOCAL:
case REPAIR_JMP | BRANCH_LOCAL:
case REPAIR_CALL | BRANCH_LOCAL:
pInsn = BuildLocalInstruction(pAnalyzers, pAnalyzer);
if (NULL == pInsn) {
status = STATUS_UNSUCCESSFUL;
}
break;
case REPAIR_JCC | BRANCH_REMOTE:
pInsn = BuildRemoteJccInstruction(pAnalyzer);
if (NULL == pInsn) {
status = STATUS_UNSUCCESSFUL;
}
break;
case REPAIR_JMP | BRANCH_REMOTE:
pInsn = BuildRemoteJmpInstruction(pAnalyzer);
if (NULL == pInsn) {
status = STATUS_UNSUCCESSFUL;
}
break;
case REPAIR_JMP | BRANCH_IMP:
pInsn = BuildImpJmpInstruction(pAnalyzer);
if (NULL == pInsn) {
status = STATUS_UNSUCCESSFUL;
}
break;
case REPAIR_CALL | BRANCH_REMOTE:
pInsn = BuildRemoteCallInstruction(pAnalyzer);
if (pInsn == NULL) {
status = STATUS_UNSUCCESSFUL;
}
break;
case REPAIR_CALL | BRANCH_IMP:
pInsn = BuildImpCallInstruction(pAnalyzer);
if (pInsn == NULL) {
status = STATUS_UNSUCCESSFUL;
}
break;
}
if (!NT_SUCCESS(status)) {
break;
}
}
return status;
}
PUCHAR BuildLocalInstruction(_In_ PANALYZER pAnalyzers, _In_ PANALYZER pAnalyzer) {
ZyanStatus status = ZYAN_STATUS_SUCCESS;
ZyanUSize length = 0;
pAnalyzer->Encoder.Request.branch_type = ZYDIS_BRANCH_TYPE_NEAR;
pAnalyzer->Encoder.Request.branch_width = ZYDIS_BRANCH_WIDTH_32;
pAnalyzer->Encoder.Request.operands[0].imm.s
= (ZyanI64)pAnalyzers[pAnalyzer->Repair.Index].Encoder.Address
- (ZyanI64)pAnalyzer->Encoder.Address - pAnalyzer->Encoder.Length;
length = 15;
status = ZydisEncoderEncodeInstruction(
&pAnalyzer->Encoder.Request,
pAnalyzer->Encoder.Address, &length
);
s_TotalSize += length;
if (!ZYAN_SUCCESS(status)) {
return NULL;
}
return pAnalyzer->Encoder.Address;
}
PUCHAR BuildRemoteJccInstruction(_In_ PANALYZER pAnalyzer) {
SIZE_T size = sizeof(ZydisEncoderRequest) * 6;
ZydisEncoderRequest* pRequests = (ZydisEncoderRequest*)ExAllocatePoolWithTag(NonPagedPool,
size, 'tqer');
if (NULL == pRequests) {
return NULL;
}
RtlZeroMemory(pRequests, size);
pRequests[0].machine_mode = ZYDIS_MACHINE_MODE_LONG_64;
pRequests[0].allowed_encodings = ZYDIS_ENCODABLE_ENCODING_LEGACY;
pRequests[0].mnemonic = pAnalyzer->Encoder.Request.mnemonic;
pRequests[0].branch_type = ZYDIS_BRANCH_TYPE_SHORT;
pRequests[0].branch_width = ZYDIS_BRANCH_WIDTH_8;
pRequests[0].address_size_hint = ZYDIS_ADDRESS_SIZE_HINT_64;
pRequests[0].operand_size_hint = ZYDIS_OPERAND_SIZE_HINT_64;
pRequests[0].operand_count = 1;
pRequests[0].operands[0].type = ZYDIS_OPERAND_TYPE_IMMEDIATE;
pRequests[0].operands[0].imm.s = 2;
pRequests[1].machine_mode = ZYDIS_MACHINE_MODE_LONG_64;
pRequests[1].allowed_encodings = ZYDIS_ENCODABLE_ENCODING_LEGACY;
pRequests[1].mnemonic = ZYDIS_MNEMONIC_JMP;
pRequests[1].branch_type = ZYDIS_BRANCH_TYPE_SHORT;
pRequests[1].branch_width = ZYDIS_BRANCH_WIDTH_8;
pRequests[1].address_size_hint = ZYDIS_ADDRESS_SIZE_HINT_64;
pRequests[1].operand_size_hint = ZYDIS_OPERAND_SIZE_HINT_64;
pRequests[1].operand_count = 1;
pRequests[1].operands[0].type = ZYDIS_OPERAND_TYPE_IMMEDIATE;
pRequests[1].operands[0].imm.s = 16;
pRequests[2].machine_mode = ZYDIS_MACHINE_MODE_LONG_64;
pRequests[2].allowed_encodings = ZYDIS_ENCODABLE_ENCODING_LEGACY;
pRequests[2].mnemonic = ZYDIS_MNEMONIC_PUSH;
pRequests[2].address_size_hint = ZYDIS_ADDRESS_SIZE_HINT_64;
pRequests[2].operand_size_hint = ZYDIS_OPERAND_SIZE_HINT_64;
pRequests[2].operand_count = 1;
pRequests[2].operands[0].type = ZYDIS_OPERAND_TYPE_REGISTER;
pRequests[2].operands[0].reg.value = ZYDIS_REGISTER_RAX;
pRequests[3].machine_mode = ZYDIS_MACHINE_MODE_LONG_64;
pRequests[3].allowed_encodings = ZYDIS_ENCODABLE_ENCODING_LEGACY;
pRequests[3].mnemonic = ZYDIS_MNEMONIC_MOV;
pRequests[3].branch_type = ZYDIS_BRANCH_TYPE_NONE;
pRequests[3].branch_width = ZYDIS_BRANCH_WIDTH_NONE;
pRequests[3].address_size_hint = ZYDIS_ADDRESS_SIZE_HINT_64;
pRequests[3].operand_size_hint = ZYDIS_OPERAND_SIZE_HINT_64;
pRequests[3].operand_count = 2;
pRequests[3].operands[0].type = ZYDIS_OPERAND_TYPE_REGISTER;
pRequests[3].operands[0].reg.value = ZYDIS_REGISTER_RAX;
pRequests[3].operands[1].type = ZYDIS_OPERAND_TYPE_IMMEDIATE;
pRequests[3].operands[1].imm.u = (ZyanU64)pAnalyzer->Repair.Address;
pRequests[4].machine_mode = ZYDIS_MACHINE_MODE_LONG_64;
pRequests[4].allowed_encodings = ZYDIS_ENCODABLE_ENCODING_LEGACY;
pRequests[4].mnemonic = ZYDIS_MNEMONIC_XCHG;
pRequests[4].branch_type = ZYDIS_BRANCH_TYPE_NONE;
pRequests[4].branch_width = ZYDIS_BRANCH_WIDTH_NONE;
pRequests[4].address_size_hint = ZYDIS_ADDRESS_SIZE_HINT_64;
pRequests[4].operand_size_hint = ZYDIS_OPERAND_SIZE_HINT_32;
pRequests[4].operand_count = 2;
pRequests[4].operands[0].type = ZYDIS_OPERAND_TYPE_MEMORY;
pRequests[4].operands[0].mem.base = ZYDIS_REGISTER_RSP;
pRequests[4].operands[0].mem.index = ZYDIS_REGISTER_NONE;
pRequests[4].operands[0].mem.scale = 0;
pRequests[4].operands[0].mem.displacement = 0;
pRequests[4].operands[0].mem.size = 8;
pRequests[4].operands[1].type = ZYDIS_OPERAND_TYPE_REGISTER;
pRequests[4].operands[1].reg.value = ZYDIS_REGISTER_RAX;
pRequests[5].machine_mode = ZYDIS_MACHINE_MODE_LONG_64;
pRequests[5].allowed_encodings = ZYDIS_ENCODABLE_ENCODING_LEGACY;
pRequests[5].mnemonic = ZYDIS_MNEMONIC_RET;
pRequests[5].branch_type = ZYDIS_BRANCH_TYPE_NEAR;
pRequests[5].branch_width = ZYDIS_BRANCH_WIDTH_64;
pRequests[5].address_size_hint = ZYDIS_ADDRESS_SIZE_HINT_64;
pRequests[5].operand_size_hint = ZYDIS_OPERAND_SIZE_HINT_64;
pRequests[5].operand_count = 0;
PUCHAR pInst = BuildInstructionFromRequest(
pAnalyzer->Encoder.Address,
size / sizeof(ZydisEncoderRequest),
pRequests);
ExFreePool(pRequests);
return pInst;
}
PUCHAR BuildRemoteJmpInstruction(_In_ PANALYZER pAnalyzer) {
UCHAR code[] = {
// push rax
0x50,
// mov rax,0x8877665544332211
0x48, 0xB8, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
// xchg qword ptr ss:[rsp],rax
0x48, 0x87, 0x04, 0x24,
// ret
0xC3,
};
*(PUCHAR*)&code[3] = pAnalyzer->Repair.Address;
RtlCopyMemory(pAnalyzer->Encoder.Address, code, sizeof(code));
s_TotalSize += sizeof(code);
return pAnalyzer->Encoder.Address;
}
PUCHAR BuildImpJmpInstruction(_In_ PANALYZER pAnalyzer) {
UCHAR code[] = {
// push rax
0x50,
// mov rax,0x8877665544332211
0x48, 0xB8, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
// mov rax,qword ptr ds:[rax]
0x48, 0x8B, 0x00,
// xchg qword ptr ss:[rsp],rax
0x48, 0x87, 0x04, 0x24,
// ret
0xC3
};
*(PUCHAR*)&code[3] = pAnalyzer->Repair.Address;
RtlCopyMemory(pAnalyzer->Encoder.Address, code, sizeof(code));
s_TotalSize += sizeof(code);
return pAnalyzer->Encoder.Address;
}
PUCHAR BuildRemoteCallInstruction(_In_ PANALYZER pAnalyzer) {
UCHAR code[] = {
// call rip + 2 + 5
0xE8, 0x02, 0x00, 0x00, 0x00,
// jmp rip + 0x10 + 2
0xEB, 0x10,
// push rax
0x50,
// mov rax,0x8877665544332211
0x48, 0xB8, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
// xchg qword ptr ss:[rsp],rax
0x48, 0x87, 0x04, 0x24,
// ret
0xC3
};
*(PUCHAR*)&code[10] = pAnalyzer->Repair.Address;
RtlCopyMemory(pAnalyzer->Encoder.Address, code, sizeof(code));
s_TotalSize += sizeof(code);
return pAnalyzer->Encoder.Address;
}
PUCHAR BuildImpCallInstruction(_In_ PANALYZER pAnalyzer) {
UCHAR code[] = {
// call rip + 2 + 5
0xE8, 0x02, 0x00, 0x00, 0x00,
// jmp rip + 0x13 + 2
0xEB, 0x13,
// push rax
0x50,
// mov rax, 0x8877665544332211
0x48, 0xB8, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
// mov rax, qword ptr ds:[rax]
0x48, 0x8B, 0x00,
// xchg qword ptr ss:[rsp],rax
0x48, 0x87, 0x04, 0x24,
// ret
0xC3
};
*(PUCHAR*)&code[10] = pAnalyzer->Repair.Address;
RtlCopyMemory(pAnalyzer->Encoder.Address, code, sizeof(code));
s_TotalSize += sizeof(code);
return pAnalyzer->Encoder.Address;
}