├── LICENSE ├── README.md └── main.cpp /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 0vm 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simple HWID Checker 2 | 3 | The HWID Checker is an easy to use but not so simple hardware identification tool that collects detailed system information using low-level direct hardware access methods. It provides hardware identifiers that are difficult to spoof or modify, making it suitable for secure hardware identification. 4 | 5 | ## Code Overview 6 | 7 | This application is written in C++ and uses direct hardware access methods, as well as Windows APIs, to fetch system-specific data that is difficult to spoof. 8 | 9 | **Key Functions:** 10 | 11 | - **Hardware Identifiers:** 12 | - `GetCPUInfo()`: Retrieves detailed CPU information using direct CPUID instruction 13 | - `GetMotherboardInfo()`: Extracts motherboard data from SMBIOS tables 14 | - `GetDiskInfo()`: Accesses physical disk properties using DeviceIoControl 15 | - `GetGPUInfo()`: Enumerates graphics hardware through DirectX interfaces 16 | - `GetMonitorInfo()`: Retrieves EDID data directly from display devices 17 | - `GetNetworkInfo()`: Collects network adapter information via low-level API calls 18 | - `GetMACHardwareID()`: Generates unique identifier based on MAC addresses 19 | - `GetBIOSInfo()`: Extracts BIOS data through direct memory access 20 | - `GetTPMInfo()`: Communicates with the Trusted Platform Module for secure identifiers 21 | - `GetRAMInfo()`: Retrieves memory configuration and hardware details 22 | 23 | - **Software Identifiers:** 24 | - `GetOSInfo()`: Gathers detailed OS version information using RtlGetVersion 25 | - `GetUserInfo()`: Retrieves current user and computer name 26 | - `GetVolumeInfo()`: Extracts storage volume details and serial numbers 27 | - `GetWindowsProductID()`: Accesses Windows licensing information 28 | - `GetInstallationTime()`: Determines Windows installation timestamp 29 | 30 | - **Processing & Generation:** 31 | - `HashString()`: Creates cryptographic hashes of hardware identifiers 32 | - `GenerateHardwareHWID()`: Combines hardware identifiers into a unified fingerprint 33 | - `GenerateSoftwareHWID()`: Creates a software environment fingerprint 34 | - `GetSystemUUID()`: Retrieves the system's unique universal identifier 35 | - `GetAllHardwareIDs()`: Collects all hardware identifiers in one call 36 | - `GetAllSoftwareIDs()`: Retrieves all software environment identifiers 37 | - `ConvertToHexString()`: Formats binary data into readable hexadecimal 38 | - `FormatIdentifier()`: Standardises identifier formatting 39 | 40 | 41 | ## Direct Hardware Access Methods 42 | 43 | This tool uses **low-level Windows APIs and direct hardware access methods** to retrieve hardware identifiers that are difficult to spoof: 44 | 45 | - Native Windows API calls 46 | - Direct device I/O control codes 47 | - Low-level CPUID instruction access 48 | - DirectX interfaces for GPU enumeration 49 | - SetupAPI for detailed device enumeration 50 | - Raw SMBIOS/EDID data parsing 51 | - Direct TPM (Trusted Platform Module) access 52 | - BCrypt cryptographic operations 53 | 54 | ## Features 55 | 56 | - **Hardware Identifiers** (using low-level direct access): 57 | - CPU information (brand string, ID, signature, features) 58 | - Motherboard details (manufacturer, model, serial number) 59 | - Disk drive information (model, serial number, interface) 60 | - Network adapter MAC addresses 61 | - GPU details (vendor ID, device ID, memory) 62 | - Monitor information (EDID data, manufacturer, serial) 63 | - TPM (Trusted Platform Module) data 64 | 65 | - **Software Identifiers**: 66 | - Volume serial numbers 67 | - Windows product ID 68 | - Computer name 69 | - User account SID 70 | - Installation date 71 | 72 | - **Generated IDs**: 73 | - Individual component IDs (both raw and hashed) 74 | - Combined hardware identifier (spoof-resistant) 75 | - Combined software identifier 76 | - Complete system HWID 77 | 78 | - **WMIC-Based Identifiers** (included for comparison only): 79 | - Various hardware information retrieved via WMIC 80 | - Clearly marked as unreliable and not recommended for secure identification 81 | 82 | ## Warning About WMIC-Based Identifiers 83 | 84 | > ⚠️ **WARNING**: WMIC-based identifiers can be easily altered or spoofed and should not be considered trustworthy for secure identification purposes. The tool clearly marks these as unreliable. 85 | 86 | While this tool primarily uses secure direct hardware access methods, it also includes WMIC-based identifiers for educational and comparison purposes. These are explicitly marked as unreliable in the program output. 87 | 88 | ## Dependencies 89 | 90 | This project relies on the following libraries: 91 | 92 | - Windows API (`Windows.h`) 93 | - IP Helper API (`Iphlpapi.h`) 94 | - Intel Intrinsics (`intrin.h`) 95 | - COM Definitions (`comdef.h`) 96 | - WMI Interface (`Wbemidl.h`) 97 | - Setup API (`SetupAPI.h`) 98 | - Device GUID (`devguid.h`) 99 | - DirectX Graphics Infrastructure (`dxgi.h`, `dxgi1_6.h`, `d3d11.h`) 100 | - Storage Device Interface (`ntddscsi.h`, `winioctl.h`) 101 | - ATL Base (`atlbase.h`) 102 | - Shell API (`shlwapi.h`) 103 | - Cryptography API (`Wincrypt.h`, `bcrypt.h`, `ncrypt.h`) 104 | - Terminal Services (`Wtsapi32.h`) 105 | - Security Descriptor (`sddl.h`) 106 | - Windows NT API (`winternl.h`) 107 | 108 | Required libraries to link: 109 | ``` 110 | #pragma comment(lib, "iphlpapi.lib") 111 | #pragma comment(lib, "wbemuuid.lib") 112 | #pragma comment(lib, "dxgi.lib") 113 | #pragma comment(lib, "d3d11.lib") 114 | #pragma comment(lib, "setupapi.lib") 115 | #pragma comment(lib, "advapi32.lib") 116 | #pragma comment(lib, "crypt32.lib") 117 | #pragma comment(lib, "shlwapi.lib") 118 | #pragma comment(lib, "tbs.lib") 119 | #pragma comment(lib, "bcrypt.lib") 120 | #pragma comment(lib, "ncrypt.lib") 121 | ``` 122 | 123 | ## License 124 | 125 | This project is licensed under the [MIT License](LICENSE). 126 | 127 | ### Tags 128 | HWID Checker, HWID Grabber, Hardware ID Authentication 129 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | // Define TPM-related structures and functions if not already defined 32 | #ifndef TBS_SUCCESS 33 | #define TBS_SUCCESS 0 34 | typedef UINT32 TBS_RESULT; 35 | typedef UINT32 TBS_HCONTEXT; 36 | typedef struct TBS_CONTEXT_PARAMS { 37 | UINT32 version; 38 | BOOL asynchronous; 39 | } TBS_CONTEXT_PARAMS; 40 | #define TBS_CONTEXT_VERSION_ONE 1 41 | #define TBS_CONTEXT_VERSION_TWO 2 42 | 43 | // TPM Base Service function prototypes 44 | extern "C" { 45 | __declspec(dllimport) TBS_RESULT __stdcall Tbsi_Context_Create( 46 | _In_ const TBS_CONTEXT_PARAMS* pContextParams, 47 | _Out_ TBS_HCONTEXT* phContext 48 | ); 49 | 50 | __declspec(dllimport) TBS_RESULT __stdcall Tbsi_Context_Close( 51 | _In_ TBS_HCONTEXT hContext 52 | ); 53 | 54 | __declspec(dllimport) TBS_RESULT __stdcall Tbsi_GetDeviceInfo( 55 | _In_ UINT32 Size, 56 | _Out_ PVOID Information 57 | ); 58 | 59 | __declspec(dllimport) TBS_RESULT __stdcall Tbsi_GetRandom( 60 | _In_ TBS_HCONTEXT hContext, 61 | _Out_ BYTE* pRgbRandom, 62 | _In_ UINT32 cbRandom 63 | ); 64 | 65 | __declspec(dllimport) TBS_RESULT __stdcall Tbsi_GetTpmProperty( 66 | _In_ TBS_HCONTEXT hContext, 67 | _In_ UINT32 PropertyId, 68 | _In_ UINT32 PropertySubId, 69 | _In_ UINT32 Size, 70 | _Out_ PBYTE PropertyValue 71 | ); 72 | } 73 | #endif 74 | 75 | // TPM-related definitions 76 | #define TPM_AVAILABLE 77 | #define TPM_BASE 0x0 78 | #define TPM_RESULT_COUNT 0x8 79 | #define TPM_ORD_GetRandom 0x46 80 | 81 | #pragma comment(lib, "iphlpapi.lib") 82 | #pragma comment(lib, "wbemuuid.lib") 83 | #pragma comment(lib, "dxgi.lib") 84 | #pragma comment(lib, "d3d11.lib") 85 | #pragma comment(lib, "setupapi.lib") 86 | #pragma comment(lib, "advapi32.lib") 87 | #pragma comment(lib, "crypt32.lib") 88 | #pragma comment(lib, "shlwapi.lib") 89 | #pragma comment(lib, "tbs.lib") 90 | #pragma comment(lib, "bcrypt.lib") 91 | #pragma comment(lib, "ncrypt.lib") 92 | 93 | // SMBIOS table access definitions 94 | #define SMBIOS_HARDWARE_SECURITY 0x25 95 | #define SMBIOS_SYSTEM_INFORMATION 0x1 96 | #define SMBIOS_BIOS_INFORMATION 0x0 97 | 98 | // IOCTL codes for disk operations 99 | #ifndef IOCTL_STORAGE_QUERY_PROPERTY 100 | #define IOCTL_STORAGE_QUERY_PROPERTY 0x2d1400 101 | #endif 102 | 103 | enum class IdType { 104 | HARDWARE, // Physical hardware identifiers that typically won't change 105 | SOFTWARE // Software-based identifiers that can change with reinstalls/resets 106 | }; 107 | 108 | class HWIDGrabber { 109 | private: 110 | std::string GetStringFromBytes(const std::vector& bytes) { 111 | std::stringstream ss; 112 | for (size_t i = 0; i < bytes.size(); i++) { 113 | ss << std::hex << std::setw(2) << std::setfill('0') << static_cast(bytes[i]); 114 | if (i < bytes.size() - 1) ss << "-"; 115 | } 116 | return ss.str(); 117 | } 118 | 119 | std::string GetWMIProperty(IWbemClassObject* obj, const wchar_t* property) { 120 | VARIANT vtProp; 121 | HRESULT hr = obj->Get(property, 0, &vtProp, 0, 0); 122 | std::string result; 123 | 124 | if (SUCCEEDED(hr)) { 125 | if (vtProp.vt == VT_BSTR && vtProp.bstrVal != nullptr) { 126 | _bstr_t bstr_t(vtProp.bstrVal, false); 127 | result = static_cast(bstr_t); 128 | } 129 | VariantClear(&vtProp); 130 | } 131 | 132 | return result; 133 | } 134 | 135 | template 136 | void SafeRelease(T** ppT) { 137 | if (*ppT) { 138 | (*ppT)->Release(); 139 | *ppT = nullptr; 140 | } 141 | } 142 | 143 | // More secure hashing using BCrypt (modern Windows crypto API) 144 | std::string BCryptHashString(const std::string& input) { 145 | BCRYPT_ALG_HANDLE hAlg = NULL; 146 | BCRYPT_HASH_HANDLE hHash = NULL; 147 | NTSTATUS status = 0; 148 | DWORD cbData = 0, cbHash = 0, cbHashObject = 0; 149 | PBYTE pbHashObject = NULL; 150 | PBYTE pbHash = NULL; 151 | std::string hashStr = ""; 152 | std::stringstream ss; 153 | 154 | // Open algorithm provider 155 | status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA256_ALGORITHM, NULL, 0); 156 | if (!BCRYPT_SUCCESS(status)) { 157 | goto Cleanup; 158 | } 159 | 160 | // Get hash object size 161 | status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbHashObject, sizeof(DWORD), &cbData, 0); 162 | if (!BCRYPT_SUCCESS(status)) { 163 | goto Cleanup; 164 | } 165 | 166 | pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHashObject); 167 | if (NULL == pbHashObject) { 168 | goto Cleanup; 169 | } 170 | 171 | // Get hash length 172 | status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PBYTE)&cbHash, sizeof(DWORD), &cbData, 0); 173 | if (!BCRYPT_SUCCESS(status)) { 174 | goto Cleanup; 175 | } 176 | 177 | pbHash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHash); 178 | if (NULL == pbHash) { 179 | goto Cleanup; 180 | } 181 | 182 | // Create hash 183 | status = BCryptCreateHash(hAlg, &hHash, pbHashObject, cbHashObject, NULL, 0, 0); 184 | if (!BCRYPT_SUCCESS(status)) { 185 | goto Cleanup; 186 | } 187 | 188 | // Hash data 189 | status = BCryptHashData(hHash, (PUCHAR)input.c_str(), static_cast(input.length()), 0); 190 | if (!BCRYPT_SUCCESS(status)) { 191 | goto Cleanup; 192 | } 193 | 194 | // Finalize hash 195 | status = BCryptFinishHash(hHash, pbHash, cbHash, 0); 196 | if (!BCRYPT_SUCCESS(status)) { 197 | goto Cleanup; 198 | } 199 | 200 | // Format hash as hex string 201 | for (DWORD i = 0; i < cbHash; i++) { 202 | ss << std::hex << std::setw(2) << std::setfill('0') << (int)pbHash[i]; 203 | } 204 | hashStr = ss.str(); 205 | 206 | Cleanup: 207 | if (hHash) BCryptDestroyHash(hHash); 208 | if (hAlg) BCryptCloseAlgorithmProvider(hAlg, 0); 209 | if (pbHashObject) HeapFree(GetProcessHeap(), 0, pbHashObject); 210 | if (pbHash) HeapFree(GetProcessHeap(), 0, pbHash); 211 | 212 | return hashStr; 213 | } 214 | 215 | // Get SMBIOS information directly for more reliable hardware identification 216 | std::string GetSMBIOSData() { 217 | DWORD smbiosDataSize = 0; 218 | std::vector smbiosData; 219 | std::stringstream result; 220 | 221 | // Get size of SMBIOS data 222 | DWORD smbiosSize = GetSystemFirmwareTable('RSMB', 0, NULL, 0); 223 | if (smbiosSize > 0) { 224 | smbiosData.resize(smbiosSize); 225 | DWORD bytesRead = GetSystemFirmwareTable('RSMB', 0, smbiosData.data(), smbiosSize); 226 | 227 | if (bytesRead > 0) { 228 | // Raw SMBIOS data fingerprint - harder to spoof than WMI 229 | result << "SMBIOS Data Signature: " << GetStringFromBytes(std::vector(smbiosData.begin(), smbiosData.begin() + 16)) << std::endl; 230 | 231 | // Extract SMBIOS version 232 | if (smbiosData.size() > 0x08) { 233 | result << "SMBIOS Version: " 234 | << static_cast(smbiosData[0x06]) << "." 235 | << static_cast(smbiosData[0x07]) << std::endl; 236 | } 237 | 238 | // Process structures after header 239 | BYTE* ptr = smbiosData.data() + 8; // Skip header 240 | BYTE* endPtr = smbiosData.data() + smbiosSize; 241 | 242 | while (ptr < endPtr) { 243 | BYTE type = *ptr; 244 | BYTE length = *(ptr + 1); 245 | 246 | if (type == 0 && length < 4) break; // End of table 247 | 248 | if (type == SMBIOS_SYSTEM_INFORMATION && length >= 8) { 249 | result << "System Manufacturer: " << (const char*)(ptr + 4) << std::endl; 250 | result << "System Product: " << (const char*)(ptr + 5) << std::endl; 251 | result << "System Serial: " << (const char*)(ptr + 7) << std::endl; 252 | } 253 | 254 | // Find the string area ending (double NUL) 255 | BYTE* strPtr = ptr + length; 256 | while (strPtr < endPtr && !(*strPtr == 0 && *(strPtr + 1) == 0)) { 257 | strPtr++; 258 | } 259 | 260 | // Move to the next structure 261 | ptr = strPtr + 2; 262 | } 263 | } 264 | } 265 | 266 | return result.str(); 267 | } 268 | 269 | // Get TPM identifier if available - extremely difficult to spoof 270 | std::string GetTPMInfo() { 271 | std::stringstream result; 272 | TBS_CONTEXT_PARAMS contextParams; 273 | TBS_HCONTEXT hContext = 0; 274 | UINT32 tpmVersion = 0; 275 | 276 | // Initialize the context parameters for TPM 2.0 277 | contextParams.version = TBS_CONTEXT_VERSION_TWO; 278 | contextParams.asynchronous = FALSE; 279 | 280 | // Attempt to create a context with the TPM Base Services 281 | HRESULT hr = Tbsi_Context_Create(&contextParams, &hContext); 282 | if (SUCCEEDED(hr)) { 283 | // Get TPM version 284 | hr = Tbsi_GetDeviceInfo(sizeof(UINT32), &tpmVersion); 285 | if (SUCCEEDED(hr)) { 286 | result << "TPM Version: " << (tpmVersion == 1 ? "1.2" : "2.0") << std::endl; 287 | 288 | // Get TPM properties (2.0 specific) 289 | if (tpmVersion == 2) { 290 | UINT32 tpmProps[2] = { 0 }; // Manufacturer and version info 291 | UINT32 propSize = sizeof(tpmProps); 292 | 293 | hr = Tbsi_GetTpmProperty(hContext, 1, TPM_BASE, propSize, (PBYTE)tpmProps); 294 | if (SUCCEEDED(hr)) { 295 | result << "TPM Manufacturer: 0x" << std::hex << tpmProps[0] << std::endl; 296 | result << "TPM Version: 0x" << std::hex << tpmProps[1] << std::endl; 297 | } 298 | } 299 | 300 | // Get a random value from the TPM as a unique identifier that's hardware-bound 301 | BYTE randomBytes[32] = { 0 }; 302 | hr = Tbsi_GetRandom(hContext, randomBytes, sizeof(randomBytes)); 303 | if (SUCCEEDED(hr)) { 304 | std::vector randomVec(randomBytes, randomBytes + sizeof(randomBytes)); 305 | result << "TPM Random ID: " << GetStringFromBytes(randomVec) << std::endl; 306 | } 307 | } 308 | 309 | // Close TPM context 310 | Tbsi_Context_Close(hContext); 311 | } 312 | else { 313 | result << "TPM not available or accessible" << std::endl; 314 | } 315 | 316 | return result.str(); 317 | } 318 | 319 | std::string ExecuteWMICCommand(const std::string& command) { 320 | std::string result; 321 | char buffer[128]; 322 | std::string cmd = "wmic " + command + " 2>&1"; 323 | 324 | FILE* pipe = _popen(cmd.c_str(), "r"); 325 | if (!pipe) { 326 | return "Error executing WMIC command"; 327 | } 328 | 329 | while (!feof(pipe)) { 330 | if (fgets(buffer, sizeof(buffer), pipe) != nullptr) { 331 | result += buffer; 332 | } 333 | } 334 | 335 | _pclose(pipe); 336 | return result; 337 | } 338 | 339 | public: 340 | std::string HashString(const std::string& input) { 341 | return BCryptHashString(input); 342 | } 343 | 344 | // Get CPU Information with low-level access (HARDWARE) 345 | std::string GetCPUInfo() { 346 | int cpuInfo[4] = { 0 }; 347 | std::array brandString = { 0 }; 348 | 349 | __cpuid(cpuInfo, 0x80000002); 350 | memcpy(brandString.data(), cpuInfo, sizeof(cpuInfo)); 351 | 352 | __cpuid(cpuInfo, 0x80000003); 353 | memcpy(brandString.data() + 16, cpuInfo, sizeof(cpuInfo)); 354 | 355 | __cpuid(cpuInfo, 0x80000004); 356 | memcpy(brandString.data() + 32, cpuInfo, sizeof(cpuInfo)); 357 | 358 | __cpuid(cpuInfo, 1); 359 | DWORD cpuId = cpuInfo[0]; 360 | 361 | __cpuid(cpuInfo, 1); 362 | DWORD signatureEax = cpuInfo[0]; // Contains stepping, model, family 363 | DWORD featureFlags = cpuInfo[3]; // EDX features 364 | 365 | // Get CPU microcode version (more specific info) 366 | unsigned int microcode = 0; 367 | 368 | // Get CPU thermal and power info (harder to spoof) 369 | __cpuid(cpuInfo, 0x6); 370 | DWORD thermalInfo = cpuInfo[0]; 371 | 372 | // Read CPU extended features 373 | __cpuid(cpuInfo, 7); 374 | DWORD extFeatures = cpuInfo[1]; // EBX: Extended Features 375 | 376 | std::stringstream ss; 377 | ss << "CPU: " << brandString.data() << std::endl; 378 | ss << "CPU ID: " << std::hex << std::uppercase << cpuId << std::endl; 379 | ss << "Signature: " << std::hex << std::uppercase << signatureEax << std::endl; 380 | ss << "Features: " << std::hex << std::uppercase << featureFlags << std::endl; 381 | ss << "Microcode: " << std::hex << std::uppercase << microcode << std::endl; 382 | ss << "Thermal Info: " << std::hex << std::uppercase << thermalInfo << std::endl; 383 | ss << "Extended Features: " << std::hex << std::uppercase << extFeatures; 384 | 385 | return ss.str(); 386 | } 387 | 388 | // Get CPU hardware identifier (stabilized version with deeper hardware access) 389 | std::string GetCPUHardwareID() { 390 | int cpuInfo[4] = { 0 }; 391 | std::array brandString = { 0 }; 392 | 393 | __cpuid(cpuInfo, 0x80000002); 394 | memcpy(brandString.data(), cpuInfo, sizeof(cpuInfo)); 395 | 396 | __cpuid(cpuInfo, 0x80000003); 397 | memcpy(brandString.data() + 16, cpuInfo, sizeof(cpuInfo)); 398 | 399 | __cpuid(cpuInfo, 0x80000004); 400 | memcpy(brandString.data() + 32, cpuInfo, sizeof(cpuInfo)); 401 | 402 | // Get detailed processor information - family, model, stepping 403 | __cpuid(cpuInfo, 1); 404 | int family = ((cpuInfo[0] >> 8) & 0xF) + ((cpuInfo[0] >> 20) & 0xFF); // Base + Extended Family 405 | int model = ((cpuInfo[0] >> 4) & 0xF) | ((cpuInfo[0] >> 12) & 0xF0); // Base + Extended Model 406 | int stepping = cpuInfo[0] & 0xF; 407 | DWORD signature = cpuInfo[0]; 408 | 409 | // Additional CPU features that are hardware-specific and difficult to spoof 410 | DWORD features = cpuInfo[3]; // Standard features 411 | 412 | // Extended processor info 413 | __cpuid(cpuInfo, 7); 414 | DWORD extFeatures = cpuInfo[1]; // EBX register contains newer features 415 | 416 | // Format as a stable hardware ID string with extended info 417 | std::stringstream cpuIdStream; 418 | cpuIdStream << std::string(brandString.data()) << "-" 419 | << std::hex << std::uppercase 420 | << family << model << stepping << "-" 421 | << signature << "-" 422 | << features << "-" 423 | << extFeatures; 424 | 425 | return cpuIdStream.str(); 426 | } 427 | 428 | // Motherboard Information (HARDWARE) 429 | std::string GetMotherboardInfo() { 430 | HRESULT hres; 431 | std::string result = "Motherboard Info (HARDWARE):\n"; 432 | 433 | hres = CoInitializeEx(0, COINIT_MULTITHREADED); 434 | if (FAILED(hres)) return "Failed to initialize COM library"; 435 | 436 | IWbemLocator* pLoc = nullptr; 437 | hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc); 438 | if (FAILED(hres)) { 439 | CoUninitialize(); 440 | return "Failed to create IWbemLocator object"; 441 | } 442 | 443 | IWbemServices* pSvc = nullptr; 444 | hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc); 445 | if (FAILED(hres)) { 446 | pLoc->Release(); 447 | CoUninitialize(); 448 | return "Could not connect to WMI server"; 449 | } 450 | 451 | hres = CoSetProxyBlanket( 452 | pSvc, 453 | RPC_C_AUTHN_WINNT, 454 | RPC_C_AUTHZ_NONE, 455 | NULL, 456 | RPC_C_AUTHN_LEVEL_CALL, 457 | RPC_C_IMP_LEVEL_IMPERSONATE, 458 | NULL, 459 | EOAC_NONE 460 | ); 461 | 462 | if (FAILED(hres)) { 463 | pSvc->Release(); 464 | pLoc->Release(); 465 | CoUninitialize(); 466 | return "Could not set proxy blanket"; 467 | } 468 | 469 | IEnumWbemClassObject* pEnumerator = nullptr; 470 | hres = pSvc->ExecQuery( 471 | bstr_t("WQL"), 472 | bstr_t("SELECT * FROM Win32_BaseBoard"), 473 | WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 474 | NULL, 475 | &pEnumerator 476 | ); 477 | 478 | if (FAILED(hres)) { 479 | pSvc->Release(); 480 | pLoc->Release(); 481 | CoUninitialize(); 482 | return "Query for motherboard failed"; 483 | } 484 | 485 | IWbemClassObject* pclsObj = nullptr; 486 | ULONG uReturn = 0; 487 | 488 | while (pEnumerator) { 489 | hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); 490 | if (uReturn == 0) break; 491 | 492 | std::string manufacturer = GetWMIProperty(pclsObj, L"Manufacturer"); 493 | std::string product = GetWMIProperty(pclsObj, L"Product"); 494 | std::string serialNumber = GetWMIProperty(pclsObj, L"SerialNumber"); 495 | 496 | result += " Manufacturer: " + manufacturer + "\n"; 497 | result += " Model: " + product + "\n"; 498 | result += " Serial Number: " + serialNumber + "\n"; 499 | 500 | pclsObj->Release(); 501 | } 502 | 503 | // Get BIOS information 504 | pEnumerator->Release(); 505 | hres = pSvc->ExecQuery( 506 | bstr_t("WQL"), 507 | bstr_t("SELECT * FROM Win32_BIOS"), 508 | WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 509 | NULL, 510 | &pEnumerator 511 | ); 512 | 513 | if (SUCCEEDED(hres)) { 514 | while (pEnumerator) { 515 | hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); 516 | if (uReturn == 0) break; 517 | 518 | std::string biosVersion = GetWMIProperty(pclsObj, L"Version"); 519 | std::string biosSerialNumber = GetWMIProperty(pclsObj, L"SerialNumber"); 520 | std::string manufacturerBIOS = GetWMIProperty(pclsObj, L"Manufacturer"); 521 | 522 | result += "BIOS Info (HARDWARE):\n"; 523 | result += " Manufacturer: " + manufacturerBIOS + "\n"; 524 | result += " Version: " + biosVersion + "\n"; 525 | result += " Serial Number: " + biosSerialNumber + "\n"; 526 | 527 | pclsObj->Release(); 528 | } 529 | } 530 | 531 | pEnumerator->Release(); 532 | pSvc->Release(); 533 | pLoc->Release(); 534 | CoUninitialize(); 535 | 536 | return result; 537 | } 538 | 539 | // Get motherboard hardware ID using direct SMBIOS access 540 | std::string GetMotherboardHardwareID() { 541 | HRESULT hres; 542 | std::string motherboardId = ""; 543 | 544 | // First try using direct SMBIOS access (harder to spoof than WMI) 545 | DWORD smbiosSize = GetSystemFirmwareTable('RSMB', 0, NULL, 0); 546 | if (smbiosSize > 0) { 547 | std::vector smbiosData(smbiosSize); 548 | DWORD bytesRead = GetSystemFirmwareTable('RSMB', 0, smbiosData.data(), smbiosSize); 549 | 550 | if (bytesRead > 0) { 551 | // Process structures to find System Information (Type 1) 552 | BYTE* ptr = smbiosData.data() + 8; // Skip header 553 | BYTE* endPtr = smbiosData.data() + smbiosSize; 554 | std::string manufacturer, product, serialNumber; 555 | 556 | while (ptr < endPtr) { 557 | BYTE type = *ptr; 558 | BYTE length = *(ptr + 1); 559 | 560 | if (type == 0 && length < 4) break; // End of table 561 | 562 | if (type == SMBIOS_SYSTEM_INFORMATION && length >= 8) { 563 | // Extract string pointers 564 | BYTE manufacturerPtr = *(ptr + 4); 565 | BYTE productPtr = *(ptr + 5); 566 | BYTE serialPtr = *(ptr + 7); 567 | 568 | // Find the string table 569 | BYTE* strPtr = ptr + length; 570 | 571 | // Extract strings 572 | std::vector strings; 573 | std::string currentStr; 574 | 575 | while (strPtr < endPtr) { 576 | if (*strPtr == 0) { 577 | strings.push_back(currentStr); 578 | currentStr.clear(); 579 | 580 | // Check for end of string list (double null) 581 | if (*(strPtr + 1) == 0) break; 582 | } 583 | else { 584 | currentStr += *strPtr; 585 | } 586 | strPtr++; 587 | } 588 | 589 | // Assign values from string index 590 | if (manufacturerPtr > 0 && manufacturerPtr <= strings.size()) 591 | manufacturer = strings[manufacturerPtr - 1]; 592 | 593 | if (productPtr > 0 && productPtr <= strings.size()) 594 | product = strings[productPtr - 1]; 595 | 596 | if (serialPtr > 0 && serialPtr <= strings.size()) 597 | serialNumber = strings[serialPtr - 1]; 598 | 599 | // Combine to form a unique ID 600 | motherboardId = manufacturer + "-" + product + "-" + serialNumber; 601 | break; 602 | } 603 | 604 | // Find the next structure 605 | BYTE* strPtr = ptr + length; 606 | while (strPtr < endPtr && !(*strPtr == 0 && *(strPtr + 1) == 0)) { 607 | strPtr++; 608 | } 609 | ptr = strPtr + 2; 610 | } 611 | } 612 | } 613 | 614 | // Fall back to WMI if SMBIOS access didn't yield results 615 | if (motherboardId.empty()) { 616 | hres = CoInitializeEx(0, COINIT_MULTITHREADED); 617 | if (FAILED(hres)) return ""; 618 | 619 | IWbemLocator* pLoc = nullptr; 620 | hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc); 621 | if (FAILED(hres)) { 622 | CoUninitialize(); 623 | return ""; 624 | } 625 | 626 | IWbemServices* pSvc = nullptr; 627 | hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc); 628 | if (FAILED(hres)) { 629 | pLoc->Release(); 630 | CoUninitialize(); 631 | return ""; 632 | } 633 | 634 | hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, 635 | RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE); 636 | 637 | if (FAILED(hres)) { 638 | pSvc->Release(); 639 | pLoc->Release(); 640 | CoUninitialize(); 641 | return ""; 642 | } 643 | 644 | // Query motherboard data 645 | IEnumWbemClassObject* pEnumerator = nullptr; 646 | hres = pSvc->ExecQuery( 647 | bstr_t("WQL"), 648 | bstr_t("SELECT Manufacturer, Product, SerialNumber FROM Win32_BaseBoard"), 649 | WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 650 | NULL, 651 | &pEnumerator 652 | ); 653 | 654 | if (SUCCEEDED(hres)) { 655 | IWbemClassObject* pclsObj = nullptr; 656 | ULONG uReturn = 0; 657 | 658 | if (pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn) == S_OK && uReturn > 0) { 659 | std::string manufacturer = GetWMIProperty(pclsObj, L"Manufacturer"); 660 | std::string product = GetWMIProperty(pclsObj, L"Product"); 661 | std::string serialNumber = GetWMIProperty(pclsObj, L"SerialNumber"); 662 | 663 | // Combine to form a unique ID 664 | motherboardId = manufacturer + "-" + product + "-" + serialNumber; 665 | pclsObj->Release(); 666 | } 667 | 668 | pEnumerator->Release(); 669 | } 670 | 671 | // Cleanup 672 | pSvc->Release(); 673 | pLoc->Release(); 674 | CoUninitialize(); 675 | } 676 | 677 | return motherboardId; 678 | } 679 | 680 | // Hard Disk Information (HARDWARE) 681 | std::string GetDiskInfo() { 682 | std::string result = "Disk Information (HARDWARE):\n"; 683 | 684 | HRESULT hres; 685 | 686 | // Initialize COM 687 | hres = CoInitializeEx(0, COINIT_MULTITHREADED); 688 | if (FAILED(hres)) return "Failed to initialize COM library"; 689 | 690 | // Initialize WMI 691 | IWbemLocator* pLoc = nullptr; 692 | hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc); 693 | if (FAILED(hres)) { 694 | CoUninitialize(); 695 | return "Failed to create IWbemLocator object"; 696 | } 697 | 698 | // Connect to WMI 699 | IWbemServices* pSvc = nullptr; 700 | hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc); 701 | if (FAILED(hres)) { 702 | pLoc->Release(); 703 | CoUninitialize(); 704 | return "Could not connect to WMI server"; 705 | } 706 | 707 | // Set security levels 708 | hres = CoSetProxyBlanket( 709 | pSvc, 710 | RPC_C_AUTHN_WINNT, 711 | RPC_C_AUTHZ_NONE, 712 | NULL, 713 | RPC_C_AUTHN_LEVEL_CALL, 714 | RPC_C_IMP_LEVEL_IMPERSONATE, 715 | NULL, 716 | EOAC_NONE 717 | ); 718 | 719 | if (FAILED(hres)) { 720 | pSvc->Release(); 721 | pLoc->Release(); 722 | CoUninitialize(); 723 | return "Could not set proxy blanket"; 724 | } 725 | 726 | // Query disk drive data 727 | IEnumWbemClassObject* pEnumerator = nullptr; 728 | hres = pSvc->ExecQuery( 729 | bstr_t("WQL"), 730 | bstr_t("SELECT * FROM Win32_DiskDrive"), 731 | WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 732 | NULL, 733 | &pEnumerator 734 | ); 735 | 736 | if (FAILED(hres)) { 737 | pSvc->Release(); 738 | pLoc->Release(); 739 | CoUninitialize(); 740 | return "Query for disk drives failed"; 741 | } 742 | 743 | // Get the data 744 | IWbemClassObject* pclsObj = nullptr; 745 | ULONG uReturn = 0; 746 | int diskIndex = 0; 747 | 748 | while (pEnumerator) { 749 | hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); 750 | if (uReturn == 0) break; 751 | 752 | // Get properties 753 | std::string model = GetWMIProperty(pclsObj, L"Model"); 754 | std::string serialNumber = GetWMIProperty(pclsObj, L"SerialNumber"); 755 | std::string diskInterface = GetWMIProperty(pclsObj, L"InterfaceType"); 756 | std::string sizeStr = GetWMIProperty(pclsObj, L"Size"); 757 | 758 | result += " Disk " + std::to_string(diskIndex++) + ":\n"; 759 | result += " Model: " + model + "\n"; 760 | result += " Serial: " + serialNumber + "\n"; 761 | result += " Interface: " + diskInterface + "\n"; 762 | 763 | if (!sizeStr.empty()) { 764 | uint64_t sizeBytes = std::stoull(sizeStr); 765 | uint64_t sizeGB = sizeBytes / (1024 * 1024 * 1024); 766 | result += " Size: " + std::to_string(sizeGB) + " GB\n"; 767 | } 768 | 769 | pclsObj->Release(); 770 | } 771 | 772 | // Cleanup 773 | pEnumerator->Release(); 774 | pSvc->Release(); 775 | pLoc->Release(); 776 | CoUninitialize(); 777 | 778 | return result; 779 | } 780 | 781 | // Get disk hardware ID using direct device I/O control 782 | std::string GetDiskHardwareID() { 783 | std::stringstream diskIdStream; 784 | 785 | // Try direct I/O control first - much harder to spoof 786 | for (char driveLetter = 'C'; driveLetter <= 'Z'; driveLetter++) { 787 | std::string physicalDrivePath = "\\\\.\\PhysicalDrive0"; // Start with primary drive 788 | 789 | // Open the physical drive 790 | HANDLE hDrive = CreateFileA( 791 | physicalDrivePath.c_str(), 792 | GENERIC_READ, 793 | FILE_SHARE_READ | FILE_SHARE_WRITE, 794 | NULL, 795 | OPEN_EXISTING, 796 | 0, 797 | NULL 798 | ); 799 | 800 | if (hDrive != INVALID_HANDLE_VALUE) { 801 | // Get device properties using IOCTL 802 | STORAGE_PROPERTY_QUERY query; 803 | DWORD bytesReturned = 0; 804 | char buffer[1024] = { 0 }; 805 | 806 | query.PropertyId = StorageDeviceProperty; 807 | query.QueryType = PropertyStandardQuery; 808 | 809 | if (DeviceIoControl( 810 | hDrive, 811 | IOCTL_STORAGE_QUERY_PROPERTY, 812 | &query, 813 | sizeof(query), 814 | buffer, 815 | sizeof(buffer), 816 | &bytesReturned, 817 | NULL)) { 818 | 819 | STORAGE_DEVICE_DESCRIPTOR* deviceDesc = (STORAGE_DEVICE_DESCRIPTOR*)buffer; 820 | 821 | // Extract model, serial number, and firmware from the descriptor 822 | std::string vendor, product, serial; 823 | 824 | if (deviceDesc->VendorIdOffset > 0 && buffer[deviceDesc->VendorIdOffset] != '\0') { 825 | vendor = &buffer[deviceDesc->VendorIdOffset]; 826 | } 827 | 828 | if (deviceDesc->ProductIdOffset > 0 && buffer[deviceDesc->ProductIdOffset] != '\0') { 829 | product = &buffer[deviceDesc->ProductIdOffset]; 830 | } 831 | 832 | if (deviceDesc->SerialNumberOffset > 0 && buffer[deviceDesc->SerialNumberOffset] != '\0') { 833 | serial = &buffer[deviceDesc->SerialNumberOffset]; 834 | } 835 | 836 | if (!product.empty() && !serial.empty()) { 837 | diskIdStream << product << "-" << serial << ";"; 838 | } 839 | } 840 | 841 | // Try SCSI INQUIRY for additional details 842 | SCSI_PASS_THROUGH_DIRECT sptd; 843 | char inquiryBuffer[256] = { 0 }; 844 | 845 | ZeroMemory(&sptd, sizeof(SCSI_PASS_THROUGH_DIRECT)); 846 | sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT); 847 | sptd.CdbLength = 6; 848 | sptd.DataIn = SCSI_IOCTL_DATA_IN; 849 | sptd.DataTransferLength = sizeof(inquiryBuffer); 850 | sptd.DataBuffer = inquiryBuffer; 851 | sptd.TimeOutValue = 2; 852 | 853 | // INQUIRY command 854 | sptd.Cdb[0] = 0x12; // INQUIRY 855 | sptd.Cdb[4] = sizeof(inquiryBuffer); 856 | 857 | if (DeviceIoControl( 858 | hDrive, 859 | IOCTL_SCSI_PASS_THROUGH_DIRECT, 860 | &sptd, 861 | sizeof(SCSI_PASS_THROUGH_DIRECT), 862 | &sptd, 863 | sizeof(SCSI_PASS_THROUGH_DIRECT), 864 | &bytesReturned, 865 | NULL)) { 866 | 867 | // Extract vendor and product data from inquiry response 868 | char vendor[9] = { 0 }; 869 | char product[17] = { 0 }; 870 | 871 | memcpy(vendor, inquiryBuffer + 8, 8); 872 | memcpy(product, inquiryBuffer + 16, 16); 873 | 874 | // Trim spaces 875 | std::string vendorStr(vendor); 876 | std::string productStr(product); 877 | 878 | if (!vendorStr.empty() && !productStr.empty()) { 879 | diskIdStream << vendorStr << "-" << productStr << ";"; 880 | } 881 | } 882 | 883 | CloseHandle(hDrive); 884 | } 885 | 886 | break; // For now only check primary drive 887 | } 888 | 889 | // Fallback to WMI if direct access yields no results 890 | if (diskIdStream.str().empty()) { 891 | HRESULT hres; 892 | 893 | hres = CoInitializeEx(0, COINIT_MULTITHREADED); 894 | if (FAILED(hres)) return ""; 895 | 896 | IWbemLocator* pLoc = nullptr; 897 | hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc); 898 | if (FAILED(hres)) { 899 | CoUninitialize(); 900 | return ""; 901 | } 902 | 903 | IWbemServices* pSvc = nullptr; 904 | hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc); 905 | if (FAILED(hres)) { 906 | pLoc->Release(); 907 | CoUninitialize(); 908 | return ""; 909 | } 910 | 911 | hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, 912 | RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE); 913 | 914 | if (FAILED(hres)) { 915 | pSvc->Release(); 916 | pLoc->Release(); 917 | CoUninitialize(); 918 | return ""; 919 | } 920 | 921 | IEnumWbemClassObject* pEnumerator = nullptr; 922 | hres = pSvc->ExecQuery( 923 | bstr_t("WQL"), 924 | bstr_t("SELECT Model, SerialNumber FROM Win32_DiskDrive"), 925 | WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 926 | NULL, 927 | &pEnumerator 928 | ); 929 | 930 | if (SUCCEEDED(hres)) { 931 | IWbemClassObject* pclsObj = nullptr; 932 | ULONG uReturn = 0; 933 | 934 | while (pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn) == S_OK && uReturn > 0) { 935 | std::string model = GetWMIProperty(pclsObj, L"Model"); 936 | std::string serialNumber = GetWMIProperty(pclsObj, L"SerialNumber"); 937 | 938 | if (!serialNumber.empty()) { 939 | diskIdStream << model << "-" << serialNumber << ";"; 940 | } 941 | 942 | pclsObj->Release(); 943 | } 944 | 945 | pEnumerator->Release(); 946 | } 947 | 948 | pSvc->Release(); 949 | pLoc->Release(); 950 | CoUninitialize(); 951 | } 952 | 953 | return diskIdStream.str(); 954 | } 955 | 956 | // MAC Address Information (HARDWARE) 957 | std::string GetMACAddresses() { 958 | std::string result = "Network Adapters (HARDWARE):\n"; 959 | 960 | PIP_ADAPTER_INFO pAdapterInfo; 961 | PIP_ADAPTER_INFO pAdapter = NULL; 962 | DWORD dwRetVal = 0; 963 | 964 | ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); 965 | pAdapterInfo = (IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO)); 966 | if (pAdapterInfo == NULL) return "Error allocating memory for adapter info"; 967 | 968 | // Make an initial call to GetAdaptersInfo to get the necessary size 969 | if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { 970 | free(pAdapterInfo); 971 | pAdapterInfo = (IP_ADAPTER_INFO*)malloc(ulOutBufLen); 972 | if (pAdapterInfo == NULL) return "Error allocating memory for adapter info"; 973 | } 974 | 975 | if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { 976 | pAdapter = pAdapterInfo; 977 | int i = 0; 978 | while (pAdapter) { 979 | result += " Adapter " + std::to_string(i++) + ":\n"; 980 | result += " Description: " + std::string(pAdapter->Description) + "\n"; 981 | 982 | // Format MAC address 983 | std::stringstream macStream; 984 | for (UINT j = 0; j < pAdapter->AddressLength; j++) { 985 | if (j > 0) macStream << "-"; 986 | macStream << std::hex << std::setw(2) << std::setfill('0') << static_cast(pAdapter->Address[j]); 987 | } 988 | result += " MAC Address: " + macStream.str() + "\n"; 989 | 990 | pAdapter = pAdapter->Next; 991 | } 992 | } 993 | else { 994 | result += " GetAdaptersInfo failed with error: " + std::to_string(dwRetVal) + "\n"; 995 | } 996 | 997 | if (pAdapterInfo) free(pAdapterInfo); 998 | 999 | return result; 1000 | } 1001 | 1002 | // Get MAC address hardware ID 1003 | std::string GetMACHardwareID() { 1004 | std::stringstream macIdStream; 1005 | 1006 | PIP_ADAPTER_INFO pAdapterInfo; 1007 | PIP_ADAPTER_INFO pAdapter = NULL; 1008 | 1009 | ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); 1010 | pAdapterInfo = (IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO)); 1011 | if (pAdapterInfo == NULL) return ""; 1012 | 1013 | // Make an initial call to GetAdaptersInfo to get the necessary size 1014 | if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { 1015 | free(pAdapterInfo); 1016 | pAdapterInfo = (IP_ADAPTER_INFO*)malloc(ulOutBufLen); 1017 | if (pAdapterInfo == NULL) return ""; 1018 | } 1019 | 1020 | if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == NO_ERROR) { 1021 | pAdapter = pAdapterInfo; 1022 | 1023 | // Get only physical adapters (Ethernet and WiFi) 1024 | while (pAdapter) { 1025 | // Skip virtual adapters, VPNs, etc. 1026 | if (pAdapter->Type == MIB_IF_TYPE_ETHERNET || pAdapter->Type == IF_TYPE_IEEE80211) { 1027 | std::stringstream macStream; 1028 | for (UINT j = 0; j < pAdapter->AddressLength; j++) { 1029 | if (j > 0) macStream << "-"; 1030 | macStream << std::hex << std::setw(2) << std::setfill('0') 1031 | << static_cast(pAdapter->Address[j]); 1032 | } 1033 | macIdStream << macStream.str() << ";"; 1034 | } 1035 | pAdapter = pAdapter->Next; 1036 | } 1037 | } 1038 | 1039 | if (pAdapterInfo) free(pAdapterInfo); 1040 | 1041 | return macIdStream.str(); 1042 | } 1043 | 1044 | // GPU Information (HARDWARE) 1045 | std::string GetGPUInfo() { 1046 | std::string result = "GPU Information (HARDWARE):\n"; 1047 | 1048 | // Create DXGI Factory 1049 | IDXGIFactory1* pFactory = nullptr; 1050 | HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast(&pFactory)); 1051 | 1052 | if (FAILED(hr)) { 1053 | return result + " Failed to create DXGI Factory\n"; 1054 | } 1055 | 1056 | UINT i = 0; 1057 | IDXGIAdapter1* pAdapter = nullptr; 1058 | 1059 | while (pFactory->EnumAdapters1(i, &pAdapter) != DXGI_ERROR_NOT_FOUND) { 1060 | DXGI_ADAPTER_DESC1 desc; 1061 | pAdapter->GetDesc1(&desc); 1062 | 1063 | char szDescription[256]; 1064 | wcstombs_s(nullptr, szDescription, sizeof(szDescription), desc.Description, sizeof(szDescription)); 1065 | 1066 | result += " GPU " + std::to_string(i) + ":\n"; 1067 | result += " Description: " + std::string(szDescription) + "\n"; 1068 | result += " Vendor ID: 0x" + std::to_string(desc.VendorId) + "\n"; 1069 | result += " Device ID: 0x" + std::to_string(desc.DeviceId) + "\n"; 1070 | result += " Dedicated Video Memory: " + 1071 | std::to_string(desc.DedicatedVideoMemory / (1024 * 1024)) + " MB\n"; 1072 | 1073 | // Device LUID can be used as a unique identifier 1074 | std::stringstream ss; 1075 | ss << std::hex << std::uppercase << desc.AdapterLuid.HighPart 1076 | << "-" << desc.AdapterLuid.LowPart; 1077 | result += " Adapter LUID: " + ss.str() + "\n"; 1078 | 1079 | SafeRelease(&pAdapter); 1080 | i++; 1081 | } 1082 | 1083 | SafeRelease(&pFactory); 1084 | 1085 | return result; 1086 | } 1087 | 1088 | // Get GPU hardware ID (doesn't change unless GPU is physically changed) 1089 | std::string GetGPUHardwareID() { 1090 | std::stringstream gpuIdStream; 1091 | 1092 | // Create DXGI Factory 1093 | IDXGIFactory1* pFactory = nullptr; 1094 | HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast(&pFactory)); 1095 | 1096 | if (SUCCEEDED(hr)) { 1097 | UINT i = 0; 1098 | IDXGIAdapter1* pAdapter = nullptr; 1099 | 1100 | while (pFactory->EnumAdapters1(i, &pAdapter) != DXGI_ERROR_NOT_FOUND) { 1101 | DXGI_ADAPTER_DESC1 desc; 1102 | pAdapter->GetDesc1(&desc); 1103 | 1104 | // Combine vendor ID and device ID for a hardware identifier 1105 | gpuIdStream << std::hex << std::uppercase 1106 | << desc.VendorId << "-" 1107 | << desc.DeviceId << "-" 1108 | << desc.SubSysId << ";"; 1109 | 1110 | SafeRelease(&pAdapter); 1111 | i++; 1112 | } 1113 | 1114 | SafeRelease(&pFactory); 1115 | } 1116 | 1117 | return gpuIdStream.str(); 1118 | } 1119 | 1120 | // Monitor Information with EDID details (HARDWARE) 1121 | std::string GetMonitorInfo() { 1122 | std::string result = "Monitor Information (HARDWARE):\n"; 1123 | 1124 | HDEVINFO deviceInfoSet = SetupDiGetClassDevs(&GUID_DEVCLASS_MONITOR, NULL, NULL, DIGCF_PRESENT); 1125 | 1126 | if (deviceInfoSet == INVALID_HANDLE_VALUE) { 1127 | return result + " Failed to get monitor device information\n"; 1128 | } 1129 | 1130 | SP_DEVINFO_DATA deviceInfoData; 1131 | deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 1132 | 1133 | for (DWORD i = 0; SetupDiEnumDeviceInfo(deviceInfoSet, i, &deviceInfoData); i++) { 1134 | result += " Monitor " + std::to_string(i) + ":\n"; 1135 | 1136 | char deviceInstanceID[MAX_PATH]; 1137 | if (SetupDiGetDeviceInstanceIdA(deviceInfoSet, &deviceInfoData, deviceInstanceID, sizeof(deviceInstanceID), NULL)) { 1138 | result += " Device ID: " + std::string(deviceInstanceID) + "\n"; 1139 | } 1140 | 1141 | HKEY deviceKey = SetupDiOpenDevRegKey( 1142 | deviceInfoSet, &deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); 1143 | 1144 | if (deviceKey != INVALID_HANDLE_VALUE) { 1145 | char friendlyName[256] = { 0 }; 1146 | DWORD dataSize = sizeof(friendlyName); 1147 | DWORD dataType = 0; 1148 | 1149 | if (RegQueryValueExA(deviceKey, "FriendlyName", NULL, &dataType, 1150 | reinterpret_cast(friendlyName), &dataSize) == ERROR_SUCCESS) { 1151 | result += " Name: " + std::string(friendlyName) + "\n"; 1152 | } 1153 | 1154 | RegCloseKey(deviceKey); 1155 | } 1156 | 1157 | // Try to get EDID data (contains manufacturer, model, serial number, etc.) 1158 | HKEY edidKey = SetupDiOpenDevRegKey( 1159 | deviceInfoSet, &deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); 1160 | 1161 | if (edidKey != INVALID_HANDLE_VALUE) { 1162 | BYTE edidData[256] = { 0 }; 1163 | DWORD dataSize = sizeof(edidData); 1164 | DWORD dataType = 0; 1165 | 1166 | if (RegQueryValueExA(edidKey, "EDID", NULL, &dataType, edidData, &dataSize) == ERROR_SUCCESS) { 1167 | // Extract manufacturer ID (3 character code from bytes 8-9) 1168 | char manufacturerId[4] = { 0 }; 1169 | manufacturerId[0] = 'A' + ((edidData[8] >> 2) & 0x1F) - 1; 1170 | manufacturerId[1] = 'A' + (((edidData[8] & 0x03) << 3) | ((edidData[9] >> 5) & 0x07)) - 1; 1171 | manufacturerId[2] = 'A' + (edidData[9] & 0x1F) - 1; 1172 | 1173 | result += " Manufacturer ID: " + std::string(manufacturerId) + "\n"; 1174 | 1175 | // Extract product ID (bytes 10-11) 1176 | WORD productId = edidData[10] | (edidData[11] << 8); 1177 | result += " Product ID: 0x" + std::to_string(productId) + "\n"; 1178 | 1179 | // Extract serial number (bytes 12-15) 1180 | DWORD serialNumber = edidData[12] | (edidData[13] << 8) | 1181 | (edidData[14] << 16) | (edidData[15] << 24); 1182 | result += " Serial Number: " + std::to_string(serialNumber) + "\n"; 1183 | 1184 | // Extract manufacture date (bytes 16-17) 1185 | BYTE weekOfManufacture = edidData[16]; 1186 | BYTE yearOfManufacture = edidData[17] + 1990; 1187 | result += " Manufacture Date: Week " + std::to_string(weekOfManufacture) + 1188 | ", Year " + std::to_string(yearOfManufacture) + "\n"; 1189 | 1190 | // Extract display size (bytes 21-22) in cm 1191 | if (edidData[21] != 0 && edidData[22] != 0) { 1192 | result += " Physical Size: " + std::to_string(edidData[21]) + 1193 | " cm x " + std::to_string(edidData[22]) + " cm\n"; 1194 | } 1195 | 1196 | // Generate unique monitor ID from the above data 1197 | std::stringstream monitorIdStream; 1198 | monitorIdStream << manufacturerId << "-" << std::hex << productId << "-" << serialNumber; 1199 | result += " Monitor ID: " + monitorIdStream.str() + "\n"; 1200 | } 1201 | 1202 | RegCloseKey(edidKey); 1203 | } 1204 | } 1205 | 1206 | SetupDiDestroyDeviceInfoList(deviceInfoSet); 1207 | 1208 | return result; 1209 | } 1210 | 1211 | std::string GetMonitorHardwareID() { 1212 | std::stringstream monitorIdStream; 1213 | 1214 | HDEVINFO deviceInfoSet = SetupDiGetClassDevs(&GUID_DEVCLASS_MONITOR, NULL, NULL, DIGCF_PRESENT); 1215 | 1216 | if (deviceInfoSet != INVALID_HANDLE_VALUE) { 1217 | SP_DEVINFO_DATA deviceInfoData; 1218 | deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 1219 | 1220 | for (DWORD i = 0; SetupDiEnumDeviceInfo(deviceInfoSet, i, &deviceInfoData); i++) { 1221 | HKEY edidKey = SetupDiOpenDevRegKey( 1222 | deviceInfoSet, &deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); 1223 | 1224 | if (edidKey != INVALID_HANDLE_VALUE) { 1225 | BYTE edidData[256] = { 0 }; 1226 | DWORD dataSize = sizeof(edidData); 1227 | DWORD dataType = 0; 1228 | 1229 | if (RegQueryValueExA(edidKey, "EDID", NULL, &dataType, edidData, &dataSize) == ERROR_SUCCESS) { 1230 | // Extract manufacturer ID 1231 | char manufacturerId[4] = { 0 }; 1232 | manufacturerId[0] = 'A' + ((edidData[8] >> 2) & 0x1F) - 1; 1233 | manufacturerId[1] = 'A' + (((edidData[8] & 0x03) << 3) | ((edidData[9] >> 5) & 0x07)) - 1; 1234 | manufacturerId[2] = 'A' + (edidData[9] & 0x1F) - 1; 1235 | 1236 | // Extract product ID 1237 | WORD productId = edidData[10] | (edidData[11] << 8); 1238 | 1239 | // Extract serial number 1240 | DWORD serialNumber = edidData[12] | (edidData[13] << 8) | 1241 | (edidData[14] << 16) | (edidData[15] << 24); 1242 | 1243 | // Generate unique monitor ID 1244 | monitorIdStream << manufacturerId << "-" << std::hex << productId 1245 | << "-" << serialNumber << ";"; 1246 | } 1247 | 1248 | RegCloseKey(edidKey); 1249 | } 1250 | } 1251 | 1252 | SetupDiDestroyDeviceInfoList(deviceInfoSet); 1253 | } 1254 | 1255 | return monitorIdStream.str(); 1256 | } 1257 | 1258 | // Get Volume Serial Number (SOFTWARE - can change with reformatting) 1259 | std::string GetVolumeSerialNumber() { 1260 | std::string result = "Volume Information (SOFTWARE - can change with reformatting):\n"; 1261 | 1262 | DWORD serialNumber = 0; 1263 | char volumeName[MAX_PATH + 1] = { 0 }; 1264 | char fileSystemName[MAX_PATH + 1] = { 0 }; 1265 | 1266 | if (GetVolumeInformationA( 1267 | "C:\\", 1268 | volumeName, 1269 | ARRAYSIZE(volumeName), 1270 | &serialNumber, 1271 | NULL, 1272 | NULL, 1273 | fileSystemName, 1274 | ARRAYSIZE(fileSystemName))) { 1275 | 1276 | result += " C: Drive\n"; 1277 | result += " Volume Name: " + std::string(volumeName) + "\n"; 1278 | result += " Serial Number: " + std::to_string(serialNumber) + " (0x" + 1279 | std::to_string(static_cast(serialNumber)) + ")\n"; 1280 | result += " File System: " + std::string(fileSystemName) + "\n"; 1281 | } 1282 | else { 1283 | result += " Failed to get volume information. Error: " + std::to_string(GetLastError()) + "\n"; 1284 | } 1285 | 1286 | return result; 1287 | } 1288 | 1289 | // Get volume software ID (changes with reformatting) 1290 | std::string GetVolumeSoftwareID() { 1291 | std::stringstream volumeIdStream; 1292 | 1293 | DWORD serialNumber = 0; 1294 | if (GetVolumeInformationA("C:\\", NULL, 0, &serialNumber, NULL, NULL, NULL, 0)) { 1295 | volumeIdStream << std::hex << std::uppercase << serialNumber; 1296 | } 1297 | 1298 | return volumeIdStream.str(); 1299 | } 1300 | 1301 | // Windows Product ID (SOFTWARE - changes with reinstallation) 1302 | std::string GetWindowsProductID() { 1303 | std::string result = "Windows Product ID (SOFTWARE - changes with reinstallation):\n"; 1304 | 1305 | HKEY hKey; 1306 | if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, 1307 | "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 1308 | 0, KEY_READ, &hKey) == ERROR_SUCCESS) { 1309 | 1310 | char productId[64] = { 0 }; 1311 | DWORD dataSize = sizeof(productId); 1312 | DWORD dataType = 0; 1313 | 1314 | if (RegQueryValueExA(hKey, "ProductId", NULL, &dataType, 1315 | reinterpret_cast(productId), &dataSize) == ERROR_SUCCESS) { 1316 | result += " Product ID: " + std::string(productId) + "\n"; 1317 | } 1318 | 1319 | // Get Installation ID 1320 | char installationID[64] = { 0 }; 1321 | dataSize = sizeof(installationID); 1322 | 1323 | if (RegQueryValueExA(hKey, "DigitalProductId", NULL, &dataType, 1324 | reinterpret_cast(installationID), &dataSize) == ERROR_SUCCESS) { 1325 | result += " Digital Product ID: [Binary data]\n"; 1326 | } 1327 | 1328 | RegCloseKey(hKey); 1329 | } 1330 | else { 1331 | result += " Failed to access registry\n"; 1332 | } 1333 | 1334 | return result; 1335 | } 1336 | 1337 | // Get Windows software ID (changes with reinstallation) 1338 | std::string GetWindowsSoftwareID() { 1339 | std::string windowsId = ""; 1340 | 1341 | HKEY hKey; 1342 | if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, 1343 | "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 1344 | 0, KEY_READ, &hKey) == ERROR_SUCCESS) { 1345 | 1346 | char productId[64] = { 0 }; 1347 | DWORD dataSize = sizeof(productId); 1348 | DWORD dataType = 0; 1349 | 1350 | if (RegQueryValueExA(hKey, "ProductId", NULL, &dataType, 1351 | reinterpret_cast(productId), &dataSize) == ERROR_SUCCESS) { 1352 | windowsId = std::string(productId); 1353 | } 1354 | 1355 | RegCloseKey(hKey); 1356 | } 1357 | 1358 | return windowsId; 1359 | } 1360 | 1361 | // Computer Name (SOFTWARE - user changeable) 1362 | std::string GetComputerName() { 1363 | std::string result = "Computer Name (SOFTWARE - user changeable):\n"; 1364 | 1365 | char computerName[MAX_COMPUTERNAME_LENGTH + 1] = { 0 }; 1366 | DWORD size = sizeof(computerName); 1367 | 1368 | if (::GetComputerNameA(computerName, &size)) { 1369 | result += " Name: " + std::string(computerName) + "\n"; 1370 | } 1371 | else { 1372 | result += " Failed to get computer name. Error: " + std::to_string(GetLastError()) + "\n"; 1373 | } 1374 | 1375 | return result; 1376 | } 1377 | 1378 | // Get computer name for software ID 1379 | std::string GetComputerNameSoftwareID() { 1380 | char computerName[MAX_COMPUTERNAME_LENGTH + 1] = { 0 }; 1381 | DWORD size = sizeof(computerName); 1382 | 1383 | if (::GetComputerNameA(computerName, &size)) { 1384 | return std::string(computerName); 1385 | } 1386 | 1387 | return ""; 1388 | } 1389 | 1390 | // User Account SID (SOFTWARE - changes with user account) 1391 | std::string GetUserSID() { 1392 | std::string result = "User Account SID (SOFTWARE - changes with user account):\n"; 1393 | 1394 | char username[256] = { 0 }; 1395 | DWORD usernameSize = sizeof(username); 1396 | 1397 | if (GetUserNameA(username, &usernameSize)) { 1398 | result += " Username: " + std::string(username) + "\n"; 1399 | 1400 | PSID sidPtr = NULL; 1401 | SID_NAME_USE sidType; 1402 | char domainName[256] = { 0 }; 1403 | DWORD domainSize = sizeof(domainName); 1404 | DWORD sidSize = 0; 1405 | 1406 | // First call to get size 1407 | LookupAccountNameA(NULL, username, NULL, &sidSize, domainName, &domainSize, &sidType); 1408 | 1409 | if (sidSize > 0) { 1410 | sidPtr = (PSID)malloc(sidSize); 1411 | 1412 | if (LookupAccountNameA(NULL, username, sidPtr, &sidSize, domainName, &domainSize, &sidType)) { 1413 | LPSTR sidString = NULL; 1414 | 1415 | if (::ConvertSidToStringSidA(sidPtr, &sidString)) { 1416 | result += " SID: " + std::string(sidString) + "\n"; 1417 | LocalFree(sidString); 1418 | } 1419 | } 1420 | 1421 | free(sidPtr); 1422 | } 1423 | } 1424 | else { 1425 | result += " Failed to get username. Error: " + std::to_string(GetLastError()) + "\n"; 1426 | } 1427 | 1428 | return result; 1429 | } 1430 | 1431 | // Get user SID for software ID 1432 | std::string GetUserSIDSoftwareID() { 1433 | std::string sidString = ""; 1434 | 1435 | char username[256] = { 0 }; 1436 | DWORD usernameSize = sizeof(username); 1437 | 1438 | if (GetUserNameA(username, &usernameSize)) { 1439 | PSID sidPtr = NULL; 1440 | SID_NAME_USE sidType; 1441 | char domainName[256] = { 0 }; 1442 | DWORD domainSize = sizeof(domainName); 1443 | DWORD sidSize = 0; 1444 | 1445 | // First call to get size 1446 | LookupAccountNameA(NULL, username, NULL, &sidSize, domainName, &domainSize, &sidType); 1447 | 1448 | if (sidSize > 0) { 1449 | sidPtr = (PSID)malloc(sidSize); 1450 | 1451 | if (LookupAccountNameA(NULL, username, sidPtr, &sidSize, domainName, &domainSize, &sidType)) { 1452 | LPSTR sidStr = NULL; 1453 | 1454 | if (::ConvertSidToStringSidA(sidPtr, &sidStr)) { 1455 | sidString = std::string(sidStr); 1456 | LocalFree(sidStr); 1457 | } 1458 | } 1459 | 1460 | free(sidPtr); 1461 | } 1462 | } 1463 | 1464 | return sidString; 1465 | } 1466 | 1467 | // Generate a hardware-based HWID (doesn't change unless hardware is physically changed) 1468 | std::string GenerateHardwareHWID() { 1469 | // Collect hardware identifiers 1470 | std::string cpuId = GetCPUHardwareID(); 1471 | std::string motherboardId = GetMotherboardHardwareID(); 1472 | std::string diskId = GetDiskHardwareID(); 1473 | std::string macId = GetMACHardwareID(); 1474 | std::string gpuId = GetGPUHardwareID(); 1475 | std::string monitorId = GetMonitorHardwareID(); 1476 | 1477 | // Combine all hardware IDs 1478 | std::string combinedId = cpuId + "|" + motherboardId + "|" + diskId + "|" 1479 | + macId + "|" + gpuId + "|" + monitorId; 1480 | 1481 | // Hash the combined ID to create a fingerprint 1482 | return "Hardware ID: " + HashString(combinedId); 1483 | } 1484 | 1485 | // Generate a software-based HWID (changes with system reinstalls/resets) 1486 | std::string GenerateSoftwareHWID() { 1487 | // Collect software identifiers 1488 | std::string volumeId = GetVolumeSoftwareID(); 1489 | std::string windowsId = GetWindowsSoftwareID(); 1490 | std::string computerName = GetComputerNameSoftwareID(); 1491 | std::string userSid = GetUserSIDSoftwareID(); 1492 | 1493 | // Combine all software IDs 1494 | std::string combinedId = volumeId + "|" + windowsId + "|" + computerName + "|" + userSid; 1495 | 1496 | // Hash the combined ID to create a fingerprint 1497 | return "Software ID: " + HashString(combinedId); 1498 | } 1499 | 1500 | // Generate a complete HWID based on combined hardware and software identifiers 1501 | std::string GenerateHWID() { 1502 | // Create a string with key hardware and software identifiers 1503 | std::string hardwareId = GenerateHardwareHWID().substr(13); // Remove "Hardware ID: " prefix 1504 | std::string softwareId = GenerateSoftwareHWID().substr(13); // Remove "Software ID: " prefix 1505 | 1506 | // Combine hardware and software IDs 1507 | return "Complete HWID:\n Hardware Component: " + hardwareId + "\n Software Component: " + softwareId; 1508 | } 1509 | 1510 | // WMIC-Based Hardware Identification Methods 1511 | // WARNING: These methods use WMIC which can be easily spoofed and are NOT recommended for secure hardware identification 1512 | 1513 | std::string GetWMICBasedWarning() { 1514 | std::stringstream ss; 1515 | ss << "====================================================" << std::endl; 1516 | ss << " WARNING: WMIC-BASED IDENTIFIERS (LESS RELIABLE) " << std::endl; 1517 | ss << "====================================================" << std::endl << std::endl; 1518 | ss << "The following identifiers are retrieved using Windows Management" << std::endl; 1519 | ss << "Instrumentation Command-line (WMIC) and can be easily spoofed or" << std::endl; 1520 | ss << "altered. They should NOT be used for secure hardware identification." << std::endl; 1521 | ss << "For reliable identification, use the hardware-based methods above." << std::endl << std::endl; 1522 | return ss.str(); 1523 | } 1524 | 1525 | std::string GetWMICBasedCPUInfo() { 1526 | std::stringstream ss; 1527 | ss << "WMIC CPU Information (Unreliable):" << std::endl; 1528 | ss << ExecuteWMICCommand("cpu get Name, ProcessorId, Manufacturer, MaxClockSpeed, NumberOfCores, NumberOfLogicalProcessors /format:list"); 1529 | return ss.str(); 1530 | } 1531 | 1532 | std::string GetWMICBasedMotherboardInfo() { 1533 | std::stringstream ss; 1534 | ss << "WMIC Motherboard Information (Unreliable):" << std::endl; 1535 | ss << ExecuteWMICCommand("baseboard get Manufacturer, Product, SerialNumber, Version /format:list"); 1536 | return ss.str(); 1537 | } 1538 | 1539 | std::string GetWMICBasedBIOSInfo() { 1540 | std::stringstream ss; 1541 | ss << "WMIC BIOS Information (Unreliable):" << std::endl; 1542 | ss << ExecuteWMICCommand("bios get Manufacturer, SMBIOSBIOSVersion, SerialNumber, Version /format:list"); 1543 | return ss.str(); 1544 | } 1545 | 1546 | std::string GetWMICBasedDiskInfo() { 1547 | std::stringstream ss; 1548 | ss << "WMIC Disk Information (Unreliable):" << std::endl; 1549 | ss << ExecuteWMICCommand("diskdrive get Model, SerialNumber, Size, MediaType /format:list"); 1550 | return ss.str(); 1551 | } 1552 | 1553 | std::string GetWMICBasedNetworkAdapterInfo() { 1554 | std::stringstream ss; 1555 | ss << "WMIC Network Adapter Information (Unreliable):" << std::endl; 1556 | ss << ExecuteWMICCommand("nicconfig get Description, MACAddress, IPAddress /format:list"); 1557 | return ss.str(); 1558 | } 1559 | 1560 | std::string GetWMICBasedGPUInfo() { 1561 | std::stringstream ss; 1562 | ss << "WMIC GPU Information (Unreliable):" << std::endl; 1563 | ss << ExecuteWMICCommand("path win32_VideoController get Name, DriverVersion, VideoProcessor, AdapterRAM /format:list"); 1564 | return ss.str(); 1565 | } 1566 | 1567 | std::string GetWMICBasedOSInfo() { 1568 | std::stringstream ss; 1569 | ss << "WMIC OS Information (Unreliable):" << std::endl; 1570 | ss << ExecuteWMICCommand("os get Caption, SerialNumber, Version, OSArchitecture /format:list"); 1571 | return ss.str(); 1572 | } 1573 | 1574 | std::string GetWMICBasedMemoryInfo() { 1575 | std::stringstream ss; 1576 | ss << "WMIC Memory Information (Unreliable):" << std::endl; 1577 | ss << ExecuteWMICCommand("memorychip get BankLabel, Capacity, PartNumber, Speed /format:list"); 1578 | return ss.str(); 1579 | } 1580 | 1581 | std::string GetWMICBasedLogicalDiskInfo() { 1582 | std::stringstream ss; 1583 | ss << "WMIC Logical Disk Information (Unreliable):" << std::endl; 1584 | ss << ExecuteWMICCommand("logicaldisk get DeviceID, FileSystem, Size, VolumeSerialNumber /format:list"); 1585 | return ss.str(); 1586 | } 1587 | 1588 | std::string GetWMICBasedSMBIOSInfo() { 1589 | std::stringstream ss; 1590 | ss << "WMIC SMBIOS Information (Unreliable):" << std::endl; 1591 | ss << ExecuteWMICCommand("path win32_SystemEnclosure get SerialNumber, SMBIOSAssetTag, Manufacturer /format:list"); 1592 | return ss.str(); 1593 | } 1594 | 1595 | std::string GetAllWMICBasedInfo() { 1596 | std::stringstream ss; 1597 | // Warning is added here only once 1598 | ss << GetWMICBasedWarning(); 1599 | ss << GetWMICBasedCPUInfo() << std::endl; 1600 | ss << GetWMICBasedMotherboardInfo() << std::endl; 1601 | ss << GetWMICBasedBIOSInfo() << std::endl; 1602 | ss << GetWMICBasedDiskInfo() << std::endl; 1603 | ss << GetWMICBasedNetworkAdapterInfo() << std::endl; 1604 | ss << GetWMICBasedGPUInfo() << std::endl; 1605 | ss << GetWMICBasedOSInfo() << std::endl; 1606 | ss << GetWMICBasedMemoryInfo() << std::endl; 1607 | ss << GetWMICBasedLogicalDiskInfo() << std::endl; 1608 | ss << GetWMICBasedSMBIOSInfo() << std::endl; 1609 | 1610 | ss << std::endl << "Note: The above information can be easily modified or spoofed." << std::endl; 1611 | ss << "For reliable hardware identification, use the hardware-based methods." << std::endl; 1612 | 1613 | return ss.str(); 1614 | } 1615 | 1616 | std::string GetInstallDate() { 1617 | std::string result = "Windows Install Date (SOFTWARE):\n"; 1618 | 1619 | HKEY hKey; 1620 | LONG lRes = RegOpenKeyExA( 1621 | HKEY_LOCAL_MACHINE, 1622 | "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 1623 | 0, 1624 | KEY_READ, 1625 | &hKey); 1626 | 1627 | if (lRes == ERROR_SUCCESS) { 1628 | DWORD installDateDword = 0; 1629 | DWORD dataSize = sizeof(installDateDword); 1630 | DWORD dataType = 0; 1631 | 1632 | lRes = RegQueryValueExA( 1633 | hKey, 1634 | "InstallDate", 1635 | 0, 1636 | &dataType, 1637 | reinterpret_cast(&installDateDword), 1638 | &dataSize); 1639 | 1640 | if (lRes == ERROR_SUCCESS && dataType == REG_DWORD) { 1641 | time_t installTime = static_cast(installDateDword); 1642 | 1643 | char dateStr[100]; 1644 | struct tm* timeinfo = localtime(&installTime); 1645 | strftime(dateStr, sizeof(dateStr), "%Y-%m-%d %H:%M:%S", timeinfo); 1646 | 1647 | result += " Install Date: " + std::string(dateStr) + "\n"; 1648 | result += " Unix Timestamp: " + std::to_string(installDateDword) + "\n"; 1649 | } 1650 | else { 1651 | result += " Failed to get install date. Error: " + std::to_string(lRes) + "\n"; 1652 | } 1653 | 1654 | RegCloseKey(hKey); 1655 | } 1656 | else { 1657 | result += " Failed to open registry key. Error: " + std::to_string(lRes) + "\n"; 1658 | } 1659 | 1660 | return result; 1661 | } 1662 | 1663 | std::string GetUserInfo() { 1664 | std::string result = "User Information (SOFTWARE):\n"; 1665 | 1666 | char username[UNLEN + 1]; 1667 | DWORD usernameLen = UNLEN + 1; 1668 | 1669 | if (GetUserNameA(username, &usernameLen)) { 1670 | result += " Username: " + std::string(username) + "\n"; 1671 | } 1672 | else { 1673 | result += " Failed to get username. Error: " + std::to_string(GetLastError()) + "\n"; 1674 | } 1675 | 1676 | char computerName[MAX_COMPUTERNAME_LENGTH + 1]; 1677 | DWORD computerNameLen = MAX_COMPUTERNAME_LENGTH + 1; 1678 | 1679 | if (::GetComputerNameA(computerName, &computerNameLen)) { 1680 | result += " Computer Name: " + std::string(computerName) + "\n"; 1681 | } 1682 | else { 1683 | result += " Failed to get computer name. Error: " + std::to_string(GetLastError()) + "\n"; 1684 | } 1685 | 1686 | return result; 1687 | } 1688 | 1689 | std::string GetOSInfo() { 1690 | std::string result = "Operating System Information (SOFTWARE):\n"; 1691 | 1692 | // Use RtlGetVersion which is more reliable than GetVersionEx 1693 | typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); 1694 | HMODULE hMod = GetModuleHandleW(L"ntdll.dll"); 1695 | if (hMod) { 1696 | RtlGetVersionPtr RtlGetVersion = (RtlGetVersionPtr)GetProcAddress(hMod, "RtlGetVersion"); 1697 | if (RtlGetVersion) { 1698 | RTL_OSVERSIONINFOW osvi = { 0 }; 1699 | osvi.dwOSVersionInfoSize = sizeof(osvi); 1700 | if (NT_SUCCESS(RtlGetVersion(&osvi))) { 1701 | result += " Windows Version: " + std::to_string(osvi.dwMajorVersion) + "." + 1702 | std::to_string(osvi.dwMinorVersion) + "." + 1703 | std::to_string(osvi.dwBuildNumber) + "\n"; 1704 | 1705 | if (osvi.szCSDVersion[0] != L'\0') { 1706 | // Convert wide string to narrow string 1707 | char csdVersion[128] = { 0 }; 1708 | WideCharToMultiByte(CP_ACP, 0, osvi.szCSDVersion, -1, 1709 | csdVersion, sizeof(csdVersion), NULL, NULL); 1710 | result += " Service Pack: " + std::string(csdVersion) + "\n"; 1711 | } 1712 | } 1713 | } 1714 | } 1715 | 1716 | // Get more detailed information from registry 1717 | HKEY hKey; 1718 | LONG lRes = RegOpenKeyExA( 1719 | HKEY_LOCAL_MACHINE, 1720 | "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 1721 | 0, 1722 | KEY_READ, 1723 | &hKey); 1724 | 1725 | if (lRes == ERROR_SUCCESS) { 1726 | char productName[256] = { 0 }; 1727 | DWORD dataSize = sizeof(productName); 1728 | DWORD dataType = 0; 1729 | 1730 | if (RegQueryValueExA(hKey, "ProductName", 0, &dataType, 1731 | reinterpret_cast(productName), &dataSize) == ERROR_SUCCESS) { 1732 | result += " Product Name: " + std::string(productName) + "\n"; 1733 | } 1734 | 1735 | char editionID[256] = { 0 }; 1736 | dataSize = sizeof(editionID); 1737 | 1738 | if (RegQueryValueExA(hKey, "EditionID", 0, &dataType, 1739 | reinterpret_cast(editionID), &dataSize) == ERROR_SUCCESS) { 1740 | result += " Edition ID: " + std::string(editionID) + "\n"; 1741 | } 1742 | 1743 | char releaseId[256] = { 0 }; 1744 | dataSize = sizeof(releaseId); 1745 | 1746 | if (RegQueryValueExA(hKey, "ReleaseId", 0, &dataType, 1747 | reinterpret_cast(releaseId), &dataSize) == ERROR_SUCCESS) { 1748 | result += " Release ID: " + std::string(releaseId) + "\n"; 1749 | } 1750 | 1751 | char currentBuild[256] = { 0 }; 1752 | dataSize = sizeof(currentBuild); 1753 | 1754 | if (RegQueryValueExA(hKey, "CurrentBuild", 0, &dataType, 1755 | reinterpret_cast(currentBuild), &dataSize) == ERROR_SUCCESS) { 1756 | result += " Current Build: " + std::string(currentBuild) + "\n"; 1757 | } 1758 | 1759 | char ubr[256] = { 0 }; 1760 | dataSize = sizeof(ubr); 1761 | DWORD ubrDword = 0; 1762 | 1763 | if (RegQueryValueExA(hKey, "UBR", 0, &dataType, 1764 | reinterpret_cast(&ubrDword), &dataSize) == ERROR_SUCCESS) { 1765 | result += " UBR: " + std::to_string(ubrDword) + "\n"; 1766 | 1767 | // Combine build number and UBR 1768 | if (currentBuild[0] != '\0') { 1769 | result += " Full Build: " + std::string(currentBuild) + "." + 1770 | std::to_string(ubrDword) + "\n"; 1771 | } 1772 | } 1773 | 1774 | RegCloseKey(hKey); 1775 | } 1776 | 1777 | // Get system architecture 1778 | SYSTEM_INFO sysInfo; 1779 | GetNativeSystemInfo(&sysInfo); 1780 | 1781 | std::string architecture; 1782 | switch (sysInfo.wProcessorArchitecture) { 1783 | case PROCESSOR_ARCHITECTURE_AMD64: 1784 | architecture = "x64 (AMD64)"; 1785 | break; 1786 | case PROCESSOR_ARCHITECTURE_INTEL: 1787 | architecture = "x86 (Intel)"; 1788 | break; 1789 | case PROCESSOR_ARCHITECTURE_ARM: 1790 | architecture = "ARM"; 1791 | break; 1792 | case PROCESSOR_ARCHITECTURE_ARM64: 1793 | architecture = "ARM64"; 1794 | break; 1795 | default: 1796 | architecture = "Unknown"; 1797 | } 1798 | 1799 | result += " System Architecture: " + architecture + "\n"; 1800 | 1801 | return result; 1802 | } 1803 | }; 1804 | 1805 | int main() { 1806 | try { 1807 | HWIDGrabber hwid; 1808 | 1809 | std::cout << "===== github.com/0vm =====" << std::endl << std::endl; 1810 | 1811 | // Hardware-based identifiers 1812 | std::cout << "=============================" << std::endl; 1813 | std::cout << " HARDWARE-BASED IDENTIFIERS " << std::endl; 1814 | std::cout << "=============================" << std::endl << std::endl; 1815 | 1816 | std::cout << "Getting CPU info..." << std::endl; 1817 | std::cout << hwid.GetCPUInfo() << std::endl; 1818 | std::string cpuId = hwid.GetCPUHardwareID(); 1819 | std::cout << " Raw CPU ID: " << cpuId << std::endl; 1820 | std::cout << " Hashed CPU ID: " << hwid.HashString(cpuId) << std::endl << std::endl; 1821 | 1822 | std::cout << "Getting motherboard info..." << std::endl; 1823 | std::cout << hwid.GetMotherboardInfo() << std::endl; 1824 | std::string mbId = hwid.GetMotherboardHardwareID(); 1825 | std::cout << " Raw Motherboard ID: " << mbId << std::endl; 1826 | std::cout << " Hashed Motherboard ID: " << hwid.HashString(mbId) << std::endl << std::endl; 1827 | 1828 | std::cout << "Getting disk info..." << std::endl; 1829 | std::cout << hwid.GetDiskInfo() << std::endl; 1830 | std::string diskId = hwid.GetDiskHardwareID(); 1831 | std::cout << " Raw Disk ID: " << diskId << std::endl; 1832 | std::cout << " Hashed Disk ID: " << hwid.HashString(diskId) << std::endl << std::endl; 1833 | 1834 | std::cout << "Getting MAC addresses..." << std::endl; 1835 | std::cout << hwid.GetMACAddresses() << std::endl; 1836 | std::string macId = hwid.GetMACHardwareID(); 1837 | std::cout << " Raw MAC ID: " << macId << std::endl; 1838 | std::cout << " Hashed MAC ID: " << hwid.HashString(macId) << std::endl << std::endl; 1839 | 1840 | std::cout << "Getting GPU info..." << std::endl; 1841 | std::cout << hwid.GetGPUInfo() << std::endl; 1842 | std::string gpuId = hwid.GetGPUHardwareID(); 1843 | std::cout << " Raw GPU ID: " << gpuId << std::endl; 1844 | std::cout << " Hashed GPU ID: " << hwid.HashString(gpuId) << std::endl << std::endl; 1845 | 1846 | std::cout << "Getting monitor info..." << std::endl; 1847 | std::cout << hwid.GetMonitorInfo() << std::endl; 1848 | std::string monitorId = hwid.GetMonitorHardwareID(); 1849 | std::cout << " Raw Monitor ID: " << monitorId << std::endl; 1850 | std::cout << " Hashed Monitor ID: " << hwid.HashString(monitorId) << std::endl << std::endl; 1851 | 1852 | // Software-based identifiers 1853 | std::cout << "=============================" << std::endl; 1854 | std::cout << " SOFTWARE-BASED IDENTIFIERS " << std::endl; 1855 | std::cout << "=============================" << std::endl << std::endl; 1856 | 1857 | std::cout << "Getting volume serial number..." << std::endl; 1858 | std::cout << hwid.GetVolumeSerialNumber() << std::endl; 1859 | std::string volumeId = hwid.GetVolumeSoftwareID(); 1860 | std::cout << " Raw Volume ID: " << volumeId << std::endl; 1861 | std::cout << " Hashed Volume ID: " << hwid.HashString(volumeId) << std::endl << std::endl; 1862 | 1863 | std::cout << "Getting Windows product ID..." << std::endl; 1864 | std::cout << hwid.GetWindowsProductID() << std::endl; 1865 | std::string windowsId = hwid.GetWindowsSoftwareID(); 1866 | std::cout << " Raw Windows ID: " << windowsId << std::endl; 1867 | std::cout << " Hashed Windows ID: " << hwid.HashString(windowsId) << std::endl << std::endl; 1868 | 1869 | std::cout << "Getting computer name..." << std::endl; 1870 | std::cout << hwid.GetComputerName() << std::endl; 1871 | std::string computerNameId = hwid.GetComputerNameSoftwareID(); 1872 | std::cout << " Raw Computer Name ID: " << computerNameId << std::endl; 1873 | std::cout << " Hashed Computer Name ID: " << hwid.HashString(computerNameId) << std::endl << std::endl; 1874 | 1875 | std::cout << "Getting user SID..." << std::endl; 1876 | std::cout << hwid.GetUserSID() << std::endl; 1877 | std::string userId = hwid.GetUserSIDSoftwareID(); 1878 | std::cout << " Raw User SID: " << userId << std::endl; 1879 | std::cout << " Hashed User SID: " << hwid.HashString(userId) << std::endl << std::endl; 1880 | 1881 | // Generate combined HWID 1882 | std::cout << "=============================" << std::endl; 1883 | std::cout << " COMBINED HWIDs " << std::endl; 1884 | std::cout << "=============================" << std::endl << std::endl; 1885 | 1886 | // Hardware HWID - combine raw IDs first 1887 | std::string combinedHardwareId = cpuId + "|" + mbId + "|" + diskId + "|" + macId + "|" + gpuId + "|" + monitorId; 1888 | std::cout << "Raw Combined Hardware ID:" << std::endl; 1889 | std::cout << " " << combinedHardwareId << std::endl << std::endl; 1890 | 1891 | std::cout << "Hashed Hardware ID:" << std::endl; 1892 | std::cout << " " << hwid.HashString(combinedHardwareId) << std::endl << std::endl; 1893 | 1894 | // Software HWID - combine raw IDs first 1895 | std::string combinedSoftwareId = volumeId + "|" + windowsId + "|" + computerNameId + "|" + userId; 1896 | std::cout << "Raw Combined Software ID:" << std::endl; 1897 | std::cout << " " << combinedSoftwareId << std::endl << std::endl; 1898 | 1899 | std::cout << "Hashed Software ID:" << std::endl; 1900 | std::cout << " " << hwid.HashString(combinedSoftwareId) << std::endl << std::endl; 1901 | 1902 | // Complete HWID 1903 | std::cout << "Complete HWID:" << std::endl; 1904 | std::cout << " Hardware Component: " << hwid.HashString(combinedHardwareId) << std::endl; 1905 | std::cout << " Software Component: " << hwid.HashString(combinedSoftwareId) << std::endl << std::endl; 1906 | 1907 | // WMIC-based identifiers - Don't print the warning as GetAllWMICBasedInfo already includes it 1908 | std::cout << hwid.GetAllWMICBasedInfo() << std::endl; 1909 | } 1910 | catch (const std::exception& e) { 1911 | std::cerr << "Exception caught: " << e.what() << std::endl; 1912 | } 1913 | catch (...) { 1914 | std::cerr << "Unknown exception caught!" << std::endl; 1915 | } 1916 | 1917 | return 0; 1918 | } 1919 | --------------------------------------------------------------------------------