#pragma once #include #include #include #include #include #ifdef _MSC_VER #include #define bswap_32(x) _byteswap_ulong(x) #define bswap_64(x) _byteswap_uint64(x) #define bswap_16(x) _byteswap_ushort(x) #elif defined(__APPLE__) // Mac OS X / Darwin features #include #define bswap_32(x) OSSwapInt32(x) #define bswap_64(x) OSSwapInt64(x) #elif defined(__sun) || defined(sun) #include #define bswap_32(x) BSWAP_32(x) #define bswap_64(x) BSWAP_64(x) #elif defined(__FreeBSD__) #include #define bswap_32(x) bswap32(x) #define bswap_64(x) bswap64(x) #elif defined(__OpenBSD__) #include #define bswap_32(x) swap32(x) #define bswap_64(x) swap64(x) #elif defined(__NetBSD__) #include #include #if defined(__BSWAP_RENAME) && !defined(__bswap_32) #define bswap_32(x) bswap32(x) #define bswap_64(x) bswap64(x) #endif #else #include #endif using u8 = unsigned char; using u16 = unsigned short; using u32 = unsigned int; using u64 = unsigned long long; using u128 = __m128; using zydis_decoded_instr_t = ZydisDecodedInstruction; using zydis_register_t = ZydisRegister; using zydis_mnemonic_t = ZydisMnemonic; using zydis_decoded_operand_t = ZydisDecodedOperand; struct zydis_instr_t { zydis_decoded_instr_t instr; std::vector raw; std::uintptr_t addr; }; using zydis_routine_t = std::vector; /// /// utils used by the other cpp files... misc things that get used a lot... /// namespace vm::util { /// /// utils pertaining to native registers... /// namespace reg { /// /// converts say... AL to RAX... /// /// a zydis decoded register value... /// returns the largest width register of the given register... AL /// gives RAX... zydis_register_t to64(zydis_register_t reg); /// /// compares to registers with each other... calls to64 and compares... /// /// register a... /// register b... /// returns true if register to64(a) == to64(b)... bool compare(zydis_register_t a, zydis_register_t b); } // namespace reg /// /// get the instruction that fetches an operand out of VIP... /// /// this is a deobfuscated, flattened, view of any set of /// native instructions that read an operand out of VIP... can be calc_jmp, /// vm_entry, or vm handlers... /// returns true of the fetch operand native instruction is /// found... bool get_fetch_operand(const zydis_routine_t &routine, zydis_instr_t &fetch_instr); /// /// gets the instruction that fetches an operand out of VIP and returns an /// iterator to it... /// /// this is a deobfuscated, flattened, view of any set of /// native instructions that read an operand out of VIP... can be calc_jmp, /// vm_entry, or vm handlers... returns the iterator of the /// native instruction, else an empty std::optional... std::optional get_fetch_operand( zydis_routine_t &routine); /// /// prints a disassembly view of a routine... /// /// reference to a zydis_routine_t to be /// printed... void print(zydis_routine_t &routine); /// /// prints a single disassembly view of an instruction... /// /// instruction to print... void print(const zydis_decoded_instr_t &instr); /// /// determines if a given decoded native instruction is a JCC... /// /// /// bool is_jmp(const zydis_decoded_instr_t &instr); /// /// flatten native instruction stream, takes every JCC (follows the branch)... /// /// filled with decoded instructions... /// linear virtual address to start flattening /// from... keep JCC's in the flattened /// instruction stream... returns true if flattened was /// successful... bool flatten(zydis_routine_t &routine, std::uintptr_t routine_addr, bool keep_jmps = false, std::uint32_t max_instrs = 500, std::uintptr_t module_base = 0ull); /// /// deadstore deobfuscation of a flattened routine... /// /// reference to a flattened instruction vector... void deobfuscate(zydis_routine_t &routine); } // namespace vm::util