2222 * - License: MIT
2323 */
2424
25- #include < string>
26- #include < iostream>
2725#include < vector>
28- #include < cstdint>
2926#include < chrono>
3027
3128#if (defined(__GNUC__) || defined(__linux__))
32- #include < unistd.h>
3329 #define CLI_LINUX 1
3430#else
3531 #define CLI_LINUX 0
3632#endif
3733
34+ #if (defined(__APPLE__) || defined(__APPLE_CPP__) || defined(__MACH__) || defined(__DARWIN))
35+ #define CLI_APPLE 1
36+ #include < mach-o/dyld.h>
37+ #else
38+ #define CLI_APPLE 0
39+ #endif
3840
3941#if (defined(_MSC_VER) || defined(_WIN32) || defined(_WIN64) || defined(__MINGW32__))
4042 #define CLI_WINDOWS 1
4143 #define WIN32_LEAN_AND_MEAN
4244 #define NOMINMAX
43- #include < windows.h>
4445#else
4546 #define CLI_WINDOWS 0
4647#endif
@@ -63,6 +64,7 @@ std::string grey = "\x1B[38;2;108;108;108m";
6364using u8 = std::uint8_t ;
6465using u16 = std::uint16_t ;
6566using u32 = std::uint32_t ;
67+ using u64 = std::uint64_t ;
6668using i32 = std::int32_t ;
6769
6870enum arg_enum : u8 {
@@ -141,6 +143,179 @@ class win_ansi_enabler_t
141143};
142144#endif
143145
146+ struct SHA256 {
147+ u8 buf[64 ] = {}; // message block buffer
148+ u32 len = 0 ; // bytes currently in buf
149+ u64 bits = 0 ; // total bits processed
150+ u32 s[8 ] = {}; // from h0 to h7
151+
152+ // Initialize state to SHA-256 IVs so that compiler doesn't complain
153+ void init () {
154+ len = 0 ;
155+ bits = 0 ;
156+ s[0 ] = 0x6a09e667 ;
157+ s[1 ] = 0xbb67ae85 ;
158+ s[2 ] = 0x3c6ef372 ;
159+ s[3 ] = 0xa54ff53a ;
160+ s[4 ] = 0x510e527f ;
161+ s[5 ] = 0x9b05688c ;
162+ s[6 ] = 0x1f83d9ab ;
163+ s[7 ] = 0x5be0cd19 ;
164+ }
165+
166+ // bitwise helpers
167+ static u32 rotr (u32 x, int n) { return (x >> n) | (x << (32 - n)); }
168+ static u32 ch (u32 x, u32 y, u32 z) { return (x & y) ^ (~x & z); }
169+ static u32 maj (u32 x, u32 y, u32 z) { return (x & y) ^ (x & z) ^ (y & z); }
170+ static u32 ep0 (u32 x) { return rotr (x, 2 ) ^ rotr (x, 13 ) ^ rotr (x, 22 ); }
171+ static u32 ep1 (u32 x) { return rotr (x, 6 ) ^ rotr (x, 11 ) ^ rotr (x, 25 ); }
172+ static u32 sig0 (u32 x) { return rotr (x, 7 ) ^ rotr (x, 18 ) ^ (x >> 3 ); }
173+ static u32 sig1 (u32 x) { return rotr (x, 17 ) ^ rotr (x, 19 ) ^ (x >> 10 ); }
174+
175+ // we need to process one 512-bit block from buf
176+ void transform () {
177+ static const u32 k[64 ] = {
178+ 0x428a2f98 ,0x71374491 ,0xb5c0fbcf ,0xe9b5dba5 ,0x3956c25b ,0x59f111f1 ,0x923f82a4 ,0xab1c5ed5 ,
179+ 0xd807aa98 ,0x12835b01 ,0x243185be ,0x550c7dc3 ,0x72be5d74 ,0x80deb1fe ,0x9bdc06a7 ,0xc19bf174 ,
180+ 0xe49b69c1 ,0xefbe4786 ,0x0fc19dc6 ,0x240ca1cc ,0x2de92c6f ,0x4a7484aa ,0x5cb0a9dc ,0x76f988da ,
181+ 0x983e5152 ,0xa831c66d ,0xb00327c8 ,0xbf597fc7 ,0xc6e00bf3 ,0xd5a79147 ,0x06ca6351 ,0x14292967 ,
182+ 0x27b70a85 ,0x2e1b2138 ,0x4d2c6dfc ,0x53380d13 ,0x650a7354 ,0x766a0abb ,0x81c2c92e ,0x92722c85 ,
183+ 0xa2bfe8a1 ,0xa81a664b ,0xc24b8b70 ,0xc76c51a3 ,0xd192e819 ,0xd6990624 ,0xf40e3585 ,0x106aa070 ,
184+ 0x19a4c116 ,0x1e376c08 ,0x2748774c ,0x34b0bcb5 ,0x391c0cb3 ,0x4ed8aa4a ,0x5b9cca4f ,0x682e6ff3 ,
185+ 0x748f82ee ,0x78a5636f ,0x84c87814 ,0x8cc70208 ,0x90befffa ,0xa4506ceb ,0xbef9a3f7 ,0xc67178f2
186+ };
187+ u32 m[64 ];
188+ for (u32 i = 0 , j = 0 ; i < 16 ; ++i, j += 4 ) {
189+ m[i] = (u32 )buf[j] << 24 | (u32 )buf[j + 1 ] << 16 | (u32 )buf[j + 2 ] << 8 | (u32 )buf[j + 3 ];
190+ }
191+ for (u32 i = 16 ; i < 64 ; ++i) {
192+ m[i] = sig1 (m[i - 2 ]) + m[i - 7 ] + sig0 (m[i - 15 ]) + m[i - 16 ];
193+ }
194+ u32 a = s[0 ];
195+ u32 b = s[1 ];
196+ u32 c = s[2 ];
197+ u32 d = s[3 ];
198+ u32 e = s[4 ];
199+ u32 f = s[5 ];
200+ u32 g = s[6 ];
201+ u32 h = s[7 ];
202+ for (u32 i = 0 ; i < 64 ; ++i) {
203+ u32 t1 = h + ep1 (e) + ch (e, f, g) + k[i] + m[i];
204+ u32 t2 = ep0 (a) + maj (a, b, c);
205+ h = g;
206+ g = f;
207+ f = e;
208+ e = d + t1;
209+ d = c;
210+ c = b;
211+ b = a;
212+ a = t1 + t2;
213+ }
214+ s[0 ] += a;
215+ s[1 ] += b;
216+ s[2 ] += c;
217+ s[3 ] += d;
218+ s[4 ] += e;
219+ s[5 ] += f;
220+ s[6 ] += g;
221+ s[7 ] += h;
222+ }
223+
224+ // arbitrary bytes into the digest
225+ void update (const u8 * data, size_t n) {
226+ for (size_t i = 0 ; i < n; ++i) {
227+ buf[len++] = data[i];
228+ if (len == 64 ) {
229+ transform ();
230+ bits += 512 ;
231+ len = 0 ;
232+ }
233+ }
234+ }
235+
236+ // 32-byte digest IN big-endian
237+ void final (u8 out[32 ]) {
238+ size_t i = len;
239+ if (len < 56 ) {
240+ buf[i++] = 0x80 ;
241+ while (i < 56 ) buf[i++] = 0 ;
242+ }
243+ else {
244+ buf[i++] = 0x80 ;
245+ while (i < 64 ) buf[i++] = 0 ;
246+ transform ();
247+ for (size_t j = 0 ; j < 56 ; ++j) buf[j] = 0 ;
248+ }
249+ bits += (u64 )len * 8 ;
250+ for (int j = 0 ; j < 8 ; ++j) {
251+ buf[63 - j] = (u8 )((bits >> (8 * j)) & 0xFF );
252+ }
253+ transform ();
254+ for (i = 0 ; i < 4 ; ++i) {
255+ for (size_t j = 0 ; j < 8 ; ++j) {
256+ out[i + j * 4 ] = (u8 )((s[j] >> (24 - i * 8 )) & 0xFF );
257+ }
258+ }
259+ }
260+ };
261+
262+ static std::string exe_path () {
263+ #if (CLI_WINDOWS)
264+ std::vector<char > buf (32768 );
265+ DWORD r = GetModuleFileNameA (NULL , buf.data (), (DWORD )buf.size ());
266+ if (r == 0 || r >= buf.size ()) return {};
267+ return std::string (buf.data (), r);
268+ #elif (CLI_APPLE)
269+ uint32_t sz = 0 ;
270+ _NSGetExecutablePath (nullptr , &sz);
271+ std::vector<char > b (sz);
272+ if (_NSGetExecutablePath (b.data (), &sz) != 0 ) return {};
273+ std::vector<char > resolved (PATH_MAX );
274+ if (realpath (b.data (), resolved.data ())) {
275+ return std::string (resolved.data ());
276+ }
277+ return std::string (b.data ());
278+ #else
279+ std::vector<char > b (PATH_MAX );
280+ ssize_t l = ::readlink (" /proc/self/exe" , b.data (), b.size () - 1 );
281+ if (l <= 0 ) return {};
282+ b[(size_t )l] = ' \0 ' ;
283+ std::vector<char > resolved (PATH_MAX );
284+ if (realpath (b.data (), resolved.data ())) {
285+ return std::string (resolved.data ());
286+ }
287+ return std::string (b.data ());
288+ #endif
289+ }
290+
291+ std::string compute_self_sha256 () {
292+ std::string path = exe_path ();
293+ if (path.empty ()) return {};
294+ std::ifstream ifs (path, std::ios::binary);
295+ if (!ifs) return {};
296+ SHA256 sha;
297+ sha.init ();
298+
299+ std::vector<char > chunk (64 * 1024 );
300+ while (ifs) {
301+ ifs.read (chunk.data (), static_cast <std::streamsize>(chunk.size ()));
302+ std::streamsize r = ifs.gcount ();
303+ if (r > 0 ) {
304+ sha.update (reinterpret_cast <const u8 *>(chunk.data ()), static_cast <size_t >(r));
305+ }
306+ }
307+
308+ u8 digest[32 ];
309+ sha.final (digest);
310+ static const char hex[] = " 0123456789abcdef" ;
311+ std::string out;
312+ out.reserve (64 );
313+ for (int i = 0 ; i < 32 ; ++i) {
314+ out.push_back (hex[(digest[i] >> 4 ) & 0xF ]);
315+ out.push_back (hex[digest[i] & 0xF ]);
316+ }
317+ return out;
318+ }
144319
145320[[noreturn]] static void help (void ) {
146321 std::cout <<
@@ -220,76 +395,75 @@ static const char* color(const u8 score) {
220395
221396[[noreturn]] static void brand_list () {
222397 std::cout <<
223- R"( VirtualBox
224- VMware
225- VMware Express
226- VMware ESX
227- VMware GSX
228- VMware Workstation
229- VMware Fusion
230- bhyve
231- QEMU
232- KVM
233- KVM Hyper-V Enlightenment
234- QEMU+KVM Hyper-V Enlightenment
235- QEMU+KVM
236- Virtual PC
237- Microsoft Hyper-V
238- Microsoft Virtual PC/Hyper-V
239- Parallels
240- Xen HVM
241- ACRN
242- QNX hypervisor
243- Hybrid Analysis
244- Sandboxie
245- Docker
246- Wine
247- Anubis
248- JoeBox
249- ThreatExpert
250- CWSandbox
251- Comodo
252- Bochs
253- Lockheed Martin LMHS
254- NVMM
255- OpenBSD VMM
256- Intel HAXM
257- Unisys s-Par
258- Cuckoo
259- BlueStacks
260- Jailhouse
261- Apple VZ
262- Intel KGT (Trusty)
263- Microsoft Azure Hyper-V
264- Xbox NanoVisor (Hyper-V)
265- SimpleVisor
266- Hyper-V artifact (host with Hyper-V enabled)
267- User-mode Linux
268- IBM PowerVM
269- Google Compute Engine (KVM)
270- OpenStack (KVM)
271- KubeVirt (KVM)
272- AWS Nitro System (KVM-based)
273- Podman
274- WSL
275- OpenVZ
276- ANY.RUN
277- Barevisor
278- HyperPlatform
279- MiniVisor
280- Intel TDX
281- LKVM
282- AMD SEV
283- AMD SEV-ES
284- AMD SEV-SNP
285- Neko Project II
286- NoirVisor
287- Qihoo 360 Sandbox
288- nsjail
289- DBVM
290- UTM
291- )" ;
292-
398+ R"( VirtualBox
399+ VMware
400+ VMware Express
401+ VMware ESX
402+ VMware GSX
403+ VMware Workstation
404+ VMware Fusion
405+ bhyve
406+ QEMU
407+ KVM
408+ KVM Hyper-V Enlightenment
409+ QEMU+KVM Hyper-V Enlightenment
410+ QEMU+KVM
411+ Virtual PC
412+ Microsoft Hyper-V
413+ Microsoft Virtual PC/Hyper-V
414+ Parallels
415+ Xen HVM
416+ ACRN
417+ QNX hypervisor
418+ Hybrid Analysis
419+ Sandboxie
420+ Docker
421+ Wine
422+ Anubis
423+ JoeBox
424+ ThreatExpert
425+ CWSandbox
426+ Comodo
427+ Bochs
428+ Lockheed Martin LMHS
429+ NVMM
430+ OpenBSD VMM
431+ Intel HAXM
432+ Unisys s-Par
433+ Cuckoo
434+ BlueStacks
435+ Jailhouse
436+ Apple VZ
437+ Intel KGT (Trusty)
438+ Microsoft Azure Hyper-V
439+ Xbox NanoVisor (Hyper-V)
440+ SimpleVisor
441+ Hyper-V artifact (host with Hyper-V enabled)
442+ User-mode Linux
443+ IBM PowerVM
444+ Google Compute Engine (KVM)
445+ OpenStack (KVM)
446+ KubeVirt (KVM)
447+ AWS Nitro System (KVM-based)
448+ Podman
449+ WSL
450+ OpenVZ
451+ ANY.RUN
452+ Barevisor
453+ HyperPlatform
454+ MiniVisor
455+ Intel TDX
456+ LKVM
457+ AMD SEV
458+ AMD SEV-ES
459+ AMD SEV-SNP
460+ Neko Project II
461+ NoirVisor
462+ Qihoo 360 Sandbox
463+ nsjail
464+ DBVM
465+ UTM
466+ )" ;
293467 std::exit (0 );
294468}
295469
@@ -687,7 +861,7 @@ static void general(
687861 const VM ::enum_flags dynamic
688862) {
689863 bool notes_enabled = false ;
690-
864+
691865 if (arg_bitset.test (NO_ANSI )) {
692866 detected = (" [ DETECTED ]" );
693867 not_detected = (" [NOT DETECTED]" );
@@ -723,6 +897,11 @@ static void general(
723897 }
724898 #endif
725899
900+ const std::string hash = compute_self_sha256 ();
901+ if (!hash.empty ()) {
902+ std::cout << " SHA256: " << hash << ' \n ' ;
903+ }
904+
726905 const auto t1 = std::chrono::high_resolution_clock::now ();
727906
728907 checker (VM ::VMID , " VMID" );
0 commit comments