testing new vmprofiler lambda zydis instr...

merge-requests/2/head
_xeroxz 4 years ago
parent 05ba2cc84b
commit 05c8f779d0

@ -56,7 +56,7 @@ namespace vm
update_key
};
using map_t = std::map<transform::type, ZydisDecodedInstruction>;
using map_t = std::map<transform::type, zydis_decoded_instr_t>;
template <class T>
inline const auto _bswap = [](T a, T b) -> T
@ -193,7 +193,7 @@ namespace vm
}
}
inline bool has_imm(ZydisDecodedInstruction* instr)
inline bool has_imm(zydis_decoded_instr_t* instr)
{
return instr->operand_count > 1 &&
(instr->operands[1].type & ZYDIS_OPERAND_TYPE_IMMEDIATE);

@ -14,7 +14,7 @@ namespace vm
void inverse_transforms(transform::map_t& transforms, transform::map_t& inverse);
bool get_calc_jmp(const zydis_routine_t& vm_entry, zydis_routine_t& calc_jmp);
bool get_vinstr_rva_transform(
const zydis_routine_t& vm_entry, ZydisDecodedInstruction* transform_instr);
const zydis_routine_t& vm_entry, zydis_decoded_instr_t* transform_instr);
struct handler_t
{
@ -42,10 +42,10 @@ namespace vm
namespace table
{
std::uintptr_t* get(const zydis_routine_t& vm_entry);
bool get_transform(const zydis_routine_t& vm_entry, ZydisDecodedInstruction* transform_instr);
bool get_transform(const zydis_routine_t& vm_entry, zydis_decoded_instr_t* transform_instr);
std::uint64_t encrypt(ZydisDecodedInstruction& transform_instr, std::uint64_t val);
std::uint64_t decrypt(ZydisDecodedInstruction& transform_instr, std::uint64_t val);
std::uint64_t encrypt(zydis_decoded_instr_t& transform_instr, std::uint64_t val);
std::uint64_t decrypt(zydis_decoded_instr_t& transform_instr, std::uint64_t val);
}
}
}

