Skip to content

Commit 9b71d49

Browse files
committed
2 parents 92c737e + 9c84a2e commit 9b71d49

11 files changed

Lines changed: 711 additions & 169 deletions

CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,12 @@ add_test(executable, "${BUILD_DIR}/${TARGET}")
9191
# release stuff
9292
if (NOT MSVC)
9393
if(CMAKE_BUILD_TYPE MATCHES "Release")
94-
install(TARGETS ${TARGET} DESTINATION ${CMAKE_SOURCE_DIR})
94+
install(TARGETS ${TARGET} DESTINATION /usr/local/bin)
9595
install(FILES "src/vmaware.hpp" DESTINATION /usr/include)
96+
else()
97+
install(TARGETS ${TARGET} DESTINATION ${CMAKE_SOURCE_DIR})
9698
endif()
9799
elseif(MSVC)
98100
set(CMAKE_INSTALL_PREFIX "C:\\Program Files\\YourApplication")
99101
install(TARGETS ${TARGET} DESTINATION .)
100-
endif()
102+
endif()

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ The library is:
1515
- Very easy to use, with only 5 functions in its public interface
1616
- Very flexible, with total fine-grained control over which techniques get executed
1717
- Cross-platform (Windows + MacOS + Linux)
18-
- Compatible with ARM architecture
18+
- Compatible with ARM architecture and 32-bit Windows
1919
- Header-only
2020
- Available with C++11 and above
21-
- Features up to 70+ unique techniques
21+
- Features up to 80+ unique techniques
2222
- Able to detect VMware, VirtualBox, QEMU, KVM, Parallels, and [much more](https://github.com/kernelwernel/VMAware/blob/v0.2/docs/documentation.md#vmbrand)
2323
- Able to detect semi-VM technologies like hypervisors, docker, and wine
2424
- Able to guess the VM brand
@@ -115,7 +115,7 @@ You can view the full docs [here](docs/documentation.md). Trust me, it's not too
115115
> Yes. There are some techniques that are trivially spoofable, and there's nothing the library can do about it whether it's a deliberate 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.
116116
117117
- Can I use this for malware?
118-
> This project is not soliciting the development of malware for obvious reasons. Even if you intend to use it for concealment purposes, it'll most likely be flagged by antiviruses anyway and nothing is obfuscated to begin with. Good luck manually obfuscating 5000 lines of C++ code lmfao
118+
> This project is not soliciting the development of malware for obvious reasons. Even if you intend to use it for concealment purposes, it'll most likely be flagged by antiviruses anyway and nothing is obfuscated to begin with. Good luck manually obfuscating 6000 lines of C++ code lmfao
119119
120120
- Why GPL 3.0 and MIT?
121121
> I would've made it strictly MIT so proprietary software can make use of the library, but some of the techniques employed are from GPL 3.0 projects, and I have no choice but to use the same license for legal reasons. This gave me an idea to make an MIT version without all of the GPL code so it can also be used without forcing your code to be open-source. It should be noted that the MIT version removes **8** techniques, and the lesser the number of mechanisms, the less accurate the overall result might be.
@@ -147,6 +147,10 @@ And if you found this project useful, a star would be appreciated :)
147147
- [Vladyslav Miachkov](https://github.com/fameowner99)
148148
- [(Offensive Security) Danny Quist](chamuco@gmail.com)
149149
- [(Offensive Security) Val Smith](mvalsmith@metasploit.com)
150+
- Tom Liston + Ed Skoudis
151+
- [Tobias Klein](https://www.trapkit.de/index.html)
152+
- [(S21sec) Alfredo Omella](https://www.s21sec.com/)
153+
- [(eEye Digital Security) Derek Soeder]()
150154

151155
<br>
152156

TODO.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
- [ ] revise sidt check
21
- [ ] analyse the UUID check technique's efficiency
32
- [X] fix c++11 debug function param error
43
- [X] completely remove std::system() grep commands
@@ -20,7 +19,8 @@
2019
- [X] add a python script to automatically set the lines of the seperate sections in the header
2120
- [ ] add C++20 concepts for the VM::add_custom() function
2221
- [ ] check for valid monitor technique
23-
22+
- [ ] fix the is_admin code for windows
23+
- [ ] test it on compiler explorer with windows 32-bit settings
2424

2525
# Distant plans
2626
- add ARM support

assets/demo.png

19.6 KB
Loading

docs/documentation.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,7 @@ This will essentially return the VM brand as a `std::string`. The exact possible
9898
- `Anubis`
9999
- `JoeBox`
100100
- `Thread Expert`
101-
- `CW Sandbox`
102-
- `SunBelt`
101+
- `CWSandbox`
103102
- `Comodo`
104103
- `Bochs`
105104

@@ -262,7 +261,7 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
262261
| `VM::VM_PROCESSES` | Check for any VM processes that are active | Windows | 30% | | |
263262
| `VM::LINUX_USER_HOST` | Check for default VM username and hostname for linux | Linux | 35% | | |
264263
| `VM::VBOX_WINDOW_CLASS` | Check for the window class for VirtualBox | Windows | 10% | | GPL |
265-
| `VM::WMIC` | Check top-level default window level | Windows | 20% | | |
264+
| `VM::WMIC` | Check top-level default window level | Windows | 20% | | |
266265
| `VM::GAMARUE` | Check for Gamarue ransomware technique which compares VM-specific Window product IDs | Windows | 40% | | |
267266
| `VM::VMID_0X4` | Check if the CPU manufacturer ID matches that of a VM brand with leaf 0x40000000 | Yes | 100% | | |
268267
| `VM::PARALLELS_VM` | Check for indications of Parallels VM | Windows | 50% | | |
@@ -297,6 +296,7 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
297296
| `VM::OFFSEC_SIDT` | Check for Offensive Security SIDT method | Windows | 60% | | |
298297
| `VM::OFFSEC_SGDT` | Check for Offensive Security SGDT method | Windows | 60% | | |
299298
| `VM::OFFSEC_SLDT` | Check for Offensive Security SLDT method | Windows | 20% | | |
299+
| `VM::VPC_SIDT` | Check for VPC range for SIDT | Windows | 15% | | |
300300
| `VM::HYPERV_BOARD` | Check for Hyper-V string in motherboard | Windows | 45% | | |
301301
| `VM::VM_FILES_EXTRA` | Check for VPC and Parallels files | Windows | 70% | | |
302302

papers/0003921.pdf

635 KB
Binary file not shown.
645 KB
Binary file not shown.
211 KB
Binary file not shown.

src/cli.cpp

Lines changed: 84 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,12 @@ R"(Usage:
6262
6363
Options:
6464
-h | --help prints this help menu
65-
-v | --version print version and other stuff
65+
-v | --version print cli version and other details
6666
-d | --detect returns the result as a boolean (1 = VM, 0 = baremetal)
6767
-s | --stdout returns either 0 or 1 to STDOUT without any text output (0 = VM, 1 = baremetal)
6868
-b | --brand returns the VM brand string (consult documentation for full output list)
6969
-p | --percent returns the VM percentage between 0 and 100
70+
-c | --conclusion returns the conclusion message string
7071
)";
7172
}
7273

@@ -79,6 +80,68 @@ void version(void) {
7980
"Developed and maintained by kernelwernel, see https://github.com/kernelwernel\n";
8081
}
8182

83+
const char* color(const std::uint8_t score) {
84+
if (score == 0) {
85+
return red;
86+
} else if (score <= 12) {
87+
return red;
88+
} else if (score <= 25) {
89+
return red_orange;
90+
} else if (score < 50) {
91+
return red_orange;
92+
} else if (score <= 62) {
93+
return orange;
94+
} else if (score <= 75) {
95+
return green_orange;
96+
} else if (score < 100) {
97+
return green;
98+
} else if (score == 100) {
99+
return green;
100+
}
101+
102+
return "";
103+
}
104+
105+
std::string message(const std::uint8_t score, const std::string &brand) {
106+
constexpr const char* baremetal = "Running in baremetal";
107+
constexpr const char* very_unlikely = "Very unlikely a VM";
108+
constexpr const char* unlikely = "Unlikely a VM";
109+
110+
std::string potentially = "Potentially a VM";
111+
std::string might = "Might be a VM";
112+
std::string likely = "Likely a VM";
113+
std::string very_likely = "Very likely a VM";
114+
std::string inside_vm = "Running inside a VM";
115+
116+
if (brand != "Unknown") {
117+
potentially = "Potentially a " + brand + " VM";
118+
might = "Might be a " + brand + " VM";
119+
likely = "Likely a " + brand + " VM";
120+
very_likely = "Very likely a " + brand + " VM";
121+
inside_vm = "Running inside a " + brand + " VM";
122+
}
123+
124+
if (score == 0) {
125+
return baremetal;
126+
} else if (score <= 12) {
127+
return very_unlikely;
128+
} else if (score <= 25) {
129+
return unlikely;
130+
} else if (score < 50) {
131+
return potentially;
132+
} else if (score <= 62) {
133+
return might;
134+
} else if (score <= 75) {
135+
return likely;
136+
} else if (score < 100) {
137+
return very_likely;
138+
} else if (score == 100) {
139+
return inside_vm;
140+
}
141+
142+
return "Unknown error";
143+
}
144+
82145
int main(int argc, char* argv[]) {
83146
#if (MSVC)
84147
win_ansi_enabler_t ansi_enabler;
@@ -177,16 +240,27 @@ int main(int argc, char* argv[]) {
177240
checker(VM::OFFSEC_SIDT, "Offensive Security SIDT");
178241
checker(VM::OFFSEC_SGDT, "Offensive Security SGDT");
179242
checker(VM::OFFSEC_SLDT, "Offensive Security SLDT");
243+
checker(VM::VPC_SIDT, "VirtualPC SIDT");
180244
checker(VM::HYPERV_BOARD, "Hyper-V motherboard");
181245
checker(VM::VM_FILES_EXTRA, "Extra VM files");
246+
checker(VM::VMWARE_IOMEM, "/proc/iomem file");
247+
checker(VM::VMWARE_IOPORTS, "/proc/ioports file");
248+
checker(VM::VMWARE_SCSI, "/proc/scsi/scsi file");
249+
checker(VM::VMWARE_DMESG, "VMware dmesg");
250+
checker(VM::VMWARE_EMULATION, "VMware emulation mode");
251+
checker(VM::VMWARE_STR, "STR instruction");
252+
checker(VM::VMWARE_BACKDOOR, "VMware IO port backdoor");
253+
checker(VM::SMSW, "SMSW instruction");
254+
checker(VM::VMWARE_PORT_MEM, "VMware port memory");
255+
182256
std::printf("\n");
183257

184258
const std::string brand = VM::brand();
185259

186260
std::cout << "VM brand: " << (brand == "Unknown" ? red : green) << brand << ansi_exit << "\n";
187261

188262
const char* percent_color = "";
189-
std::uint8_t percent = VM::percentage();
263+
const std::uint8_t percent = VM::percentage();
190264

191265
if (percent == 0) {
192266
percent_color = red;
@@ -206,52 +280,8 @@ int main(int argc, char* argv[]) {
206280

207281
std::cout << "VM confirmation: " << (is_detected ? green : red) << std::boolalpha << is_detected << std::noboolalpha << ansi_exit << "\n\n";
208282

209-
const char* conclusion_color = "";
210-
std::string conclusion_message = "";
211-
212-
constexpr const char* baremetal = "Running in baremetal";
213-
constexpr const char* very_unlikely = "Very unlikely a VM";
214-
constexpr const char* unlikely = "Unlikely a VM";
215-
216-
std::string potentially = "Potentially a VM";
217-
std::string might = "Might be a VM";
218-
std::string likely = "Likely a VM";
219-
std::string very_likely = "Very likely a VM";
220-
std::string inside_vm = "Running inside a VM";
221-
222-
if (brand != "Unknown") {
223-
potentially = "Potentially a " + brand + " VM";
224-
might = "Might be a " + brand + " VM";
225-
likely = "Likely a " + brand + " VM";
226-
very_likely = "Very likely a " + brand + " VM";
227-
inside_vm = "Running inside a " + brand + " VM";
228-
}
229-
230-
if (percent == 0) {
231-
conclusion_color = red;
232-
conclusion_message = baremetal;
233-
} else if (percent <= 12) {
234-
conclusion_color = red;
235-
conclusion_message = very_unlikely;
236-
} else if (percent <= 25) {
237-
conclusion_color = red_orange;
238-
conclusion_message = unlikely;
239-
} else if (percent < 50) { // not <= on purpose
240-
conclusion_color = red_orange;
241-
conclusion_message = potentially;
242-
} else if (percent <= 62) {
243-
conclusion_color = orange;
244-
conclusion_message = might;
245-
} else if (percent <= 75) {
246-
conclusion_color = green_orange;
247-
conclusion_message = likely;
248-
} else if (percent < 100) {
249-
conclusion_color = green;
250-
conclusion_message = very_likely;
251-
} else if (percent == 100) {
252-
conclusion_color = green;
253-
conclusion_message = inside_vm;
254-
}
283+
const char* conclusion_color = color(percent);
284+
std::string conclusion_message = message(percent, brand);
255285

256286
std::cout
257287
<< bold
@@ -282,11 +312,16 @@ int main(int argc, char* argv[]) {
282312
std::cout << VM::brand() << "\n";
283313
return 0;
284314
} else if (cmp(arg, "-p") || cmp(arg, "--percent")) {
285-
std::cout << VM::percentage() << "\n";
315+
std::cout << static_cast<std::uint32_t>(VM::percentage()) << "\n";
286316
return 0;
287317
} else if (cmp(arg, "-d") || cmp(arg, "--detect")) {
288318
std::cout << VM::detect() << "\n";
289319
return 0;
320+
} else if (cmp(arg, "-c") || cmp(arg, "--conclusion")) {
321+
const std::uint8_t percent = VM::percentage();
322+
const std::string brand = VM::brand();
323+
std::cout << message(percent, brand) << "\n";
324+
return 0;
290325
} else {
291326
std::cerr << "Unknown argument provided, consult the help menu with --help\n";
292327
return 1;

0 commit comments

Comments
 (0)