the coupe does 190 but it feels like 60 mph

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

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

@ -3,6 +3,7 @@
#include <Zydis/Zydis.h>
#include <xmmintrin.h>
#include <memory>
#include <optional>
#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...
/// </summary>
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>
/// utils pertaining to native registers...
/// </summary>

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

@ -60,21 +60,16 @@ std::optional<zydis_routine_t::iterator> get_fetch_operand(
void print(const zydis_decoded_instr_t &instr) {
char buffer[256];
ZydisFormatter formatter;
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
ZydisFormatterFormatInstruction(&formatter, &instr, buffer, sizeof(buffer),
0u);
ZydisFormatterFormatInstruction(vm::util::g_formatter.get(), &instr, buffer,
sizeof(buffer), 0u);
std::puts(buffer);
}
void print(zydis_routine_t &routine) {
char buffer[256];
ZydisFormatter formatter;
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
for (auto [instr, raw, addr] : routine) {
ZydisFormatterFormatInstruction(&formatter, &instr, buffer, sizeof(buffer),
addr);
ZydisFormatterFormatInstruction(vm::util::g_formatter.get(), &instr, buffer,
sizeof(buffer), addr);
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 keep_jmps, std::uint32_t max_instrs,
std::uintptr_t module_base) {
ZydisDecoder decoder;
zydis_decoded_instr_t instr;
ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64,
ZYDIS_ADDRESS_WIDTH_64);
std::uint32_t instr_cnt = 0u;
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;
// detect if we have already been at this instruction... if so that means
// 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});
ZydisCalcAbsoluteAddress(&instr, &instr.operands[0], routine_addr,
&routine_addr);
} else if (instr.mnemonic == ZYDIS_MNEMONIC_RET) {
routine.push_back({instr, raw_instr, routine_addr});
return true;

Loading…
Cancel
Save