@ -5,6 +5,8 @@ namespace vm
{
namespace handler
{
using instr_callback_t = bool(*)(const zydis_decoded_instr_t& instr);
enum extention_t
{
none,
@ -16,351 +18,57 @@ namespace vm
{
const char* name;
u8 imm_size;
std::vector<std::vector<u8>> signature;
std::vector<instr_callback_t> signature;
extention_t extention;
};
namespace profile
{
// store a value from the stack into scratch register X (RDI+X)...
// where X is an 8bit immediate value...
// MOV RDX, [RBP]
// ADD RBP, 8
// MOV [RAX+RDI], RDX
inline vm::handler::profile_t sregq =
{
"SREGQ", 8,
{
{ 0x48, 0x8B, 0x55, 0x0 }, // mov rdx, [rbp+0]
{ 0x48, 0x83, 0xC5, 0x8 }, // add rbp, 8
{ 0x48, 0x89, 0x14, 0x38 }, // mov [rax+rdi], rdx
}
};
inline vm::handler::profile_t sregdw =
{
"SREGDW", 8,
{
{ 0x8B, 0x55, 0x00 },
{ 0x48, 0x83, 0xC5, 0x04 },
{ 0x89, 0x14, 0x38 }
}
};
inline vm::handler::profile_t sregw =
{
"SREGW", 8,
{
{ 0x66, 0x8B, 0x55, 0x00 }, // mov dx, [rbp]
{ 0x48, 0x83, 0xC5, 0x02 }, // add rbp, 0x02
{ 0x66, 0x89, 0x14, 0x38 } // mov [rax+rdi], dx
}
};
// load scratch register value onto virtual stack...
inline vm::handler::profile_t lregq =
{
"LREGQ", 8,
{
{0x48, 0x8B, 0x14, 0x38}, // mov rdx, [rax+rdi]
{0x48, 0x83, 0xED, 0x08}, // sub rbp, 8
{0x48, 0x89, 0x55, 0x0} // mov [rbp+0], rdx
}
};
/*
> 0x00007FF64724445C mov edx, [rax+rdi*1]
> 0x00007FF647244463 sub rbp, 0x04
> 0x00007FF647246333 mov [rbp], edx
*/
inline vm::handler::profile_t lregdw =
{
"LREGDW", 8,
{
{ 0x8B, 0x14, 0x38 },
{ 0x48, 0x83, 0xED, 0x04 },
{ 0x89, 0x55, 0x00 }
}
};
// load constant value into stack....
inline vm::handler::profile_t lconstq =
{
"LCONSTQ", 64,
{
{0x48, 0x83, 0xED, 0x08}, // sub rbp, 8
{0x48, 0x89, 0x45, 0x00} // mov [rbp+0], rax
}
};
// load 1 byte constant zero extended into 2bytes on the stack...
inline vm::handler::profile_t lconstbzx =
{
"LCONSTBZX", 8,
{
{0x48, 0x83, 0xED, 0x02}, // sub rbp, 2
{0x66, 0x89, 0x45, 0x00} // mov [rbp+0], ax
}
};
inline vm::handler::profile_t lconstbsx =
{
"LCONSTBSX", 8,
{
{ 0x98 },
{ 0x48, 0x83, 0xED, 0x04 },
{ 0x89, 0x45, 0x00 }
},
vm::handler::extention_t::sign_extend
};
// load 4 byte constant value sign extended qword into vsp...
inline vm::handler::profile_t lconstbsx1 =
{
"LCONSTBSX", 8,
// MOV RDX, [RBP]
[](const zydis_decoded_instr_t& instr) -> bool
{
{0x48, 0x98}, // cdqe
{0x48, 0x83, 0xED, 0x8}, // sub rbp, 8
{0x48, 0x89, 0x45, 0x0}, // mov [rbp+0], rax
return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RDX &&
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP;
},
vm::handler::extention_t::sign_extend
};
// load 4 byte constant value sign extended qword into vsp...
inline vm::handler::profile_t lconstdsx =
{
"LCONSTDSX", 32,
{
{0x48, 0x98}, // cdqe
{0x48, 0x83, 0xED, 0x8}, // sub rbp, 8
{0x48, 0x89, 0x45, 0x0}, // mov [rbp+0], rax
// ADD RBP, 8
[](const zydis_decoded_instr_t& instr) -> bool
{
return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP &&
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
instr.operands[1].imm.value.u == 8;
},
vm::handler::extention_t::sign_extend
};
// load 2 byte constant value sign extended qword into vsp...
inline vm::handler::profile_t lconstwsx =
{
"LCONSTWSX", 16,
{
{0x48, 0x98}, // cdqe
{0x48, 0x83, 0xED, 0x8}, // sub rbp, 8
{0x48, 0x89, 0x45, 0x0}, // mov [rbp+0], rax
},
vm::handler::extention_t::sign_extend
};
inline vm::handler::profile_t lconstw =
{
"LCONSTW", 8,
{
{ 0x48, 0x83, 0xED, 0x02 }, // sub rbp, 0x02
{ 0x66, 0x89, 0x45, 0x00 } // mov [rbp], ax
}
};
inline vm::handler::profile_t lconstdw =
{
"LCONSTDW", 32,
{
{ 0x48, 0x83, 0xED, 0x04 },
{ 0x89, 0x45, 0x00 }
}
};
inline vm::handler::profile_t pushvsp =
{
"PUSHVSP", 0,
{
{0x48, 0x89, 0xE8}, // mov rax, rbp
{0x48, 0x83, 0xED, 0x08}, // sub rbp, 8
{0x48, 0x89, 0x45, 0x0} // mov [rbp+0], rax
}
};
// add two stack values together...
inline vm::handler::profile_t addq =
{
"ADDQ", 0,
{
{0x48, 0x1, 0x45, 0x8}, // add [rbp+8], rax
{0x9C}, // pushfq
{0x8F, 0x45, 0x0} // pop qword ptr [rbp+0]
}
};
inline vm::handler::profile_t adddw =
{
"ADDDW", 0,
{
{ 0x01, 0x45, 0x08 }, // add [rbp+0x08], eax
{ 0x9C }, // pushfq
{ 0x8F, 0x45, 0x00 } // pop [rbp]
}
};
// two qwords on the top of the stack together then not the result...
// ~(VSP[0] | VSP[1])...
inline vm::handler::profile_t nandq =
{
"NANDQ", 0,
{
{0x48, 0x8B, 0x45, 0x0}, // mov rax, [rbp+0]
{0x48, 0x8B, 0x55, 0x8}, // mov rdx, [rbp+8]
{0x48, 0xF7, 0xD0}, // not rax
{0x48, 0xF7, 0xD2}, // not rdx
{0x48, 0x21, 0xD0}, // and rax, rdx
{0x48, 0x89, 0x45, 0x8}, // mov [rbp+8], rax
{0x9C}, // pushfq
{0x8F, 0x45, 0x0} // pop qword ptr [rbp+0]
}
};
// leaves the virtual machine...
inline vm::handler::profile_t vmexit =
{
"VMEXIT", 0,
{
{0x48, 0x89, 0xec}, // mov rsp, rbp
{0x9d}, // popfq
{0xc3} // ret
}
};
inline vm::handler::profile_t jmp =
{
"JMP", 0,
{
{ 0x8B, 0x75, 0x00 }, // mov esi, [rbp]
{ 0x48, 0x01, 0xC6 }, // add rsi, rax
{ 0x48, 0x89, 0xF3 }, // mov rbx, rsi
{ 0x48, 0x03, 0x75, 0x00 } // add rsi, [rbp]
}
};
inline vm::handler::profile_t readw =
{
"READW", 0,
{
{ 0x48, 0x8B, 0x45, 0x00 }, // mov rax, [rbp]
{ 0x48, 0x83, 0xC5, 0x06 }, // add rbp, 0x06
{ 0x36, 0x66, 0x8B, 0x00 }, // mov ax, ss:[rax]
{ 0x66, 0x89, 0x45, 0x00 } // mov [rbp], ax
}
};
inline vm::handler::profile_t writeq =
{
"WRITEQ", 0,
{
{ 0x48, 0x8B, 0x45, 0x00 }, // mov rax, [rbp]
{ 0x48, 0x8B, 0x55, 0x08 }, // mov rdx, [rbp+0x08]
{ 0x48, 0x83, 0xC5, 0x10 }, // add rbp, 0x10
{ 0x36, 0x48, 0x89, 0x10 }, // mov ss:[rax], rdx
}
};
inline vm::handler::profile_t writeq1 =
{
"WRITEQ", 0,
// MOV [RAX+RDI], RDX
[](const zydis_decoded_instr_t& instr) -> bool
{
{ 0x48, 0x8B, 0x45, 0x00 }, // mov rax, [rbp]
{ 0x48, 0x8B, 0x55, 0x08 }, // mov rdx, [rbp+0x08]
{ 0x48, 0x83, 0xC5, 0x10 }, // add rbp, 0x10
{ 0x48, 0x89, 0x10 } // mov [rax], rdx
return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
(instr.operands[0].mem.base == ZYDIS_REGISTER_RAX ||
instr.operands[0].mem.base == ZYDIS_REGISTER_RDI) &&
(instr.operands[0].mem.index == ZYDIS_REGISTER_RDI ||
instr.operands[0].mem.index == ZYDIS_REGISTER_RAX) &&
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[1].reg.value == ZYDIS_REGISTER_RDX;
}
};
inline vm::handler::profile_t shrw =
{
"SHRW", 0,
{
{ 0x66, 0x8B, 0x45, 0x00 },
{ 0x8A, 0x4D, 0x02 },
{ 0x48, 0x83, 0xED, 0x06 },
{ 0x66, 0xD3, 0xE8 },
{ 0x66, 0x89, 0x45, 0x08 },
{ 0x9C },
{ 0x8F, 0x45, 0x00 }
}
};
inline vm::handler::profile_t shrdw =
{
"SHRDW", 0,
{
{ 0x8B, 0x45, 0x00 },
{ 0x8A, 0x4D, 0x04 },
{ 0x48, 0x83, 0xED, 0x06 },
{ 0xD3, 0xE8 },
{ 0x89, 0x45, 0x08 },
{ 0x9C },
{ 0x8F, 0x45, 0x00 }
}
};
inline vm::handler::profile_t shrq =
{
"SHRQ", 0,
{
{ 0x48, 0x8B, 0x45, 0x00 },
{ 0x8A, 0x4D, 0x08 },
{ 0x48, 0x83, 0xED, 0x06 },
{ 0x48, 0xD3, 0xE8 },
{ 0x48, 0x89, 0x45, 0x08 },
{ 0x9C },
{ 0x8F, 0x45, 0x00 },
}
};
inline vm::handler::profile_t nanddw =
{
"NANDDW", 0,
{
{ 0x48, 0xF7, 0x55, 0x00 }, // not qword ptr [rbp+0]
{ 0x8B, 0x45, 0x00 }, // mov eax, [rbp+0]
{ 0x48, 0x83, 0xED, 0x04 }, // sub rbp, 4
{ 0x21, 0x45, 0x08 }, // and [rbp+8], eax
{ 0x9C }, // pushfq
{ 0x8F, 0x45, 0x00 } // pop qword ptr [rbp+0]
}
};
inline vm::handler::profile_t lvsp =
{
"LVSP", 0,
{
{ 0x48, 0x8B, 0x6D, 0x00 } // mov rbp, [rbp]
}
};
inline std::vector<vm::handler::profile_t*> all =
{
&sregq,
&lregq,
&lconstq,
&lconstdsx,
&lconstwsx,
&lconstbzx,
&addq,
&nandq,
&pushvsp,
&vmexit,
&jmp,
&adddw,
&writeq,
&sregw,
&lconstw,
&shrw,
&shrq,
&writeq1,
&readw,
&lregdw,
&shrdw,
&sregdw,
&lconstbsx,
&lconstbsx1,
&shrq,
&lvsp,
&lconstdw,
&nanddw
&sregq
};
}
}

@ -10,9 +10,12 @@ using u32 = unsigned int;
using u64 = unsigned long long;
using u128 = __m128;
using zydis_decoded_instr_t = ZydisDecodedInstruction;
using zydis_register_t = ZydisRegister;
struct zydis_instr_t
{
ZydisDecodedInstruction instr;
zydis_decoded_instr_t instr;
std::vector<u8> raw;
std::uintptr_t addr;
};
@ -26,13 +29,13 @@ namespace vm
namespace reg
{
// converts say... AL to RAX...
ZydisRegister to64(ZydisRegister reg);
bool compare(ZydisRegister a, ZydisRegister b);
zydis_register_t to64(zydis_register_t reg);
bool compare(zydis_register_t a, zydis_register_t b);
}
void print(zydis_routine_t& routine);
void print(const ZydisDecodedInstruction& instr);
bool is_jmp(const ZydisDecodedInstruction& instr);
void print(const zydis_decoded_instr_t& instr);
bool is_jmp(const zydis_decoded_instr_t& instr);
bool flatten(zydis_routine_t& routine, std::uintptr_t routine_addr, bool keep_jmps = false);
void deobfuscate(zydis_routine_t& routine);

@ -194,7 +194,7 @@ namespace vm
}
bool get_vinstr_rva_transform(
const zydis_routine_t& vm_entry, ZydisDecodedInstruction* transform_instr)
const zydis_routine_t& vm_entry, zydis_decoded_instr_t* transform_instr)
{
//
// find mov esi, [rsp+0xA0]
@ -314,7 +314,7 @@ namespace vm
bool get_all(std::uintptr_t module_base, std::uintptr_t image_base,
zydis_routine_t& vm_entry, std::uintptr_t* vm_handler_table, std::vector<vm::handler_t>& vm_handlers)
{
ZydisDecodedInstruction instr;
zydis_decoded_instr_t instr;
if (!vm::handler::table::get_transform(vm_entry, &instr))
return false;
@ -452,7 +452,7 @@ namespace vm
}
);
ZydisDecodedInstruction nogeneric0;
zydis_decoded_instr_t nogeneric0;
nogeneric0.mnemonic = ZYDIS_MNEMONIC_INVALID;
transforms[transform::type::generic0] =
@ -505,17 +505,7 @@ namespace vm
vm_handler->instrs.end(),
[&](zydis_instr_t& instr_data) -> bool
{
if (instr_data.raw.size() != instr.size())
return false;
return std::equal
(
instr_data.raw.begin(),
instr_data.raw.end(),
instr.begin()
);
}
{ return instr(instr_data.instr); }
);
if (contains == vm_handler->instrs.end())
@ -562,9 +552,9 @@ namespace vm
return reinterpret_cast<std::uintptr_t*>(ptr);
}
bool get_transform(const zydis_routine_t& vm_entry, ZydisDecodedInstruction* transform_instr)
bool get_transform(const zydis_routine_t& vm_entry, zydis_decoded_instr_t* transform_instr)
{
ZydisRegister rcx_or_rdx = ZYDIS_REGISTER_NONE;
zydis_register_t rcx_or_rdx = ZYDIS_REGISTER_NONE;
auto handler_fetch = std::find_if(
vm_entry.begin(), vm_entry.end(),
@ -616,7 +606,7 @@ namespace vm
return true;
}
std::uint64_t encrypt(ZydisDecodedInstruction& transform_instr, std::uint64_t val)
std::uint64_t encrypt(zydis_decoded_instr_t& transform_instr, std::uint64_t val)
{
assert(transform_instr.operands[0].size == 64,
"invalid transformation for vm handler table entries...");
@ -629,7 +619,7 @@ namespace vm
return vm::transform::apply(bitsize, operation, val, imm);
}
std::uint64_t decrypt(ZydisDecodedInstruction& transform_instr, std::uint64_t val)
std::uint64_t decrypt(zydis_decoded_instr_t& transform_instr, std::uint64_t val)
{
assert(transform_instr.operands[0].size == 64,
"invalid transformation for vm handler table entries...");

@ -7,7 +7,7 @@ namespace vm
{
namespace reg
{
ZydisRegister to64(ZydisRegister reg)
zydis_register_t to64(zydis_register_t reg)
{
switch (reg)
{
@ -119,13 +119,13 @@ namespace vm
return reg;
}
bool compare(ZydisRegister a, ZydisRegister b)
bool compare(zydis_register_t a, zydis_register_t b)
{
return to64(a) == to64(b);
}
}
void print(const ZydisDecodedInstruction& instr)
void print(const zydis_decoded_instr_t& instr)
{
char buffer[256];
ZydisFormatter formatter;
@ -152,7 +152,7 @@ namespace vm
}
}
bool is_jmp(const ZydisDecodedInstruction& instr)
bool is_jmp(const zydis_decoded_instr_t& instr)
{
switch (instr.mnemonic)
{
@ -188,7 +188,7 @@ namespace vm
bool flatten(zydis_routine_t& routine, std::uintptr_t routine_addr, bool keep_jmps)
{
ZydisDecoder decoder;
ZydisDecodedInstruction instr;
zydis_decoded_instr_t instr;
ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64);
while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(&decoder, reinterpret_cast<void*>(
@ -229,7 +229,7 @@ namespace vm
void deobfuscate(zydis_routine_t& routine)
{
static const auto _uses =
[](ZydisDecodedOperand& op, ZydisRegister reg) -> bool
[](ZydisDecodedOperand& op, zydis_register_t reg) -> bool
{
switch (op.type)
{
@ -247,7 +247,7 @@ namespace vm
};
static const auto _writes =
[](ZydisDecodedInstruction& inst) -> bool
[](zydis_decoded_instr_t& inst) -> bool
{
for (auto idx = 0; idx < inst.operand_count; ++idx)
if (inst.operands[idx].actions & ZYDIS_OPERAND_ACTION_MASK_WRITE)
@ -258,7 +258,7 @@ namespace vm
static const auto _remove =
[](zydis_routine_t& routine, zydis_routine_t::iterator itr,
ZydisRegister reg, u32 opcode_size) -> void
zydis_register_t reg, u32 opcode_size) -> void
{
for (; itr >= routine.begin(); --itr)
{

Loading…
Cancel
Save