the coupe does 190 but it feels like 60 mph

master
John Doe 3 years ago
parent 78033b5ba2
commit 05748c67be

@ -3,45 +3,46 @@
#include <vmhandlers.hpp> #include <vmhandlers.hpp>
#include <vmp2.hpp> #include <vmp2.hpp>
namespace vm namespace vm {
{ /// <summary>
/// <summary> /// vm::ctx_t class is used to auto generate vm_entry, calc_jmp, and other
/// vm::ctx_t class is used to auto generate vm_entry, calc_jmp, and other per-vm entry information... /// per-vm entry information... creating a vm::ctx_t object can make it easier
/// creating a vm::ctx_t object can make it easier to pass around information pertaining to a given vm entry... /// to pass around information pertaining to a given vm entry...
/// </summary> /// </summary>
class ctx_t class ctx_t {
{ public:
public: /// <summary>
/// <summary> /// default constructor for vm::ctx_t... all information for a given vm entry
/// default constructor for vm::ctx_t... all information for a given vm entry must be provided... /// must be provided...
/// </summary> /// </summary>
/// <param name="module_base">the linear virtual address of the module base...</param> /// <param name="module_base">the linear virtual address of the module
/// <param name="image_base">image base from optional nt header... <a /// base...</param> <param name="image_base">image base from optional nt
/// href="https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header64">IMAGE_OPTIONAL_HEADER64</a>...</param> /// header... <a
/// <param name="image_size">image size from optional nt header... <a /// href="https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header64">IMAGE_OPTIONAL_HEADER64</a>...</param>
/// href="https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header64">IMAGE_OPTIONAL_HEADER64</a>...</param> /// <param name="image_size">image size from optional nt header... <a
/// <param name="vm_entry_rva">relative virtual address from the module base address to the first push prior to /// href="https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header64">IMAGE_OPTIONAL_HEADER64</a>...</param>
/// a vm entry...</param> /// <param name="vm_entry_rva">relative virtual address from the module base
explicit ctx_t( std::uintptr_t module_base, std::uintptr_t image_base, std::uintptr_t image_size, /// address to the first push prior to a vm entry...</param>
std::uintptr_t vm_entry_rva ); explicit ctx_t(std::uintptr_t module_base, std::uintptr_t image_base,
std::uintptr_t image_size, std::uintptr_t vm_entry_rva);
/// <summary> /// <summary>
/// init all per-vm entry data such as vm_entry, calc_jmp, and vm handlers... /// init all per-vm entry data such as vm_entry, calc_jmp, and vm handlers...
/// </summary> /// </summary>
/// <returns>returns true if no errors...</returns> /// <returns>returns true if no errors...</returns>
bool init(); bool init();
const std::uintptr_t module_base, image_base, vm_entry_rva, image_size; const std::uintptr_t module_base, image_base, vm_entry_rva, image_size;
/// <summary> /// <summary>
/// the order in which VIP advances... /// the order in which VIP advances...
/// </summary> /// </summary>
vmp2::exec_type_t exec_type; vmp2::exec_type_t exec_type;
zydis_routine_t vm_entry, calc_jmp; zydis_routine_t vm_entry, calc_jmp;
/// <summary> /// <summary>
/// all the vm handlers for the given vm entry... /// all the vm handlers for the given vm entry...
/// </summary> /// </summary>
std::vector< vm::handler::handler_t > vm_handlers; std::vector<vm::handler::handler_t> vm_handlers;
}; };
} // namespace vm } // namespace vm

@ -3,6 +3,7 @@
#include <Zydis/Zydis.h> #include <Zydis/Zydis.h>
#include <xmmintrin.h> #include <xmmintrin.h>
#include <memory>
#include <optional> #include <optional>
#include <vector> #include <vector>
@ -76,6 +77,23 @@ using zydis_routine_t = std::vector<zydis_instr_t>;
/// utils used by the other cpp files... misc things that get used a lot... /// utils used by the other cpp files... misc things that get used a lot...
/// </summary> /// </summary>
namespace vm::util { namespace vm::util {
inline std::shared_ptr<ZydisDecoder> g_decoder = nullptr;
inline std::shared_ptr<ZydisFormatter> g_formatter = nullptr;
inline void init() {
if (!vm::util::g_decoder && !vm::util::g_formatter) {
vm::util::g_decoder = std::make_shared<ZydisDecoder>();
vm::util::g_formatter = std::make_shared<ZydisFormatter>();
ZydisDecoderInit(vm::util::g_decoder.get(), ZYDIS_MACHINE_MODE_LONG_64,
ZYDIS_ADDRESS_WIDTH_64);
ZydisFormatterInit(vm::util::g_formatter.get(),
ZYDIS_FORMATTER_STYLE_INTEL);
}
}
/// <summary> /// <summary>
/// utils pertaining to native registers... /// utils pertaining to native registers...
/// </summary> /// </summary>

@ -1,31 +1,33 @@
#include <Zydis/Zydis.h>
#include <vmprofiler.hpp> #include <vmprofiler.hpp>
namespace vm namespace vm {
{ ctx_t::ctx_t(std::uintptr_t module_base, std::uintptr_t image_base,
ctx_t::ctx_t( std::uintptr_t module_base, std::uintptr_t image_base, std::uintptr_t image_size, std::uintptr_t image_size, std::uintptr_t vm_entry_rva)
std::uintptr_t vm_entry_rva ) : module_base(module_base),
: module_base( module_base ), image_base( image_base ), image_size( image_size ), vm_entry_rva( vm_entry_rva ) image_base(image_base),
{ image_size(image_size),
} vm_entry_rva(vm_entry_rva) {}
bool ctx_t::init() bool ctx_t::init() {
{ vm::util::init();
if ( !vm::util::flatten( vm_entry, vm_entry_rva + module_base ) ) if (!vm::util::flatten(vm_entry, vm_entry_rva + module_base)) return false;
return false;
vm::util::deobfuscate( vm_entry ); vm::util::deobfuscate(vm_entry);
if ( !vm::calc_jmp::get( vm_entry, calc_jmp ) ) if (!vm::calc_jmp::get(vm_entry, calc_jmp)) return false;
return false;
if ( auto vm_handler_table = vm::handler::table::get( vm_entry ); if (auto vm_handler_table = vm::handler::table::get(vm_entry);
!vm::handler::get_all( module_base, image_base, vm_entry, vm_handler_table, vm_handlers ) ) !vm::handler::get_all(module_base, image_base, vm_entry, vm_handler_table,
return false; vm_handlers))
return false;
if ( auto advancement = vm::calc_jmp::get_advancement( calc_jmp ); advancement.has_value() ) if (auto advancement = vm::calc_jmp::get_advancement(calc_jmp);
exec_type = advancement.value(); advancement.has_value())
else exec_type = advancement.value();
return false; else
return false;
return true; return true;
} }
} // namespace vm } // namespace vm

@ -60,21 +60,16 @@ std::optional<zydis_routine_t::iterator> get_fetch_operand(
void print(const zydis_decoded_instr_t &instr) { void print(const zydis_decoded_instr_t &instr) {
char buffer[256]; char buffer[256];
ZydisFormatter formatter; ZydisFormatterFormatInstruction(vm::util::g_formatter.get(), &instr, buffer,
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL); sizeof(buffer), 0u);
ZydisFormatterFormatInstruction(&formatter, &instr, buffer, 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];
ZydisFormatter formatter;
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
for (auto [instr, raw, addr] : routine) { for (auto [instr, raw, addr] : routine) {
ZydisFormatterFormatInstruction(&formatter, &instr, buffer, sizeof(buffer), ZydisFormatterFormatInstruction(vm::util::g_formatter.get(), &instr, buffer,
addr); sizeof(buffer), addr);
std::printf("> %p %s\n", addr, buffer); std::printf("> %p %s\n", addr, buffer);
} }
} }
@ -87,15 +82,12 @@ bool is_jmp(const zydis_decoded_instr_t &instr) {
bool flatten(zydis_routine_t &routine, std::uintptr_t routine_addr, bool flatten(zydis_routine_t &routine, std::uintptr_t routine_addr,
bool keep_jmps, std::uint32_t max_instrs, bool keep_jmps, std::uint32_t max_instrs,
std::uintptr_t module_base) { std::uintptr_t module_base) {
ZydisDecoder decoder;
zydis_decoded_instr_t instr; zydis_decoded_instr_t instr;
ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64,
ZYDIS_ADDRESS_WIDTH_64);
std::uint32_t instr_cnt = 0u; std::uint32_t instr_cnt = 0u;
while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer( while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(
&decoder, reinterpret_cast<void *>(routine_addr), 0x1000, &instr))) { vm::util::g_decoder.get(), reinterpret_cast<void *>(routine_addr), 0x1000,
&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...
@ -116,9 +108,9 @@ bool flatten(zydis_routine_t &routine, std::uintptr_t routine_addr,
} }
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;

Loading…
Cancel
Save