Skip to content

Commit 8325998

Browse files
authored
Merge pull request #594 from kernelwernel/dev
New arg handler and guidelines
2 parents b4e50ce + 5d5f73f commit 8325998

5 files changed

Lines changed: 358 additions & 427 deletions

File tree

.github/workflows/updater.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Python script to update documentations and header details on merge
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
jobs:
9+
run-script:
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- name: Checkout repository
14+
uses: actions/checkout@v4
15+
16+
- name: Set up Python
17+
uses: actions/setup-python@v5
18+
with:
19+
python-version: '3.x'
20+
21+
- name: Install dependencies
22+
run: |
23+
pip install -r requirements.txt || true # skip if no file
24+
25+
- name: Run script
26+
run: python auxiliary/updater.py
27+
28+
- name: Commit and push changes
29+
if: success()
30+
run: |
31+
git config user.name "github-actions[bot]"
32+
git config user.email "github-actions[bot]@users.noreply.github.com"
33+
git add -A
34+
git diff-index --quiet HEAD || git commit -m "Automated update after merge"
35+
git push

CONTRIBUTING.md

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,79 @@ Also, please consider adding your name and github in the vmaware.hpp file and th
88

99

1010
## Translations
11-
If you're making translations, please make sure that you actually speak the language, and you have the intention to be as accurate as possible.
12-
13-
What you SHOULDN'T translate are:
14-
- text that's in a codeblock
15-
- text in images
16-
- text of usernames
17-
- code
18-
- and other stuff that should obviously not be translated.
11+
If you're making translations, please make sure that you have the intention to be as accurate as possible. If you're unsure which parts should be translated or not, you can use the other translated files as a reference to guide you.
1912

2013
Using translation software like google translate is allowed, but only if you cross-check between the english and translation version to verify if it's done correctly.
2114

2215
The README is quite big, so this is quite an effort. I'm sure you have better thing to do in your life but if you can do this, it would be greatly appreciated :)
2316

2417

2518
## Code contributions
26-
If you're making code changes to the cli or header file, we have a useful script at `auxiliary/updater.py` that will update:
27-
- the section line numbers in the header banner
28-
- the date of the update
29-
- and the library documentation for technique links
30-
31-
It's highly recommended to use this script before sending the PR so that all the above don't have to be manually updated, which can be time consuming and can potentially creep in some human errors.
19+
The general rules are:
20+
- Keep it C++11 compatible, this is extremely important
21+
- Use snake_case
22+
- Be as simple as possible
23+
- Prefer readability over aggressive optimisations (especially intrinsics)
24+
- Keep indentations at a minimum
25+
- Don't create huge one-liners, try to break down statements line by line
26+
- Write as few lines as possible for what you're trying to achieve
27+
- Document your code and intentions very clearly, but don't overdo them for very obvious code.
28+
- Avoid `std::function`, `std::shared_ptr`, `std::bind`, `std::list`, or very obscure C++ features.
29+
- Indent size should be 4 spaces
30+
31+
There are other formatting rules, which will be covered with a demonstration:
32+
33+
```cpp
34+
int main() {
35+
const u32 number = 10; // 1. use const whenever it should be used.
36+
// 2. use the rust integral type convention from 8 to 64 (i.e. i8, u16, u64, etc...)
37+
// 3. keep the names as simple and clear as possible, don't call it "n", call it "number".
38+
// Try to name the variables into something that can universally be discerned by anybody,
39+
// Make sure it's also context-aware and should make sense. Calling it "tmp" is also fine.
40+
// Consistency is also key in this aspect, don't do "u32 number = find_num()", do find_number().
41+
42+
if (number >= 54) { // 4. avoid magic numbers, put a comment or make a constexpr variable prior to using it,
43+
something(); // preferably the latter.
44+
} else if (number) { // 5. make the if, else if, and else statement lines the same without breaking lines, so don't do:
45+
something_else(); // if ()
46+
} // {
47+
// something();
48+
// }
49+
// else
50+
// {
51+
// something_else();
52+
// }
53+
//
54+
// try to follow as shown in this actual demonstration.
55+
56+
if (
57+
((number % 4) == 0) && // 6. use separate lines for each statement of a condition check. While this might look ok
58+
(number > 50) && // on a single line, in practice your conditions will most likely not be as short and
59+
(number < 100) // and simple as this. Try to avoid multiple condition checks in a single line for simplicity.
60+
) {
61+
something()
62+
}
63+
64+
65+
for (u8 i = 0; i < number; i++) { // 6. Be as simple as possible without using fancy features like iterators if it's not necessary.
66+
something();
67+
}
68+
69+
// Other rules will be added in the future, this is just a rough guideline for the moment.
70+
}
71+
```
72+
73+
> [!WARNING]
74+
> ## Note from the developer:
75+
> It should be mentioned that not all of the codebase is formatted this way. This standard guideline has been introduced 2 years after the project has started, and the lack of any guideline has resulted in the codebase looking fragmented, inconsistent, and very different in some portions due to differing coding styles among developers. This is completely my fault, and it has accumulated technical debt over the years. Although the current state isn't formatted consistently, the guideline is meant to slowly evolve the library into a much simpler version that's approachable to anybody trying to contribute and read through the code.
3276
3377

