machine_code.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #include "machine_code.h"
  2. #include <algorithm>
  3. #include <cstring>
  4. #include <sstream>
  5. #include <vector>
  6. #ifdef _WIN32
  7. #ifndef WIN32_LEAN_AND_MEAN
  8. #define WIN32_LEAN_AND_MEAN
  9. #endif
  10. #include <windows.h>
  11. #include <winioctl.h>
  12. #include <intrin.h>
  13. #elif defined(__APPLE__)
  14. #include <sys/sysctl.h>
  15. #include <sys/mount.h>
  16. #include <sys/stat.h>
  17. #else // Linux
  18. #if defined(__x86_64__) || defined(__i386__)
  19. #include <cpuid.h>
  20. #endif
  21. #include <sys/statfs.h>
  22. #include <unistd.h>
  23. #endif
  24. namespace reginfo {
  25. namespace {
  26. // === SHA-256 implementation ===
  27. static const unsigned int SHA256_K[64] = {
  28. 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  29. 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  30. 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  31. 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  32. 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  33. 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  34. 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  35. 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
  36. };
  37. static inline unsigned int rotr(unsigned int x, unsigned int n) {
  38. return (x >> n) | (x << (32 - n));
  39. }
  40. std::string sha256(const std::string& input) {
  41. // Pre-processing: pad the message
  42. std::vector<unsigned char> msg(input.begin(), input.end());
  43. unsigned long long bitLen = msg.size() * 8;
  44. msg.push_back(0x80);
  45. while ((msg.size() + 8) % 64 != 0)
  46. msg.push_back(0x00);
  47. for (int i = 7; i >= 0; --i)
  48. msg.push_back(static_cast<unsigned char>((bitLen >> (i * 8)) & 0xFF));
  49. // Initial hash values
  50. unsigned int H[8] = {
  51. 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
  52. 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
  53. };
  54. // Process each 512-bit chunk
  55. for (size_t chunk = 0; chunk < msg.size(); chunk += 64) {
  56. unsigned int W[64];
  57. for (int i = 0; i < 16; ++i) {
  58. size_t off = chunk + i * 4;
  59. W[i] = (static_cast<unsigned int>(msg[off]) << 24)
  60. | (static_cast<unsigned int>(msg[off + 1]) << 16)
  61. | (static_cast<unsigned int>(msg[off + 2]) << 8)
  62. | static_cast<unsigned int>(msg[off + 3]);
  63. }
  64. for (int i = 16; i < 64; ++i) {
  65. unsigned int s0 = rotr(W[i - 15], 7) ^ rotr(W[i - 15], 18) ^ (W[i - 15] >> 3);
  66. unsigned int s1 = rotr(W[i - 2], 17) ^ rotr(W[i - 2], 19) ^ (W[i - 2] >> 10);
  67. W[i] = W[i - 16] + s0 + W[i - 7] + s1;
  68. }
  69. unsigned int a = H[0], b = H[1], c = H[2], d = H[3];
  70. unsigned int e = H[4], f = H[5], g = H[6], h = H[7];
  71. for (int i = 0; i < 64; ++i) {
  72. unsigned int S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
  73. unsigned int ch = (e & f) ^ (~e & g);
  74. unsigned int temp1 = h + S1 + ch + SHA256_K[i] + W[i];
  75. unsigned int S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
  76. unsigned int maj = (a & b) ^ (a & c) ^ (b & c);
  77. unsigned int temp2 = S0 + maj;
  78. h = g; g = f; f = e; e = d + temp1;
  79. d = c; c = b; b = a; a = temp1 + temp2;
  80. }
  81. H[0] += a; H[1] += b; H[2] += c; H[3] += d;
  82. H[4] += e; H[5] += f; H[6] += g; H[7] += h;
  83. }
  84. // Format as 64 hex characters
  85. char hex[65];
  86. snprintf(hex, sizeof(hex),
  87. "%08X%08X%08X%08X%08X%08X%08X%08X",
  88. H[0], H[1], H[2], H[3], H[4], H[5], H[6], H[7]);
  89. return std::string(hex);
  90. }
  91. #ifdef _WIN32
  92. std::string getCpuIdWin32() {
  93. SetThreadAffinityMask(GetCurrentThread(), 1);
  94. int cpuInfo[4] = {0};
  95. __cpuid(cpuInfo, 1);
  96. unsigned int cpuSerial = (unsigned int)((cpuInfo[0])^ (cpuInfo[1]) ^ (cpuInfo[2])^ (cpuInfo[3]));
  97. __cpuid(cpuInfo, 0x80000000);
  98. unsigned int extMax = static_cast<unsigned int>(cpuInfo[0]);
  99. std::string brand;
  100. if (extMax >= 0x80000004) {
  101. for (unsigned int i = 0x80000002; i <= 0x80000004; ++i) {
  102. __cpuid(cpuInfo, static_cast<int>(i));
  103. brand.append(reinterpret_cast<char*>(cpuInfo), 16);
  104. }
  105. // Trim trailing nulls/spaces
  106. while (!brand.empty() && (brand.back() == '\0' || brand.back() == ' '))
  107. brand.pop_back();
  108. }
  109. return brand + "|" + std::to_string(cpuSerial);
  110. }
  111. std::string getSystemDiskSerialWin32() {
  112. DWORD serialNumber = 0;
  113. char systemDrive[4] = {0};
  114. GetEnvironmentVariableA("SystemDrive", systemDrive, sizeof(systemDrive));
  115. if (systemDrive[0] == '\0')
  116. strcpy_s(systemDrive, "C:");
  117. std::string rootPath = std::string(systemDrive) + "\\";
  118. GetVolumeInformationA(rootPath.c_str(), nullptr, 0, &serialNumber,
  119. nullptr, nullptr, nullptr, 0);
  120. DWORD physSerial = 0;
  121. std::string diskPath = std::string("\\\\.\\") + systemDrive[0] + ":";
  122. HANDLE hDevice = CreateFileA(diskPath.c_str(), 0,
  123. FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
  124. if (hDevice != INVALID_HANDLE_VALUE) {
  125. STORAGE_DEVICE_NUMBER devNum;
  126. DWORD bytesReturned = 0;
  127. if (DeviceIoControl(hDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER,
  128. nullptr, 0, &devNum, sizeof(devNum), &bytesReturned, nullptr)) {
  129. physSerial = devNum.DeviceNumber ^ devNum.PartitionNumber;
  130. }
  131. CloseHandle(hDevice);
  132. }
  133. return std::to_string(serialNumber) + "|" + std::to_string(physSerial);
  134. }
  135. #elif defined(__APPLE__)
  136. std::string getCpuIdMac() {
  137. char buffer[256];
  138. size_t bufLen = sizeof(buffer);
  139. if (sysctlbyname("machdep.cpu.brand_string", buffer, &bufLen, nullptr, 0) == 0) {
  140. return std::string(buffer, bufLen - 1);
  141. }
  142. return "0";
  143. }
  144. std::string getSystemDiskSerialMac() {
  145. struct statfs fs;
  146. if (statfs("/", &fs) == 0) {
  147. unsigned long long diskId = 0;
  148. memcpy(&diskId, &fs.f_fsid, sizeof(fs.f_fsid));
  149. return std::to_string(diskId);
  150. }
  151. return "0";
  152. }
  153. #else // Linux
  154. std::string getCpuIdLinux() {
  155. std::string result;
  156. #if defined(__x86_64__) || defined(__i386__)
  157. unsigned int eax, ebx, ecx, edx;
  158. if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
  159. unsigned int cpuSerial = eax ^ ebx ^ ecx ^ edx;
  160. result = std::to_string(cpuSerial);
  161. }
  162. #endif
  163. FILE* fp = fopen("/proc/cpuinfo", "r");
  164. if (fp) {
  165. char line[256];
  166. std::string modelName;
  167. while (fgets(line, sizeof(line), fp)) {
  168. if (strstr(line, "model name") || strstr(line, "Model Name")) {
  169. const char* colon = strchr(line, ':');
  170. if (colon) modelName = colon + 1;
  171. break;
  172. }
  173. }
  174. fclose(fp);
  175. if (!modelName.empty()) {
  176. while (!modelName.empty() && (modelName.back() == '\n' || modelName.back() == ' '))
  177. modelName.pop_back();
  178. result += "|" + modelName;
  179. }
  180. }
  181. return result.empty() ? "0" : result;
  182. }
  183. std::string getSystemDiskSerialLinux() {
  184. struct statfs fs;
  185. if (statfs("/", &fs) == 0) {
  186. unsigned long long diskId = 0;
  187. memcpy(&diskId, &fs.f_fsid, sizeof(fs.f_fsid));
  188. return std::to_string(diskId);
  189. }
  190. return "0";
  191. }
  192. #endif
  193. } // anonymous namespace
  194. std::string getMachineCode() {
  195. #ifdef _WIN32
  196. std::string raw = getCpuIdWin32() + "|" + getSystemDiskSerialWin32();
  197. #elif defined(__APPLE__)
  198. std::string raw = getCpuIdMac() + "|" + getSystemDiskSerialMac();
  199. #else
  200. std::string raw = getCpuIdLinux() + "|" + getSystemDiskSerialLinux();
  201. #endif
  202. return sha256(raw);
  203. }
  204. } // namespace reginfo