Windows C++ / QEMU CPU brand evasion
Author | kernelwernel |
Platform | Windows |
Language | C++ |
Technique | QEMU CPU brand evasion |
Code
#if (defined(_MSC_VER) || defined(_WIN32) || defined(_WIN64) || defined(__MINGW32__))
#define MSVC 1
#define LINUX 0
#elif (defined(__linux__))
#define MSVC 0
#define LINUX 1
#else
#define MSVC 0
#define LINUX 0
#endif
#if (LINUX)
#include <cpuid.h>
#elif (MSVC)
#include <intrin.h>
#endif
#include <cstdint>
#include <array>
#include <iostream>
#include <regex>
#include <string>
#include <cstring>
// cross-platform wrapper function for linux and MSVC cpuid
void cpuid(
std::uint32_t& a,
std::uint32_t& b,
std::uint32_t& c,
std::uint32_t& d,
const std::uint32_t a_leaf
) {
#if (MSVC)
std::int32_t x[4]{};
__cpuid((std::int32_t*)x, static_cast<std::int32_t>(a_leaf));
a = static_cast<std::uint32_t>(x[0]);
b = static_cast<std::uint32_t>(x[1]);
c = static_cast<std::uint32_t>(x[2]);
d = static_cast<std::uint32_t>(x[3]);
#elif (LINUX)
__get_cpuid(a_leaf, &a, &b, &c, &d);
#else
return;
#endif
}
// checks if the leaf is high enough for the CPU to support
bool is_leaf_supported(const std::uint32_t p_leaf) {
std::uint32_t eax, unused = 0;
cpuid(eax, unused, unused, unused, 0x80000000);
return (p_leaf <= eax);
}
// get the CPU product
std::string get_brand() {
if (!is_leaf_supported(0x80000004)) {
return "";
}
std::array<std::uint32_t, 4> buffer{};
constexpr std::size_t buffer_size = sizeof(int32_t) * buffer.size();
std::array<char, 64> charbuffer{};
constexpr std::array<std::uint32_t, 3> ids = {{
0x80000002,
0x80000003,
0x80000004
}};
std::string brand = "";
for (const std::uint32_t& id : ids) {
cpuid(buffer.at(0), buffer.at(1), buffer.at(2), buffer.at(3), id);
std::memcpy(charbuffer.data(), buffer.data(), buffer_size);
const char* convert = charbuffer.data();
brand += convert;
}
return brand;
}
// main code, checks if the CPU brand matches with QEMU's
bool cpu_brand_qemu() {
std::string brand = get_brand();
std::regex qemu_pattern("QEMU Virtual CPU", std::regex_constants::icase);
if (std::regex_match(brand, qemu_pattern)) {
return true;
}
return false;
}
int main() {
std::cout << "is the CPU brand \"QEMU Virtual CPU\"? = " << (cpu_brand_qemu() ? "Yes, very likely a QEMU CPU\n" : "No, most likely baremetal\n");
}
Created
September 2, 2024
Last Revised
September 2, 2024