3478
## I want to add a new technique, how would I do that?
3579
There's a few steps that should be taken:
3680
1. Make sure to add the technique name in the enums of all the techniques in the appropriate place.
3781
2. Add the technique function itself in the technique section of the library. Make sure to add it in the right place, as there's preprocessor directives for each platform (Linux, Windows, and Apple)
3882
3. Add the technique in the technique table situated at the end of the header file. The score should be between 10 and 100. Although there are exceptions, it's advised to follow the aforementioned score range.
83+
4. Add it to the CLI's technique runner list.
3984

4085

4186
## I want to make a major change to the library

docs/documentation.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,9 @@ struct vmaware {
416416
std::uint8_t percentage;
417417
std::uint8_t detected_count;
418418
std::uint8_t technique_count;
419+
std::vector<enum_flags> detected_techniques;
420+
std::vector<std::string> detected_technique_strings;
421+
std::vector<enum_flags> disabled_techniques;
419422
};
420423
```
421424
@@ -534,7 +537,7 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
534537
| `VM::VMWARE_IOMEM` | Check for VMware string in /proc/iomem | 🐧 | 0% | | | | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L5094) |
535538
| `VM::VMWARE_IOPORTS` | Check for VMware string in /proc/ioports | 🐧 | 0% | | | | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L5606) |
536539
| `VM::VMWARE_SCSI` | Check for VMware string in /proc/scsi/scsi | 🐧 | 0% | | | | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L5403) |
537-
| `VM::VMWARE_DMESG` | Check for VMware-specific device name in dmesg output | 🪟 | 0% | Admin | | Disabled by default | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L5422) |
540+
| `VM::VMWARE_DMESG` | Check for VMware-specific device name in dmesg output | 🐧 | 0% | Admin | | Disabled by default | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L5422) |
538541
| `VM::VMWARE_STR` | Check str assembly instruction method for VMware | 🪟 | 0% | | 32-bit | | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L7528) |
539542
| `VM::VMWARE_BACKDOOR` | Check for official VMware io port backdoor technique | 🪟 | 0% | | 32-bit | | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L7553) |
540543
| `VM::MUTEX` | Check for mutex strings of VM brands | 🪟 | 0% | | | | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L7614) |
@@ -584,10 +587,10 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
584587
| `VM::MAC_SYS` | Check for VM-strings in system profiler commands for MacOS | 🍏 | 0% | | | | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L7074) |
585588
| `VM::OBJECTS` | Check for any signs of VMs in Windows kernel object entities | 🪟 | 0% | | | | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L9336) |
586589
| `VM::NVRAM` | Check for known NVRAM signatures that are present on virtual firmware | 🪟 | 0% | Admin | | | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L9505) |
587-
| `VM::SMBIOS_INTEGRITY` | Check if SMBIOS is malformed/corrupted in a way that is typical for VMs | 🪟 | 0% | | | | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L9958) |
588-
| `VM::EDID` | Check for non-standard EDID configurations | 🪟 | 0% | | | | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L9969) |
589-
| `VM::CPU_HEURISTIC` | Check whether the CPU is genuine and its reported instruction capabilities are not masked | 🪟 | 0% | | | | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L10194) |
590-
| `VM::CLOCK` | Check the presence of system timers | 🪟 | 0% | | | | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L10659) |
590+
| `VM::SMBIOS_INTEGRITY` | Check if SMBIOS is malformed/corrupted in a way that is typical for VMs | 🪟 | 0% | | | | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L9957) |
591+
| `VM::EDID` | Check for non-standard EDID configurations | 🪟 | 0% | | | | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L9968) |
592+
| `VM::CPU_HEURISTIC` | Check whether the CPU is genuine and its reported instruction capabilities are not masked | 🪟 | 0% | | | | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L10193) |
593+
| `VM::CLOCK` | Check the presence of system timers | 🪟 | 0% | | | | [link](https://github.com/kernelwernel/VMAware/tree/main/src/vmaware.hpp#L10658) |
591594
<!-- END OF TECHNIQUE DOCUMENTATION -->
592595
593596
<br>

src/cli.cpp

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ enum arg_enum : u8 {
8989
NULL_ARG
9090
};
9191

92-
constexpr u8 max_bits = static_cast<u8>(VM::MULTIPLE) + 1;
9392
constexpr u8 arg_bits = static_cast<u8>(NULL_ARG) + 1;
9493

9594
std::bitset<arg_bits> arg_bitset;
@@ -373,24 +372,6 @@ static bool is_unsupported(VM::enum_flags flag) {
373372
#endif
374373
}
375374

376-
static std::bitset<max_bits> settings() {
377-
std::bitset<max_bits> tmp;
378-
379-
if (arg_bitset.test(HIGH_THRESHOLD)) {
380-
tmp.set(VM::HIGH_THRESHOLD);
381-
}
382-
383-
if (arg_bitset.test(ALL)) {
384-
tmp.set(VM::ALL);
385-
}
386-
387-
if (arg_bitset.test(DYNAMIC)) {
388-
tmp.set(VM::DYNAMIC);
389-
}
390-
391-
return tmp;
392-
}
393-
394375
// just a simple string replacer
395376
static void replace(std::string &text, const std::string &original, const std::string &new_brand) {
396377
size_t start_pos = 0;
@@ -697,7 +678,11 @@ const bool is_anyrun_driver = anyrun_driver();
697678
const bool is_anyrun = (is_anyrun_directory || is_anyrun_driver);
698679

699680

700-
static void general() {
681+
static void general(
682+
const VM::enum_flags high_threshold,
683+
const VM::enum_flags all,
684+
const VM::enum_flags dynamic
685+
) {
701686
bool notes_enabled = false;
702687

703688
if (arg_bitset.test(NO_ANSI)) {
@@ -840,8 +825,7 @@ static void general() {
840825
#endif
841826

842827
// struct containing the whole overview of the VM data
843-
VM::vmaware vm(VM::MULTIPLE, settings());
844-
828+
VM::vmaware vm(VM::MULTIPLE, high_threshold, all, dynamic);
845829

846830
// brand manager
847831
{
@@ -1036,7 +1020,11 @@ static void general() {
10361020
// finishing touches with notes
10371021
if (notes_enabled) {
10381022
if (vm.detected_count != 0) {
1039-
std::cout << note << " If you found a false positive, please make sure to create an issue at https://github.com/kernelwernel/VMAware/issues\n\n";
1023+
std::cout <<
1024+
note <<
1025+
" If you found a false positive, please make sure to create\n \
1026+
an issue at https://github.com/kernelwernel/VMAware/issues\n\n";
1027+
// ^ do not modify the space above
10401028
}
10411029
}
10421030

@@ -1120,7 +1108,7 @@ int main(int argc, char* argv[]) {
11201108
VM::add_custom(35, anyrun_directory);
11211109

11221110
if (arg_count == 0) {
1123-
general();
1111+
general(VM::NULL_ARG, VM::NULL_ARG, VM::DYNAMIC);
11241112
return 0;
11251113
}
11261114

@@ -1224,28 +1212,32 @@ int main(int argc, char* argv[]) {
12241212
static_cast<u32>(arg_bitset.test(CONCLUSION))
12251213
);
12261214

1215+
const VM::enum_flags high_threshold = (arg_bitset.test(HIGH_THRESHOLD) ? VM::HIGH_THRESHOLD : VM::NULL_ARG);
1216+
const VM::enum_flags all = (arg_bitset.test(ALL) ? VM::ALL : VM::NULL_ARG);
1217+
const VM::enum_flags dynamic = (arg_bitset.test(DYNAMIC) ? VM::DYNAMIC : VM::NULL_ARG);
1218+
12271219
if (returners > 0) { // at least one of the options are set
12281220
if (returners > 1) { // more than 2 options are set
12291221
std::cerr << "--stdout, --percent, --detect, --brand, --type, and --conclusion must NOT be a combination, choose only a single one\n";
12301222
return 1;
12311223
}
12321224

12331225
if (arg_bitset.test(STDOUT)) {
1234-
return (!VM::detect(settings()));
1226+
return (!VM::detect(high_threshold, all, dynamic));
12351227
}
12361228

12371229
if (arg_bitset.test(PERCENT)) {
1238-
std::cout << static_cast<u32>(VM::percentage(settings())) << "\n";
1230+
std::cout << static_cast<u32>(VM::percentage(high_threshold, all, dynamic)) << "\n";
12391231
return 0;
12401232
}
12411233

12421234
if (arg_bitset.test(DETECT)) {
1243-
std::cout << VM::detect(settings()) << "\n";
1235+
std::cout << VM::detect(high_threshold, all, dynamic) << "\n";
12441236
return 0;
12451237
}
12461238

12471239
if (arg_bitset.test(BRAND)) {
1248-
std::string brand = VM::brand(VM::MULTIPLE, settings());
1240+
std::string brand = VM::brand(VM::MULTIPLE, high_threshold, all, dynamic);
12491241

12501242
if (is_anyrun && (brand == brands::NULL_BRAND)) {
12511243
brand = "ANY.RUN";
@@ -1257,7 +1249,7 @@ int main(int argc, char* argv[]) {
12571249
}
12581250

12591251
if (arg_bitset.test(TYPE)) {
1260-
std::string type = VM::type(VM::MULTIPLE, settings());
1252+
std::string type = VM::type(VM::MULTIPLE, high_threshold, all, dynamic);
12611253

12621254
if (is_anyrun && (type == brands::NULL_BRAND)) {
12631255
type = "Sandbox";
@@ -1269,7 +1261,7 @@ int main(int argc, char* argv[]) {
12691261
}
12701262

12711263
if (arg_bitset.test(CONCLUSION)) {
1272-
std::string conclusion = VM::conclusion(VM::MULTIPLE, settings());
1264+
std::string conclusion = VM::conclusion(VM::MULTIPLE, high_threshold, all, dynamic);
12731265

12741266
if (is_anyrun) {
12751267
const std::string original = brands::NULL_BRAND;
@@ -1284,6 +1276,6 @@ int main(int argc, char* argv[]) {
12841276
}
12851277

12861278
// at this point, it's assumed that the user's intention is for the general summary to be ran
1287-
general();
1279+
general(high_threshold, all, dynamic);
12881280
return 0;
1289-
}
1281+
}

0 commit comments

Comments
 (0)