added some code to vm::util::flatten so that vmp3 bins can be supported

master
xerox 2 years ago
parent eed247229f
commit 14cc72c0ff

@ -1,18 +1,5 @@
--- ---
BasedOnStyle: Microsoft BasedOnStyle: Chromium
AlignAfterOpenBracket: Align
AllowAllArgumentsOnNextLine: 'true'
AllowAllParametersOfDeclarationOnNextLine: 'true'
AllowShortIfStatementsOnASingleLine: Never
BreakBeforeBraces: Allman
IndentWidth: '4'
Language: Cpp
NamespaceIndentation: All
SpacesInAngles: 'true'
SpacesInCStyleCastParentheses: 'true'
SpacesInContainerLiterals: 'true'
SpacesInParentheses: 'true'
SpacesInSquareBrackets: 'true'
UseTab: Never
... ...

@ -1,5 +1,3 @@
#include <Zydis/Zydis.h>
#include <vmprofiler.hpp> #include <vmprofiler.hpp>
namespace vm { namespace vm {

@ -11,11 +11,11 @@ bool compare(zydis_register_t a, zydis_register_t b) {
} }
} // namespace reg } // namespace reg
bool get_fetch_operand(const zydis_routine_t &routine, bool get_fetch_operand(const zydis_routine_t& routine,
zydis_instr_t &fetch_instr) { zydis_instr_t& fetch_instr) {
const auto result = std::find_if( const auto result = std::find_if(
routine.begin(), routine.end(), routine.begin(), routine.end(),
[](const zydis_instr_t &instr_data) -> bool { [](const zydis_instr_t& instr_data) -> bool {
// mov/movsx/movzx rax/eax/ax/al, [rsi] // mov/movsx/movzx rax/eax/ax/al, [rsi]
return instr_data.instr.operand_count > 1 && return instr_data.instr.operand_count > 1 &&
(instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || (instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
@ -29,17 +29,18 @@ bool get_fetch_operand(const zydis_routine_t &routine,
instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSI; instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSI;
}); });
if (result == routine.end()) return false; if (result == routine.end())
return false;
fetch_instr = *result; fetch_instr = *result;
return true; return true;
} }
std::optional<zydis_routine_t::iterator> get_fetch_operand( std::optional<zydis_routine_t::iterator> get_fetch_operand(
zydis_routine_t &routine) { zydis_routine_t& routine) {
auto result = std::find_if( auto result = std::find_if(
routine.begin(), routine.end(), routine.begin(), routine.end(),
[](const zydis_instr_t &instr_data) -> bool { [](const zydis_instr_t& instr_data) -> bool {
// mov/movsx/movzx rax/eax/ax/al, [rsi] // mov/movsx/movzx rax/eax/ax/al, [rsi]
return instr_data.instr.operand_count > 1 && return instr_data.instr.operand_count > 1 &&
(instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || (instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
@ -53,19 +54,20 @@ std::optional<zydis_routine_t::iterator> get_fetch_operand(
instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSI; instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSI;
}); });
if (result == routine.end()) return {}; if (result == routine.end())
return {};
return result; return result;
} }
void print(const zydis_decoded_instr_t &instr) { void print(const zydis_decoded_instr_t& instr) {
char buffer[256]; char buffer[256];
ZydisFormatterFormatInstruction(vm::util::g_formatter.get(), &instr, buffer, ZydisFormatterFormatInstruction(vm::util::g_formatter.get(), &instr, buffer,
sizeof(buffer), 0u); sizeof(buffer), 0u);
std::puts(buffer); std::puts(buffer);
} }
void print(zydis_routine_t &routine) { void print(zydis_routine_t& routine) {
char buffer[256]; char buffer[256];
for (auto [instr, raw, addr] : routine) { for (auto [instr, raw, addr] : routine) {
ZydisFormatterFormatInstruction(vm::util::g_formatter.get(), &instr, buffer, ZydisFormatterFormatInstruction(vm::util::g_formatter.get(), &instr, buffer,
@ -74,43 +76,48 @@ void print(zydis_routine_t &routine) {
} }
} }
bool is_jmp(const zydis_decoded_instr_t &instr) { bool is_jmp(const zydis_decoded_instr_t& instr) {
return instr.mnemonic >= ZYDIS_MNEMONIC_JB && return instr.mnemonic >= ZYDIS_MNEMONIC_JB &&
instr.mnemonic <= ZYDIS_MNEMONIC_JZ; instr.mnemonic <= ZYDIS_MNEMONIC_JZ;
} }
bool flatten(zydis_routine_t &routine, std::uintptr_t routine_addr, bool flatten(zydis_routine_t& routine,
bool keep_jmps, std::uint32_t max_instrs, std::uintptr_t routine_addr,
bool keep_jmps,
std::uint32_t max_instrs,
std::uintptr_t module_base) { std::uintptr_t module_base) {
zydis_decoded_instr_t instr; zydis_decoded_instr_t instr;
std::uint32_t instr_cnt = 0u; std::uint32_t instr_cnt = 0u;
while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer( while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(
vm::util::g_decoder.get(), reinterpret_cast<void *>(routine_addr), 0x1000, vm::util::g_decoder.get(), reinterpret_cast<void*>(routine_addr), 0x1000,
&instr))) { &instr))) {
if (++instr_cnt > max_instrs) return false; if (++instr_cnt > max_instrs)
return false;
// detect if we have already been at this instruction... if so that means // detect if we have already been at this instruction... if so that means
// there is a loop and we are going to just return... // there is a loop and we are going to just return...
if (std::find_if(routine.begin(), routine.end(), if (std::find_if(routine.begin(), routine.end(),
[&](const zydis_instr_t &zydis_instr) -> bool { [&](const zydis_instr_t& zydis_instr) -> bool {
return zydis_instr.addr == routine_addr; return zydis_instr.addr == routine_addr;
}) != routine.end()) }) != routine.end())
return true; return true;
std::vector<u8> raw_instr; std::vector<u8> raw_instr;
raw_instr.insert(raw_instr.begin(), (u8 *)routine_addr, raw_instr.insert(raw_instr.begin(), (u8*)routine_addr,
(u8 *)routine_addr + instr.length); (u8*)routine_addr + instr.length);
if (is_jmp(instr)) { if (is_jmp(instr) ||
instr.mnemonic == ZYDIS_MNEMONIC_CALL &&
instr.operands[0].type != ZYDIS_OPERAND_TYPE_REGISTER) {
if (instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER) { if (instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER) {
routine.push_back({instr, raw_instr, routine_addr}); routine.push_back({instr, raw_instr, routine_addr});
return true; return true;
} }
if (keep_jmps) routine.push_back({instr, raw_instr, routine_addr}); if (keep_jmps)
routine.push_back({instr, raw_instr, routine_addr});
ZydisCalcAbsoluteAddress(&instr, &instr.operands[0], routine_addr, ZydisCalcAbsoluteAddress(&instr, &instr.operands[0], routine_addr,
&routine_addr); &routine_addr);
} else if (instr.mnemonic == ZYDIS_MNEMONIC_RET) { } else if (instr.mnemonic == ZYDIS_MNEMONIC_RET) {
routine.push_back({instr, raw_instr, routine_addr}); routine.push_back({instr, raw_instr, routine_addr});
return true; return true;
@ -126,8 +133,8 @@ bool flatten(zydis_routine_t &routine, std::uintptr_t routine_addr,
return false; return false;
} }
void deobfuscate(zydis_routine_t &routine) { void deobfuscate(zydis_routine_t& routine) {
static const auto _uses_reg = [](zydis_decoded_operand_t &op, static const auto _uses_reg = [](zydis_decoded_operand_t& op,
zydis_register_t reg) -> bool { zydis_register_t reg) -> bool {
switch (op.type) { switch (op.type) {
case ZYDIS_OPERAND_TYPE_MEMORY: { case ZYDIS_OPERAND_TYPE_MEMORY: {
@ -143,7 +150,7 @@ void deobfuscate(zydis_routine_t &routine) {
return false; return false;
}; };
static const auto _reads = [](zydis_decoded_instr_t &instr, static const auto _reads = [](zydis_decoded_instr_t& instr,
zydis_register_t reg) -> bool { zydis_register_t reg) -> bool {
if (instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && if (instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
reg::compare(instr.operands[0].mem.base, reg)) reg::compare(instr.operands[0].mem.base, reg))
@ -156,7 +163,7 @@ void deobfuscate(zydis_routine_t &routine) {
return false; return false;
}; };
static const auto _writes = [](zydis_decoded_instr_t &instr, static const auto _writes = [](zydis_decoded_instr_t& instr,
zydis_register_t reg) -> bool { zydis_register_t reg) -> bool {
for (auto op_idx = 0u; op_idx < instr.operand_count; ++op_idx) for (auto op_idx = 0u; op_idx < instr.operand_count; ++op_idx)
// if instruction writes to the specific register... // if instruction writes to the specific register...
@ -202,12 +209,12 @@ void deobfuscate(zydis_routine_t &routine) {
if (reg != ZYDIS_REGISTER_NONE) { if (reg != ZYDIS_REGISTER_NONE) {
// find the next place that this register is written too... // find the next place that this register is written too...
auto write_result = std::find_if(itr + 1, routine.end(), auto write_result = std::find_if(itr + 1, routine.end(),
[&](zydis_instr_t &instr) -> bool { [&](zydis_instr_t& instr) -> bool {
return _writes(instr.instr, reg); return _writes(instr.instr, reg);
}); });
auto read_result = std::find_if(itr + 1, write_result, auto read_result = std::find_if(itr + 1, write_result,
[&](zydis_instr_t &instr) -> bool { [&](zydis_instr_t& instr) -> bool {
return _reads(instr.instr, reg); return _reads(instr.instr, reg);
}); });

Loading…
Cancel
Save