mirror of
https://github.com/Alukym/VMProtect-Source.git
synced 2025-06-11 06:07:57 -05:00
Initial commit
This commit is contained in:
688
runtime/hwid.cc
Normal file
688
runtime/hwid.cc
Normal file
@ -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);
|
||||
}
|
Reference in New Issue
Block a user