Skip to content

Commit

Permalink
added hwmodel and updated readme
Browse files Browse the repository at this point in the history
  • Loading branch information
kernelwernel committed Sep 18, 2023
1 parent 364995d commit e6d7b11
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 33 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ src/vmtest.cpp
resources/
archive/
.vscode/
build/
build/
milestones.md
45 changes: 26 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,42 +17,41 @@ The library is:
- Cross-platform (to an extent)
- Header-only
- Available with C++11 and above
- Able to detect VMware, VirtualBox, QEMU, KVM, Parallels, and much more!
- Able to detect VMware, VirtualBox, QEMU, KVM, Parallels, and much more
- Able to detect semi-VM technologies like hypervisors, docker, and wine
- Able to determine the VM brand
- Incredibly fast (takes around 1~5 milliseconds)
- Memoized, meaning past results are cached and retrieved if ran again for performance benefits

- - -

**IMPORTANT:** The library is currently a beta, so more improvements and cross-compatibility fixes are planned (especially for Windows which I'm currently working on fixing). I don't recommend using this for any serious projects for now.
**IMPORTANT:** The library is currently a beta, so more improvements and cross-compatibility fixes are planned (especially for Windows which I'm currently working on fixing). Although the project is improving on a daily basis, I don't recommend using this for any serious projects for now.

- - -


# Example 🧪
## Example 🧪
```cpp
#include "vmaware.hpp"
#include <iostream>

int main() {
if (VM::detect()) {
std::cout << "Virtual machine detected!\n";
std::cout << "VM name: " << VM::brand() << "\n";
std::cout << "Virtual machine detected!" << std::endl;
std::cout << "VM name: " << VM::brand() << std::endl;
} else {
std::cout << "Running in baremetal\n";
std::cout << "Running in baremetal" << std::endl;
}
}
```


# CLI tool 🔧
## CLI tool 🔧
This project also provides a tiny, but handy CLI tool utilising the full potential of what the library can do.

<img src="assets/image.png" width="500" title="cli">


# Installation 📥
## Installation 📥
To install the library, simply download or copy and paste the [vmaware.hpp](src/vmaware.hpp) file to your project. No CMake or build frameworks are necessary, it's literally that simple.

However, if you want the full project (globally accessible headers with <vmaware.hpp> and the CLI tool), follow these commands:
Expand All @@ -67,37 +66,45 @@ sudo make install
> NOTE: I'm most likely going to change my username in the future. If the github link doesn't exist, search for the VMAware project and you should find it.

# Documentation 📒
## Documentation 📒
You can view the full docs [here](docs/documentation.md). Trust me, it's not too intimidating


# Q&A ❓
## Q&A ❓
- Who is this library for?
> It's designed for anticheat developers, security researchers, VM engineers, and pretty much anybody who needs a practical and rock-solid VM detection mechanism in their project. For example, if you're a gamer developer and you want to prevent exploit developers probing the game in a VM or anybody attempting a ban evasion, this is a suitable project for those use cases.
> It's designed for security researchers, VM engineers, anticheat developers*, and pretty much anybody who needs a practical and rock-solid VM detection mechanism in their project. For example, if you're making a VM and you're testing the effectiveness of concealing itself, or if you're a malware analyst and you want to check if your VM environment is good enough.
- Why another VM detection project?
> There's already loads of projects that have the same goal such as [InviZzzible](https://github.com/CheckPointSW/InviZzzible), [pafish](https://github.com/a0rtega/pafish) and [Al-Khaser](https://github.com/LordNoteworthy/al-khaser). But the difference between the aforementioned projects is that they have little to no support with non-Windows systems. On top of this, I wanted the VM detection techniques to be accessible programmatically for everybody to find something useful out of it rather than providing just a CLI tool like the projects above.
> There's already loads of projects that have the same goal such as [InviZzzible](https://github.com/CheckPointSW/InviZzzible), [pafish](https://github.com/a0rtega/pafish) and [Al-Khaser](https://github.com/LordNoteworthy/al-khaser). But the difference between the aforementioned projects is that they have little to no support with non-Windows systems. On top of this, I wanted the core detection techniques to be accessible programmatically for everybody to get something useful out of it rather than providing just a CLI tool like the projects above.
- Is it possible to spoof the result?
> Yes. There are some techniques that are trivially spoofable, and there's nothing the library can do about it whether it's a false negative or even a false positive. This is a problem that every VM detection project is facing, which is why the library is trying to test every technique possible to get the best result based on the environment it's running under.
- Can I use this for malware?
> This project is not soliciting the development of malware for any malicious purpose. Even if you intend to use it that way, it'll most likely be flagged by antiviruses anyway.
> This project is not soliciting the development of malware for any malicious intentions. Even if you intend to use it that way, it'll most likely be flagged by antiviruses anyway.
- If it's designed for anti-cheat, why is it GPL?
> I used/modified a few GPL-3.0 code from other projects. Works that are derived from that license must use the same license, so I had no choice but to use it. An open-source anti-cheat sounds like a bad idea, and frankly it is for a few reasons. Although it's possible, this isn't a good library for anti-cheats in that regard even if it can be used for that purpose. On the other hand, it can prevent exploit developers probing the game in a VM or anybody attempting a ban evasion, which is worth a mention.
- When will a 1.0 be available?
> Pretty soon, maybe around a week or 2 (I just started university a few days ago, so I can't guarantee anything)
> Pretty soon, maybe around November (I just started university a few days ago, so I can't guarantee anything)

## Issues and pull requests
If you have any suggestions, ideas, or any sort of contribution, feel free to ask! I'll be more than happy to discuss. If you want to personally say something for whatever reason, my discord is `kr.nl`

# Issues and pull requests
If you have any suggestions, ideas, or any sort of contribution, feel free to ask! I'll be more than happy to discuss. If you found this project useful, a star would be appreciated :)
If you found this project useful, a star would be appreciated :)


# Credits ✒️
## Credits ✒️
- [Check Point Research](https://research.checkpoint.com/)
- [Unprotect Project](https://unprotect.it/)
- [Al-Khaser](https://github.com/LordNoteworthy/al-khaser)
- [pafish](https://github.com/a0rtega/pafish)
- [Matteo Malvica](https://www.matteomalvica.com)


# Legal 📜
## Legal 📜
I am not responsible nor liable for any damage you cause through any malicious usage of this project.

License: GPL-3.0
1 change: 1 addition & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
- revise sidt check
- analyse the UUID check technique's efficiency
- create a technique table so i don't have to manually add them for VM::detect() and VM::check()

- ~~make a flagcheck function~~
- ~~create a standard cpuid function (replace __cpuidex bc wine)~~
Expand Down
1 change: 1 addition & 0 deletions docs/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
| Check Wine | Find for a Wine-specific file | `VM::WINE_CHECK` | Windows |
| Check boot time | Analyse the OS uptime | `VM::BOOT` | Yes |
| Check VM files | Find if any VM-specific files exists | `VM::VM_FILES` | Windows |
| Check hwmodel | Check if the sysctl for the hwmodel does not contain the "Mac" string | `VM::HWMODEL` | MacOS |

# Non-technique flags
| Flag | Description |
Expand Down
2 changes: 1 addition & 1 deletion src/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ R"(Usage:
}

void version(void) {
std::cout << "v" << ver << " (" << date << ")\n\n" <<
std::cout << "vmaware " << "v" << ver << " (" << date << ")\n\n" <<
"Derived project of VMAware library at https://github.com/kernelwernel/VMAware"
"License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.\n" <<
"This is free software: you are free to change and redistribute it.\n" <<
Expand Down
77 changes: 65 additions & 12 deletions src/vmaware.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* ██║ ██║██╔████╔██║███████║██║ █╗ ██║███████║██████╔╝█████╗
* ╚██╗ ██╔╝██║╚██╔╝██║██╔══██║██║███╗██║██╔══██║██╔══██╗██╔══╝
* ╚████╔╝ ██║ ╚═╝ ██║██║ ██║╚███╔███╔╝██║ ██║██║ ██║███████╗
* ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ v1.0
* ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ v0.1
*
* A C++ VM detection library
*
Expand Down Expand Up @@ -82,8 +82,8 @@


#if (MSVC)
#include <intrin.h>
#include <windows.h>
#include <intrin.h>
#include <tchar.h>
#include <stdbool.h>
#include <stdio.h>
Expand Down Expand Up @@ -352,7 +352,7 @@ struct VM {
VM(VM&&) = delete; // Delete move constructor

static constexpr u64
VMID = 1 << 0,
VMID = 1 << 0,
BRAND = 1 << 1,
HYPERV_BIT = 1 << 2,
CPUID_0x4 = 1 << 3,
Expand Down Expand Up @@ -385,6 +385,7 @@ struct VM {
WINE_CHECK = 1ULL << 47,
BOOT = 1ULL << 48,
VM_FILES = 1ULL << 49,
HWMODEL = 1ULL << 50,

// settings
NO_MEMO = 1ULL << 63,
Expand Down Expand Up @@ -1643,7 +1644,7 @@ struct VM {
#if (!MSVC)
return false;
#else
if (disabled(WINE)) {
if (disabled(WINE_CHECK)) {
#ifdef __VMAWARE_DEBUG__
debug("WINE: ", "precondition return called");
#endif
Expand Down Expand Up @@ -1676,12 +1677,15 @@ struct VM {
}

#if (MSVC)
// doesn't work for some reason, fix this whenever i have time
/*
SYSTEM_TIME_OF_DAY_INFORMATION SysTimeInfo;
LARGE_INTEGER LastBootTime;
NtQuerySystemInformation(SystemTimeOfDayInformation, &SysTimeInfo, sizeof(SysTimeInfo), 0);
LastBootTime = wmi_Get_LastBootTime();
return ((wmi_LastBootTime.QuadPart - SysTimeInfo.BootTime.QuadPart) / 10000000 != 0); // 0 seconds
*/
#elif (LINUX)
// TODO: finish this shit tomorrow
#endif
Expand Down Expand Up @@ -1764,8 +1768,55 @@ struct VM {
} catch (...) { return false; }


/**
* @brief Check for sysctl hardware model
* @author MacRansom ransomware
* @todo TEST IF THIS WORKS
* @category MacOS
*/
[[nodiscard]] static bool hwmodel() try {
#if (!APPLE)
return false;
#else
if (disabled(HWMODEL)) {
#ifdef __VMAWARE_DEBUG__
debug("HWMODEL: ", "precondition return called");
#endif
return false;
}

auto result = sys_result("sysctl -n hw.model");

// LABEL (ignore this line, it's just a label so I can easily teleport to this line on my IDE with CTRL+F)
std::smatch match;

if (result == nullptr) {
#ifdef __VMAWARE_DEBUG__
debug("HWMODEL: ", "null result received");
#endif
return false;
}

#ifdef __VMAWARE_DEBUG__
debug("HWMODEL: ", "output = ", *result);
#endif

// if string contains "Mac" anywhere in the string, assume it's baremetal
if (std::regex_search(*result, match, std::regex("Mac"))) {
return false;
}

// not sure about the other VMs, more could potentially be added
if (std::regex_search(*result, match, std::regex("VMware"))) {
return add(VMWARE);
}

return true;
#endif
}



// LABEL (ignore this, it's just a label so I can easily teleport to this line on my IDE with CTRL+F)

public:
/**
Expand All @@ -1788,6 +1839,10 @@ struct VM {
}
#endif

if (p_flags == ALL) {
throw std::invalid_argument("Flag argument cannot be set to VM::ALL, consult the documentation's flag list");
}

if (count > 1) {
throw std::invalid_argument("Flag argument must only contain a single option, consult the documentation's flag list");
}
Expand Down Expand Up @@ -1839,6 +1894,7 @@ struct VM {
case VM::WINE_CHECK: result = wine(); break;
case VM::BOOT: result = boot_time(); break;
case VM::VM_FILES: result = vm_files(); break;
case VM::HWMODEL: result = hwmodel(); break;
default: throw std::invalid_argument("Unknown flag provided for VM::check() function");
}

Expand Down Expand Up @@ -1917,20 +1973,17 @@ struct VM {
if (sunbelt_check()) { points += 1; }
if (wine()) { points += 3.5; }
if (boot_time()) { points += 0.5; }
if (vm_files()) { points += 4; }
if (hwmodel()) { points += 2.5; }

/**
* you can change this threshold score to a maximum
* of something like 10~14 if you want to be extremely
* sure, but this can risk the result to be a false
* negative if the detection bar is far too high.
*/
// arbitrary threshold score
const bool result = (points >= 6.5);

sv current_brand = "";

#ifdef __VMAWARE_DEBUG__
for (const auto p : scoreboard) {
std::cout << "\n" << (int)p.second << " : " << p.first;
debug("scoreboard: ", (int)p.second, " : ", p.first);
}
#endif

Expand Down

0 comments on commit e6d7b11

Please sign in to comment.