diff options
Diffstat (limited to 'runtime/core.cc')
-rw-r--r-- | runtime/core.cc | 1365 |
1 files changed, 1365 insertions, 0 deletions
diff --git a/runtime/core.cc b/runtime/core.cc new file mode 100644 index 0000000..1344322 --- /dev/null +++ b/runtime/core.cc @@ -0,0 +1,1365 @@ +#include "common.h" +#include "utils.h" +#include "objects.h" + +#include "crypto.h" +#include "core.h" +#include "string_manager.h" +#include "licensing_manager.h" +#include "hwid.h" + +#ifdef VMP_GNU +#include "loader.h" +#elif defined(WIN_DRIVER) +#include "loader.h" +#else +#include "resource_manager.h" +#include "file_manager.h" +#include "registry_manager.h" +#include "hook_manager.h" +#endif + +GlobalData *loader_data = NULL; +#ifdef WIN_DRIVER +__declspec(noinline) void * ExAllocateNonPagedPoolNx(size_t size) +{ + return ExAllocatePool((POOL_TYPE)FACE_NON_PAGED_POOL_NX, size); +} + +void * __cdecl operator new(size_t size) +{ + if (size) + return ExAllocateNonPagedPoolNx(size); + + return NULL; +} + +void __cdecl operator delete(void* p) +{ + if (p) + ExFreePool(p); +} + +void __cdecl operator delete(void* p, size_t) +{ + if (p) + ExFreePool(p); +} + +void * __cdecl operator new[](size_t size) +{ + if (size) + return ExAllocateNonPagedPoolNx(size); + + return NULL; +} + +void __cdecl operator delete[](void *p) +{ + if (p) + ExFreePool(p); +} +#endif + +/** + * initialization functions + */ + +#ifdef VMP_GNU + +EXPORT_API bool WINAPI DllMain(HMODULE hModule, bool is_init) __asm__ ("DllMain"); +bool WINAPI DllMain(HMODULE hModule, bool is_init) +{ + if (is_init) { + if (!Core::Instance()->Init(hModule)) { + Core::Free(); + return false; + } + } else { + Core::Free(); + } + return true; +} + +#elif defined(WIN_DRIVER) + +NTSTATUS DllMain(HMODULE hModule, bool is_init) +{ + if (is_init) { + if (!Core::Instance()->Init(hModule)) { + Core::Free(); + return STATUS_ACCESS_DENIED; + } + } else { + Core::Free(); + } + return STATUS_SUCCESS; +} + +#else + +BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) +{ + switch (dwReason) { + case DLL_PROCESS_ATTACH: + if (!Core::Instance()->Init(hModule)) { + Core::Free(); + return FALSE; + } + break; + case DLL_PROCESS_DETACH: + Core::Free(); + break; + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + } + return TRUE; +} +#endif + +/** + * exported functions + */ + +NOINLINE bool InternalFindFirmwareVendor(const uint8_t *data, size_t data_size) +{ + for (size_t i = 0; i < data_size; i++) { +#ifdef __unix__ + if (i + 3 < data_size && data[i + 0] == 'Q' && data[i + 1] == 'E' && data[i + 2] == 'M' && data[i + 3] == 'U') + return true; + if (i + 8 < data_size && data[i + 0] == 'M' && data[i + 1] == 'i' && data[i + 2] == 'c' && data[i + 3] == 'r' && data[i + 4] == 'o' && data[i + 5] == 's' && data[i + 6] == 'o' && data[i + 7] == 'f' && data[i + 8] == 't') + return true; + if (i + 6 < data_size && data[i + 0] == 'i' && data[i + 1] == 'n' && data[i + 2] == 'n' && data[i + 3] == 'o' && data[i + 4] == 't' && data[i + 5] == 'e' && data[i + 6] == 'k') + return true; +#else + if (i + 9 < data_size && data[i + 0] == 'V' && data[i + 1] == 'i' && data[i + 2] == 'r' && data[i + 3] == 't' && data[i + 4] == 'u' && data[i + 5] == 'a' && data[i + 6] == 'l' && data[i + 7] == 'B' && data[i + 8] == 'o' && data[i + 9] == 'x') + return true; +#endif + if (i + 5 < data_size && data[i + 0] == 'V' && data[i + 1] == 'M' && data[i + 2] == 'w' && data[i + 3] == 'a' && data[i + 4] == 'r' && data[i + 5] == 'e') + return true; + if (i + 8 < data_size && data[i + 0] == 'P' && data[i + 1] == 'a' && data[i + 2] == 'r' && data[i + 3] == 'a' && data[i + 4] == 'l' && data[i + 5] == 'l' && data[i + 6] == 'e' && data[i + 7] == 'l' && data[i + 8] == 's') + return true; + } + return false; +} + +#ifdef VMP_GNU +EXPORT_API bool WINAPI ExportedIsValidImageCRC() __asm__ ("ExportedIsValidImageCRC"); +EXPORT_API bool WINAPI ExportedIsDebuggerPresent(bool check_kernel_mode) __asm__ ("ExportedIsDebuggerPresent"); +EXPORT_API bool WINAPI ExportedIsVirtualMachinePresent() __asm__ ("ExportedIsVirtualMachinePresent"); +EXPORT_API bool WINAPI ExportedIsProtected() __asm__ ("ExportedIsProtected"); +#endif + +struct CRCData { + uint8_t *ImageBase; + uint32_t Table; + uint32_t Size; + uint32_t Hash; + NOINLINE CRCData() + { + ImageBase = reinterpret_cast<uint8_t *>(FACE_IMAGE_BASE); + Table = FACE_CRC_TABLE_ENTRY; + Size = FACE_CRC_TABLE_SIZE; + Hash = FACE_CRC_TABLE_HASH; + } +}; + +bool WINAPI ExportedIsValidImageCRC() +{ + if (loader_data->is_patch_detected()) + return false; + + const CRCData crc_data; + + bool res = true; + uint8_t *image_base = crc_data.ImageBase; + uint8_t *crc_table = image_base + crc_data.Table; + uint32_t crc_table_size = *reinterpret_cast<uint32_t *>(image_base + crc_data.Size); + uint32_t crc_table_hash = *reinterpret_cast<uint32_t *>(image_base + crc_data.Hash); + +#ifdef WIN_DRIVER + uint32_t image_size = 0; + if (loader_data->loader_status() == STATUS_SUCCESS) { + IMAGE_DOS_HEADER *dos_header = reinterpret_cast<IMAGE_DOS_HEADER *>(image_base); + if (dos_header->e_magic == IMAGE_DOS_SIGNATURE) { + IMAGE_NT_HEADERS *pe_header = reinterpret_cast<IMAGE_NT_HEADERS *>(image_base + dos_header->e_lfanew); + if (pe_header->Signature == IMAGE_NT_SIGNATURE) { + IMAGE_SECTION_HEADER *sections = reinterpret_cast<IMAGE_SECTION_HEADER *>(reinterpret_cast<uint8_t *>(pe_header) + offsetof(IMAGE_NT_HEADERS, OptionalHeader) + pe_header->FileHeader.SizeOfOptionalHeader); + for (size_t i = 0; i < pe_header->FileHeader.NumberOfSections; i++) { + IMAGE_SECTION_HEADER *section = sections + i; + if (section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) { + image_size = section->VirtualAddress; + break; + } + } + } + } + } +#endif + + // check memory CRC + { + if (crc_table_hash != CalcCRC(crc_table, crc_table_size)) + res = false; + CRCValueCryptor crc_cryptor; + for (size_t i = 0; i < crc_table_size; i += sizeof(CRC_INFO)) { + CRC_INFO crc_info = *reinterpret_cast<CRC_INFO *>(crc_table + i); + crc_info.Address = crc_cryptor.Decrypt(crc_info.Address); + crc_info.Size = crc_cryptor.Decrypt(crc_info.Size); + crc_info.Hash = crc_cryptor.Decrypt(crc_info.Hash); +#ifdef WIN_DRIVER + if (image_size && image_size < crc_info.Address + crc_info.Size) + continue; +#endif + + if (crc_info.Hash != CalcCRC(image_base + crc_info.Address, crc_info.Size)) + res = false; + } + } + + // check header and loader CRC + crc_table = image_base + loader_data->loader_crc_info(); + crc_table_size = static_cast<uint32_t>(loader_data->loader_crc_size()); + crc_table_hash = static_cast<uint32_t>(loader_data->loader_crc_hash()); + { + if (crc_table_hash != CalcCRC(crc_table, crc_table_size)) + res = false; + CRCValueCryptor crc_cryptor; + for (size_t i = 0; i < crc_table_size; i += sizeof(CRC_INFO)) { + CRC_INFO crc_info = *reinterpret_cast<CRC_INFO *>(crc_table + i); + crc_info.Address = crc_cryptor.Decrypt(crc_info.Address); + crc_info.Size = crc_cryptor.Decrypt(crc_info.Size); + crc_info.Hash = crc_cryptor.Decrypt(crc_info.Hash); +#ifdef WIN_DRIVER + if (image_size && image_size < crc_info.Address + crc_info.Size) + continue; +#endif + + if (crc_info.Hash != CalcCRC(image_base + crc_info.Address, crc_info.Size)) + res = false; + } + } + +#ifndef DEMO +#ifdef VMP_GNU +#elif defined(WIN_DRIVER) +#else + // check memory type of loader_data + HMODULE ntdll = GetModuleHandleA(VMProtectDecryptStringA("ntdll.dll")); + typedef NTSTATUS(NTAPI tNtQueryVirtualMemory)(HANDLE ProcessHandle, PVOID BaseAddress, MEMORY_INFORMATION_CLASS MemoryInformationClass, PVOID MemoryInformation, SIZE_T MemoryInformationLength, PSIZE_T ReturnLength); + tNtQueryVirtualMemory *query_virtual_memory = reinterpret_cast<tNtQueryVirtualMemory *>(InternalGetProcAddress(ntdll, VMProtectDecryptStringA("NtQueryVirtualMemory"))); + if (query_virtual_memory) { + MEMORY_BASIC_INFORMATION memory_info; + NTSTATUS status = query_virtual_memory(NtCurrentProcess(), loader_data, MemoryBasicInformation, &memory_info, sizeof(memory_info), NULL); + if (NT_SUCCESS(status) && memory_info.AllocationBase == image_base) + res = false; + } +#endif +#endif + + return res; +} + +bool WINAPI ExportedIsVirtualMachinePresent() +{ + // hardware detection + int cpu_info[4]; + __cpuid(cpu_info, 1); + if ((cpu_info[2] >> 31) & 1) { +#ifndef VMP_GNU + // check Hyper-V root partition + cpu_info[1] = 0; + cpu_info[2] = 0; + cpu_info[3] = 0; + __cpuid(cpu_info, 0x40000000); + if (cpu_info[1] == 0x7263694d && cpu_info[2] == 0x666f736f && cpu_info[3] == 0x76482074) { // "Microsoft Hv" + cpu_info[1] = 0; + __cpuid(cpu_info, 0x40000003); + if (cpu_info[1] & 1) + return false; + } +#endif + return true; + } + +#ifndef VMP_GNU + uint64_t val; + uint8_t mem_val; + __try { + // set T flag + __writeeflags(__readeflags() | 0x100); + val = __rdtsc(); + __nop(); + loader_data->set_is_debugger_detected(true); + } __except(mem_val = *static_cast<uint8_t *>((GetExceptionInformation())->ExceptionRecord->ExceptionAddress), EXCEPTION_EXECUTE_HANDLER) { + if (mem_val != 0x90) + return true; + } + + __try { + // set T flag + __writeeflags(__readeflags() | 0x100); + __cpuid(cpu_info, 1); + __nop(); + loader_data->set_is_debugger_detected(true); + } __except(mem_val = *static_cast<uint8_t *>((GetExceptionInformation())->ExceptionRecord->ExceptionAddress), EXCEPTION_EXECUTE_HANDLER) { + if (mem_val != 0x90) + return true; + } +#endif + + // software detection +#ifdef __APPLE__ + // FIXME +#elif defined(__unix__) + FILE *fsys_vendor = fopen(VMProtectDecryptStringA("/sys/devices/virtual/dmi/id/sys_vendor"), "r"); + if (fsys_vendor) { + char sys_vendor[256] = {0}; + fgets(sys_vendor, sizeof(sys_vendor), fsys_vendor); + fclose(fsys_vendor); + if (InternalFindFirmwareVendor(reinterpret_cast<uint8_t *>(sys_vendor), sizeof(sys_vendor))) + return true; + } +#elif defined(WIN_DRIVER) + // FIXME +#else + HMODULE dll = GetModuleHandleA(VMProtectDecryptStringA("kernel32.dll")); + bool is_found = false; + typedef UINT (WINAPI tEnumSystemFirmwareTables)(DWORD FirmwareTableProviderSignature, PVOID pFirmwareTableEnumBuffer, DWORD BufferSize); + typedef UINT (WINAPI tGetSystemFirmwareTable)(DWORD FirmwareTableProviderSignature, DWORD FirmwareTableID, PVOID pFirmwareTableBuffer, DWORD BufferSize); + tEnumSystemFirmwareTables *enum_system_firmware_tables = reinterpret_cast<tEnumSystemFirmwareTables *>(InternalGetProcAddress(dll, VMProtectDecryptStringA("EnumSystemFirmwareTables"))); + tGetSystemFirmwareTable *get_system_firmware_table = reinterpret_cast<tGetSystemFirmwareTable *>(InternalGetProcAddress(dll, VMProtectDecryptStringA("GetSystemFirmwareTable"))); + + if (enum_system_firmware_tables && get_system_firmware_table) { + UINT tables_size = enum_system_firmware_tables('FIRM', NULL, 0); + if (tables_size) { + DWORD *tables = new DWORD[tables_size / sizeof(DWORD)]; + enum_system_firmware_tables('FIRM', tables, tables_size); + for (size_t i = 0; i < tables_size / sizeof(DWORD); i++) { + UINT data_size = get_system_firmware_table('FIRM', tables[i], NULL, 0); + if (data_size) { + uint8_t *data = new uint8_t[data_size]; + get_system_firmware_table('FIRM', tables[i], data, data_size); + if (InternalFindFirmwareVendor(data, data_size)) + is_found = true; + delete [] data; + } + } + delete [] tables; + } + } else { + dll = LoadLibraryA(VMProtectDecryptStringA("ntdll.dll")); + typedef NTSTATUS (WINAPI tNtOpenSection)(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes); + typedef NTSTATUS (WINAPI tNtMapViewOfSection)(HANDLE SectionHandle, HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits, SIZE_T CommitSize, PLARGE_INTEGER SectionOffset, PSIZE_T ViewSize, SECTION_INHERIT InheritDisposition, ULONG AllocationType, ULONG Win32Protect); + typedef NTSTATUS (WINAPI tNtUnmapViewOfSection)(HANDLE ProcessHandle, PVOID BaseAddress); + typedef NTSTATUS (WINAPI tNtClose)(HANDLE Handle); + + tNtOpenSection *open_section = reinterpret_cast<tNtOpenSection *>(InternalGetProcAddress(dll, VMProtectDecryptStringA("NtOpenSection"))); + tNtMapViewOfSection *map_view_of_section = reinterpret_cast<tNtMapViewOfSection *>(InternalGetProcAddress(dll, VMProtectDecryptStringA("NtMapViewOfSection"))); + tNtUnmapViewOfSection *unmap_view_of_section = reinterpret_cast<tNtUnmapViewOfSection *>(InternalGetProcAddress(dll, VMProtectDecryptStringA("NtUnmapViewOfSection"))); + tNtClose *close = reinterpret_cast<tNtClose *>(InternalGetProcAddress(dll, VMProtectDecryptStringA("NtClose"))); + + if (open_section && map_view_of_section && unmap_view_of_section && close) { + HANDLE process = NtCurrentProcess(); + HANDLE physical_memory = NULL; + UNICODE_STRING str; + OBJECT_ATTRIBUTES attrs; + + wchar_t buf[] = {'\\','d','e','v','i','c','e','\\','p','h','y','s','i','c','a','l','m','e','m','o','r','y',0}; + str.Buffer = buf; + str.Length = sizeof(buf) - sizeof(wchar_t); + str.MaximumLength = sizeof(buf); + + InitializeObjectAttributes(&attrs, &str, OBJ_CASE_INSENSITIVE, NULL, NULL); + NTSTATUS status = open_section(&physical_memory, SECTION_MAP_READ, &attrs); + if (NT_SUCCESS(status)) { + void *data = NULL; + SIZE_T data_size = 0x10000; + LARGE_INTEGER offset; + offset.QuadPart = 0xc0000; + + status = map_view_of_section(physical_memory, process, &data, NULL, data_size, &offset, &data_size, ViewShare, 0, PAGE_READONLY); + if (NT_SUCCESS(status)) { + if (InternalFindFirmwareVendor(static_cast<uint8_t *>(data), data_size)) + is_found = true; + unmap_view_of_section(process, data); + } + close(physical_memory); + } + } + } + if (is_found) + return true; + + if (GetModuleHandleA(VMProtectDecryptStringA("sbiedll.dll"))) + return true; +#endif + + return false; +} + +bool WINAPI ExportedIsDebuggerPresent(bool check_kernel_mode) +{ + if (loader_data->is_debugger_detected()) + return true; + +#if defined(__unix__) + FILE *file = fopen(VMProtectDecryptStringA("/proc/self/status"), "r"); + if (file) { + char data[100]; + int tracer_pid = 0; + while (fgets(data, sizeof(data), file)) { + if (data[0] == 'T' && data[1] == 'r' && data[2] == 'a' && data[3] == 'c' && data[4] == 'e' && data[5] == 'r' && data[6] == 'P' && data[7] == 'i' && data[8] == 'd' && data[9] == ':') { + char *tracer_ptr = data + 10; + // skip spaces + while (char c = *tracer_ptr) { + if (c == ' ' || c == '\t') { + tracer_ptr++; + continue; + } + else { + break; + } + } + // atoi + while (char c = *tracer_ptr++) { + if (c >= '0' && c <= '9') { + tracer_pid *= 10; + tracer_pid += c - '0'; + } + else { + if (c != '\n' && c != '\r') + tracer_pid = 0; + break; + } + } + break; + } + } + fclose(file); + + if (tracer_pid && tracer_pid != 1) + return true; + } +#elif defined(__APPLE__) + (void)check_kernel_mode; + + int junk; + int mib[4]; + kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0); + + // We're being debugged if the P_TRACED flag is set. + if ((info.kp_proc.p_flag & P_TRACED) != 0) + return true; +#else +#ifdef WIN_DRIVER +#else + HMODULE kernel32 = GetModuleHandleA(VMProtectDecryptStringA("kernel32.dll")); + HMODULE ntdll = GetModuleHandleA(VMProtectDecryptStringA("ntdll.dll")); + HANDLE process = NtCurrentProcess(); + size_t syscall = FACE_SYSCALL; + uint32_t sc_query_information_process = 0; + + if (ntdll) { +#ifndef DEMO + if (InternalGetProcAddress(ntdll, VMProtectDecryptStringA("wine_get_version")) == NULL) { +#ifndef _WIN64 + BOOL is_wow64 = FALSE; + typedef BOOL(WINAPI tIsWow64Process)(HANDLE Process, PBOOL Wow64Process); + tIsWow64Process *is_wow64_process = reinterpret_cast<tIsWow64Process *>(InternalGetProcAddress(kernel32, VMProtectDecryptStringA("IsWow64Process"))); + if (is_wow64_process) + is_wow64_process(process, &is_wow64); +#endif + + uint32_t os_build_number = loader_data->os_build_number(); + + if (os_build_number == WINDOWS_XP) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x009a; + } + else +#endif + { + sc_query_information_process = 0x0016; + } + } + else if (os_build_number == WINDOWS_2003) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00a1; + } + else +#endif + { + sc_query_information_process = 0x0016; + } + } + else if (os_build_number == WINDOWS_VISTA) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00e4; + } + else +#endif + { + sc_query_information_process = 0x0016; + } + } + else if (os_build_number == WINDOWS_VISTA_SP1) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00e4; + } + else +#endif + { + sc_query_information_process = 0x0016; + } + + } + else if (os_build_number == WINDOWS_VISTA_SP2) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00e4; + } + else +#endif + { + sc_query_information_process = 0x0016; + } + } + else if (os_build_number == WINDOWS_7) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00ea; + } + else +#endif + { + sc_query_information_process = 0x0016; + } + } + else if (os_build_number == WINDOWS_7_SP1) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00ea; + } + else +#endif + { + sc_query_information_process = 0x0016; + } + } + else if (os_build_number == WINDOWS_8) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00b0; + } + else +#endif + { + sc_query_information_process = 0x0017; + } + } + else if (os_build_number == WINDOWS_8_1) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00b3; + } + else +#endif + { + sc_query_information_process = 0x0018; + } + } + else if (os_build_number == WINDOWS_10_TH1) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00b5; + } + else +#endif + { + sc_query_information_process = 0x0019; + } + } + else if (os_build_number == WINDOWS_10_TH2) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00b5; + } + else +#endif + { + sc_query_information_process = 0x0019; + } + } + else if (os_build_number == WINDOWS_10_RS1) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00b7; + } + else +#endif + { + sc_query_information_process = 0x0019; + } + } + else if (os_build_number == WINDOWS_10_RS2) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00b8; + } + else +#endif + { + sc_query_information_process = 0x0019; + } + } + else if (os_build_number == WINDOWS_10_RS3) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00b9; + } + else +#endif + { + sc_query_information_process = 0x0019; + } + } + else if (os_build_number == WINDOWS_10_RS4) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00b9; + } + else +#endif + { + sc_query_information_process = 0x0019; + } + } + else if (os_build_number == WINDOWS_10_RS5) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00b9; + } + else +#endif + { + sc_query_information_process = 0x0019; + } + } + else if (os_build_number == WINDOWS_10_19H1) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00b9; + } + else +#endif + { + sc_query_information_process = 0x0019; + } + } + else if (os_build_number == WINDOWS_10_19H2) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00b9; + } + else +#endif + { + sc_query_information_process = 0x0019; + } + } + else if (os_build_number == WINDOWS_10_20H1) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00b9; + } + else +#endif + { + sc_query_information_process = 0x0019; + } + } + else if (os_build_number == WINDOWS_10_20H2) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00b9; + } + else +#endif + { + sc_query_information_process = 0x0019; + } + } + else if (os_build_number == WINDOWS_10_21H1) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00b9; + } + else +#endif + { + sc_query_information_process = 0x0019; + } + } + else if (os_build_number == WINDOWS_10_21H2) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00b9; + } + else +#endif + { + sc_query_information_process = 0x0019; + } + } + else if (os_build_number == WINDOWS_10_22H2) { +#ifndef _WIN64 + if (!is_wow64) { + sc_query_information_process = 0x00b9; + } + else +#endif + { + sc_query_information_process = 0x0019; + } + } +#ifndef _WIN64 + if (is_wow64 && sc_query_information_process) { + sc_query_information_process |= WOW64_FLAG | (0x03 << 24); + } +#endif + } +#endif + } + +#ifdef _WIN64 + PEB64 *peb = reinterpret_cast<PEB64 *>(__readgsqword(0x60)); +#else + PEB32 *peb = reinterpret_cast<PEB32 *>(__readfsdword(0x30)); +#endif + if (peb->BeingDebugged) + return true; + + { + size_t drx; + uint64_t val; + CONTEXT *ctx; + __try { + __writeeflags(__readeflags() | 0x100); + val = __rdtsc(); + __nop(); + return true; + } + __except (ctx = (GetExceptionInformation())->ContextRecord, + drx = (ctx->ContextFlags & CONTEXT_DEBUG_REGISTERS) ? ctx->Dr0 | ctx->Dr1 | ctx->Dr2 | ctx->Dr3 : 0, + EXCEPTION_EXECUTE_HANDLER) { + if (drx) + return true; + } + } + + typedef NTSTATUS(NTAPI tNtQueryInformationProcess)(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength); + if (sc_query_information_process) { + HANDLE debug_object; + if (NT_SUCCESS(reinterpret_cast<tNtQueryInformationProcess *>(syscall | sc_query_information_process)(process, ProcessDebugPort, &debug_object, sizeof(debug_object), NULL)) && debug_object != 0) + return true; + debug_object = 0; + if (NT_SUCCESS(reinterpret_cast<tNtQueryInformationProcess *>(syscall | sc_query_information_process)(process, ProcessDebugObjectHandle, &debug_object, sizeof(debug_object), reinterpret_cast<PULONG>(&debug_object))) + || debug_object == 0) + return true; + } + else if (tNtQueryInformationProcess *query_information_process = reinterpret_cast<tNtQueryInformationProcess *>(InternalGetProcAddress(ntdll, VMProtectDecryptStringA("NtQueryInformationProcess")))) { + HANDLE debug_object; + if (NT_SUCCESS(query_information_process(process, ProcessDebugPort, &debug_object, sizeof(debug_object), NULL)) && debug_object != 0) + return true; + if (NT_SUCCESS(query_information_process(process, ProcessDebugObjectHandle, &debug_object, sizeof(debug_object), NULL))) + return true; + } + +#endif +#ifdef WIN_DRIVER + if (true) { +#else + if (check_kernel_mode) { +#endif + bool is_found = false; + typedef NTSTATUS (NTAPI tNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength); +#ifdef WIN_DRIVER + tNtQuerySystemInformation *nt_query_system_information = &NtQuerySystemInformation; +#else + tNtQuerySystemInformation *nt_query_system_information = reinterpret_cast<tNtQuerySystemInformation *>(InternalGetProcAddress(ntdll, VMProtectDecryptStringA("NtQuerySystemInformation"))); + if (nt_query_system_information) { +#endif + SYSTEM_KERNEL_DEBUGGER_INFORMATION info; + NTSTATUS status = nt_query_system_information(SystemKernelDebuggerInformation, &info, sizeof(info), NULL); + if (NT_SUCCESS(status) && info.DebuggerEnabled && !info.DebuggerNotPresent) + return true; + + SYSTEM_MODULE_INFORMATION *buffer = NULL; + ULONG buffer_size = 0; + /*status = */nt_query_system_information(SystemModuleInformation, &buffer, 0, &buffer_size); + if (buffer_size) { + buffer = reinterpret_cast<SYSTEM_MODULE_INFORMATION *>(new uint8_t[buffer_size * 2]); + status = nt_query_system_information(SystemModuleInformation, buffer, buffer_size * 2, NULL); + if (NT_SUCCESS(status)) { + for (size_t i = 0; i < buffer->Count && !is_found; i++) { + SYSTEM_MODULE_ENTRY *module_entry = &buffer->Module[i]; + char module_name[11]; + for (size_t j = 0; j < 5; j++) { + switch (j) { + case 0: + module_name[0] = 's'; + module_name[1] = 'i'; + module_name[2] = 'c'; + module_name[3] = 'e'; + module_name[4] = '.'; + module_name[5] = 's'; + module_name[6] = 'y'; + module_name[7] = 's'; + module_name[8] = 0; + break; + case 1: + module_name[0] = 's'; + module_name[1] = 'i'; + module_name[2] = 'w'; + module_name[3] = 'v'; + module_name[4] = 'i'; + module_name[5] = 'd'; + module_name[6] = '.'; + module_name[7] = 's'; + module_name[8] = 'y'; + module_name[9] = 's'; + module_name[10] = 0; + break; + case 2: + module_name[0] = 'n'; + module_name[1] = 't'; + module_name[2] = 'i'; + module_name[3] = 'c'; + module_name[4] = 'e'; + module_name[5] = '.'; + module_name[6] = 's'; + module_name[7] = 'y'; + module_name[8] = 's'; + module_name[9] = 0; + break; + case 3: + module_name[0] = 'i'; + module_name[1] = 'c'; + module_name[2] = 'e'; + module_name[3] = 'e'; + module_name[4] = 'x'; + module_name[5] = 't'; + module_name[6] = '.'; + module_name[7] = 's'; + module_name[8] = 'y'; + module_name[9] = 's'; + module_name[10] = 0; + break; + case 4: + module_name[0] = 's'; + module_name[1] = 'y'; + module_name[2] = 's'; + module_name[3] = 'e'; + module_name[4] = 'r'; + module_name[5] = '.'; + module_name[6] = 's'; + module_name[7] = 'y'; + module_name[8] = 's'; + module_name[9] = 0; + break; + } + if (_stricmp(module_entry->Name + module_entry->PathLength, module_name) == 0) { + is_found = true; + break; + } + } + } + } + delete [] buffer; + } +#ifndef WIN_DRIVER + } +#endif + if (is_found) + return true; + } +#endif + return false; +} + +bool WINAPI ExportedIsProtected() +{ + return true; +} + +#ifdef VMP_GNU +#elif defined(WIN_DRIVER) +#else + +/** + * VirtualObject + */ + +VirtualObject::VirtualObject(VirtualObjectType type, void *ref, HANDLE handle, uint32_t access) + : ref_(ref), handle_(handle), type_(type), file_position_(0), attributes_(0), access_(access) +{ + if(access & MAXIMUM_ALLOWED) + { + access_ |= KEY_ALL_ACCESS; + } +} + +VirtualObject::~VirtualObject() +{ + +} + +/** + * VirtualObjectList + */ + +VirtualObjectList::VirtualObjectList() +{ + CriticalSection::Init(critical_section_); +} + +VirtualObjectList::~VirtualObjectList() +{ + for (size_t i = 0; i < size(); i++) { + VirtualObject *object = v_[i]; + delete object; + } + v_.clear(); + + CriticalSection::Free(critical_section_); +} + +VirtualObject *VirtualObjectList::Add(VirtualObjectType type, void *ref, HANDLE handle, uint32_t access) +{ + VirtualObject *object = new VirtualObject(type, ref, handle, access); + v_.push_back(object); + return object; +} + +void VirtualObjectList::Delete(size_t index) +{ + VirtualObject *object = v_[index]; + v_.erase(index); + delete object; +} + +void VirtualObjectList::DeleteObject(HANDLE handle) +{ + handle = EXHANDLE(handle); + for (size_t i = size(); i > 0; i--) { + size_t index = i - 1; + VirtualObject *object = v_[index]; + if (object->handle() == handle) + Delete(index); + } +} + +void VirtualObjectList::DeleteRef(void *ref, HANDLE handle) +{ + handle = EXHANDLE(handle); + for (size_t i = size(); i > 0; i--) { + size_t index = i - 1; + VirtualObject *object = v_[index]; + if (object->ref() == ref && (!handle || object->handle() == handle)) + Delete(index); + } +} + +VirtualObject *VirtualObjectList::GetObject(HANDLE handle) const +{ + handle = EXHANDLE(handle); + for (size_t i = 0; i < size(); i++) { + VirtualObject *object = v_[i]; + if (object->handle() == handle) + return object; + } + return NULL; +} + +VirtualObject *VirtualObjectList::GetFile(HANDLE handle) const +{ + VirtualObject *object = GetObject(handle); + return (object && object->type() == OBJECT_FILE) ? object : NULL; +} + +VirtualObject *VirtualObjectList::GetSection(HANDLE handle) const +{ + VirtualObject *object = GetObject(handle); + return (object && object->type() == OBJECT_SECTION) ? object : NULL; +} + +VirtualObject *VirtualObjectList::GetMap(HANDLE process, void *map) const +{ + for (size_t i = 0; i < size(); i++) { + VirtualObject *object = v_[i]; + if (object->type() == OBJECT_MAP && object->handle() == process && object->ref() == map) + return object; + } + return NULL; +} + +VirtualObject *VirtualObjectList::GetKey(HANDLE handle) const +{ + VirtualObject *object = GetObject(handle); + return (object && object->type() == OBJECT_KEY) ? object : NULL; +} + +uint32_t VirtualObjectList::GetHandleCount(HANDLE handle) const +{ + uint32_t res = 0; + for (size_t i = 0; i < size(); i++) { + VirtualObject *object = v_[i]; + if (object->handle() == handle) + res++; + } + return res; +} + +uint32_t VirtualObjectList::GetPointerCount(const void *ref) const +{ + uint32_t res = 0; + for (size_t i = 0; i < size(); i++) { + VirtualObject *object = v_[i]; + if (object->ref() == ref) + res++; + } + return res; +} +#endif + +/** + * Core + */ + +Core *Core::self_ = NULL; + +Core::Core() + : string_manager_(NULL), licensing_manager_(NULL), hardware_id_(NULL) +#ifdef VMP_GNU +#elif defined(WIN_DRIVER) +#else + , resource_manager_(NULL), file_manager_(NULL), registry_manager_(NULL) + , hook_manager_(NULL), nt_protect_virtual_memory_(NULL), nt_close_(NULL) + , nt_query_object_(NULL), dbg_ui_remote_breakin_(NULL) +#endif +{ + +} + +Core::~Core() +{ + delete string_manager_; + delete licensing_manager_; + delete hardware_id_; + +#ifdef VMP_GNU +#elif defined(WIN_DRIVER) +#else + if (resource_manager_) { + resource_manager_->UnhookAPIs(*hook_manager_); + delete resource_manager_; + } + if (file_manager_) { + file_manager_->UnhookAPIs(*hook_manager_); + delete file_manager_; + } + if (registry_manager_) { + registry_manager_->UnhookAPIs(*hook_manager_); + delete registry_manager_; + } + + if (nt_protect_virtual_memory_ || nt_close_ || dbg_ui_remote_breakin_) + UnhookAPIs(*hook_manager_); + + delete hook_manager_; +#endif +} + +Core *Core::Instance() +{ + if (!self_) + self_ = new Core(); + return self_; +} + +void Core::Free() +{ + if (self_) { + delete self_; + self_ = NULL; + } +} + +struct CoreData { + uint32_t Strings; + uint32_t Resources; + uint32_t Storage; + uint32_t Registry; + uint32_t LicenseData; + uint32_t LicenseDataSize; + uint32_t TrialHWID; + uint32_t TrialHWIDSize; + uint32_t Key; + uint32_t Options; + + NOINLINE CoreData() + { + Strings = FACE_STRING_INFO; + Resources = FACE_RESOURCE_INFO; + Storage = FACE_STORAGE_INFO; + Registry = FACE_REGISTRY_INFO; + Key = FACE_KEY_INFO; + LicenseData = FACE_LICENSE_INFO; + LicenseDataSize = FACE_LICENSE_INFO_SIZE; + TrialHWID = FACE_TRIAL_HWID; + TrialHWIDSize = FACE_TRIAL_HWID_SIZE; + Options = FACE_CORE_OPTIONS; + } +}; + +bool Core::Init(HMODULE instance) +{ + const CoreData data; + + uint8_t *key = reinterpret_cast<uint8_t *>(instance) + data.Key; + if (data.Strings) + string_manager_ = new StringManager(reinterpret_cast<uint8_t *>(instance) + data.Strings, instance, key); + + if (data.LicenseData) + licensing_manager_ = new LicensingManager(reinterpret_cast<uint8_t *>(instance) + data.LicenseData, data.LicenseDataSize, key); + + if (data.TrialHWID) { + uint8_t hwid_data[64]; + { + CipherRC5 cipher(key); + cipher.Decrypt(reinterpret_cast<uint8_t *>(instance) + data.TrialHWID, reinterpret_cast<uint8_t *>(&hwid_data), sizeof(hwid_data)); + } + if (!hardware_id()->IsCorrect(hwid_data, data.TrialHWIDSize)) { + const VMP_CHAR *message; +#ifdef VMP_GNU + message = VMProtectDecryptStringA(MESSAGE_HWID_MISMATCHED_STR); +#else + message = VMProtectDecryptStringW(MESSAGE_HWID_MISMATCHED_STR); +#endif + ShowMessage(message); + return false; + } + } + +#ifdef VMP_GNU +#elif defined(WIN_DRIVER) +#else + if (data.Resources || data.Storage || data.Registry || (data.Options & (CORE_OPTION_MEMORY_PROTECTION | CORE_OPTION_CHECK_DEBUGGER))) + hook_manager_ = new HookManager(); + + if (data.Resources) { + resource_manager_ = new ResourceManager(reinterpret_cast<uint8_t *>(instance) + data.Resources, instance, key); + resource_manager_->HookAPIs(*hook_manager_); //-V595 + } + if (data.Storage) { + file_manager_ = new FileManager(reinterpret_cast<uint8_t *>(instance) + data.Storage, instance, key, &objects_); + file_manager_->HookAPIs(*hook_manager_); + } + if (data.Registry) { + registry_manager_ = new RegistryManager(reinterpret_cast<uint8_t *>(instance) + data.Registry, instance, key, &objects_); + registry_manager_->HookAPIs(*hook_manager_); + } + if (hook_manager_) + HookAPIs(*hook_manager_, data.Options); + if (file_manager_) { + if (!file_manager_->OpenFiles(*registry_manager_)) + return false; + } +#endif + + return true; +} + +HardwareID *Core::hardware_id() +{ + if (!hardware_id_) + hardware_id_ = new HardwareID; + return hardware_id_; +} + +#ifdef VMP_GNU +#elif defined(WIN_DRIVER) +#else +NTSTATUS WINAPI HookedNtProtectVirtualMemory(HANDLE ProcesssHandle, LPVOID *BaseAddress, SIZE_T *Size, DWORD NewProtect, PDWORD OldProtect) +{ + Core *core = Core::Instance(); + return core->NtProtectVirtualMemory(ProcesssHandle, BaseAddress, Size, NewProtect, OldProtect); +} + +void WINAPI HookedDbgUiRemoteBreakin() +{ + ::TerminateProcess(::GetCurrentProcess(), 0xDEADC0DE); +} + +NTSTATUS WINAPI HookedNtClose(HANDLE Handle) +{ + Core *core = Core::Instance(); + return core->NtClose(Handle); +} + +NTSTATUS WINAPI HookedNtQueryObject(HANDLE Handle, OBJECT_INFORMATION_CLASS ObjectInformationClass, PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength) +{ + Core *core = Core::Instance(); + return core->NtQueryObject(Handle, ObjectInformationClass, ObjectInformation, ObjectInformationLength, ReturnLength); +} + +void Core::HookAPIs(HookManager &hook_manager, uint32_t options) +{ + hook_manager.Begin(); + HMODULE dll = GetModuleHandleA(VMProtectDecryptStringA("ntdll.dll")); + if (options & CORE_OPTION_MEMORY_PROTECTION) + hook_manager.HookAPI(dll, VMProtectDecryptStringA("NtProtectVirtualMemory"), &HookedNtProtectVirtualMemory, true, &nt_protect_virtual_memory_); + if (options & CORE_OPTION_CHECK_DEBUGGER) + dbg_ui_remote_breakin_ = hook_manager.HookAPI(dll, VMProtectDecryptStringA("DbgUiRemoteBreakin"), &HookedDbgUiRemoteBreakin, false); + if (file_manager_ || registry_manager_) { + nt_close_ = hook_manager.HookAPI(dll, VMProtectDecryptStringA("NtClose"), &HookedNtClose); + nt_query_object_ = hook_manager.HookAPI(dll, VMProtectDecryptStringA("NtQueryObject"), &HookedNtQueryObject); + } + hook_manager.End(); +} + +void Core::UnhookAPIs(HookManager &hook_manager) +{ + hook_manager.Begin(); + hook_manager.UnhookAPI(nt_protect_virtual_memory_); + hook_manager.UnhookAPI(nt_close_); + hook_manager.UnhookAPI(nt_query_object_); + hook_manager.UnhookAPI(dbg_ui_remote_breakin_); + hook_manager.End(); +} + +NTSTATUS Core::NtProtectVirtualMemory(HANDLE ProcesssHandle, LPVOID *BaseAddress, SIZE_T *Size, DWORD NewProtect, PDWORD OldProtect) +{ + if (ProcesssHandle == GetCurrentProcess()) { + const CRCData crc_data; + + uint8_t *image_base = crc_data.ImageBase; + size_t crc_image_size = loader_data->crc_image_size(); + try { + uint8_t *user_address = static_cast<uint8_t *>(*BaseAddress); + size_t user_size = *Size; + if (user_address + user_size > image_base && user_address < image_base + crc_image_size) { + uint8_t *crc_table = image_base + crc_data.Table; + uint32_t crc_table_size = *reinterpret_cast<uint32_t *>(image_base + crc_data.Size); + CRCValueCryptor crc_cryptor; + + // check regions + for (size_t i = 0; i < crc_table_size; i += sizeof(CRC_INFO)) { + CRC_INFO crc_info = *reinterpret_cast<CRC_INFO *>(crc_table + i); + crc_info.Address = crc_cryptor.Decrypt(crc_info.Address); + crc_info.Size = crc_cryptor.Decrypt(crc_info.Size); + crc_info.Hash = crc_cryptor.Decrypt(crc_info.Hash); + + uint8_t *crc_address = image_base + crc_info.Address; + if (user_address + user_size > crc_address && user_address < crc_address + crc_info.Size) + return STATUS_ACCESS_DENIED; + } + } + } catch(...) { + return STATUS_ACCESS_VIOLATION; + } + } + + return TrueNtProtectVirtualMemory(ProcesssHandle, BaseAddress, Size, NewProtect, OldProtect); +} + +NTSTATUS Core::NtClose(HANDLE Handle) +{ + { + CriticalSection cs(objects_.critical_section()); + + objects_.DeleteObject(Handle); + } + + return TrueNtClose(Handle); +} + +NTSTATUS Core::NtQueryObject(HANDLE Handle, OBJECT_INFORMATION_CLASS ObjectInformationClass, PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength) +{ + { + CriticalSection cs(objects_.critical_section()); + + VirtualObject *object = objects_.GetObject(Handle); + if (object) { + try { + switch (ObjectInformationClass) { + case ObjectBasicInformation: + { + if (ObjectInformationLength != sizeof(PUBLIC_OBJECT_BASIC_INFORMATION)) + return STATUS_INFO_LENGTH_MISMATCH; + + PUBLIC_OBJECT_BASIC_INFORMATION info = {}; + info.GrantedAccess = object->access(); + info.HandleCount = objects_.GetHandleCount(Handle); + info.PointerCount = objects_.GetPointerCount(object->ref()); + + if (ReturnLength) + *ReturnLength = sizeof(info); + } + return STATUS_SUCCESS; + default: + return STATUS_INVALID_PARAMETER; + } + } catch (...) { + return STATUS_ACCESS_VIOLATION; + } + } + } + + return TrueNtQueryObject(Handle, ObjectInformationClass, ObjectInformation, ObjectInformationLength, ReturnLength); +} + +NTSTATUS __forceinline Core::TrueNtProtectVirtualMemory(HANDLE ProcesssHandle, LPVOID *BaseAddress, SIZE_T *Size, DWORD NewProtect, PDWORD OldProtect) +{ + typedef NTSTATUS (WINAPI tNtProtectVirtualMemory)(HANDLE ProcesssHandle, LPVOID *BaseAddress, SIZE_T *Size, DWORD NewProtect, PDWORD OldProtect); + return reinterpret_cast<tNtProtectVirtualMemory *>(nt_protect_virtual_memory_)(ProcesssHandle, BaseAddress, Size, NewProtect, OldProtect); +} + +NTSTATUS __forceinline Core::TrueNtClose(HANDLE Handle) +{ + typedef NTSTATUS (WINAPI tNtClose)(HANDLE Handle); + return reinterpret_cast<tNtClose *>(nt_close_)(Handle); +} + +NTSTATUS __forceinline Core::TrueNtQueryObject(HANDLE Handle, OBJECT_INFORMATION_CLASS ObjectInformationClass, PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength) +{ + typedef NTSTATUS (WINAPI tNtQueryObject)(HANDLE Handle, OBJECT_INFORMATION_CLASS ObjectInformationClass, PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength); + return reinterpret_cast<tNtQueryObject *>(nt_query_object_)(Handle, ObjectInformationClass, ObjectInformation, ObjectInformationLength, ReturnLength); +} + +#endif
\ No newline at end of file |