Skip to content

Commit b703a79

Browse files
author
Requiem
committed
feat: improved AES/AES-NI checks
1 parent b1c7e58 commit b703a79

1 file changed

Lines changed: 32 additions & 50 deletions

File tree

src/vmaware.hpp

Lines changed: 32 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -9989,65 +9989,24 @@ struct VM {
99899989

99909990

99919991
/**
9992-
* @brief Check if the CPU is capable of running certain instructions successfully
9993-
* @category Windows
9994-
* @implements VM::CPU_HEURISTIC
9995-
*/
9992+
* @brief Check if the CPU is capable of running certain instructions successfully
9993+
* @category Windows
9994+
* @implements VM::CPU_HEURISTIC
9995+
*/
99969996
[[nodiscard]] static bool cpu_heuristic() {
9997-
using NtAllocateVirtualMemory_t = NTSTATUS(__stdcall*)(HANDLE, PVOID*, ULONG_PTR, PSIZE_T, ULONG, ULONG);
9998-
using NtProtectVirtualMemory_t = NTSTATUS(__stdcall*)(HANDLE, PVOID*, PSIZE_T, ULONG, PULONG);
9999-
using NtFreeVirtualMemory_t = NTSTATUS(__stdcall*)(HANDLE, PVOID*, PSIZE_T, ULONG);
10000-
using NtFlushInstructionCache_t = NTSTATUS(__stdcall*)(HANDLE, PVOID, SIZE_T);
10001-
100029997
// 1) Check for commonly disabled instructions on patches
10003-
const HMODULE ntdll = util::get_ntdll();
10004-
if (!ntdll) return false;
10005-
10006-
const char* names[] = { "NtAllocateVirtualMemory", "NtProtectVirtualMemory", "NtFlushInstructionCache", "NtFreeVirtualMemory"
10007-
};
10008-
void* funcs[ARRAYSIZE(names)] = {};
10009-
util::get_function_address(ntdll, names, funcs, ARRAYSIZE(names));
10010-
10011-
const auto pNtAllocateVirtualMemory = reinterpret_cast<NtAllocateVirtualMemory_t>(funcs[0]);
10012-
const auto pNtProtectVirtualMemory = reinterpret_cast<NtProtectVirtualMemory_t>(funcs[1]);
10013-
const auto pNtFlushInstructionCache = reinterpret_cast<NtFlushInstructionCache_t>(funcs[2]);
10014-
const auto pNtFreeVirtualMemory = reinterpret_cast<NtFreeVirtualMemory_t>(funcs[3]);
10015-
10016-
if (!pNtAllocateVirtualMemory || !pNtProtectVirtualMemory || !pNtFlushInstructionCache || !pNtFreeVirtualMemory) {
10017-
return false;
10018-
}
10019-
10020-
PVOID freeBase = nullptr;
10021-
SIZE_T freeSize = 0;
10022-
100239998
bool ok = true;
10024-
alignas(16) unsigned char plaintext[16] = {
10025-
0x00,0x11,0x22,0x33, 0x44,0x55,0x66,0x77,
10026-
0x88,0x99,0xAA,0xBB, 0xCC,0xDD,0xEE,0xFF
10027-
};
10028-
alignas(16) unsigned char key[16] = {
10029-
0x0F,0x0E,0x0D,0x0C, 0x0B,0x0A,0x09,0x08,
10030-
0x07,0x06,0x05,0x04, 0x03,0x02,0x01,0x00
10031-
};
10032-
alignas(16) unsigned char out[16] = { 0 };
10033-
10034-
__try {
10035-
__m128i block = _mm_loadu_si128(reinterpret_cast<const __m128i*>(plaintext));
10036-
__m128i key_vec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(key));
100379999

10038-
__m128i tmp = _mm_xor_si128(block, key_vec);
10039-
tmp = _mm_aesenc_si128(tmp, key_vec);
10000+
u32 a = 0, b = 0, c = 0, d = 0;
10001+
cpu::cpuid(a, b, c, d, 1u);
1004010002

10041-
_mm_storeu_si128(reinterpret_cast<__m128i*>(out), tmp);
10042-
}
10043-
__except (GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION
10044-
? EXCEPTION_EXECUTE_HANDLER
10045-
: EXCEPTION_CONTINUE_SEARCH) {
10003+
constexpr u32 AES_NI_BIT = 1u << 25;
10004+
if ((c & AES_NI_BIT) == 0) {
1004610005
ok = false;
1004710006
}
1004810007

1004910008
if (!ok) {
10050-
debug("CPU_HEURISTIC: Failed to handle AES encryption correctly");
10009+
debug("CPU_HEURISTIC: CPU does not report AES");
1005110010
return true;
1005210011
}
1005310012

@@ -10082,6 +10041,8 @@ struct VM {
1008210041

1008310042
LPVOID amd_target_mem = nullptr;
1008410043
LPVOID exec_mem = nullptr;
10044+
PVOID freeBase = nullptr;
10045+
SIZE_T freeSize = 0;
1008510046

1008610047
const bool claimed_amd = cpu::is_amd();
1008710048
const bool claimed_intel = cpu::is_intel();
@@ -10099,6 +10060,27 @@ struct VM {
1009910060
// one cache line = 64 bytes
1010010061
const SIZE_T targetSize = 64;
1010110062

10063+
const HMODULE ntdll = util::get_ntdll();
10064+
if (!ntdll) return false;
10065+
10066+
const char* names[] = { "NtAllocateVirtualMemory", "NtProtectVirtualMemory", "NtFlushInstructionCache", "NtFreeVirtualMemory"
10067+
};
10068+
void* funcs[ARRAYSIZE(names)] = {};
10069+
util::get_function_address(ntdll, names, funcs, ARRAYSIZE(names));
10070+
10071+
using NtAllocateVirtualMemory_t = NTSTATUS(__stdcall*)(HANDLE, PVOID*, ULONG_PTR, PSIZE_T, ULONG, ULONG);
10072+
using NtProtectVirtualMemory_t = NTSTATUS(__stdcall*)(HANDLE, PVOID*, PSIZE_T, ULONG, PULONG);
10073+
using NtFreeVirtualMemory_t = NTSTATUS(__stdcall*)(HANDLE, PVOID*, PSIZE_T, ULONG);
10074+
using NtFlushInstructionCache_t = NTSTATUS(__stdcall*)(HANDLE, PVOID, SIZE_T);
10075+
const auto pNtAllocateVirtualMemory = reinterpret_cast<NtAllocateVirtualMemory_t>(funcs[0]);
10076+
const auto pNtProtectVirtualMemory = reinterpret_cast<NtProtectVirtualMemory_t>(funcs[1]);
10077+
const auto pNtFlushInstructionCache = reinterpret_cast<NtFlushInstructionCache_t>(funcs[2]);
10078+
const auto pNtFreeVirtualMemory = reinterpret_cast<NtFreeVirtualMemory_t>(funcs[3]);
10079+
10080+
if (!pNtAllocateVirtualMemory || !pNtProtectVirtualMemory || !pNtFlushInstructionCache || !pNtFreeVirtualMemory) {
10081+
return false;
10082+
}
10083+
1010210084
{
1010310085
PVOID base = nullptr;
1010410086
SIZE_T sz = targetSize;

0 commit comments

Comments
 (0)