diff options
author | jmpoep <OriginalEntryPoint@qq.com> | 2023-12-07 16:51:07 +0800 |
---|---|---|
committer | jmpoep <OriginalEntryPoint@qq.com> | 2023-12-07 16:51:07 +0800 |
commit | 28008a746a31abb7909dd86cb0cd413ac8943b0b (patch) | |
tree | a30b74b8cad548048c3c1551d652828ab76fa9bd /runtime/hwid.cc | |
download | vmprotect-3.5.1-master.tar vmprotect-3.5.1-master.tar.gz vmprotect-3.5.1-master.tar.bz2 vmprotect-3.5.1-master.zip |
Diffstat (limited to 'runtime/hwid.cc')
-rw-r--r-- | runtime/hwid.cc | 688 |
1 files changed, 688 insertions, 0 deletions
diff --git a/runtime/hwid.cc b/runtime/hwid.cc new file mode 100644 index 0000000..e7d1bac --- /dev/null +++ b/runtime/hwid.cc @@ -0,0 +1,688 @@ +#include "common.h" +#include "objects.h" +#include "utils.h" +#include "hwid.h" +#include "core.h" +#include "crypto.h" + +#ifdef __unix__ +#include <mntent.h> +#include <dirent.h> +#include <net/if.h> +#include <pthread.h> +#endif +#ifdef VMP_GNU +EXPORT_API int WINAPI ExportedGetCurrentHWID(char *buffer, int size) __asm__ ("ExportedGetCurrentHWID"); +#endif +#ifdef WIN_DRIVER +#include <ntddndis.h> +extern "C" { + NTSYSAPI + NTSTATUS + NTAPI + ZwCreateEvent ( + PHANDLE EventHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + EVENT_TYPE EventType, + BOOLEAN InitialState + ); + + NTSYSAPI + NTSTATUS + NTAPI + ZwWaitForSingleObject( + HANDLE Handle, + BOOLEAN Alertable, + PLARGE_INTEGER Timeout +); +} +#endif + +int WINAPI ExportedGetCurrentHWID(char *buffer, int size) +{ + HardwareID *hardware_id = Core::Instance()->hardware_id(); + return hardware_id ? hardware_id->GetCurrent(buffer, size) : 0; +} + +/** + * HardwareID + */ + +#ifdef WIN_DRIVER +bool GetRegValue(LPCWSTR reg_path, LPCWSTR value_name, LPWSTR buffer, size_t *size) +{ + UNICODE_STRING unicode_reg_path, unicode_value_name; + OBJECT_ATTRIBUTES object_attributes; + NTSTATUS status; + HANDLE key_handle; + ULONG information_size; + KEY_VALUE_PARTIAL_INFORMATION *information; + bool res = false; + + RtlInitUnicodeString(&unicode_reg_path, reg_path); + RtlInitUnicodeString(&unicode_value_name, value_name); + InitializeObjectAttributes(&object_attributes, &unicode_reg_path, OBJ_CASE_INSENSITIVE, NULL, NULL); + status = ZwOpenKey(&key_handle, KEY_QUERY_VALUE, &object_attributes); + if (NT_SUCCESS(status)) { + information_size = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + MAX_PATH * sizeof(WCHAR); + information = reinterpret_cast<KEY_VALUE_PARTIAL_INFORMATION*>(new uint8_t[information_size]); + status = ZwQueryValueKey(key_handle, &unicode_value_name, KeyValuePartialInformation, information, information_size, &information_size); + if (NT_SUCCESS(status)) { + size_t len = information->DataLength / sizeof(wchar_t); + if (*size < len + 1) { + *size = len + 1; + } else { + RtlCopyMemory(buffer, information->Data, information->DataLength); + buffer[len] = 0; + *size = wcslen(buffer); + res = true; + } + } + delete [] information; + ZwClose(key_handle); + } + return res; +} +#endif + +HardwareID::HardwareID() + : block_count_(0), start_block_(0) +{ + uint64_t timestamp = __rdtsc(); // exactly 8 bytes + timestamp ^= ~timestamp << 32; // remove zeroes at the beginning + blocks_ = new CryptoContainer(sizeof(uint32_t) * MAX_BLOCKS, reinterpret_cast<uint8_t *>(×tamp)); + + // old methods + GetCPU(0); + GetCPU(1); + start_block_ = block_count_; + // new methods, we'll return HWID starting from this DWORD + GetCPU(2); + GetMachineName(); + GetHDD(); + GetMacAddresses(); +} + +HardwareID::~HardwareID() +{ + delete blocks_; +} + +void HardwareID::AddBlock(const void *p, size_t size, BlockType type) +{ + if (block_count_ == MAX_BLOCKS) return; // no free space + + SHA1 hash; + hash.Input(reinterpret_cast<const uint8_t *>(p), size); + uint32_t block = __builtin_bswap32(*reinterpret_cast<const uint32_t *>(hash.Result())); + + block &= ~TYPE_MASK; // zero two lower bits + block |= type & TYPE_MASK; // set type bits + + // check existing blocks + for (size_t i = block_count_; i > start_block_; i--) { + uint32_t prev_block = blocks_->GetDWord((i - 1) * sizeof(uint32_t)); + if (prev_block == block) + return; + if ((prev_block & TYPE_MASK) != (block & TYPE_MASK)) + break; + } + + blocks_->SetDWord(block_count_ * sizeof(uint32_t), block); + block_count_++; +} + +void HardwareID::GetCPU(uint8_t method) +{ + uint32_t old_block_count = block_count_; + +#ifdef WIN_DRIVER + KAFFINITY system_mask = KeQueryActiveProcessors(); + KAFFINITY mask = 1; +#endif +#ifdef VMP_GNU + // set process affinity mask to system affinity mask +#ifdef __APPLE__ + //FIXME + if (0) { +#else + cpu_set_t process_mask, system_mask; + memset(&system_mask, 0xFF, sizeof(system_mask)); + if (0 == sched_getaffinity(0, sizeof(process_mask), &process_mask)) { + sched_setaffinity(0, sizeof(system_mask), &system_mask); //try all CPUs, will set MAX CPUs + sched_getaffinity(0, sizeof(system_mask), &system_mask); //get MAX CPUs +#endif +#else +#ifndef WIN_DRIVER + DWORD_PTR process_mask, system_mask; + HANDLE process = GetCurrentProcess(); + if (GetProcessAffinityMask(process, &process_mask, &system_mask)) { + if (process_mask != system_mask) + SetProcessAffinityMask(process, system_mask); + DWORD_PTR mask = 1; + HANDLE thread = GetCurrentThread(); +#endif +#endif +#ifdef VMP_GNU + // set thread affinity mask to mask +#ifdef __APPLE__ + //FIXME + while (false) { + if (false) { +#else + for (size_t i = 0; i < sizeof(system_mask) * 8; i++) { + if (__CPU_ISSET_S(i, sizeof(system_mask), &system_mask)) { + cpu_set_t mask; + __CPU_ZERO_S(sizeof(mask), &mask); + __CPU_SET_S(i, sizeof(mask), &mask); + sched_setaffinity(0, sizeof(mask), &mask); +#endif +#else + 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 +#endif + ProcessCPU(method); +#ifdef VMP_GNU + // set thread affinity mask back to old_mask +#ifdef __APPLE__ + //FIXME +#else + //do nothing +#endif +#else +#ifdef WIN_DRIVER + KeRevertToUserAffinityThread(); +#else + SetThreadAffinityMask(thread, old_mask); +#endif +#endif + } +#ifndef VMP_GNU + mask <<= 1; +#endif + } +#ifndef WIN_DRIVER +#ifdef VMP_GNU + // set process affinity mask back to process_mask +#ifdef __APPLE__ + //FIXME +#else + sched_setaffinity(0, sizeof(process_mask), &process_mask); +#endif +#else + if (process_mask != system_mask) + SetProcessAffinityMask(process, process_mask); +#endif + } +#endif + + if (old_block_count == block_count_) + ProcessCPU(method); +} + +void HardwareID::ProcessCPU(uint8_t method) +{ + int info[4]; + __cpuid(info, 1); + if ((info[0] & 0xFF0) == 0xFE0) + info[0] ^= 0x20; // fix Athlon bug + info[1] &= 0x00FFFFFF; // mask out APIC Physical ID + + if (method == 2) { + info[2] = 0; + } else if (method == 1) { + info[2] &= ~(1 << 27); + } + + AddBlock(info, sizeof(info), BLOCK_CPU); +} + +void HardwareID::GetMachineName() +{ +#ifdef __APPLE__ + CFStringRef computer_name = SCDynamicStoreCopyComputerName(NULL, NULL); + if (!computer_name) + return; + + CFIndex len = CFStringGetLength(computer_name); + CFIndex size = CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8); + char *buf = new char[size]; + if (CFStringGetCString(computer_name, buf, size, kCFStringEncodingUTF8)) + AddBlock(buf, strlen(buf), BLOCK_HOST); + delete [] buf; + CFRelease(computer_name); +#elif defined(__unix__) + char buf[HOST_NAME_MAX+1] = {0}; + if (0 == gethostname(buf, HOST_NAME_MAX)) + AddBlock(buf, strlen(buf), BLOCK_HOST); +#elif defined(WIN_DRIVER) + #define MAX_COMPUTERNAME_LENGTH 31 + + wchar_t buf[MAX_COMPUTERNAME_LENGTH + 1]; + size_t size = _countof(buf); + + if (GetRegValue(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName\\ComputerName", L"ComputerName", buf, &size) || + GetRegValue(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName", L"ComputerName", buf, &size)) { + AddBlock(buf, size * sizeof(wchar_t), BLOCK_HOST); + } +#else + HMODULE dll = LoadLibraryA(VMProtectDecryptStringA("kernel32.dll")); + if (!dll) + return; + + typedef ULONG (WINAPI *GET_COMPUTER_NAME) (wchar_t *, uint32_t *); + GET_COMPUTER_NAME get_computer_name = reinterpret_cast<GET_COMPUTER_NAME>(InternalGetProcAddress(dll, VMProtectDecryptStringA("GetComputerNameW"))); + + if (get_computer_name) { + wchar_t buf[MAX_COMPUTERNAME_LENGTH + 1]; + uint32_t size = _countof(buf); + + if (get_computer_name(buf, &size)) + AddBlock(buf, size * sizeof(wchar_t), BLOCK_HOST); + } + + FreeLibrary(dll); +#endif +} + +void HardwareID::ProcessMAC(const uint8_t *p, size_t size) +{ + // this big IF construction allows to put constants to the code, not to the data segment + // it is harder to find them in the code after virtualisation + uint32_t dw = (p[0] << 16) + (p[1] << 8) + p[2]; + if (dw == 0x000569 || dw == 0x000C29 || dw == 0x001C14 || dw == 0x005056 || // vmware + dw == 0x0003FF || dw == 0x000D3A || dw == 0x00125A || dw == 0x00155D || dw == 0x0017FA || dw == 0x001DD8 || dw == 0x002248 || dw == 0x0025AE || dw == 0x0050F2 || // microsoft + dw == 0x001C42 || // parallels + dw == 0x0021F6) // virtual iron + return; + + AddBlock(p, size, BLOCK_MAC); +} + +void HardwareID::GetMacAddresses() +{ +#ifdef __APPLE__ + ifaddrs *addrs; + if (getifaddrs(&addrs) == 0) { + uint32_t block_count_no_mac = block_count_; + const uint8_t *mac = NULL; + size_t size = 0; + for (ifaddrs *cur_addr = addrs; cur_addr != 0; cur_addr = cur_addr->ifa_next) { + if (cur_addr->ifa_addr->sa_family != AF_LINK) + continue; + + const sockaddr_dl *dl_addr = reinterpret_cast<const sockaddr_dl *>(cur_addr->ifa_addr); + if (dl_addr->sdl_type == IFT_ETHER) { + mac = reinterpret_cast<const uint8_t *>(&dl_addr->sdl_data[dl_addr->sdl_nlen]); + size = dl_addr->sdl_alen; + ProcessMAC(mac, size); + } + } + if (block_count_no_mac == block_count_ && mac && size) + AddBlock(mac, size, BLOCK_MAC); + freeifaddrs(addrs); + } +#elif defined(__unix__) + std::string dir_name("/sys/class/net/"); + if (DIR *dir = opendir(dir_name.c_str())) { + uint32_t block_count_no_mac = block_count_; + uint8_t mac[6]; + size_t size = 0; + while (struct dirent *entry = readdir(dir)) { + // skip "." and ".." + if (entry->d_name[0] == '.') { + if (entry->d_name[1] == 0 || (entry->d_name[1] == '.' && entry->d_name[2] == 0)) + continue; + } + + struct stat st; + if (fstatat(dirfd(dir), entry->d_name, &st, 0) >= 0 && S_ISDIR(st.st_mode)) { + std::string file_name = dir_name + entry->d_name + "/address"; + if (FILE *faddr = fopen(file_name.c_str(), "r")) { + char addr[18] = {0}; + if (fgets(addr, sizeof(addr) - 1, faddr)) { + uint8_t m[6]; + size_t c = sscanf_s(addr, "%02hx:%02hx:%02hx:%02hx:%02hx:%02hx", + m+0, m+1, m+2, m+3, m+4, m+5); + if (c == 6 && m[0]+m[1]+m[2]+m[3]+m[4]+m[5] != 0) { + memcpy(mac, m, sizeof(mac)); + size = c; + ProcessMAC(mac, size); + } + } + fclose(faddr); + } + } + } + closedir(dir); + if (block_count_no_mac == block_count_ && size) + AddBlock(mac, size, BLOCK_MAC); + } +#elif defined(WIN_DRIVER) + UNICODE_STRING unicode_string; + OBJECT_ATTRIBUTES object_attributes; + NTSTATUS status; + HANDLE key_handle, file_handle, event_handle; + IO_STATUS_BLOCK status_block; + ULONG code = OID_802_3_CURRENT_ADDRESS; + uint8_t mac[6]; + size_t size = 0; + + InitializeObjectAttributes(&object_attributes, NULL, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); + status = ZwCreateEvent(&event_handle, EVENT_ALL_ACCESS, &object_attributes, NotificationEvent, FALSE); + if (!NT_SUCCESS(status)) + return; + + RtlInitUnicodeString(&unicode_string, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Adapters"); + InitializeObjectAttributes(&object_attributes, &unicode_string, OBJ_CASE_INSENSITIVE, NULL, NULL); + status = ZwOpenKey(&key_handle, GENERIC_READ, &object_attributes); + if (NT_SUCCESS(status)) { + uint32_t block_count_no_mac = block_count_; + ULONG sub_key_size = sizeof(KEY_BASIC_INFORMATION) + sizeof(wchar_t) * MAX_PATH; + KEY_BASIC_INFORMATION *sub_key_value = static_cast<KEY_BASIC_INFORMATION *>(ExAllocatePool(PagedPool, sub_key_size)); + wchar_t *service_name = static_cast<wchar_t *>(ExAllocatePool(PagedPool, sizeof(wchar_t) * MAX_PATH)); + + ULONG ret_size; + for (ULONG i = 0; NT_SUCCESS(ZwEnumerateKey(key_handle, i, KeyBasicInformation, sub_key_value, sub_key_size, &ret_size)); i++) { + if (sub_key_value->NameLength > (MAX_PATH - 10) * sizeof(wchar_t)) + continue; + + if (sub_key_value->NameLength == 18 && _wcsnicmp(sub_key_value->Name, L"NdisWanIp", 9) == 0) + continue; + + RtlZeroMemory(service_name, sizeof(wchar_t) * MAX_PATH); +#if WDK_NTDDI_VERSION > NTDDI_WIN7 + wcscat_s(service_name, MAX_PATH, L"\\??\\"); +#else + wcscat(service_name, L"\\??\\"); +#endif + RtlCopyMemory(service_name + wcslen(service_name), sub_key_value->Name, sub_key_value->NameLength); + RtlInitUnicodeString(&unicode_string, service_name); + InitializeObjectAttributes(&object_attributes, &unicode_string, OBJ_CASE_INSENSITIVE, NULL, NULL); + + status = ZwOpenFile(&file_handle, 0, &object_attributes, &status_block, FILE_SHARE_READ | FILE_SHARE_WRITE, 0); + if (NT_SUCCESS(status)) { + status = ZwDeviceIoControlFile(file_handle, event_handle, 0, 0, &status_block, IOCTL_NDIS_QUERY_GLOBAL_STATS, &code, sizeof(code), mac, sizeof(mac)); + if (status == STATUS_PENDING) + status = ZwWaitForSingleObject(event_handle, FALSE, NULL); + if (NT_SUCCESS(status)) { + size = sizeof(mac); + ProcessMAC(mac, size); + } + ZwClose(file_handle); + } + } + ExFreePool(service_name); + ExFreePool(sub_key_value); + ZwClose(key_handle); + + if (block_count_no_mac == block_count_ && size) + AddBlock(mac, size, BLOCK_MAC); + } + ZwClose(event_handle); + +#else + HMODULE dll = LoadLibraryA(VMProtectDecryptStringA("iphlpapi.dll")); + if (!dll) + return; + + typedef ULONG (WINAPI *GET_ADAPTERS_INFO) (PIP_ADAPTER_INFO AdapterInfo, PULONG SizePointer); + GET_ADAPTERS_INFO get_adapters_info = reinterpret_cast<GET_ADAPTERS_INFO>(InternalGetProcAddress(dll, VMProtectDecryptStringA("GetAdaptersInfo"))); + + if (get_adapters_info) { + ULONG buf_len = 0; + if (ERROR_BUFFER_OVERFLOW == get_adapters_info(NULL, &buf_len)) { + uint32_t block_count_no_mac = block_count_; + const uint8_t *mac = NULL; + size_t size = 0; + uint8_t *info = new uint8_t[buf_len]; + if (ERROR_SUCCESS == get_adapters_info(reinterpret_cast<IP_ADAPTER_INFO *>(info), &buf_len)) { + for (IP_ADAPTER_INFO *adapter_info = reinterpret_cast<IP_ADAPTER_INFO *>(info); adapter_info != 0; adapter_info = adapter_info->Next) { + mac = adapter_info->Address; + size = adapter_info->AddressLength; + ProcessMAC(mac, size); + } + } + if (block_count_no_mac == block_count_ && mac && size) + AddBlock(mac, size, BLOCK_MAC); + delete [] info; + } + } + FreeLibrary(dll); +#endif +} + +void HardwareID::GetHDD() +{ +#ifdef __APPLE__ + DASessionRef session = DASessionCreate(NULL); + if (session) { + struct statfs statFS; + statfs ("/", &statFS); + DADiskRef disk = DADiskCreateFromBSDName(NULL, session, statFS.f_mntfromname); + if (disk) { + CFDictionaryRef descDict = DADiskCopyDescription(disk); + if (descDict) { + CFUUIDRef value = (CFUUIDRef)CFDictionaryGetValue(descDict, CFSTR("DAVolumeUUID")); + CFUUIDBytes bytes = CFUUIDGetUUIDBytes(value); + AddBlock(&bytes, sizeof(bytes), BLOCK_HDD); + CFRelease(descDict); + } + CFRelease(disk); + } + CFRelease(session); + } +#elif defined(__unix__) + std::string root_uuid; + if (FILE *mtab = setmntent("/etc/mtab", "r")) { + std::string root_fs_path; + while (struct mntent *entry = getmntent(mtab)) { + if (entry->mnt_dir[0] == '/' && entry->mnt_dir[1] == 0) { + root_fs_path = entry->mnt_fsname; + break; + } + } + endmntent(mtab); + + if (!root_fs_path.empty()) { + std::string dir_name("/dev/disk/by-uuid/"); + if (DIR *dir = opendir(dir_name.c_str())) { + while (struct dirent *entry = readdir(dir)) { + // skip "." and ".." + if (entry->d_name[0] == '.') { + if (entry->d_name[1] == 0 || (entry->d_name[1] == '.' && entry->d_name[2] == 0)) + continue; + } + + char resolved_link_path[PATH_MAX]; + std::string path = dir_name + entry->d_name; + if (realpath(path.c_str(), resolved_link_path)) { + if (strcmp(resolved_link_path, root_fs_path.c_str()) == 0) { + root_uuid = entry->d_name; + break; + } + } + } + closedir(dir); + } + } + } + if (!root_uuid.empty()) + AddBlock(root_uuid.c_str(), root_uuid.size(), BLOCK_HDD); +#elif defined(WIN_DRIVER) + wchar_t buf[MAX_PATH]; + size_t size = _countof(buf); + UNICODE_STRING unicode_string; + OBJECT_ATTRIBUTES object_attributes; + NTSTATUS status; + HANDLE handle; + IO_STATUS_BLOCK status_block; + + if (!GetRegValue(L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion", L"SystemRoot", buf, &size)) + return; + + if (buf[1] == ':' && buf[2] == '\\') { + wchar_t system_drive[] = {'\\', 'D', 'o', 's', 'D', 'e', 'v', 'i', 'c', 'e', 's', '\\', buf[0], ':', '\\', 0}; + + RtlInitUnicodeString(&unicode_string, system_drive); + InitializeObjectAttributes(&object_attributes, &unicode_string, OBJ_CASE_INSENSITIVE, NULL, NULL); + status = ZwCreateFile(&handle, SYNCHRONIZE | FILE_READ_ACCESS, + &object_attributes, + &status_block, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + if (NT_SUCCESS(status)) { + RtlInitUnicodeString(&unicode_string, L"ZwQueryVolumeInformationFile"); + typedef NTSTATUS (NTAPI *QUERY_VOLUME_INFORMATION_FILE) (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FS_INFORMATION_CLASS); + QUERY_VOLUME_INFORMATION_FILE query_volume_information_file = reinterpret_cast<QUERY_VOLUME_INFORMATION_FILE>(MmGetSystemRoutineAddress(&unicode_string)); + if (query_volume_information_file) { + ULONG size = sizeof(FILE_FS_VOLUME_INFORMATION) + MAX_PATH * sizeof(WCHAR); + FILE_FS_VOLUME_INFORMATION *information = reinterpret_cast<FILE_FS_VOLUME_INFORMATION*>(new uint8_t[size]); + status = query_volume_information_file(handle, &status_block, information, size, FileFsVolumeInformation); + if (NT_SUCCESS(status)) + AddBlock(&information->VolumeSerialNumber, sizeof(information->VolumeSerialNumber), BLOCK_HDD); + delete [] information; + } + ZwClose(handle); + } + } +#else + HMODULE dll = LoadLibraryA(VMProtectDecryptStringA("kernel32.dll")); + if (!dll) + return; + + typedef ULONG (WINAPI *GET_WINDOWS_DIRECTORY) (wchar_t *, DWORD); + GET_WINDOWS_DIRECTORY get_windows_directory = reinterpret_cast<GET_WINDOWS_DIRECTORY>(InternalGetProcAddress(dll, VMProtectDecryptStringA("GetWindowsDirectoryW"))); + typedef BOOL (WINAPI *GET_VOLUME_INFORMATION) (const wchar_t *, wchar_t *, DWORD, DWORD *, DWORD *, DWORD *, wchar_t *, DWORD); + GET_VOLUME_INFORMATION get_volume_information = reinterpret_cast<GET_VOLUME_INFORMATION>(InternalGetProcAddress(dll, VMProtectDecryptStringA("GetVolumeInformationW"))); + + if (get_windows_directory && get_volume_information) { + wchar_t buf[MAX_PATH] = {0}; + UINT ures = get_windows_directory(buf, _countof(buf)); + if (ures > 0 && buf[1] == ':' && buf[2] == '\\') { + buf[3] = 0; + DWORD volumeSerialNumber = 0; + if (get_volume_information(buf, NULL, 0, &volumeSerialNumber, NULL, NULL, NULL, 0)) { + AddBlock(&volumeSerialNumber, sizeof(volumeSerialNumber), BLOCK_HDD); + } + } + } + FreeLibrary(dll); +#endif +} + +size_t HardwareID::Copy(void *dest, size_t size) const +{ + uint32_t *p = reinterpret_cast<uint32_t *>(dest); + // need skip old methods + size_t res = std::min(static_cast<size_t>(block_count_ - start_block_), size / sizeof(uint32_t)); + for (size_t i = 0; i < res; i++) { + p[i] = blocks_->GetDWord((start_block_ + i) * sizeof(uint32_t)); + } + return res * sizeof(uint32_t); +} + +/* + Rules: + 1. if pointer to buffer is NULL, second parameter is ignored and returned size of buffer that will fit HWID (with trailing 0) + 2. if buffer is ok and the second parameters is zero, we should return zero and doesn't change the buffer + 3. if buffer is OK and the second parameter is less than we need, we should return as much bytes as we can and return the second parameter itself + and we should put 0 to the last available position at buffer + 4. if buffer is bigger that we need, we should put HWID, trailing 0 and return strlen(hwid) + 1 +*/ + +int HardwareID::GetCurrent(char *buffer, int size) +{ + if (buffer && size == 0) + return 0; // see rule #2 + + uint8_t b[MAX_BLOCKS *sizeof(uint32_t)]; + size_t hwid_size = Copy(b, sizeof(b)); + size_t need_size = Base64EncodeGetRequiredLength(hwid_size); + char *p = new char[need_size + 1]; + Base64Encode(b, hwid_size, p, need_size); // it never should return false + + size_t copy = 0; + if (buffer) { + // if nSize is less, we have to leave space for trailing zero (see rule #3) + // if nNeedSize is less, we already have this space, as we allocated nNeedSize + 1 bytes + copy = std::min(static_cast<size_t>(size - 1), need_size); + for (size_t i = 0; i < copy; i++) { + buffer[i] = p[i]; + } + buffer[copy++] = 0; + } + else { + // see rule #1 + copy = need_size + 1; + } + + delete [] p; + return static_cast<int>(copy); +} + +bool HardwareID::IsCorrect(uint8_t *p, size_t size) const +{ + if (p == 0 || size == 0 || (size & 3)) + return false; + + bool equals[4]; + bool found[4]; + for (size_t i = 0; i < 4; i++) { + equals[i] = false; + found[i] = false; + } + + size_t blocks = size / sizeof(uint32_t); + uint32_t *d = reinterpret_cast<uint32_t *>(p); + for (size_t j = 0; j < block_count_; j++) { + uint32_t id1 = blocks_->GetDWord(j * sizeof(uint32_t)); + found[id1 & 3] = true; + for (size_t i = 0; i < blocks; i++) { + uint32_t id2 = d[i]; + if (id1 == id2) { + equals[id1 & 3] = true; + break; + } + } + } + + // check CPU + if (!equals[0]) + return false; + + // check if at least 3 items are OK + size_t n = 0; + size_t c = 0; + for (size_t i = 0; i < 4; i++) { + if (found[i]) + c++; + if (equals[i]) + n++; + } + return (n == c || n >= 3); +} + +bool HardwareID::IsCorrect(CryptoContainer &cont, size_t offset, size_t size) const +{ + if (size == 0 || (size & 3) || size > MAX_BLOCKS * sizeof(uint32_t)) + return false; + + uint32_t buff[MAX_BLOCKS]; + for (size_t i = 0; i < size / sizeof(uint32_t); i++) { + buff[i] = cont.GetDWord(offset + i * sizeof(uint32_t)); + } + return IsCorrect(reinterpret_cast<uint8_t *>(buff), size); +}
\ No newline at end of file |