#include "common.h" #include "loader.h" #include "crypto.h" #include "../third-party/lzma/LzmaDecode.h" #define VIRTUAL_PROTECT_ERROR reinterpret_cast(1) #define UNPACKER_ERROR reinterpret_cast(2) #define INTERNAL_GPA_ERROR reinterpret_cast(3) #define CPU_HASH_ERROR reinterpret_cast(5) #define DECRYPT(str, pos) (str[pos] ^ (_rotl32(FACE_STRING_DECRYPT_KEY, static_cast(pos)) + pos)) static void *LoaderAlloc(size_t size) { #ifdef VMP_GNU return malloc(size); #elif defined(WIN_DRIVER) return ExAllocatePool((POOL_TYPE)FACE_NON_PAGED_POOL_NX, size); #else return LocalAlloc(0, size); #endif } static void LoaderFree(void *address) { #ifdef VMP_GNU free(address); #elif defined(WIN_DRIVER) if (address) ExFreePool(address); #else LocalFree(address); #endif } NOINLINE bool LoaderFindFirmwareVendor(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; } #ifndef VMP_GNU #define TOLOWER(c) ((c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c) int Loader_stricmp(const char *str1, const char *str2, bool is_enc) { unsigned char c1; unsigned char c2; size_t pos = 0; do { c1 = *(str1++); c2 = *(str2++); if (is_enc) { c1 ^= static_cast(_rotl32(FACE_STRING_DECRYPT_KEY, static_cast(pos)) + pos); pos++; } c1 = TOLOWER(c1); c2 = TOLOWER(c2); if (!c1) break; } while (c1 == c2); if (c1 < c2) return -1; else if (c1 > c2) return 1; return 0; } int Loader_strcmp(const char *str1, const char *str2, bool is_enc) { unsigned char c1; unsigned char c2; size_t pos = 0; do { c1 = *(str1++); c2 = *(str2++); if (is_enc) { c1 ^= (_rotl32(FACE_STRING_DECRYPT_KEY, static_cast(pos)) + pos); pos++; } if (!c1) break; } while (c1 == c2); if (c1 < c2) return -1; else if (c1 > c2) return 1; return 0; } #ifdef WIN_DRIVER int Loader_cmp_module(const char *str1, const char *str2, bool is_enc) { unsigned char c1; unsigned char c2; size_t pos = 0; do { c1 = *(str1++); c2 = *(str2++); if (is_enc) { c1 ^= static_cast(_rotl32(FACE_STRING_DECRYPT_KEY, static_cast(pos)) + pos); pos++; } c1 = TOLOWER(c1); c2 = TOLOWER(c2); if (!c1) break; } while (c1 == c2); if (c1 == '.' && c2 == 0) return 0; if (c1 < c2) return -1; else if (c1 > c2) return 1; return 0; } HMODULE WINAPI LoaderGetModuleHandle(const char *name) { HMODULE module = NULL; SYSTEM_MODULE_INFORMATION *buffer = NULL; ULONG buffer_size = 0; NTSTATUS status = NtQuerySystemInformation(SystemModuleInformation, &buffer, 0, &buffer_size); if (buffer_size) { buffer = static_cast(LoaderAlloc(buffer_size * 2)); if (buffer) { status = NtQuerySystemInformation(SystemModuleInformation, buffer, buffer_size * 2, &buffer_size); if (NT_SUCCESS(status)) { PVOID known_api; if (Loader_cmp_module(reinterpret_cast(FACE_NTOSKRNL_NAME), name, true) == 0) known_api = &IoAllocateMdl; else if (Loader_cmp_module(reinterpret_cast(FACE_HAL_NAME), name, true) == 0) known_api = &KeQueryPerformanceCounter; else known_api = NULL; if (known_api) { // search module by address for (size_t i = 0; i < buffer->Count; i++) { SYSTEM_MODULE_ENTRY *module_entry = &buffer->Module[i]; if (module_entry->BaseAddress < known_api && static_cast(module_entry->BaseAddress) + module_entry->Size > known_api) { module = reinterpret_cast(module_entry->BaseAddress); break; } } } else { // search module by name for (size_t i = 0; i < buffer->Count; i++) { SYSTEM_MODULE_ENTRY *module_entry = &buffer->Module[i]; if (Loader_cmp_module(module_entry->Name + module_entry->PathLength, name, false) == 0) { module = reinterpret_cast(module_entry->BaseAddress); break; } } } } LoaderFree(buffer); } } return module; } #else HMODULE WINAPI LoaderGetModuleHandle(const char *name) { return GetModuleHandleA(name); } __declspec(noinline) HMODULE LoaderLoadLibraryEnc(const char *name) { // decrypt DLL name char dll_name[MAX_PATH]; for (size_t j = 0; j < sizeof(dll_name); j++) { dll_name[j] = static_cast(DECRYPT(name, j)); if (!dll_name[j]) break; } return LoadLibraryA(dll_name); } __declspec(noinline) const wchar_t *LoaderFindFileVersion(const uint8_t *ptr, size_t data_size) { const wchar_t *data = reinterpret_cast(ptr); data_size /= sizeof(wchar_t); for (size_t i = 0; i < data_size; i++) { if (data_size >= 13) { if (data[i + 0] == L'F' && data[i + 1] == L'i' && data[i + 2] == L'l' && data[i + 3] == L'e' && data[i + 4] == L'V' && data[i + 5] == L'e' && data[i + 6] == L'r' && data[i + 7] == L's' && data[i + 8] == L'i' && data[i + 9] == L'o' && data[i + 10] == L'n' && data[i + 11] == 0 && data[i + 12] == 0) return data + i + 13; } if (data_size >= 15) { if (data[i + 0] == L'P' && data[i + 1] == L'r' && data[i + 2] == L'o' && data[i + 3] == L'd' && data[i + 4] == L'u' && data[i + 5] == L'c' && data[i + 6] == L't' && data[i + 7] == L'V' && data[i + 8] == L'e' && data[i + 9] == L'r' && data[i + 10] == L's' && data[i + 11] == L'i' && data[i + 12] == L'o' && data[i + 13] == L'n' && data[i + 14] == 0) return data + i + 15; } } return NULL; } __forceinline uint16_t LoaderParseOSBuildBumber(HMODULE ntdll) { uint16_t os_build_number = 0; IMAGE_DOS_HEADER *dos_header = reinterpret_cast(ntdll); if (dos_header->e_magic == IMAGE_DOS_SIGNATURE) { IMAGE_NT_HEADERS *pe_header = reinterpret_cast(reinterpret_cast(ntdll) + dos_header->e_lfanew); if (pe_header->Signature == IMAGE_NT_SIGNATURE) { uint32_t resource_adress = pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; if (resource_adress) { const uint8_t *resource_start = reinterpret_cast(ntdll) + resource_adress; const uint8_t *resource_end = resource_start + pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size; while (const wchar_t *file_version = LoaderFindFileVersion(resource_start, resource_end - resource_start)) { os_build_number = 0; for (size_t i = 0; *file_version; file_version++) { if (*file_version == L'.') i++; else if (i == 2) { while (wchar_t c = *file_version++) { if (c >= L'0' && c <= L'9') { os_build_number *= 10; os_build_number += c - L'0'; } else break; } break; } } if (IS_KNOWN_WINDOWS_BUILD(os_build_number)) break; resource_start = reinterpret_cast(file_version); } } } } return os_build_number; } __forceinline uint32_t LoaderParseSyscall(const void *p) { if (const uint8_t *ptr = reinterpret_cast(p)) { #ifdef _WIN64 if (ptr[0] == 0x4c && ptr[1] == 0x8b && (ptr[2] & 0xc0) == 0xc0) ptr += 3; #endif if (ptr[0] == 0xb8) return *reinterpret_cast(ptr + 1); } return 0; } #endif void *LoaderGetProcAddress(HMODULE module, const char *proc_name, bool is_enc) { // check input if (!module || !proc_name) return NULL; // check module's header IMAGE_DOS_HEADER *dos_header = reinterpret_cast(module); if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) return NULL; // check NT header IMAGE_NT_HEADERS *pe_header = reinterpret_cast(reinterpret_cast(module) + dos_header->e_lfanew); if (pe_header->Signature != IMAGE_NT_SIGNATURE) return NULL; // get the export directory uint32_t export_adress = pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; if (!export_adress) return NULL; uint32_t export_size = pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; uint32_t address; uint32_t ordinal_index = -1; IMAGE_EXPORT_DIRECTORY *export_directory = reinterpret_cast(reinterpret_cast(module) + export_adress); if (proc_name <= reinterpret_cast(0xFFFF)) { // ordinal ordinal_index = static_cast(INT_PTR(proc_name)) - export_directory->Base; // index is either less than base or bigger than number of functions if (ordinal_index >= export_directory->NumberOfFunctions) return NULL; // get the function offset by the ordinal address = (reinterpret_cast(reinterpret_cast(module) + export_directory->AddressOfFunctions))[ordinal_index]; // check for empty offset if (!address) return NULL; } else { // name of function if (export_directory->NumberOfNames) { // start binary search int left_index = 0; int right_index = export_directory->NumberOfNames - 1; uint32_t *names = reinterpret_cast(reinterpret_cast(module) + export_directory->AddressOfNames); while (left_index <= right_index) { uint32_t cur_index = (left_index + right_index) >> 1; switch (Loader_strcmp(proc_name, (const char *)(reinterpret_cast(module) + names[cur_index]), is_enc)) { case 0: ordinal_index = (reinterpret_cast(reinterpret_cast(module) + export_directory->AddressOfNameOrdinals))[cur_index]; left_index = right_index + 1; break; case -1: right_index = cur_index - 1; break; case 1: left_index = cur_index + 1; break; } } } // if nothing has been found if (ordinal_index >= export_directory->NumberOfFunctions) return NULL; // get the function offset by the ordinal address = (reinterpret_cast(reinterpret_cast(module) + export_directory->AddressOfFunctions))[ordinal_index]; if (!address) return NULL; } // if it is just a pointer - return it if (address < export_adress || address >= export_adress + export_size) return reinterpret_cast(reinterpret_cast(module) + address); // it is a forward const char *name = reinterpret_cast(reinterpret_cast(module) + address); // get a pointer to the module's name const char *tmp = name; const char *name_dot = NULL; // get a pointer to the function's name while (*tmp) { if (*tmp == '.') { name_dot = tmp; break; } tmp++; } if (!name_dot) return NULL; size_t name_len = name_dot - name; if (name_len >= MAX_PATH) return NULL; // copy module name char file_name[MAX_PATH]; size_t i; for (i = 0; i < name_len && name[i] != 0; i++) { file_name[i] = name[i]; } file_name[i] = 0; HMODULE tmp_module = LoaderGetModuleHandle(file_name); #ifndef WIN_DRIVER if (!tmp_module) tmp_module = LoadLibraryA(file_name); #endif if (!tmp_module) return NULL; if (tmp_module == module) { // forwarded to itself #ifdef WIN_DRIVER return NULL; #else if (is_enc) { for (i = 0; i < sizeof(file_name); i++) { char c = proc_name[i]; c ^= (_rotl32(FACE_STRING_DECRYPT_KEY, static_cast(i)) + i); file_name[i] = c; if (!c) break; } proc_name = file_name; } return GetProcAddress(module, proc_name); #endif } // now the function's name // if it is not an ordinal, just forward it if (name_dot[1] != '#') return LoaderGetProcAddress(tmp_module, name_dot + 1, false); // it is an ordinal tmp = name_dot + 2; int ordinal = 0; while (*tmp) { char c = *(tmp++); if (c >= '0' && c <= '9') { ordinal = ordinal * 10 + c - '0'; } else { break; } } return LoaderGetProcAddress(tmp_module, reinterpret_cast(INT_PTR(ordinal)), false); } __declspec(noinline) HMODULE LoaderGetModuleHandleEnc(const char *name) { // decrypt DLL name char dll_name[MAX_PATH]; for (size_t j = 0; j < sizeof(dll_name); j++) { dll_name[j] = static_cast(DECRYPT(name, j)); if (!dll_name[j]) break; } return LoaderGetModuleHandle(dll_name); } __forceinline void InitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString) { if (SourceString) DestinationString->MaximumLength = (DestinationString->Length = (USHORT)(wcslen(SourceString) * sizeof(WCHAR))) + sizeof(UNICODE_NULL); else DestinationString->MaximumLength = DestinationString->Length = 0; DestinationString->Buffer = (PWCH)SourceString; } #endif // VMP_GNU #if defined(__unix__) struct LoaderString { public: LoaderString() { capacity_ = 2; buffer_ = reinterpret_cast(LoaderAlloc(capacity_)); buffer_[0] = 0; size_ = 0; } ~LoaderString() { LoaderFree(buffer_); } const char *c_str() const { return buffer_; } size_t size() const { return size_; } LoaderString &operator +=(char c) { add_size(1); buffer_[size_++] = c; buffer_[size_] = 0; return *this; } LoaderString &operator +=(const char *str) { size_t str_len = strlen(str); add_size(str_len); __movsb(buffer_ + size_, str, str_len); size_ += str_len; buffer_[size_] = 0; return *this; } private: void add_size(size_t size) { size_t new_size = size_ + size + 1; if (new_size <= capacity_) return; while (capacity_ < new_size) { capacity_ <<= 1; } char *new_buffer = reinterpret_cast(LoaderAlloc(capacity_)); __movsb(new_buffer, buffer_, size_ + 1); LoaderFree(buffer_); buffer_ = new_buffer; } char *buffer_; size_t size_; size_t capacity_; }; #endif enum MessageType { mtInitializationError, mtProcNotFound, mtOrdinalNotFound, mtFileCorrupted, mtDebuggerFound, mtUnregisteredVersion, mtVirtualMachineFound }; void LoaderMessage(MessageType type, const void *param1 = NULL, const void *param2 = NULL) { const VMP_CHAR *message; bool need_format = false; switch (type) { case mtDebuggerFound: message = reinterpret_cast(FACE_DEBUGGER_FOUND); break; case mtVirtualMachineFound: message = reinterpret_cast(FACE_VIRTUAL_MACHINE_FOUND); break; case mtFileCorrupted: message = reinterpret_cast(FACE_FILE_CORRUPTED); break; case mtUnregisteredVersion: message = reinterpret_cast(FACE_UNREGISTERED_VERSION); break; case mtInitializationError: message = reinterpret_cast(FACE_INITIALIZATION_ERROR); need_format = true; break; case mtProcNotFound: message = reinterpret_cast(FACE_PROC_NOT_FOUND); need_format = true; break; case mtOrdinalNotFound: message = reinterpret_cast(FACE_ORDINAL_NOT_FOUND); need_format = true; break; default: return; } VMP_CHAR message_buffer[1024]; VMP_CHAR *dst = message_buffer; VMP_CHAR *end = dst + _countof(message_buffer) - 1; size_t param_index = 0; for (size_t j = 0; dst < end; j++) { VMP_CHAR c = static_cast(DECRYPT(message, j)); if (!c) break; if (need_format && c == '%') { j++; const void *param = (param_index == 0) ? param1 : param2; param_index++; c = static_cast(DECRYPT(message, j)); if (c == 's') { const char *src = reinterpret_cast(param); while (*src && dst < end) { *(dst++) = *(src++); } } else if (c == 'c') { const char *src = reinterpret_cast(param); for (size_t k = 0; dst < end; k++) { char b = static_cast(DECRYPT(src, k)); if (!b) break; *(dst++) = b; } } else if (c == 'd') { size_t value = reinterpret_cast(param); char buff[20]; char *src = buff + _countof(buff) - 1; *src = 0; do { *(--src) = '0' + value % 10; value /= 10; } while (value); while (*src && dst < end) { *(dst++) = *(src++); } } } else { *(dst++) = c; } } *dst = 0; message = message_buffer; if (!message[0]) return; #ifdef __APPLE__ char file_name[PATH_MAX]; uint32_t name_size = sizeof(file_name); const char *title = file_name; if (_NSGetExecutablePath(file_name, &name_size) == 0) { for (size_t i = 0; i < sizeof(file_name); i++) { if (!file_name[i]) break; if (file_name[i] == '/') title = file_name + i + 1; } } else { file_name[0] = 'F'; file_name[1] = 'a'; file_name[2] = 't'; file_name[3] = 'a'; file_name[4] = 'l'; file_name[5] = ' '; file_name[6] = 'E'; file_name[7] = 'r'; file_name[8] = 'r'; file_name[9] = 'o'; file_name[10] = 'r'; file_name[11] = 0; } CFStringRef title_ref = CFStringCreateWithCString(NULL, title, kCFStringEncodingMacRoman); CFStringRef message_ref = CFStringCreateWithCString(NULL, message, kCFStringEncodingUTF8); CFOptionFlags result; CFUserNotificationDisplayAlert( 0, // no timeout (type == mtUnregisteredVersion) ? kCFUserNotificationCautionAlertLevel : kCFUserNotificationStopAlertLevel, //change it depending message_type flags ( MB_ICONASTERISK.... etc.) NULL, //icon url, use default, you can change it depending message_type flags NULL, //not used NULL, //localization of strings title_ref, //title text message_ref, //message text NULL, //default "ok" text in button NULL, //alternate button title NULL, //other button title, null--> no other button &result //response flags ); CFRelease(title_ref); CFRelease(message_ref); #elif defined(__unix__) char file_name[PATH_MAX]; char self_exe[] = {'/', 'p', 'r', 'o', 'c', '/', 's', 'e', 'l', 'f', '/', 'e', 'x', 'e', 0}; const char *title = file_name; ssize_t len = ::readlink(self_exe, file_name, sizeof(file_name) - 1); if (len != -1) { for (ssize_t i = 0; i < len; i++) { if (file_name[i] == '/') title = file_name + i + 1; if (file_name[i] == '\'' || file_name[i] == '\\') file_name[i] = '"'; } file_name[len] = '\0'; } else { file_name[0] = 'F'; file_name[1] = 'a'; file_name[2] = 't'; file_name[3] = 'a'; file_name[4] = 'l'; file_name[5] = ' '; file_name[6] = 'E'; file_name[7] = 'r'; file_name[8] = 'r'; file_name[9] = 'o'; file_name[10] = 'r'; file_name[11] = 0; } LoaderString cmd_line; { char str[] = {'z', 'e', 'n', 'i', 't', 'y', 0}; cmd_line += str; } if (type == mtUnregisteredVersion) { char str[] = {' ', '-', '-', 'w', 'a', 'r', 'n', 'i', 'n', 'g', 0}; cmd_line += str; } else { char str[] = {' ', '-', '-', 'e', 'r', 'r', 'o', 'r', 0}; cmd_line += str; } { char str[] = {' ', '-', '-', 'n', 'o', '-', 'm', 'a', 'r', 'k', 'u', 'p', 0}; cmd_line += str; } { char str[] = {' ', '-', '-', 't', 'i', 't', 'l', 'e', '=', '\'', 0}; cmd_line += str; cmd_line += title; cmd_line += '\''; } { char str[] = {' ', '-', '-', 't', 'e', 'x', 't', '=', '\'', 0}; cmd_line += str; char *msg_ptr = message_buffer; while (*msg_ptr) { if (*msg_ptr == '\'' || *msg_ptr == '\\') *msg_ptr = '"'; msg_ptr++; } cmd_line += message; cmd_line += '\''; } int status = system(cmd_line.c_str()); if (status == -1 || WEXITSTATUS(status) == 127) puts(message); #elif defined(WIN_DRIVER) DbgPrint(reinterpret_cast(FACE_DRIVER_FORMAT_VALUE), message); #else wchar_t file_name[MAX_PATH]; const wchar_t *title = file_name; if (GetModuleFileNameW(reinterpret_cast(FACE_IMAGE_BASE), file_name, _countof(file_name))) { for (size_t i = 0; i < _countof(file_name); i++) { if (!file_name[i]) break; if (file_name[i] == '\\') title = file_name + i + 1; } } else { file_name[0] = 'F'; file_name[1] = 'a'; file_name[2] = 't'; file_name[3] = 'a'; file_name[4] = 'l'; file_name[5] = ' '; file_name[6] = 'E'; file_name[7] = 'r'; file_name[8] = 'r'; file_name[9] = 'o'; file_name[10] = 'r'; file_name[11] = 0; } HMODULE ntdll = LoaderGetModuleHandleEnc(reinterpret_cast(FACE_NTDLL_NAME)); typedef NTSTATUS(NTAPI tNtRaiseHardError)(NTSTATUS ErrorStatus, ULONG NumberOfParameters, ULONG UnicodeStringParameterMask, PULONG_PTR Parameters, ULONG ValidResponseOptions, HardErrorResponse *Response); if (tNtRaiseHardError *raise_hard_error = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_RAISE_HARD_ERROR_NAME), true))) { UNICODE_STRING message_str; UNICODE_STRING title_str; InitUnicodeString(&message_str, (PWSTR)message); InitUnicodeString(&title_str, (PWSTR)title); ULONG_PTR params[4] = { (ULONG_PTR)&message_str, (ULONG_PTR)&title_str, ( (ULONG)ResponseButtonOK | (type == mtUnregisteredVersion ? IconWarning : IconError) ), INFINITE }; HardErrorResponse response; raise_hard_error(STATUS_SERVICE_NOTIFICATION | HARDERROR_OVERRIDE_ERRORMODE, 4, 3, params, 0, &response); } #endif } enum { LOADER_SUCCESS = #ifdef WIN_DRIVER STATUS_SUCCESS #else TRUE #endif , LOADER_ERROR = #ifdef WIN_DRIVER STATUS_DRIVER_INTERNAL_ERROR #else FALSE #endif }; #ifdef VMP_GNU EXPORT_API void FreeImage() __asm__ ("FreeImage"); #endif #ifdef WIN_DRIVER void WINAPI FreeImage(PDRIVER_OBJECT driver_object) #else void WINAPI FreeImage() #endif { SETUP_IMAGE_DATA data; uint8_t *image_base = data.image_base(); uint32_t loader_status = LOADER_ERROR; GlobalData *loader_data = *(reinterpret_cast(image_base + data.storage())); if (loader_data) { #ifdef WIN_DRIVER if (loader_data->driver_unload()) reinterpret_cast(loader_data->driver_unload())(driver_object); #endif if (uint32_t data_runtime_entry = data.runtime_entry()) { #ifdef VMP_GNU typedef void (WINAPI tRuntimeEntry)(HMODULE hModule, bool is_init); reinterpret_cast(image_base + data_runtime_entry)(reinterpret_cast(image_base), false); #elif defined(WIN_DRIVER) typedef NTSTATUS (tRuntimeEntry)(HMODULE hModule, bool is_init); reinterpret_cast(image_base + data_runtime_entry)(reinterpret_cast(image_base), false); #else typedef BOOL (WINAPI tRuntimeEntry)(HMODULE hModule, DWORD dwReason, LPVOID lpReserved); reinterpret_cast(image_base + data_runtime_entry)(reinterpret_cast(image_base), DLL_PROCESS_DETACH, NULL); #endif } loader_status = loader_data->loader_status(); LoaderFree(loader_data); } if (loader_status == LOADER_ERROR) { #ifdef VMP_GNU exit(0xDEADC0DE); #elif defined(WIN_DRIVER) // do nothing #else if (data.options() & LOADER_OPTION_EXIT_PROCESS) ExitProcess(0xDEADC0DE); #endif } } void LoaderProcessFixups(ptrdiff_t delta_base, uint32_t data_fixup_info, uint32_t data_fixup_info_size, uint8_t *image_base, uint8_t *dst_image_base) { size_t i, j, c; FIXUP_INFO *fixup_info; for (i = 0; i < data_fixup_info_size; i += fixup_info->BlockSize) { fixup_info = reinterpret_cast(image_base + data_fixup_info + i); if (fixup_info->BlockSize < sizeof(FIXUP_INFO)) break; c = (fixup_info->BlockSize - sizeof(FIXUP_INFO)) >> 1; for (j = 0; j < c; j++) { uint16_t type_offset = reinterpret_cast(fixup_info + 1)[j]; uint8_t *address = dst_image_base + fixup_info->Address + (type_offset >> 4); // need use "if" instead "switch" uint8_t type = (type_offset & 0x0f); #ifdef __APPLE__ if (type == REBASE_TYPE_POINTER) *(reinterpret_cast(address)) += delta_base; else if (type == REBASE_TYPE_TEXT_ABSOLUTE32) *(reinterpret_cast(address)) += delta_base; #elif defined(__unix__) if (type == 8) // R_386_RELATIVE *(reinterpret_cast(address)) += delta_base; #else if (type == IMAGE_REL_BASED_HIGHLOW) *(reinterpret_cast(address)) += static_cast(delta_base); else if (type == IMAGE_REL_BASED_DIR64) *(reinterpret_cast(address)) += delta_base; else if (type == IMAGE_REL_BASED_HIGH) *(reinterpret_cast(address)) += static_cast(delta_base >> 16); else if (type == IMAGE_REL_BASED_LOW) *(reinterpret_cast(address)) += static_cast(delta_base); #endif } } } #ifdef VMP_GNU EXPORT_API uint32_t WINAPI SetupImage() __asm__ ("SetupImage"); #endif #ifdef WIN_DRIVER uint32_t WINAPI SetupImage(bool is_init, PDRIVER_OBJECT driver_object) #else uint32_t WINAPI SetupImage() #endif { size_t i, j; uint64_t session_key; SETUP_IMAGE_DATA data; uint8_t *image_base = data.image_base(); uint8_t *file_base = data.file_base(); uint8_t *dst_image_base = image_base; ptrdiff_t delta_base = image_base - file_base; GlobalData *tmp_loader_data = *(reinterpret_cast(image_base + data.storage())); if (tmp_loader_data) { #ifdef WIN_DRIVER if (!is_init && tmp_loader_data->loader_status() == LOADER_SUCCESS && driver_object->DriverUnload) { tmp_loader_data->set_driver_unload(reinterpret_cast(driver_object->DriverUnload)); driver_object->DriverUnload = FreeImage; } #endif return tmp_loader_data->loader_status(); } tmp_loader_data = reinterpret_cast(LoaderAlloc(sizeof(GlobalData))); tmp_loader_data->set_loader_status(LOADER_ERROR); tmp_loader_data->set_is_patch_detected(false); tmp_loader_data->set_is_debugger_detected(false); tmp_loader_data->set_server_date(0); tmp_loader_data->set_loader_crc_info(data.loader_crc_info()); tmp_loader_data->set_loader_crc_size(0); size_t crc_image_size = 0; tmp_loader_data->set_crc_image_size(crc_image_size); #ifdef VMP_GNU #elif defined(WIN_DRIVER) tmp_loader_data->set_driver_unload(0); #else tmp_loader_data->set_os_build_number(0); #endif size_t cpu_salt = 0; #ifdef VMP_GNU #elif defined(WIN_DRIVER) HMODULE ntoskrnl = LoaderGetModuleHandleEnc(reinterpret_cast(FACE_NTOSKRNL_NAME)); #else typedef NTSTATUS(NTAPI tNtClose)(HANDLE Handle); typedef NTSTATUS(NTAPI tNtOpenFile)(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG OpenOptions); typedef NTSTATUS(NTAPI tNtCreateSection)(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER MaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, HANDLE FileHandle); typedef NTSTATUS(NTAPI 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(NTAPI tNtUnmapViewOfSection)(HANDLE ProcessHandle, PVOID BaseAddress); typedef NTSTATUS(NTAPI tNtQueryInformationProcess)(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength); typedef NTSTATUS(NTAPI tNtSetInformationThread)(HANDLE ThreadHandle, THREADINFOCLASS ThreadInformationClass, PVOID ThreadInformation, ULONG ThreadInformationLength); typedef NTSTATUS(NTAPI tNtProtectVirtualMemory)(HANDLE ProcesssHandle, LPVOID *BaseAddress, SIZE_T *Size, DWORD NewProtect, PDWORD OldProtect); typedef NTSTATUS(NTAPI tNtOpenSection)(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes); typedef NTSTATUS(NTAPI tNtQueryVirtualMemory)(HANDLE ProcessHandle, PVOID BaseAddress, MEMORY_INFORMATION_CLASS MemoryInformationClass, PVOID MemoryInformation, SIZE_T MemoryInformationLength, PSIZE_T ReturnLength); typedef NTSTATUS(NTAPI tNtSetInformationProcess)(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength); HMODULE kernel32 = LoaderGetModuleHandleEnc(reinterpret_cast(FACE_KERNEL32_NAME)); HMODULE ntdll = LoaderGetModuleHandleEnc(reinterpret_cast(FACE_NTDLL_NAME)); HANDLE process = NtCurrentProcess(); HANDLE thread = NtCurrentThread(); size_t syscall = FACE_SYSCALL; uint32_t sc_close = 0; uint32_t sc_virtual_protect = 0; uint32_t sc_open_file = 0; uint32_t sc_create_section = 0; uint32_t sc_map_view_of_section = 0; uint32_t sc_unmap_view_of_section = 0; uint32_t sc_query_information_process = 0; uint32_t sc_set_information_thread = 0; uint32_t sc_query_virtual_memory = 0; #ifdef _WIN64 PEB64 *peb = reinterpret_cast(__readgsqword(0x60)); #else PEB32 *peb = reinterpret_cast(__readfsdword(0x30)); #endif cpu_salt = peb->OSBuildNumber << 7; #ifndef DEMO if (LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_WINE_GET_VERSION_NAME), true) == NULL) { #ifndef _WIN64 BOOL is_wow64 = FALSE; typedef BOOL(WINAPI tIsWow64Process)(HANDLE Process, PBOOL Wow64Process); tIsWow64Process *is_wow64_process = reinterpret_cast(LoaderGetProcAddress(kernel32, reinterpret_cast(FACE_IS_WOW64_PROCESS_NAME), true)); if (is_wow64_process) is_wow64_process(process, &is_wow64); #endif uint16_t os_build_number = peb->OSBuildNumber; if (!IS_KNOWN_WINDOWS_BUILD(os_build_number)) { // parse FileVersion/ProductVersion from NTDLL resources os_build_number = LoaderParseOSBuildBumber(ntdll); if (!IS_KNOWN_WINDOWS_BUILD(os_build_number)) { // load copy of NTDLL tNtQueryVirtualMemory *query_virtual_memory = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_QUERY_VIRTUAL_MEMORY_NAME), true)); tNtOpenFile *open_file = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_OPEN_FILE_NAME), true)); tNtCreateSection *create_section = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_CREATE_SECTION_NAME), true)); tNtMapViewOfSection *map_view_of_section = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_MAP_VIEW_OF_SECTION), true)); tNtUnmapViewOfSection *unmap_view_of_section = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_UNMAP_VIEW_OF_SECTION), true)); tNtClose *close = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_CLOSE), true)); if (!query_virtual_memory || !create_section || !open_file || !map_view_of_section || !unmap_view_of_section || !close) { LoaderMessage(mtInitializationError, INTERNAL_GPA_ERROR); return LOADER_ERROR; } os_build_number = 0; uint8_t buffer[MAX_PATH * sizeof(wchar_t)]; if (NT_SUCCESS(query_virtual_memory(process, ntdll, MemoryMappedFilenameInformation, buffer, sizeof(buffer), NULL))) { HANDLE file_handle; OBJECT_ATTRIBUTES object_attributes; IO_STATUS_BLOCK io_status_block; InitializeObjectAttributes(&object_attributes, reinterpret_cast(buffer), 0, NULL, NULL); if (NT_SUCCESS(open_file(&file_handle, GENERIC_READ | SYNCHRONIZE | FILE_READ_ATTRIBUTES, &object_attributes, &io_status_block, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT))) { HANDLE file_map; InitializeObjectAttributes(&object_attributes, NULL, 0, NULL, NULL); if (NT_SUCCESS(create_section(&file_map, SECTION_MAP_READ, &object_attributes, NULL, PAGE_READONLY, SEC_IMAGE_NO_EXECUTE, file_handle))) { void *copy_ntdll = NULL; SIZE_T file_size = 0; LARGE_INTEGER offset; offset.LowPart = 0; offset.HighPart = 0; if (NT_SUCCESS(map_view_of_section(file_map, process, ©_ntdll, NULL, 0, &offset, &file_size, ViewShare, 0, PAGE_READONLY))) { os_build_number = LoaderParseOSBuildBumber((HMODULE)copy_ntdll); if (!IS_KNOWN_WINDOWS_BUILD(os_build_number)) { sc_close = LoaderParseSyscall(LoaderGetProcAddress((HMODULE)copy_ntdll, reinterpret_cast(FACE_NT_CLOSE), true)); sc_virtual_protect = LoaderParseSyscall(LoaderGetProcAddress((HMODULE)copy_ntdll, reinterpret_cast(FACE_NT_VIRTUAL_PROTECT_NAME), true)); sc_open_file = LoaderParseSyscall(LoaderGetProcAddress((HMODULE)copy_ntdll, reinterpret_cast(FACE_NT_OPEN_FILE_NAME), true)); sc_create_section = LoaderParseSyscall(LoaderGetProcAddress((HMODULE)copy_ntdll, reinterpret_cast(FACE_NT_CREATE_SECTION_NAME), true)); sc_map_view_of_section = LoaderParseSyscall(LoaderGetProcAddress((HMODULE)copy_ntdll, reinterpret_cast(FACE_NT_MAP_VIEW_OF_SECTION), true)); sc_unmap_view_of_section = LoaderParseSyscall(LoaderGetProcAddress((HMODULE)copy_ntdll, reinterpret_cast(FACE_NT_UNMAP_VIEW_OF_SECTION), true)); sc_query_information_process = LoaderParseSyscall(LoaderGetProcAddress((HMODULE)copy_ntdll, reinterpret_cast(FACE_NT_QUERY_INFORMATION_PROCESS_NAME), true)); sc_set_information_thread = LoaderParseSyscall(LoaderGetProcAddress((HMODULE)copy_ntdll, reinterpret_cast(FACE_NT_SET_INFORMATION_THREAD_NAME), true)); sc_query_virtual_memory = LoaderParseSyscall(LoaderGetProcAddress((HMODULE)copy_ntdll, reinterpret_cast(FACE_QUERY_VIRTUAL_MEMORY_NAME), true)); #ifndef _WIN64 if (is_wow64) { // wow64 version of ntdll uses upper 16 bits for encoding information about arguments sc_close = static_cast(sc_close); sc_virtual_protect = static_cast(sc_virtual_protect); sc_open_file = static_cast(sc_open_file); sc_create_section = static_cast(sc_create_section); sc_map_view_of_section = static_cast(sc_map_view_of_section); sc_unmap_view_of_section = static_cast(sc_unmap_view_of_section); sc_query_information_process = static_cast(sc_query_information_process); sc_set_information_thread = static_cast(sc_set_information_thread); sc_query_virtual_memory = static_cast(sc_query_virtual_memory); } #endif } unmap_view_of_section(process, copy_ntdll); } close(file_map); } close(file_handle); } } } if (!os_build_number) { if (data.options() & LOADER_OPTION_CHECK_DEBUGGER) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } tmp_loader_data->set_is_debugger_detected(true); } } tmp_loader_data->set_os_build_number(os_build_number); if (os_build_number == WINDOWS_XP) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x0019; sc_virtual_protect = 0x0089; sc_open_file = 0x0074; sc_create_section = 0x0032; sc_map_view_of_section = 0x006c; sc_unmap_view_of_section = 0x010b; sc_query_information_process = 0x009a; sc_set_information_thread = 0x00e5; sc_query_virtual_memory = 0x00b2; } else #endif { sc_close = 0x000c; sc_virtual_protect = 0x004d; sc_open_file = 0x0030; sc_create_section = 0x0047; sc_map_view_of_section = 0x0025; sc_unmap_view_of_section = 0x0027; sc_query_information_process = 0x0016; sc_set_information_thread = 0x000a; sc_query_virtual_memory = 0x0020; } } else if (os_build_number == WINDOWS_2003) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x001b; sc_virtual_protect = 0x008f; sc_open_file = 0x007a; sc_create_section = 0x0034; sc_map_view_of_section = 0x0071; sc_unmap_view_of_section = 0x0115; sc_query_information_process = 0x00a1; sc_set_information_thread = 0x00ee; sc_query_virtual_memory = 0x00ba; } else #endif { sc_close = 0x000c; sc_virtual_protect = 0x004d; sc_open_file = 0x0030; sc_create_section = 0x0047; sc_map_view_of_section = 0x0025; sc_unmap_view_of_section = 0x0027; sc_query_information_process = 0x0016; sc_set_information_thread = 0x000a; sc_query_virtual_memory = 0x0020; } } else if (os_build_number == WINDOWS_VISTA) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x0030; sc_virtual_protect = 0x00d2; sc_open_file = 0x00ba; sc_create_section = 0x004b; sc_map_view_of_section = 0x00b1; sc_unmap_view_of_section = 0x0160; sc_query_information_process = 0x00e4; sc_set_information_thread = 0x0136; sc_query_virtual_memory = 0x00fd; } else #endif { sc_close = 0x000c; sc_virtual_protect = 0x004d; sc_open_file = 0x0030; sc_create_section = 0x0047; sc_map_view_of_section = 0x0025; sc_unmap_view_of_section = 0x0027; sc_query_information_process = 0x0016; sc_set_information_thread = 0x000a; sc_query_virtual_memory = 0x0020; } } else if (os_build_number == WINDOWS_VISTA_SP1) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x0030; sc_virtual_protect = 0x00d2; sc_open_file = 0x00ba; sc_create_section = 0x004b; sc_map_view_of_section = 0x00b1; sc_unmap_view_of_section = 0x015c; sc_query_information_process = 0x00e4; sc_set_information_thread = 0x0132; sc_query_virtual_memory = 0x00fd; } else #endif { sc_close = 0x000c; sc_virtual_protect = 0x004d; sc_open_file = 0x0030; sc_create_section = 0x0047; sc_map_view_of_section = 0x0025; sc_unmap_view_of_section = 0x0027; sc_query_information_process = 0x0016; sc_set_information_thread = 0x000a; sc_query_virtual_memory = 0x0020; } } else if (os_build_number == WINDOWS_VISTA_SP2) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x0030; sc_virtual_protect = 0x00d2; sc_open_file = 0x00ba; sc_create_section = 0x004b; sc_map_view_of_section = 0x00b1; sc_unmap_view_of_section = 0x015c; sc_query_information_process = 0x00e4; sc_set_information_thread = 0x0132; sc_query_virtual_memory = 0x00fd; } else #endif { sc_close = 0x000c; sc_virtual_protect = 0x004d; sc_open_file = 0x0030; sc_create_section = 0x0047; sc_map_view_of_section = 0x0025; sc_unmap_view_of_section = 0x0027; sc_query_information_process = 0x0016; sc_set_information_thread = 0x000a; sc_query_virtual_memory = 0x0020; } } else if (os_build_number == WINDOWS_7) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x0032; sc_virtual_protect = 0x00d7; sc_open_file = 0x00b3; sc_create_section = 0x0054; sc_map_view_of_section = 0x00a8; sc_unmap_view_of_section = 0x0181; sc_query_information_process = 0x00ea; sc_set_information_thread = 0x014f; sc_query_virtual_memory = 0x010b; } else #endif { sc_close = 0x000c; sc_virtual_protect = 0x004d; sc_open_file = 0x0030; sc_create_section = 0x0047; sc_map_view_of_section = 0x0025; sc_unmap_view_of_section = 0x0027; sc_query_information_process = 0x0016; sc_set_information_thread = 0x000a; sc_query_virtual_memory = 0x0020; } } else if (os_build_number == WINDOWS_7_SP1) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x0032; sc_virtual_protect = 0x00d7; sc_open_file = 0x00b3; sc_create_section = 0x0054; sc_map_view_of_section = 0x00a8; sc_unmap_view_of_section = 0x0181; sc_query_information_process = 0x00ea; sc_set_information_thread = 0x014f; sc_query_virtual_memory = 0x010b; } else #endif { sc_close = 0x000c; sc_virtual_protect = 0x004d; sc_open_file = 0x0030; sc_create_section = 0x0047; sc_map_view_of_section = 0x0025; sc_unmap_view_of_section = 0x0027; sc_query_information_process = 0x0016; sc_set_information_thread = 0x000a; sc_query_virtual_memory = 0x0020; } } else if (os_build_number == WINDOWS_8) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x0174; sc_virtual_protect = 0x00c3; sc_open_file = 0x00e8; sc_create_section = 0x0150; sc_map_view_of_section = 0x00f3; sc_unmap_view_of_section = 0x0013; sc_query_information_process = 0x00b0; sc_set_information_thread = 0x0048; sc_query_virtual_memory = 0x008f; } else #endif { sc_close = 0x000d; sc_virtual_protect = 0x004e; sc_open_file = 0x0031; sc_create_section = 0x0048; sc_map_view_of_section = 0x0026; sc_unmap_view_of_section = 0x0028; sc_query_information_process = 0x0017; sc_set_information_thread = 0x000b; sc_query_virtual_memory = 0x0021; } } else if (os_build_number == WINDOWS_8_1) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x0179; sc_virtual_protect = 0x00c6; sc_open_file = 0x00eb; sc_create_section = 0x0154; sc_map_view_of_section = 0x00f6; sc_unmap_view_of_section = 0x0013; sc_query_information_process = 0x00b3; sc_set_information_thread = 0x004b; sc_query_virtual_memory = 0x0092; } else #endif { sc_close = 0x000e; sc_virtual_protect = 0x004f; sc_open_file = 0x0032; sc_create_section = 0x0049; sc_map_view_of_section = 0x0027; sc_unmap_view_of_section = 0x0029; sc_query_information_process = 0x0018; sc_set_information_thread = 0x000c; sc_query_virtual_memory = 0x0022; } } else if (os_build_number == WINDOWS_10_TH1) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x0180; sc_virtual_protect = 0x00c8; sc_open_file = 0x00ee; sc_create_section = 0x015a; sc_map_view_of_section = 0x00fa; sc_unmap_view_of_section = 0x0014; sc_query_information_process = 0x00b5; sc_set_information_thread = 0x004c; sc_query_virtual_memory = 0x0094; } else #endif { sc_close = 0x000f; sc_virtual_protect = 0x0050; sc_open_file = 0x0033; sc_create_section = 0x004a; sc_map_view_of_section = 0x0028; sc_unmap_view_of_section = 0x002a; sc_query_information_process = 0x0019; sc_set_information_thread = 0x000d; sc_query_virtual_memory = 0x0023; } } else if (os_build_number == WINDOWS_10_TH2) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x0183; sc_virtual_protect = 0x00c8; sc_open_file = 0x00ee; sc_create_section = 0x015c; sc_map_view_of_section = 0x00fa; sc_unmap_view_of_section = 0x0014; sc_query_information_process = 0x00b5; sc_set_information_thread = 0x004c; sc_query_virtual_memory = 0x0094; } else #endif { sc_close = 0x000f; sc_virtual_protect = 0x0050; sc_open_file = 0x0033; sc_create_section = 0x004a; sc_map_view_of_section = 0x0028; sc_unmap_view_of_section = 0x002a; sc_query_information_process = 0x0019; sc_set_information_thread = 0x000d; sc_query_virtual_memory = 0x0023; } } else if (os_build_number == WINDOWS_10_RS1) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x0185; sc_virtual_protect = 0x00ca; sc_open_file = 0x00f0; sc_create_section = 0x015e; sc_map_view_of_section = 0x00fc; sc_unmap_view_of_section = 0x0014; sc_query_information_process = 0x00b7; sc_set_information_thread = 0x004c; sc_query_virtual_memory = 0x0095; } else #endif { sc_close = 0x000f; sc_virtual_protect = 0x0050; sc_open_file = 0x0033; sc_create_section = 0x004a; sc_map_view_of_section = 0x0028; sc_unmap_view_of_section = 0x002a; sc_query_information_process = 0x0019; sc_set_information_thread = 0x000d; sc_query_virtual_memory = 0x0023; } } else if (os_build_number == WINDOWS_10_RS2) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x018a; sc_virtual_protect = 0x00cc; sc_open_file = 0x00f2; sc_create_section = 0x0161; sc_map_view_of_section = 0x00fe; sc_unmap_view_of_section = 0x0014; sc_query_information_process = 0x00b8; sc_set_information_thread = 0x004c; sc_query_virtual_memory = 0x0096; } else #endif { sc_close = 0x000f; sc_virtual_protect = 0x0050; sc_open_file = 0x0033; sc_create_section = 0x004a; sc_map_view_of_section = 0x0028; sc_unmap_view_of_section = 0x002a; sc_query_information_process = 0x0019; sc_set_information_thread = 0x000d; sc_query_virtual_memory = 0x0023; } } else if (os_build_number == WINDOWS_10_RS3) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x018d; sc_virtual_protect = 0x00ce; sc_open_file = 0x00f4; sc_create_section = 0x0164; sc_map_view_of_section = 0x0101; sc_unmap_view_of_section = 0x0014; sc_query_information_process = 0x00b9; sc_set_information_thread = 0x004d; sc_query_virtual_memory = 0x0097; } else #endif { sc_close = 0x000f; sc_virtual_protect = 0x0050; sc_open_file = 0x0033; sc_create_section = 0x004a; sc_map_view_of_section = 0x0028; sc_unmap_view_of_section = 0x002a; sc_query_information_process = 0x0019; sc_set_information_thread = 0x000d; sc_query_virtual_memory = 0x0023; } } else if (os_build_number == WINDOWS_10_RS4) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x018d; sc_virtual_protect = 0x00ce; sc_open_file = 0x00f4; sc_create_section = 0x0164; sc_map_view_of_section = 0x0101; sc_unmap_view_of_section = 0x0014; sc_query_information_process = 0x00b9; sc_set_information_thread = 0x004d; sc_query_virtual_memory = 0x0097; } else #endif { sc_close = 0x000f; sc_virtual_protect = 0x0050; sc_open_file = 0x0033; sc_create_section = 0x004a; sc_map_view_of_section = 0x0028; sc_unmap_view_of_section = 0x002a; sc_query_information_process = 0x0019; sc_set_information_thread = 0x000d; sc_query_virtual_memory = 0x0023; } } else if (os_build_number == WINDOWS_10_RS5) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x018d; sc_virtual_protect = 0x00ce; sc_open_file = 0x00f4; sc_create_section = 0x0163; sc_map_view_of_section = 0x0101; sc_unmap_view_of_section = 0x0014; sc_query_information_process = 0x00b9; sc_set_information_thread = 0x004d; sc_query_virtual_memory = 0x0097; } else #endif { sc_close = 0x000f; sc_virtual_protect = 0x0050; sc_open_file = 0x0033; sc_create_section = 0x004a; sc_map_view_of_section = 0x0028; sc_unmap_view_of_section = 0x002a; sc_query_information_process = 0x0019; sc_set_information_thread = 0x000d; sc_query_virtual_memory = 0x0023; } } else if (os_build_number == WINDOWS_10_19H1) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x018d; sc_virtual_protect = 0x00ce; sc_open_file = 0x00f4; sc_create_section = 0x0163; sc_map_view_of_section = 0x0101; sc_unmap_view_of_section = 0x0014; sc_query_information_process = 0x00b9; sc_set_information_thread = 0x004d; sc_query_virtual_memory = 0x0097; } else #endif { sc_close = 0x000f; sc_virtual_protect = 0x0050; sc_open_file = 0x0033; sc_create_section = 0x004a; sc_map_view_of_section = 0x0028; sc_unmap_view_of_section = 0x002a; sc_query_information_process = 0x0019; sc_set_information_thread = 0x000d; sc_query_virtual_memory = 0x0023; } } else if (os_build_number == WINDOWS_10_19H2) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x018d; sc_virtual_protect = 0x00ce; sc_open_file = 0x00f4; sc_create_section = 0x0163; sc_map_view_of_section = 0x0101; sc_unmap_view_of_section = 0x0014; sc_query_information_process = 0x00b9; sc_set_information_thread = 0x004d; sc_query_virtual_memory = 0x0097; } else #endif { sc_close = 0x000f; sc_virtual_protect = 0x0050; sc_open_file = 0x0033; sc_create_section = 0x004a; sc_map_view_of_section = 0x0028; sc_unmap_view_of_section = 0x002a; sc_query_information_process = 0x0019; sc_set_information_thread = 0x000d; sc_query_virtual_memory = 0x0023; } } else if (os_build_number == WINDOWS_10_20H1) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x018e; sc_virtual_protect = 0x00ce; sc_open_file = 0x00f4; sc_create_section = 0x0163; sc_map_view_of_section = 0x0101; sc_unmap_view_of_section = 0x0014; sc_query_information_process = 0x00b9; sc_set_information_thread = 0x004d; sc_query_virtual_memory = 0x0097; } else #endif { sc_close = 0x000f; sc_virtual_protect = 0x0050; sc_open_file = 0x0033; sc_create_section = 0x004a; sc_map_view_of_section = 0x0028; sc_unmap_view_of_section = 0x002a; sc_query_information_process = 0x0019; sc_set_information_thread = 0x000d; sc_query_virtual_memory = 0x0023; } } else if (os_build_number == WINDOWS_10_20H2) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x018e; sc_virtual_protect = 0x00ce; sc_open_file = 0x00f4; sc_create_section = 0x0163; sc_map_view_of_section = 0x0101; sc_unmap_view_of_section = 0x0014; sc_query_information_process = 0x00b9; sc_set_information_thread = 0x004d; sc_query_virtual_memory = 0x0097; } else #endif { sc_close = 0x000f; sc_virtual_protect = 0x0050; sc_open_file = 0x0033; sc_create_section = 0x004a; sc_map_view_of_section = 0x0028; sc_unmap_view_of_section = 0x002a; sc_query_information_process = 0x0019; sc_set_information_thread = 0x000d; sc_query_virtual_memory = 0x0023; } } else if (os_build_number == WINDOWS_10_21H1) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x018e; sc_virtual_protect = 0x00ce; sc_open_file = 0x00f4; sc_create_section = 0x0163; sc_map_view_of_section = 0x0101; sc_unmap_view_of_section = 0x0014; sc_query_information_process = 0x00b9; sc_set_information_thread = 0x004d; sc_query_virtual_memory = 0x0097; } else #endif { sc_close = 0x000f; sc_virtual_protect = 0x0050; sc_open_file = 0x0033; sc_create_section = 0x004a; sc_map_view_of_section = 0x0028; sc_unmap_view_of_section = 0x002a; sc_query_information_process = 0x0019; sc_set_information_thread = 0x000d; sc_query_virtual_memory = 0x0023; } } else if (os_build_number == WINDOWS_10_21H2) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x018e; sc_virtual_protect = 0x00ce; sc_open_file = 0x00f4; sc_create_section = 0x0163; sc_map_view_of_section = 0x0101; sc_unmap_view_of_section = 0x0014; sc_query_information_process = 0x00b9; sc_set_information_thread = 0x004d; sc_query_virtual_memory = 0x0097; } else #endif { sc_close = 0x000f; sc_virtual_protect = 0x0050; sc_open_file = 0x0033; sc_create_section = 0x004a; sc_map_view_of_section = 0x0028; sc_unmap_view_of_section = 0x002a; sc_query_information_process = 0x0019; sc_set_information_thread = 0x000d; sc_query_virtual_memory = 0x0023; } } else if (os_build_number == WINDOWS_10_22H2) { #ifndef _WIN64 if (!is_wow64) { sc_close = 0x018e; sc_virtual_protect = 0x00ce; sc_open_file = 0x00f4; sc_create_section = 0x0163; sc_map_view_of_section = 0x0101; sc_unmap_view_of_section = 0x0014; sc_query_information_process = 0x00b9; sc_set_information_thread = 0x004d; sc_query_virtual_memory = 0x0097; } else #endif { sc_close = 0x000f; sc_virtual_protect = 0x0050; sc_open_file = 0x0033; sc_create_section = 0x004a; sc_map_view_of_section = 0x0028; sc_unmap_view_of_section = 0x002a; sc_query_information_process = 0x0019; sc_set_information_thread = 0x000d; sc_query_virtual_memory = 0x0023; } } #ifndef _WIN64 if (is_wow64 && sc_close) { sc_close |= WOW64_FLAG; sc_virtual_protect |= WOW64_FLAG | (0x01 << 24); sc_set_information_thread |= WOW64_FLAG | (0x02 << 24); sc_query_information_process |= WOW64_FLAG | (0x03 << 24); sc_map_view_of_section |= WOW64_FLAG | (0x04 << 24);; sc_unmap_view_of_section |= WOW64_FLAG | (0x05 << 24); sc_open_file |= WOW64_FLAG | (0x06 << 24); sc_create_section |= WOW64_FLAG | (0x07 << 24); sc_query_virtual_memory |= WOW64_FLAG | (0x08 << 24); } #endif } #endif #endif // detect a debugger #ifdef __APPLE__ if (data.options() & LOADER_OPTION_CHECK_DEBUGGER) { 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) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } // disable debugger void *handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW); if (handle) { typedef int (ptrace_t)(int _request, pid_t _pid, caddr_t _addr, int _data); ptrace_t *ptrace_ptr = reinterpret_cast(dlsym(handle, reinterpret_cast(FACE_GNU_PTRACE))); if (ptrace_ptr) ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0); dlclose(handle); } } #elif defined(__unix__) if (data.options() & LOADER_OPTION_CHECK_DEBUGGER) { char mode[2]; mode[0] = 'r'; mode[1] = 0; char str[18]; str[0] = '/'; str[1] = 'p'; str[2] = 'r'; str[3] = 'o'; str[4] = 'c'; str[5] = '/'; str[6] = 's'; str[7] = 'e'; str[8] = 'l'; str[9] = 'f'; str[10] = '/'; str[11] = 's'; str[12] = 't'; str[13] = 'a'; str[14] = 't'; str[15] = 'u'; str[16] = 's'; str[17] = 0; FILE *file = fopen(str, mode); 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) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } } } #else #if defined(WIN_DRIVER) #else if (data.options() & LOADER_OPTION_CHECK_DEBUGGER) { if (peb->BeingDebugged) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } if (sc_query_information_process) { // disable InstrumentationCallback if (peb->OSMajorVersion > 6) { // Windows 10 PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION info; info.Version = 0; info.Reserved = 0; info.Callback = NULL; if (tNtSetInformationProcess *set_information_process = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_SET_INFORMATION_PROCESS_NAME), true))) set_information_process(process, ProcessInstrumentationCallback, &info, sizeof(info)); } HANDLE debug_object; if (NT_SUCCESS(reinterpret_cast(syscall | sc_query_information_process)(process, ProcessDebugPort, &debug_object, sizeof(debug_object), NULL)) && debug_object != 0) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } debug_object = 0; if (NT_SUCCESS(reinterpret_cast(syscall | sc_query_information_process)(process, ProcessDebugObjectHandle, &debug_object, sizeof(debug_object), reinterpret_cast(&debug_object))) || debug_object == 0) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } } else if (tNtQueryInformationProcess *query_information_process = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_QUERY_INFORMATION_PROCESS_NAME), true))) { HANDLE debug_object; if (NT_SUCCESS(query_information_process(process, ProcessDebugPort, &debug_object, sizeof(debug_object), NULL)) && debug_object != 0) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } if (NT_SUCCESS(query_information_process(process, ProcessDebugObjectHandle, &debug_object, sizeof(debug_object), NULL))) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } } // disable debugger if (sc_set_information_thread) reinterpret_cast(syscall | sc_set_information_thread)(thread, ThreadHideFromDebugger, NULL, 0); else if (tNtSetInformationThread *set_information_thread = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_SET_INFORMATION_THREAD_NAME), true))) set_information_thread(thread, ThreadHideFromDebugger, NULL, 0); } #endif #ifdef WIN_DRIVER if (data.options() & LOADER_OPTION_CHECK_DEBUGGER) { #else if (data.options() & LOADER_OPTION_CHECK_KERNEL_DEBUGGER) { #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(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_QUERY_INFORMATION_NAME), true)); 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) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } 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(LoaderAlloc(buffer_size * 2)); if (buffer) { 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]; for (size_t j = 0; j < 5 ; j++) { const char *module_name; switch (j) { case 0: module_name = reinterpret_cast(FACE_SICE_NAME); break; case 1: module_name = reinterpret_cast(FACE_SIWVID_NAME); break; case 2: module_name = reinterpret_cast(FACE_NTICE_NAME); break; case 3: module_name = reinterpret_cast(FACE_ICEEXT_NAME); break; case 4: module_name = reinterpret_cast(FACE_SYSER_NAME); break; } if (Loader_stricmp(module_name, module_entry->Name + module_entry->PathLength, true) == 0) { is_found = true; break; } } } } LoaderFree(buffer); } } #ifndef WIN_DRIVER } #endif if (is_found) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } } #endif // check header and loader CRC if (data.loader_crc_info_size()) { uint32_t loader_crc_info_size = *reinterpret_cast(image_base + data.loader_crc_info_size()); uint32_t loader_crc_info_hash = *reinterpret_cast(image_base + data.loader_crc_info_hash()); bool is_valid_crc = true; CRCValueCryptor crc_cryptor; if (loader_crc_info_hash != CalcCRC(image_base + data.loader_crc_info(), loader_crc_info_size)) is_valid_crc = false; for (i = 0; i < loader_crc_info_size; i += sizeof(CRC_INFO)) { CRC_INFO crc_info = *reinterpret_cast(image_base + data.loader_crc_info() + 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); if (crc_info.Hash != CalcCRC(image_base + crc_info.Address, crc_info.Size)) is_valid_crc = false; } if (!is_valid_crc) { if (data.options() & LOADER_OPTION_CHECK_PATCH) { LoaderMessage(mtFileCorrupted); return LOADER_ERROR; } tmp_loader_data->set_is_patch_detected(true); } tmp_loader_data->set_loader_crc_size(loader_crc_info_size); tmp_loader_data->set_loader_crc_hash(loader_crc_info_hash); if (data.options() & LOADER_OPTION_CHECK_DEBUGGER) { // check debugger again #ifdef VMP_GNU #elif defined(WIN_DRIVER) #else if (sc_query_information_process) { HANDLE debug_object; if (NT_SUCCESS(reinterpret_cast(syscall | sc_query_information_process)(process, ProcessDebugPort, &debug_object, sizeof(debug_object), NULL)) && debug_object != 0) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } } if (sc_set_information_thread) reinterpret_cast(syscall | sc_set_information_thread)(thread, ThreadHideFromDebugger, NULL, 0); #endif } } // check file CRC if (data.file_crc_info_size()) { uint32_t file_crc_info_size = *reinterpret_cast(image_base + data.file_crc_info_size()); #ifdef VMP_GNU Dl_info info; if (dladdr(reinterpret_cast(&LzmaDecode), &info)) { int file_handle = open(info.dli_fname, O_RDONLY); if (file_handle != -1) { FILE_CRC_INFO *file_info = reinterpret_cast(image_base + data.file_crc_info()); size_t file_size = lseek(file_handle, 0, SEEK_END); bool is_valid_crc; if (file_size < file_info->FileSize) { is_valid_crc = false; } else { is_valid_crc = true; uint8_t *file_view = reinterpret_cast(mmap(0, file_size, PROT_READ, MAP_SHARED, file_handle, 0)); if (file_view != MAP_FAILED) { size_t arch_offset = 0; #ifdef __APPLE__ fat_header *fat = reinterpret_cast(file_view); if (fat->magic == FAT_MAGIC || fat->magic == FAT_CIGAM) { fat_arch *arch = reinterpret_cast(file_view + sizeof(fat_header)); mach_header *mach = reinterpret_cast(image_base); for (i = 0; i < fat->nfat_arch; i++) { fat_arch cur_arch = arch[i]; if (fat->magic == FAT_CIGAM) { cur_arch.cputype = __builtin_bswap32(cur_arch.cputype); cur_arch.cpusubtype = __builtin_bswap32(cur_arch.cpusubtype); cur_arch.offset = __builtin_bswap32(cur_arch.offset); cur_arch.size = __builtin_bswap32(cur_arch.size); } if (cur_arch.cputype == mach->cputype && cur_arch.cpusubtype == mach->cpusubtype) { arch_offset = cur_arch.offset; if (cur_arch.size < file_info->FileSize) is_valid_crc = false; break; } } } #endif if (is_valid_crc) { CRCValueCryptor crc_cryptor; for (i = sizeof(FILE_CRC_INFO); i < file_crc_info_size; i += sizeof(CRC_INFO)) { CRC_INFO crc_info = *reinterpret_cast(image_base + data.file_crc_info() + 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); if (crc_info.Hash != CalcCRC(file_view + arch_offset + crc_info.Address, crc_info.Size)) is_valid_crc = false; } } munmap(file_view, file_size); } } close(file_handle); if (!is_valid_crc) { if (data.options() & LOADER_OPTION_CHECK_PATCH) { LoaderMessage(mtFileCorrupted); return LOADER_ERROR; } tmp_loader_data->set_is_patch_detected(true); } } } #elif defined(WIN_DRIVER) // FIXME #else wchar_t file_name[MAX_PATH]; if (GetModuleFileNameW(reinterpret_cast(image_base), file_name + 6, _countof(file_name) - 6)) { wchar_t *nt_file_name; if (file_name[6] == '\\' && file_name[7] == '\\') { nt_file_name = file_name; nt_file_name[0] = '\\'; nt_file_name[1] = '?'; nt_file_name[2] = '?'; nt_file_name[3] = '\\'; nt_file_name[4] = 'U'; nt_file_name[5] = 'N'; nt_file_name[6] = 'C'; } else { nt_file_name = file_name + 2; nt_file_name[0] = '\\'; nt_file_name[1] = '?'; nt_file_name[2] = '?'; nt_file_name[3] = '\\'; } if (sc_open_file) { HANDLE file_handle; OBJECT_ATTRIBUTES object_attributes; IO_STATUS_BLOCK io_status_block; UNICODE_STRING str; InitUnicodeString(&str, nt_file_name); InitializeObjectAttributes(&object_attributes, &str, 0, NULL, NULL); if (NT_SUCCESS(reinterpret_cast(syscall | sc_open_file)(&file_handle, GENERIC_READ | SYNCHRONIZE | FILE_READ_ATTRIBUTES, &object_attributes, &io_status_block, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT))) { FILE_CRC_INFO *file_info = reinterpret_cast(image_base + data.file_crc_info()); bool is_valid_crc = true; HANDLE file_map; InitializeObjectAttributes(&object_attributes, NULL, 0, NULL, NULL); if (NT_SUCCESS(reinterpret_cast(syscall | sc_create_section)(&file_map, SECTION_MAP_READ, &object_attributes, NULL, PAGE_READONLY, SEC_COMMIT, file_handle))) { void *file_view = NULL; SIZE_T file_size = 0; LARGE_INTEGER offset; offset.LowPart = 0; offset.HighPart = 0; if (NT_SUCCESS(reinterpret_cast(syscall | sc_map_view_of_section)(file_map, process, &file_view, NULL, 0, &offset, &file_size, ViewShare, 0, PAGE_READONLY))) { if (file_size < file_info->FileSize) is_valid_crc = false; else { CRCValueCryptor crc_cryptor; for (i = sizeof(FILE_CRC_INFO); i < file_crc_info_size; i += sizeof(CRC_INFO)) { CRC_INFO crc_info = *reinterpret_cast(image_base + data.file_crc_info() + 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); if (crc_info.Hash != CalcCRC(static_cast(file_view) + crc_info.Address, crc_info.Size)) is_valid_crc = false; } } reinterpret_cast(syscall | sc_unmap_view_of_section)(process, file_view); } reinterpret_cast(syscall | sc_close)(file_map); } reinterpret_cast(syscall | sc_close)(file_handle); if (!is_valid_crc) { if (data.options() & LOADER_OPTION_CHECK_PATCH) { LoaderMessage(mtFileCorrupted); return LOADER_ERROR; } tmp_loader_data->set_is_patch_detected(true); } } } else { tNtOpenFile *open_file = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_OPEN_FILE_NAME), true)); tNtCreateSection *create_section = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_CREATE_SECTION_NAME), true)); tNtMapViewOfSection *map_view_of_section = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_MAP_VIEW_OF_SECTION), true)); tNtUnmapViewOfSection *unmap_view_of_section = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_UNMAP_VIEW_OF_SECTION), true)); tNtClose *close = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_CLOSE), true)); if (!create_section || !open_file || !map_view_of_section || !unmap_view_of_section || !close) { LoaderMessage(mtInitializationError, INTERNAL_GPA_ERROR); return LOADER_ERROR; } // check breakpoint uint8_t *ckeck_list[] = { reinterpret_cast(create_section), reinterpret_cast(open_file), reinterpret_cast(map_view_of_section), reinterpret_cast(unmap_view_of_section), reinterpret_cast(close) }; for (i = 0; i < _countof(ckeck_list); i++) { if (*ckeck_list[i] == 0xcc) { if (data.options() & LOADER_OPTION_CHECK_DEBUGGER) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } tmp_loader_data->set_is_debugger_detected(true); } } HANDLE file_handle; OBJECT_ATTRIBUTES object_attributes; IO_STATUS_BLOCK io_status_block; UNICODE_STRING str; InitUnicodeString(&str, nt_file_name); InitializeObjectAttributes(&object_attributes, &str, 0, NULL, NULL); if (NT_SUCCESS(open_file(&file_handle, GENERIC_READ | SYNCHRONIZE | FILE_READ_ATTRIBUTES, &object_attributes, &io_status_block, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT))) { FILE_CRC_INFO *file_info = reinterpret_cast(image_base + data.file_crc_info()); bool is_valid_crc = true; HANDLE file_map; InitializeObjectAttributes(&object_attributes, NULL, 0, NULL, NULL); if (NT_SUCCESS(create_section(&file_map, SECTION_MAP_READ, &object_attributes, NULL, PAGE_READONLY, SEC_COMMIT, file_handle))) { void *file_view = NULL; SIZE_T file_size = 0; LARGE_INTEGER offset; offset.LowPart = 0; offset.HighPart = 0; if (NT_SUCCESS(map_view_of_section(file_map, process, &file_view, NULL, 0, &offset, &file_size, ViewShare, 0, PAGE_READONLY))) { if (file_size < file_info->FileSize) is_valid_crc = false; else { CRCValueCryptor crc_cryptor; for (i = sizeof(FILE_CRC_INFO); i < file_crc_info_size; i += sizeof(CRC_INFO)) { CRC_INFO crc_info = *reinterpret_cast(image_base + data.file_crc_info() + 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); if (crc_info.Hash != CalcCRC(static_cast(file_view) + crc_info.Address, crc_info.Size)) is_valid_crc = false; } } unmap_view_of_section(process, file_view); } close(file_map); } close(file_handle); if (!is_valid_crc) { if (data.options() & LOADER_OPTION_CHECK_PATCH) { LoaderMessage(mtFileCorrupted); return LOADER_ERROR; } tmp_loader_data->set_is_patch_detected(true); } } } } #endif } // setup WRITABLE flag for memory pages uint32_t data_section_info_size = data.section_info_size(); uint32_t data_section_info = data.section_info(); #ifdef VMP_GNU for (i = 0; i < data_section_info_size; i += sizeof(SECTION_INFO)) { SECTION_INFO *section_info = reinterpret_cast(image_base + data_section_info + i); int protect = PROT_READ | PROT_WRITE; if (section_info->Type & PROT_EXEC) protect |= PROT_EXEC; if (mprotect(image_base + section_info->Address, section_info->Size, protect) != 0) { LoaderMessage(mtInitializationError, VIRTUAL_PROTECT_ERROR); return LOADER_ERROR; } } #elif defined(WIN_DRIVER) ULONG size = 0; for (i = 0; i < data_section_info_size; i += sizeof(SECTION_INFO)) { SECTION_INFO *section_info = reinterpret_cast(image_base + data_section_info + i); if (section_info->Address + section_info->Size > size) size = section_info->Address + section_info->Size; } PMDL mdl = NULL; if (size) { mdl = IoAllocateMdl(image_base, size, FALSE, FALSE, NULL); if (!mdl) { LoaderMessage(mtInitializationError, VIRTUAL_PROTECT_ERROR); return LOADER_ERROR; } __try { MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess); } __except (EXCEPTION_EXECUTE_HANDLER) { IoFreeMdl(mdl); LoaderMessage(mtInitializationError, VIRTUAL_PROTECT_ERROR); return LOADER_ERROR; } dst_image_base = static_cast(MmGetSystemAddressForMdlSafe(mdl, (MM_PAGE_PRIORITY)FACE_DEFAULT_MDL_PRIORITY)); if (!dst_image_base) { MmUnlockPages(mdl); IoFreeMdl(mdl); LoaderMessage(mtInitializationError, VIRTUAL_PROTECT_ERROR); return LOADER_ERROR; } } #else tNtProtectVirtualMemory *virtual_protect = NULL; if (sc_virtual_protect) { for (i = 0; i < data_section_info_size; i += sizeof(SECTION_INFO)) { SECTION_INFO *section_info = reinterpret_cast(image_base + data_section_info + i); DWORD protect, old_protect; protect = (section_info->Type & IMAGE_SCN_MEM_EXECUTE) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; void *address = image_base + section_info->Address; SIZE_T size = section_info->Size; if (!NT_SUCCESS(reinterpret_cast(syscall | sc_virtual_protect)(process, &address, &size, protect, &old_protect))) { LoaderMessage(mtInitializationError, VIRTUAL_PROTECT_ERROR); return LOADER_ERROR; } if (old_protect & PAGE_GUARD) { if (data.options() & LOADER_OPTION_CHECK_DEBUGGER) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } tmp_loader_data->set_is_debugger_detected(true); } } } else { virtual_protect = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_VIRTUAL_PROTECT_NAME), true)); if (!virtual_protect) { LoaderMessage(mtInitializationError, INTERNAL_GPA_ERROR); return LOADER_ERROR; } // check breakpoint if (*reinterpret_cast(virtual_protect) == 0xcc) { if (data.options() & LOADER_OPTION_CHECK_DEBUGGER) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } tmp_loader_data->set_is_debugger_detected(true); } for (i = 0; i < data_section_info_size; i += sizeof(SECTION_INFO)) { SECTION_INFO *section_info = reinterpret_cast(image_base + data_section_info + i); DWORD protect, old_protect; protect = (section_info->Type & IMAGE_SCN_MEM_EXECUTE) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; void *address = image_base + section_info->Address; SIZE_T size = section_info->Size; if (!NT_SUCCESS(virtual_protect(process, &address, &size, protect, &old_protect))) { LoaderMessage(mtInitializationError, VIRTUAL_PROTECT_ERROR); return LOADER_ERROR; } if (old_protect & PAGE_GUARD) { if (data.options() & LOADER_OPTION_CHECK_DEBUGGER) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } tmp_loader_data->set_is_debugger_detected(true); } } } #endif // unpack regions if (data.packer_info_size()) { #ifdef VMP_GNU #elif defined(WIN_DRIVER) #else uint32_t tls_index = 0; if (data.tls_index_info()) tls_index = *reinterpret_cast(image_base + data.tls_index_info()); #endif PACKER_INFO *packer_info = reinterpret_cast(image_base + data.packer_info()); CLzmaDecoderState state; if (LzmaDecodeProperties(&state.Properties, image_base + packer_info->Src, packer_info->Dst) != LZMA_RESULT_OK) { LoaderMessage(mtInitializationError, UNPACKER_ERROR); return LOADER_ERROR; } state.Probs = (CProb *)LoaderAlloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) { LoaderMessage(mtInitializationError, UNPACKER_ERROR); return LOADER_ERROR; } SizeT src_processed_size; SizeT dst_processed_size; for (i = sizeof(PACKER_INFO); i < data.packer_info_size(); i += sizeof(PACKER_INFO)) { packer_info = reinterpret_cast(image_base + data.packer_info() + i); if (LzmaDecode(&state, image_base + packer_info->Src, -1, &src_processed_size, dst_image_base + packer_info->Dst, -1, &dst_processed_size) != LZMA_RESULT_OK) { LoaderFree(state.Probs); LoaderMessage(mtInitializationError, UNPACKER_ERROR); return LOADER_ERROR; } } LoaderFree(state.Probs); #ifdef VMP_GNU #elif defined(WIN_DRIVER) #else if (data.tls_index_info()) *reinterpret_cast(dst_image_base + data.tls_index_info()) = tls_index; #endif } // setup fixups if (delta_base != 0) LoaderProcessFixups(delta_base, data.fixup_info(), data.fixup_info_size(), image_base, dst_image_base); // setup IAT for (i = 0; i < data.iat_info_size(); i += sizeof(IAT_INFO)) { IAT_INFO *iat_info = reinterpret_cast(image_base + data.iat_info() + i); __movsb(iat_info->Dst + dst_image_base, iat_info->Src + image_base, iat_info->Size); } // setup import #ifdef VMP_GNU #else for (i = 0; i < data.import_info_size(); i += sizeof(DLL_INFO)) { DLL_INFO *dll_info = reinterpret_cast(image_base + data.import_info() + i); const char *dll_name = reinterpret_cast(image_base + dll_info->Name); HMODULE h = LoaderGetModuleHandleEnc(dll_name); for (IMPORT_INFO *import_info = reinterpret_cast(dll_info + 1); import_info->Name != 0; import_info++, i += sizeof(IMPORT_INFO)) { const char *api_name; if (import_info->Name & IMAGE_ORDINAL_FLAG32) { api_name = LPCSTR(INT_PTR((IMAGE_ORDINAL32(import_info->Name)))); } else { api_name = LPCSTR(INT_PTR((image_base + import_info->Name))); } void *p = LoaderGetProcAddress(h, api_name, true); if (!p) { #ifndef WIN_DRIVER ULONG error_mode = 0; if (tNtQueryInformationProcess *query_information_process = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_QUERY_INFORMATION_PROCESS_NAME), true))) { query_information_process(process, ProcessDefaultHardErrorMode, &error_mode, sizeof(error_mode), NULL); } if (error_mode & SEM_FAILCRITICALERRORS) return LOADER_ERROR; #endif LoaderMessage((import_info->Name & IMAGE_ORDINAL_FLAG32) ? mtOrdinalNotFound : mtProcNotFound, api_name, dll_name); return LOADER_ERROR; } *(reinterpret_cast(dst_image_base + import_info->Address)) = reinterpret_cast(p) - import_info->Key; } i += sizeof(uint32_t); } #endif // setup internal import for (i = 0; i < data.internal_import_info_size(); i += sizeof(IMPORT_INFO)) { IMPORT_INFO *import_info = reinterpret_cast(image_base + data.internal_import_info() + i); *(reinterpret_cast(dst_image_base + import_info->Address)) = import_info->Name + dst_image_base - import_info->Key; } // setup relocations for (i = 0; i < data.relocation_info_size(); i += sizeof(RELOCATION_INFO)) { RELOCATION_INFO *relocation_info = reinterpret_cast(image_base + data.relocation_info() + i); uint8_t *address = dst_image_base + relocation_info->Address; uint8_t *source = dst_image_base + relocation_info->Source; #ifdef __unix__ if (relocation_info->Type == 0) { // R_386_IRELATIVE *reinterpret_cast(address) = reinterpret_cast(source)(); } else if (relocation_info->Type == 1) { // R_386_PC32 *reinterpret_cast(address) += *reinterpret_cast(source) - static_cast(reinterpret_cast(address)); } #else if (relocation_info->Type == 0) { *reinterpret_cast(address) += relocation_info->Source; } else { size_t data = 0; #if defined(_M_X64) || defined(__amd64__) if (relocation_info->Type == 4) data = *reinterpret_cast(address); else #endif if (relocation_info->Type == 3) data = *reinterpret_cast(address); else if (relocation_info->Type == 2) data = *reinterpret_cast(address); else if (relocation_info->Type == 1) data = *reinterpret_cast(address); data -= reinterpret_cast(source); data += *reinterpret_cast(source); #if defined(_M_X64) || defined(__amd64__) if (relocation_info->Type == 4) *reinterpret_cast(address) = static_cast(data); else #endif if (relocation_info->Type == 3) *reinterpret_cast(address) = static_cast(data); else if (relocation_info->Type == 2) *reinterpret_cast(address) = static_cast(data); else if (relocation_info->Type == 1) *reinterpret_cast(address) = static_cast(data); } #endif } #ifndef VMP_GNU #ifndef WIN_DRIVER if (data.options() & LOADER_OPTION_CHECK_DEBUGGER) { typedef BOOL (WINAPI tCloseHandle)(HANDLE hObject); tCloseHandle *close_handle = reinterpret_cast(LoaderGetProcAddress(kernel32, reinterpret_cast(FACE_CLOSE_HANDLE_NAME), true)); if (close_handle) { __try { if (close_handle(HANDLE(INT_PTR(0xDEADC0DE)))) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } } __except(EXCEPTION_EXECUTE_HANDLER) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } } size_t drx; uint64_t val; CONTEXT *ctx; __try { __writeeflags(__readeflags() | 0x100); val = __rdtsc(); __nop(); LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } __except(ctx = (GetExceptionInformation())->ContextRecord, drx = (ctx->ContextFlags & CONTEXT_DEBUG_REGISTERS) ? ctx->Dr0 | ctx->Dr1 | ctx->Dr2 | ctx->Dr3 : 0, EXCEPTION_EXECUTE_HANDLER) { if (drx) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } } } #endif #endif // detect a virtual machine if (data.options() & LOADER_OPTION_CHECK_VIRTUAL_MACHINE) { int cpu_info[4]; __cpuid(cpu_info, 1); if ((cpu_info[2] >> 31) & 1) { // hypervisor found bool is_found = true; #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) is_found = false; } #endif if (is_found) { LoaderMessage(mtVirtualMachineFound); return LOADER_ERROR; } } else { #ifdef __APPLE__ // FIXME #elif defined(__unix__) bool is_found = false; char mode[2]; mode[0] = 'r'; mode[1] = 0; char str[39]; str[0] = '/'; str[1] = 's'; str[2] = 'y'; str[3] = 's'; str[4] = '/'; str[5] = 'd'; str[6] = 'e'; str[7] = 'v'; str[8] = 'i'; str[9] = 'c'; str[10] = 'e'; str[11] = 's'; str[12] = '/'; str[13] = 'v'; str[14] = 'i'; str[15] = 'r'; str[16] = 't'; str[17] = 'u'; str[18] = 'a'; str[19] = 'l'; str[20] = '/'; str[21] = 'd'; str[22] = 'm'; str[23] = 'i'; str[24] = '/'; str[25] = 'i'; str[26] = 'd'; str[27] = '/'; str[28] = 's'; str[29] = 'y'; str[30] = 's'; str[31] = '_'; str[32] = 'v'; str[33] = 'e'; str[34] = 'n'; str[35] = 'd'; str[36] = 'o'; str[37] = 'r'; str[38] = 0; FILE *fsys_vendor = fopen(str, mode); if (fsys_vendor) { char sys_vendor[256] = { 0 }; fgets(sys_vendor, sizeof(sys_vendor), fsys_vendor); fclose(fsys_vendor); if (LoaderFindFirmwareVendor(reinterpret_cast(sys_vendor), sizeof(sys_vendor))) is_found = true; } if (is_found) { LoaderMessage(mtVirtualMachineFound); return LOADER_ERROR; } #else uint8_t mem_val; uint64_t val; __try { // set T flag __writeeflags(__readeflags() | 0x100); val = __rdtsc(); __nop(); if (data.options() & LOADER_OPTION_CHECK_DEBUGGER) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } tmp_loader_data->set_is_debugger_detected(true); } __except (mem_val = *static_cast((GetExceptionInformation())->ExceptionRecord->ExceptionAddress), EXCEPTION_EXECUTE_HANDLER) { if (mem_val != 0x90) { LoaderMessage(mtVirtualMachineFound); return LOADER_ERROR; } } __try { // set T flag __writeeflags(__readeflags() | 0x100); __cpuid(cpu_info, 1); __nop(); if (data.options() & LOADER_OPTION_CHECK_DEBUGGER) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } tmp_loader_data->set_is_debugger_detected(true); } __except (mem_val = *static_cast((GetExceptionInformation())->ExceptionRecord->ExceptionAddress), EXCEPTION_EXECUTE_HANDLER) { if (mem_val != 0x90) { LoaderMessage(mtVirtualMachineFound); return LOADER_ERROR; } } #ifdef WIN_DRIVER bool is_found = false; ULONG table_size = 0x1000; SYSTEM_FIRMWARE_TABLE_INFORMATION *table = static_cast(LoaderAlloc(table_size)); table->Action = SystemFirmwareTable_Get; table->ProviderSignature = 'FIRM'; table->TableID = 0xc0000; table->TableBufferLength = table_size; NTSTATUS status = NtQuerySystemInformation(SystemFirmwareTableInformation, table, table_size, &table_size); if (status == STATUS_BUFFER_TOO_SMALL) { LoaderFree(table); table = static_cast(LoaderAlloc(table_size)); table->Action = SystemFirmwareTable_Get; table->ProviderSignature = 'FIRM'; table->TableID = 0xc0000; table->TableBufferLength = table_size; } status = NtQuerySystemInformation(SystemFirmwareTableInformation, table, table_size, &table_size); if (NT_SUCCESS(status)) { if (LoaderFindFirmwareVendor(reinterpret_cast(table), table_size)) is_found = true; } LoaderFree(table); if (is_found) { LoaderMessage(mtVirtualMachineFound); return LOADER_ERROR; } #else 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(LoaderGetProcAddress(kernel32, reinterpret_cast(FACE_ENUM_SYSTEM_FIRMWARE_NAME), true)); tGetSystemFirmwareTable *get_system_firmware_table = reinterpret_cast(LoaderGetProcAddress(kernel32, reinterpret_cast(FACE_GET_SYSTEM_FIRMWARE_NAME), true)); if (enum_system_firmware_tables && get_system_firmware_table) { UINT tables_size = enum_system_firmware_tables('FIRM', NULL, 0); if (tables_size) { DWORD *tables = static_cast(LoaderAlloc(tables_size)); 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 = static_cast(LoaderAlloc(data_size)); get_system_firmware_table('FIRM', tables[i], data, data_size); if (LoaderFindFirmwareVendor(data, data_size)) is_found = true; LoaderFree(data); } } LoaderFree(tables); } } else { tNtOpenSection *open_section = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_OPEN_SECTION_NAME), true)); tNtMapViewOfSection *map_view_of_section = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_MAP_VIEW_OF_SECTION), true)); tNtUnmapViewOfSection *unmap_view_of_section = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_UNMAP_VIEW_OF_SECTION), true)); tNtClose *close = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_CLOSE), true)); if (open_section && map_view_of_section && unmap_view_of_section && close) { 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 }; InitUnicodeString(&str, 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 (LoaderFindFirmwareVendor(static_cast(data), data_size)) is_found = true; unmap_view_of_section(process, data); } close(physical_memory); } } } if (is_found) { LoaderMessage(mtVirtualMachineFound); return LOADER_ERROR; } if (LoaderGetModuleHandleEnc(reinterpret_cast(FACE_SBIEDLL_NAME))) { LoaderMessage(mtVirtualMachineFound); return LOADER_ERROR; } #endif #endif } } // check memory CRC if (data.memory_crc_info_size()) { bool is_valid_crc = true; #ifndef DEMO #ifdef VMP_GNU #elif defined(WIN_DRIVER) #else if (sc_query_virtual_memory) { MEMORY_BASIC_INFORMATION memory_info; // check tmp_loader_data NTSTATUS status = reinterpret_cast(syscall | sc_query_virtual_memory)(process, tmp_loader_data, MemoryBasicInformation, &memory_info, sizeof(memory_info), NULL); if (NT_SUCCESS(status) && memory_info.AllocationBase == image_base) is_valid_crc = false; // check memory after image IMAGE_DOS_HEADER *dos_header = reinterpret_cast(image_base); IMAGE_NT_HEADERS *pe_header = reinterpret_cast(image_base + dos_header->e_lfanew); status = reinterpret_cast(syscall | sc_query_virtual_memory)(process, image_base + pe_header->OptionalHeader.SizeOfImage, MemoryBasicInformation, &memory_info, sizeof(memory_info), NULL); if (NT_SUCCESS(status) && memory_info.AllocationBase == image_base) is_valid_crc = false; } else { tNtQueryVirtualMemory *query_virtual_memory = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_QUERY_VIRTUAL_MEMORY_NAME), true)); if (query_virtual_memory) { MEMORY_BASIC_INFORMATION memory_info; // check tmp_loader_data NTSTATUS status = query_virtual_memory(process, tmp_loader_data, MemoryBasicInformation, &memory_info, sizeof(memory_info), NULL); if (NT_SUCCESS(status) && memory_info.AllocationBase == image_base) is_valid_crc = false; // check memory after image IMAGE_DOS_HEADER *dos_header = reinterpret_cast(image_base); IMAGE_NT_HEADERS *pe_header = reinterpret_cast(image_base + dos_header->e_lfanew); status = query_virtual_memory(process, image_base + pe_header->OptionalHeader.SizeOfImage, MemoryBasicInformation, &memory_info, sizeof(memory_info), NULL); if (NT_SUCCESS(status) && memory_info.AllocationBase == image_base) is_valid_crc = false; } } #endif #endif if (data.memory_crc_info_hash() != CalcCRC(image_base + data.memory_crc_info(), data.memory_crc_info_size())) is_valid_crc = false; CRCValueCryptor crc_cryptor; for (i = 0; i < data.memory_crc_info_size(); i += sizeof(CRC_INFO)) { CRC_INFO crc_info = *reinterpret_cast(image_base + data.memory_crc_info() + 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); if (crc_info.Address + crc_info.Size > crc_image_size) crc_image_size = crc_info.Address + crc_info.Size; if (crc_info.Hash != CalcCRC(image_base + crc_info.Address, crc_info.Size)) is_valid_crc = false; } if (!is_valid_crc) { if (data.options() & LOADER_OPTION_CHECK_PATCH) { LoaderMessage(mtFileCorrupted); return LOADER_ERROR; } tmp_loader_data->set_is_patch_detected(true); } } // calc CPU hash int cpu_info[4]; size_t cpu_count = 0; #ifdef VMP_GNU #else #ifdef WIN_DRIVER KAFFINITY system_mask = KeQueryActiveProcessors(); KAFFINITY mask = 1; #else DWORD_PTR process_mask, system_mask; if (GetProcessAffinityMask(process, &process_mask, &system_mask)) { if (process_mask != system_mask) { if (!SetProcessAffinityMask(process, system_mask)) { LoaderMessage(mtInitializationError, CPU_HASH_ERROR); return LOADER_ERROR; } } DWORD_PTR mask = 1; #endif for (size_t i = 0; i < sizeof(mask) * 8; i++) { if (system_mask & mask) { #ifdef WIN_DRIVER KeSetSystemAffinityThread(mask); #else DWORD_PTR old_mask = SetThreadAffinityMask(thread, mask); Sleep(0); #endif __cpuid(cpu_info, 1); if ((cpu_info[0] & 0xff0) == 0xfe0) cpu_info[0] ^= 0x20; // fix Athlon bug cpu_info[1] &= 0x00ffffff; // mask out APIC Physical ID size_t cpu_hash = (cpu_info[0] + cpu_info[1] + cpu_salt) ^ reinterpret_cast(tmp_loader_data); bool cpu_found = false; for (j = 0; j < cpu_count; j++) { if (tmp_loader_data->cpu_hash(j) == cpu_hash) { cpu_found = true; break; } } if (!cpu_found) { if (cpu_count == VAR_COUNT - VAR_CPU_HASH) { LoaderMessage(mtInitializationError, CPU_HASH_ERROR); return LOADER_ERROR; } tmp_loader_data->set_cpu_hash(cpu_count++, cpu_hash); } #ifdef WIN_DRIVER KeRevertToUserAffinityThread(); #else SetThreadAffinityMask(thread, old_mask); #endif } mask <<= 1; } #ifndef WIN_DRIVER if (process_mask != system_mask) SetProcessAffinityMask(process, process_mask); } #endif #endif if (!cpu_count) { __cpuid(cpu_info, 1); if ((cpu_info[0] & 0xff0) == 0xfe0) cpu_info[0] ^= 0x20; // fix Athlon bug cpu_info[1] &= 0x00ffffff; // mask out APIC Physical ID tmp_loader_data->set_cpu_hash(cpu_count++, (cpu_info[0] + cpu_info[1] + cpu_salt) ^ reinterpret_cast(tmp_loader_data)); } tmp_loader_data->set_cpu_count(cpu_count); // create session key session_key = __rdtsc(); session_key ^= session_key >> 32; tmp_loader_data->set_session_key(static_cast(session_key)); // save pointer to loader_data *(reinterpret_cast(dst_image_base + data.storage())) = tmp_loader_data; if (uint32_t data_runtime_entry = data.runtime_entry()) { #ifdef VMP_GNU typedef bool (WINAPI tRuntimeEntry)(HMODULE hModule, bool is_init); if (reinterpret_cast(image_base + data_runtime_entry)(reinterpret_cast(image_base), true) != true) return LOADER_ERROR; #elif defined(WIN_DRIVER) typedef NTSTATUS (tRuntimeEntry)(HMODULE hModule, bool is_init); if (reinterpret_cast(image_base + data_runtime_entry)(reinterpret_cast(image_base), true) != STATUS_SUCCESS) return LOADER_ERROR; #else typedef BOOL (WINAPI tRuntimeEntry)(HMODULE hModule, DWORD dwReason, LPVOID lpReserved); if (reinterpret_cast(image_base + data_runtime_entry)(reinterpret_cast(image_base), DLL_PROCESS_ATTACH, NULL) != TRUE) return LOADER_ERROR; #endif } // setup delay import #ifdef VMP_GNU #elif defined(WIN_DRIVER) #else for (i = 0; i < data.delay_import_info_size(); i += sizeof(DLL_INFO)) { DLL_INFO *dll_info = reinterpret_cast(image_base + data.delay_import_info() + i); const char *dll_name = reinterpret_cast(image_base + dll_info->Name); HMODULE h = LoaderLoadLibraryEnc(dll_name); for (IMPORT_INFO *import_info = reinterpret_cast(dll_info + 1); import_info->Name != 0; import_info++, i += sizeof(IMPORT_INFO)) { const char *api_name; if (import_info->Name & IMAGE_ORDINAL_FLAG32) { api_name = LPCSTR(INT_PTR(IMAGE_ORDINAL32(import_info->Name))); } else { api_name = LPCSTR(INT_PTR(image_base + import_info->Name)); } void *p = LoaderGetProcAddress(h, api_name, true); if (!p) { #ifndef WIN_DRIVER ULONG error_mode = 0; if (tNtQueryInformationProcess *query_information_process = reinterpret_cast(LoaderGetProcAddress(ntdll, reinterpret_cast(FACE_NT_QUERY_INFORMATION_PROCESS_NAME), true))) { query_information_process(process, ProcessDefaultHardErrorMode, &error_mode, sizeof(error_mode), NULL); } if (error_mode & SEM_FAILCRITICALERRORS) return LOADER_ERROR; #endif LoaderMessage((import_info->Name & IMAGE_ORDINAL_FLAG32) ? mtOrdinalNotFound : mtProcNotFound, api_name, dll_name); return LOADER_ERROR; } *(reinterpret_cast(dst_image_base + import_info->Address)) = reinterpret_cast(p) - import_info->Key; } i += sizeof(uint32_t); } #endif // reset WRITABLE flag for memory pages #ifdef VMP_GNU for (i = 0; i < data_section_info_size; i += sizeof(SECTION_INFO)) { SECTION_INFO *section_info = reinterpret_cast(image_base + data_section_info + i); int protect = section_info->Type; if (mprotect(image_base + section_info->Address, section_info->Size, protect) != 0) { LoaderMessage(mtInitializationError, VIRTUAL_PROTECT_ERROR); return LOADER_ERROR; } } #elif defined(WIN_DRIVER) if (mdl) { MmUnlockPages(mdl); IoFreeMdl(mdl); dst_image_base = image_base; } #else if (sc_virtual_protect) { for (i = 0; i < data_section_info_size; i += sizeof(SECTION_INFO)) { SECTION_INFO *section_info = reinterpret_cast(image_base + data_section_info + i); DWORD protect, old_protect; if (section_info->Type & IMAGE_SCN_MEM_READ) protect = (section_info->Type & IMAGE_SCN_MEM_WRITE) ? PAGE_READWRITE : PAGE_READONLY; else protect = PAGE_NOACCESS; if (section_info->Type & IMAGE_SCN_MEM_EXECUTE) protect <<= 4; // convert PAGE_XXX to PAGE_EXECUTE_XXX void *address = image_base + section_info->Address; SIZE_T size = section_info->Size; if (!NT_SUCCESS(reinterpret_cast(syscall | sc_virtual_protect)(process, &address, &size, protect, &old_protect))) { LoaderMessage(mtInitializationError, VIRTUAL_PROTECT_ERROR); return LOADER_ERROR; } if (old_protect & (PAGE_NOACCESS | PAGE_GUARD)) { if (data.options() & LOADER_OPTION_CHECK_DEBUGGER) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } tmp_loader_data->set_is_debugger_detected(true); } } } else { // check breakpoint if (*reinterpret_cast(virtual_protect) == 0xcc) { if (data.options() & LOADER_OPTION_CHECK_DEBUGGER) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } tmp_loader_data->set_is_debugger_detected(true); } for (i = 0; i < data_section_info_size; i += sizeof(SECTION_INFO)) { SECTION_INFO *section_info = reinterpret_cast(image_base + data_section_info + i); DWORD protect, old_protect; if (section_info->Type & IMAGE_SCN_MEM_READ) protect = (section_info->Type & IMAGE_SCN_MEM_WRITE) ? PAGE_READWRITE : PAGE_READONLY; else protect = PAGE_NOACCESS; if (section_info->Type & IMAGE_SCN_MEM_EXECUTE) protect <<= 4; // convert PAGE_XXX to PAGE_EXECUTE_XXX void *address = image_base + section_info->Address; SIZE_T size = section_info->Size; if (!NT_SUCCESS(virtual_protect(process, &address, &size, protect, &old_protect))) { LoaderMessage(mtInitializationError, VIRTUAL_PROTECT_ERROR); return LOADER_ERROR; } if (old_protect & (PAGE_NOACCESS | PAGE_GUARD)) { if (data.options() & LOADER_OPTION_CHECK_DEBUGGER) { LoaderMessage(mtDebuggerFound); return LOADER_ERROR; } tmp_loader_data->set_is_debugger_detected(true); } } } tmp_loader_data->set_crc_image_size(crc_image_size); #endif #ifdef __unix__ if (data.relro_info()) { SECTION_INFO *section_info = reinterpret_cast(image_base + data.relro_info()); int protect = section_info->Type; if (mprotect(image_base + section_info->Address, section_info->Size, protect) != 0) { LoaderMessage(mtInitializationError, VIRTUAL_PROTECT_ERROR); return LOADER_ERROR; } } #endif // show nag LoaderMessage(mtUnregisteredVersion); tmp_loader_data->set_loader_status(LOADER_SUCCESS); return LOADER_SUCCESS; }