diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5e4b9ba2..55bf7fa8 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,21 +6,29 @@ project(
LANGUAGES CXX
)
-
-# set c++ standard
+# set C++ standard
if(NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 20)
endif()
-
-
-# compiler flags
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
+if(MSVC)
+ # Globally disable specific MSVC warnings from external headers
+ add_compile_options(
+ /wd5039 # 'TpSetCallbackCleanupGroup' potentially throwing
+ /wd4820 # padding added after data member
+ /wd4626 # deleted assignment operator
+ /wd5045 # Spectre mitigation notice
+ /wd4668 # undefined macro replaced with '0'
+ )
+endif()
+
+# compiler flags
if (MSVC)
set(CMAKE_CXX_FLAGS "/Wall /W4 /EHsc")
else()
- # linux and apple
+ # Linux and Apple
set(CMAKE_CXX_FLAGS "-Wextra -Wall -Wextra -Wconversion -Wdouble-promotion -Wno-unused-parameter -Wno-unused-function -Wno-sign-conversion")
endif()
@@ -28,13 +36,12 @@ if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -lstdc++ -lm")
endif()
-
# find available compilers
if (LINUX)
find_program(CLANGPP_EXECUTABLE NAMES clang++)
find_program(GPP_EXECUTABLE NAMES g++)
- # select compiler with preference for clang++ (just a personal choice of mine, i'm kinda obsessed with llvm honestly)
+ # select compiler with preference for clang++
if(CLANGPP_EXECUTABLE)
set(CMAKE_CXX_COMPILER "${CLANGPP_EXECUTABLE}")
get_filename_component(COMPILER_NAME ${CLANGPP_EXECUTABLE} NAME)
@@ -45,67 +52,59 @@ if (LINUX)
endif()
message(STATUS "Compiler: ${COMPILER_NAME}")
-#message(STATUS "Compiler version: ${CMAKE_CXX_COMPILER_VERSION}")
-
-
# fetch and set build type
set(available_build_types Debug Release)
if(NOT CMAKE_BUILD_TYPE)
-set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build (Debug or Release)" FORCE)
+ set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build (Debug or Release)" FORCE)
endif()
-
# Define preprocessor macros based on the build type
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
-add_compile_definitions(__VMAWARE_DEBUG__)
+ add_compile_definitions(__VMAWARE_DEBUG__)
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
-add_compile_definitions(__VMAWARE_RELEASE__)
+ add_compile_definitions(__VMAWARE_RELEASE__)
endif()
-
# general variables
set(PROJECT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(BUILD_DIR "${PROJECT_DIR}/build")
set(TARGET "vmaware")
-
# debug/release CXX flag options
if (MSVC)
if(CMAKE_BUILD_TYPE MATCHES "Debug")
- MESSAGE(STATUS "Build set to debug mode")
+ message(STATUS "Build set to debug mode")
elseif(CMAKE_BUILD_TYPE MATCHES "Release")
- MESSAGE(STATUS "Build set to release mode")
+ message(STATUS "Build set to release mode")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /O2")
endif()
elseif(APPLE)
if(CMAKE_BUILD_TYPE MATCHES "Debug")
- MESSAGE(STATUS "Build set to debug mode")
+ message(STATUS "Build set to debug mode")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fsanitize=address")
elseif(CMAKE_BUILD_TYPE MATCHES "Release")
- MESSAGE(STATUS "Build set to release mode")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g0 -O2")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -mtune=native")
+ message(STATUS "Build set to release mode")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g0 -O2 -march=native -mtune=native")
endif()
elseif(LINUX)
if(CMAKE_BUILD_TYPE MATCHES "Debug")
- MESSAGE(STATUS "Build set to debug mode")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fmax-errors=5 -DDEBUG -O0 -fsanitize=address,leak") # todo, add ubsan
+ message(STATUS "Build set to debug mode")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fmax-errors=5 -DDEBUG -O0 -fsanitize=address,leak")
elseif(CMAKE_BUILD_TYPE MATCHES "Release")
- MESSAGE(STATUS "Build set to release mode")
+ message(STATUS "Build set to release mode")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g0 -O2")
- if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64")
+ if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -mtune=native")
elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=native")
endif()
endif()
else()
- MESSAGE(STATUS "Build set to release mode")
+ message(STATUS "Build set to release mode")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
endif()
-
# add executable
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${BUILD_DIR}")
add_executable(${TARGET} "src/cli.cpp")
@@ -114,19 +113,17 @@ if(NOT DEFINED CMAKE_CXX_STANDARD)
endif()
set_property(TARGET ${TARGET} PROPERTY CXX_STANDARD_REQUIRED ON)
-
# CTest stuff
include(CTest)
enable_testing()
set(ARGUMENTS "--all")
if(MSVC)
-add_test(executable, "${BUILD_DIR}/Release/${TARGET}")
+ add_test(executable "${BUILD_DIR}/Release/${TARGET}")
else()
-add_test(NAME TARGET COMMAND "${BUILD_DIR}/${TARGET}" ${ARGUMENTS})
+ add_test(NAME TARGET COMMAND "${BUILD_DIR}/${TARGET}" ${ARGUMENTS})
endif()
-
-# release stuff
+# install rules
if (NOT MSVC)
if(CMAKE_BUILD_TYPE MATCHES "Release")
install(TARGETS ${TARGET} DESTINATION /usr/bin)
@@ -142,4 +139,4 @@ elseif(MSVC)
set(HEADER_INSTALL_PATH "C:\\Program Files (x86)\\YourLibrary\\include")
install(FILES "src/vmaware.hpp" DESTINATION "${HEADER_INSTALL_PATH}")
install(FILES "src/vmaware_MIT.hpp" DESTINATION "${HEADER_INSTALL_PATH}")
-endif()
\ No newline at end of file
+endif()
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index aabda035..ae9ef256 100755
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -13,9 +13,8 @@ You can create an issue, and I will reply within 24 hours. We have too much free
## Extra
-We have a tool that can update the MIT file and other details of the library with a python script for maintenance purposes. The script at `auxiliary/updater.py` will update:
+We have a useful script at `auxiliary/updater.py` will update:
- the section line numbers in the header banner
- the date of the update
-- the MIT file by copying the GPL file and removing every GPL code (so that you don't have to make the same changes on 2 different files separately, just focus on vmaware.hpp and let the script manage the vmaware_MIT.hpp file)
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.
\ No newline at end of file
diff --git a/COPYING b/COPYING
deleted file mode 100755
index 3877ae0a..00000000
--- a/COPYING
+++ /dev/null
@@ -1,674 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-
-Also add information on how to contact you by electronic and paper mail.
-
- If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
- Copyright (C)
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-.
-
- The GNU General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License. But first, please read
-.
diff --git a/README.md b/README.md
index ad6e9671..ccd18fb0 100755
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@ The library is:
- Header-only
- Free of any external dependencies
- Memoized, meaning past results are cached and retrieved if ran again for performance benefits
-- Contains separate MIT and GPL-3.0 compliant library header files
+- Fully MIT-licensed, allowing unrestricted use and distribution
@@ -116,34 +116,16 @@ Optionally, you can create a debug build by appending `-DCMAKE_BUILD_TYPE=Debug`
-
-### Vcpkg installation
-```bash
-# Note: the package is MIT. The GPL version doesn't exist.
-vcpkg install vmaware-vm-detection
-```
-
-
-
### CMake installation
```cmake
# edit this
set(DIRECTORY "/path/to/your/directory/")
-# if you want the MIT version, toggle this to ON
-option(MIT "MIT version" OFF)
-
-if (MIT)
- set(EXTENSION "_MIT")
-else()
- set(EXTENSION "")
-endif()
-
-set(DESTINATION "${DIRECTORY}vmaware${EXTENSION}.hpp")
+set(DESTINATION "${DIRECTORY}vmaware.hpp")
if (NOT EXISTS ${DESTINATION})
message(STATUS "Downloading VMAware")
- set(URL "https://github.com/kernelwernel/VMAware/releases/latest/download/vmaware${EXTENSION}.hpp")
+ set(URL "https://github.com/kernelwernel/VMAware/releases/latest/download/vmaware.hpp")
file(DOWNLOAD ${URL} ${DESTINATION} SHOW_PROGRESS)
else()
message(STATUS "VMAware already downloaded, skipping")
@@ -241,16 +223,6 @@ You can view the full docs [here](docs/documentation.md). All the details such a
-
-Why GPL-3.0 and MIT?
-
-
-> 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 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 6% of total techniques, and the lesser the number of techniques, the less accurate the overall result might be, but this has rarely any effective difference.
-
-
-
I have linker errors when compiling
@@ -306,4 +278,4 @@ And if you found this project useful, a star would be appreciated :)
## Legal 📜
I am not responsible nor liable for any damage you cause through any malicious usage of this project.
-License: GPL-3.0/MIT
+License: MIT
diff --git a/TODO.md b/TODO.md
index 3a85d4a8..94b2bb8d 100755
--- a/TODO.md
+++ b/TODO.md
@@ -8,7 +8,6 @@
- [ ] add a .so, .dll, and .dylib shared object files in the release
- [ ] /sys/class/dmi/id/product_name check this in qemu
- [ ] fix "dmidecode not found" error
-- [ ] rearrange the techniques so that the more likely ones will be executed first
- [ ] implement techniques from here https://www.cyberciti.biz/faq/linux-determine-virtualization-technology-command/
- [ ] implement techniques from virt-what
diff --git a/auxiliary/MIT_test.cpp b/auxiliary/MIT_test.cpp
deleted file mode 100755
index 543b3394..00000000
--- a/auxiliary/MIT_test.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#include "vmaware_MIT.hpp"
-#include
-
-int main() {
- if (VM::detect()) {
- std::cout << "Virtual machine detected!" << "\n";
- } else {
- std::cout << "Running on baremetal" << "\n";
- }
-
- std::cout << "VM name: " << VM::brand() << "\n";
- std::cout << "VM type: " << VM::type() << "\n";
- std::cout << "VM certainty: " << (int)VM::percentage() << "%" << "\n";
-}
\ No newline at end of file
diff --git a/auxiliary/add_technique.py b/auxiliary/add_technique.py
index a9095388..3ac3ae51 100755
--- a/auxiliary/add_technique.py
+++ b/auxiliary/add_technique.py
@@ -26,7 +26,7 @@
#
# - Made by: @kernelwernel (https://github.com/kernelwernel)
# - Repository: https://github.com/kernelwernel/VMAware
-# - License: GPL 3.0
+# - License: MIT
import questionary
import sys
diff --git a/auxiliary/benchmark.cpp b/auxiliary/benchmark.cpp
index f0eb6ed3..f7ed3742 100755
--- a/auxiliary/benchmark.cpp
+++ b/auxiliary/benchmark.cpp
@@ -17,7 +17,7 @@
* ===============================================================
*
* - Repository: https://github.com/kernelwernel/VMAware
- * - License: GPL 3.0
+ * - License: MIT
*/
#include "../src/vmaware.hpp"
diff --git a/auxiliary/cpuid_fuzzer.c b/auxiliary/cpuid_fuzzer.c
index 1862d2bd..ff4a2cc5 100755
--- a/auxiliary/cpuid_fuzzer.c
+++ b/auxiliary/cpuid_fuzzer.c
@@ -17,8 +17,8 @@
*
* - Made by: @kernelwernel (https://github.com/kernelwernel)
* - Repository: https://github.com/kernelwernel/VMAware
- * - License: GPL 3.0
- */
+ * - License: MIT
+ */
#include
diff --git a/auxiliary/test_standards.sh b/auxiliary/test_standards.sh
index d52175da..f7356f8e 100755
--- a/auxiliary/test_standards.sh
+++ b/auxiliary/test_standards.sh
@@ -17,7 +17,7 @@
#
# - Made by: @kernelwernel (https://github.com/kernelwernel)
# - Repository: https://github.com/kernelwernel/VMAware
-# - License: GPL 3.0
+# - License: MIT
clear
diff --git a/auxiliary/updater.py b/auxiliary/updater.py
index 007a5e85..4fbaadf6 100755
--- a/auxiliary/updater.py
+++ b/auxiliary/updater.py
@@ -17,17 +17,13 @@
# the structure of the headers for anybody reading it for the first
# time, it's more of a guide to point which parts are this and that.
#
-# 2. Convert the GPL file (vmaware.hpp) into an MIT file (vmaware_MIT.hpp).
-# In other words, it'll remove all the GPL code so that it qualifies
-# as MIT compliant.
-#
-# 3. Update the dates in the banner, example: "1.9 (Septmber 2024)"
+# 2. Update the dates in the banner, example: "1.9 (Septmber 2024)"
#
# ===============================================================
#
# - Made by: @kernelwernel (https://github.com/kernelwernel)
# - Repository: https://github.com/kernelwernel/VMAware
-# - License: GPL 3.0
+# - License: MIT
import sys
@@ -40,71 +36,11 @@
ansi_exit = "\033[0m"
gpl_file = os.path.join('..', 'src', 'vmaware.hpp')
-mit_file = os.path.join('..', 'src', 'vmaware_MIT.hpp')
-
-def update_MIT():
- gpl_string = '/* GPL */'
- license_string = ' * - License: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)'
- mit_full_license = ''' * - License: MIT
- *
- * MIT License
- *
- * Copyright (c) 2025 kernelwernel
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
-'''
-
- if not os.path.exists(gpl_file):
- print("vmaware.hpp file not found, aborting")
- sys.exit(1)
-
- if not os.path.exists(mit_file):
- print("vmaware_MIT.hpp file not found, aborting")
- sys.exit(1)
-
-
-
- with open(gpl_file, 'r') as file:
- lines = file.readlines()
-
- add_string_added = False
-
- filtered_lines = []
- for line in lines:
- if gpl_string in line:
- # skip
- continue
- if license_string in line:
- filtered_lines.append(mit_full_license)
- else:
- filtered_lines.append(line)
-
- with open(mit_file, 'w') as file:
- file.writelines(filtered_lines)
-
-
def update_sections(filename):
with open(filename, 'r') as vmaware_read:
header_content = vmaware_read.readlines()
- # fetch important portions
enum = "enum enum_flags"
cpu = "struct cpu {"
memo = "struct memo {"
@@ -114,9 +50,6 @@ def update_sections(filename):
public = "public: // START OF PUBLIC FUNCTIONS"
external = "// ============= EXTERNAL DEFINITIONS ============="
- # set up the arrays
- pointer_array = []
- pair_array = []
keywords = [enum, cpu, memo, util, techniques, core, public, external]
scanner_keywords = [
"__ENUM__",
@@ -129,34 +62,22 @@ def update_sections(filename):
"__EXTERNAL__"
]
- # set the indexes
+ pointer_array = []
file_pointer = 0
array_index = 0
-
- # loop and append if keyword is found
for line in header_content:
if keywords[array_index] in line:
if array_index != len(keywords) - 1:
array_index += 1
-
pointer_array.append(file_pointer)
-
file_pointer += 1
+ pair_array = []
+ for i, scanner in enumerate(scanner_keywords):
+ if i < len(pointer_array):
+ pair_array.append((scanner, pointer_array[i]))
- # create the pair array
- i = 0
- for scanner in scanner_keywords:
- tmp_pair = (scanner, pointer_array[i])
- pair_array.append(tmp_pair)
- if i != len(pointer_array) - 1:
- i += 1
-
-
- MACRO = 0
- FILE_LINE = 1
- index = 0
banner = [
" * - enums for publicly accessible techniques => line __ENUM__",
" * - struct for internal cpu operations => line __CPU__",
@@ -168,101 +89,62 @@ def update_sections(filename):
" * - start of externally defined variables => line __EXTERNAL__"
]
- # replace the macro strings with the file line numbers
- for pair in pair_array:
- for line in banner:
- if pair[MACRO] in line:
- banner[index] = line.replace(pair[MACRO], str(pair[FILE_LINE]))
- index += 1
- continue
-
- # manual filters
- tmp = banner[4]
- banner[4] = banner[5]
- banner[5] = tmp
+ index = 0
+ for macro, line_no in pair_array:
+ for j, text in enumerate(banner):
+ if macro in text:
+ banner[j] = text.replace(macro, str(line_no))
+ break
+
+ banner[4], banner[5] = banner[5], banner[4]
- # get the index file line of the section string
section_line = 0
- section_str = " * ============================== SECTIONS =================================="
+ section_marker = " * ============================== SECTIONS =================================="
for line in header_content:
- if section_str in line:
+ if section_marker in line:
break
section_line += 1
section_line += 1
- # write to the header file
- for i in range(len(banner)):
- header_content[section_line + i] = banner[i] + '\n'
+ for i, new_line in enumerate(banner):
+ header_content[section_line + i] = new_line + '\n'
+
with open(filename, 'w') as file:
file.writelines(header_content)
-
def update_date(filename):
- # fetch the first arg, which is supposed to be the new version number for a new release
args = sys.argv
first_arg = args[1] if len(args) > 1 else None
-
with open(filename, 'r') as file:
header_content = file.readlines()
- index = 0
banner_line = " * ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ "
-
- # fetch the index of where the line should be updated
+ index = 0
for line in header_content:
- if (banner_line not in line):
- index += 1
- else:
+ if banner_line in line:
break
+ index += 1
- # find "X.X.X", where X is 0-9
def find_pattern(base_str):
- pattern = r'\d+\.\d+.\d+'
-
- # Search for the pattern in the text
+ pattern = r'\d+\.\d+\.\d+'
match = re.search(pattern, base_str)
-
- # find match
if match:
return match.group()
- print("match found")
- else:
- print(f"Version number not found for {red}{bold}{base_str}{ansi_exit}, aborting")
- sys.exit(1)
-
+ print(f"Version number not found for {red}{bold}{base_str}{ansi_exit}, aborting")
+ sys.exit(1)
- # fetch the new version
header_version = find_pattern(header_content[index])
- if first_arg == None:
- arg_version = header_version
- else:
- arg_version = find_pattern(first_arg)
-
- new_version = ""
- new_date = ""
+ arg_version = find_pattern(first_arg) if first_arg else header_version
+ new_date = datetime.now().strftime("%B %Y")
+ new_content = banner_line + arg_version + " (" + new_date + ")"
- # set the version and date
- new_version = arg_version
- new_date = datetime.now().strftime("%B") + " " + str(datetime.now().year)
-
- # this will be the new content
- new_content = banner_line + new_version + " (" + new_date + ")"
-
- if 0 < index <= len(header_content):
- header_content[index] = new_content + '\n'
- else:
- print(f"Line number {red}{line_number} is out of range.")
- sys.exit(1)
+ header_content[index] = new_content + '\n'
with open(filename, 'w') as file:
- file.writelines(header_content)
-
+ file.writelines(header_content)
-update_MIT()
update_sections(gpl_file)
-update_sections(mit_file)
-update_date(gpl_file)
-update_date(mit_file)
\ No newline at end of file
+update_date(gpl_file)
\ No newline at end of file
diff --git a/auxiliary/vmaware_download.cmake b/auxiliary/vmaware_download.cmake
index b6c4c5c8..43845779 100755
--- a/auxiliary/vmaware_download.cmake
+++ b/auxiliary/vmaware_download.cmake
@@ -16,33 +16,24 @@
# include(/path/to/vmaware_download.cmake)
#
# EXAMPLE USAGE:
-# download_vmaware("/path/to/your/destination/directory/" OFF)
+# download_vmaware("/path/to/your/destination/directory/")
#
-# NOTE:
-# if you want the MIT version, switch the OFF to ON in the above example
#
# ===============================================================
#
# - Made by: @kernelwernel (https://github.com/kernelwernel)
# - Repository: https://github.com/kernelwernel/VMAware
-
-function(download_vmaware directory mit_version)
+function(download_vmaware directory)
set(DIRECTORY "${directory}" CACHE STRING "Directory to save VMAware header")
- if (mit_version)
- set(EXTENSION "_MIT")
- else()
- set(EXTENSION "")
- endif()
-
- set(DESTINATION "${DIRECTORY}/vmaware${EXTENSION}.hpp")
+ set(DESTINATION "${DIRECTORY}/vmaware.hpp")
if (NOT EXISTS ${DESTINATION})
message(STATUS "Downloading VMAware")
- set(URL "https://github.com/kernelwernel/VMAware/releases/latest/download/vmaware${EXTENSION}.hpp")
+ set(URL "https://github.com/kernelwernel/VMAware/releases/latest/download/vmaware.hpp")
file(DOWNLOAD ${URL} ${DESTINATION} SHOW_PROGRESS)
else()
message(STATUS "VMAware already downloaded, skipping")
endif()
-endfunction()
+endfunction()
\ No newline at end of file
diff --git a/auxiliary/vmtest.cpp b/auxiliary/vmtest.cpp
deleted file mode 100755
index b50b1b4e..00000000
--- a/auxiliary/vmtest.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * ██╗ ██╗███╗ ███╗ █████╗ ██╗ ██╗ █████╗ ██████╗ ███████╗
- * ██║ ██║████╗ ████║██╔══██╗██║ ██║██╔══██╗██╔══██╗██╔════╝
- * ██║ ██║██╔████╔██║███████║██║ █╗ ██║███████║██████╔╝█████╗
- * ╚██╗ ██╔╝██║╚██╔╝██║██╔══██║██║███╗██║██╔══██║██╔══██╗██╔══╝
- * ╚████╔╝ ██║ ╚═╝ ██║██║ ██║╚███╔███╔╝██║ ██║██║ ██║███████╗
- * ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝
- *
- * C++ VM detection library
- *
- * ===============================================================
- *
- * This program serves as a testing ground, it's not interesting tbh
- * so I recommend you move on
- *
- * ===============================================================
- *
- * - Made by: @kernelwernel (https://github.com/kernelwernel)
- * - Repository: https://github.com/kernelwernel/VMAware
- * - License: GPL 3.0
- */
-
-#include "../src/vmaware.hpp"
-#include
-
-int main(void) {
- //const bool test1 = VM::detect();
- //const bool test2 = VM::detect(VM::ALL);
- //const bool test3 = VM::detect(VM::DEFAULT);
- //const bool test4 = VM::detect(VM::DEFAULT, VM::ALL);
- //const bool test5 = VM::detect(VM::DISABLE(VM::TIMER));
- //const bool test6 = VM::detect(VM::DEFAULT, VM::HIGH_THRESHOLD, VM::DISABLE(VM::TIMER));
- //const bool test7 = VM::detect(VM::DEFAULT, VM::DISABLE(VM::TIMER, VM::GPU));
- //const std::string test8 = VM::brand();
- //std::cout << (int)test9 << "\n";
-
- //VM::vmaware vm;
-//
- //std::cout << "Is this a VM? = " << vm.is_vm << "\n";
- //std::cout << "How many techniques detected a VM? = " << static_cast(vm.detected_count) << "\n";
- //std::cout << "What's the overview in a human-readable message? = " << vm.conclusion << "\n";
-
- return 0;
-}
\ No newline at end of file
diff --git a/docs/documentation.md b/docs/documentation.md
index bdc06383..d06b13bf 100755
--- a/docs/documentation.md
+++ b/docs/documentation.md
@@ -454,23 +454,18 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
| `VM::HWMON` | Check if /sys/class/hwmon/ directory is present. If not, likely a VM | 🐧 | 35% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L2993) |
| `VM::DLL` | Check for VM-specific DLLs | 🪟 | 25% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3057) |
| `VM::REGISTRY` | Check for VM-specific registry values | 🪟 | 50% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3092) |
-| `VM::VM_FILES` | Find for VM-specific specific files | 🪟 | 25% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3286) |
+| `VM::FILES` | Find for VM-specific specific files | 🪟 | 25% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3286) |
| `VM::HWMODEL` | Check if the sysctl for the hwmodel does not contain the "Mac" string | 🍏 | 100% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3429) |
| `VM::DISK_SIZE` | Check if disk size is under or equal to 50GB | 🐧 | 60% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3465) |
| `VM::VBOX_DEFAULT` | Check for default RAM and DISK sizes set by VirtualBox | 🐧🪟 | 25% | Admin | | | Admin only needed for Linux | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3491) |
| `VM::VBOX_NETWORK` | Check for VirtualBox network provider string | 🪟 | 100% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3576) |
-| `VM::COMPUTER_NAME` | Check if the computer name (not username to be clear) is VM-specific | 🪟 | 10% | | GPL | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3599) |
-| `VM::WINE_CHECK` | Check wine_get_unix_file_name file for Wine | 🪟 | 100% | | GPL | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3633) |
-| `VM::HOSTNAME` | Check if hostname is specific | 🪟 | 10% | | GPL | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3655) |
-| `VM::KVM_DIRS` | Check for KVM directory "Virtio-Win" | 🪟 | 30% | | GPL | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3676) |
-| `VM::QEMU_DIR` | Check for QEMU-specific blacklisted directories | 🪟 | 30% | | GPL | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3702) |
+| `VM::WINE` | Check if the function "wine_get_unix_file_name is present and if the OS booted from a VHD container | 🪟 | 100% | | GPL | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3633) |
| `VM::POWER_CAPABILITIES` | Check what power states are enabled | 🪟 | 50% | | GPL | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3738) |
| `VM::SETUPAPI_DISK` | Check for virtual machine signatures in disk drive device identifiers | 🪟 | 100% | | GPL | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3762) |
| `VM::VM_PROCESSES` | Check for any VM processes that are active | 🪟 | 15% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3831) |
| `VM::LINUX_USER_HOST` | Check for default VM username and hostname for linux | 🐧 | 10% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3884) |
| `VM::GAMARUE` | Check for Gamarue ransomware technique which compares VM-specific Window product IDs | 🪟 | 10% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3911) |
| `VM::BOCHS_CPU` | Check for various Bochs-related emulation oversights through CPU checks | 🐧🪟🍏 | 100% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L3968) |
-| `VM::MSSMBIOS` | Check MSSMBIOS registry for VM-specific signatures | 🪟 | 100% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L4055) |
| `VM::MAC_MEMSIZE` | Check if memory is too low for MacOS system | 🍏 | 15% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L4194) |
| `VM::MAC_IOKIT` | Check MacOS' IO kit registry for VM-specific strings | 🍏 | 100% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L4231) |
| `VM::IOREG_GREP` | Check for VM-strings in ioreg commands for MacOS | 🍏 | 100% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L4317) |
@@ -494,7 +489,7 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
| `VM::XEON_THREAD_MISMATCH` | Same as above, but for Xeon Intel CPUs | 🐧🪟🍏 | 95% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L6217) |
| `VM::CUCKOO_DIR` | Check for cuckoo directory using crt and WIN API directory functions | 🪟 | 30% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L6655) |
| `VM::CUCKOO_PIPE` | Check for Cuckoo specific piping mechanism | 🪟 | 30% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L6679) |
-| `VM::HYPERV_HOSTNAME` | Check for default Azure hostname format regex (Azure uses Hyper-V as their base VM brand) | 🐧🪟 | 30% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L6706) |
+| `VM::HYPERV_HOSTNAME` | Check for default Azure hostname format (Azure uses Hyper-V as their base VM brand) | 🐧🪟 | 30% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L6706) |
| `VM::GENERAL_HOSTNAME` | Check for commonly set hostnames by certain VM brands | 🐧🪟 | 10% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L6753) |
| `VM::SCREEN_RESOLUTION` | Check for pre-set screen resolutions commonly found in VMs | 🪟 | 20% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L6789) |
| `VM::DEVICE_STRING` | Check if bogus device string would be accepted | 🪟 | 25% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L6821) |
@@ -532,9 +527,8 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
| `VM::BAD_POOLS` | Check for system pools allocated by hypervisors | 🪟 | 80% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L8513) |
| `VM::AMD_SEV` | Check for AMD-SEV MSR running on the system | 🐧🍏 | 50% | Admin | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L8812) |
| `VM::AMD_THREAD_MISMATCH` | Check for AMD CPU thread count database if it matches the system's thread count | 🐧🪟🍏 | 95% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L8871) |
-| `VM::NATIVE_VHD` | Check for OS being booted from a VHD container | 🪟 | 100% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L9482) |
| `VM::VIRTUAL_REGISTRY` | Check for particular object directory which is present in Sandboxie virtual environment but not in usual host systems | 🪟 | 65% | | | | Admin only needed for Linux | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L9505) |
-| `VM::FIRMWARE` | Check for VM signatures in ACPI firmware tables | 🐧🪟 | 100% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L9601) |
+| `VM::FIRMWARE` | Check for VM signatures on all firmware tables | 🐧🪟 | 100% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L9601) |
| `VM::FILE_ACCESS_HISTORY` | Check if the number of accessed files are too low for a human-managed environment | 🐧 | 15% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L9950) |
| `VM::AUDIO` | Check if no waveform-audio output devices are present in the system | 🪟 | 25% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L9980) |
| `VM::UNKNOWN_MANUFACTURER` | Check if the CPU manufacturer is not known | 🐧🪟🍏 | 50% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L10016) |
diff --git a/src/README.md b/src/README.md
index efc7a4e7..133b81d7 100755
--- a/src/README.md
+++ b/src/README.md
@@ -1,8 +1,7 @@
| File | Purpose |
|------|---------|
| `cli.cpp` | Entire CLI tool code |
-| `vmaware.hpp` | Official and original library header in GPL-3.0, most likely what you're looking for. |
-| `vmaware_MIT.hpp` | Same as above but in MIT. This removes around 6% of techniques but there shouldn't be any effective difference compared to the GPL version. |
+| `vmaware.hpp` | Official and original library header, most likely what you're looking for. |
diff --git a/src/cli.cpp b/src/cli.cpp
index 44f2874a..f02cfc9c 100755
--- a/src/cli.cpp
+++ b/src/cli.cpp
@@ -18,7 +18,7 @@
*
* - Made by: @kernelwernel (https://github.com/kernelwernel)
* - Repository: https://github.com/kernelwernel/VMAware
- * - License: GPL 3.0
+ * - License: MIT
*/
#include
@@ -329,7 +329,8 @@ bool is_disabled(const VM::enum_flags flag) {
switch (flag) {
case VM::VMWARE_DMESG:
- case VM::PORT_CONNECTORS:
+ case VM::PORT_CONNECTORS:
+ case VM::TEMPERATURE:
case VM::LSHW_QEMU:
default: return false;
}
@@ -412,19 +413,14 @@ bool is_unsupported(VM::enum_flags flag) {
case VM::TEMPERATURE:
case VM::DLL:
case VM::REGISTRY:
- case VM::VM_FILES:
+ case VM::FILES:
case VM::VBOX_DEFAULT:
case VM::VBOX_NETWORK:
- case VM::COMPUTER_NAME:
- case VM::WINE_CHECK:
- case VM::HOSTNAME:
- case VM::KVM_DIRS:
+ case VM::WINE:
case VM::AUDIO:
- case VM::QEMU_DIR:
case VM::VM_PROCESSES:
case VM::GAMARUE:
case VM::BOCHS_CPU:
- case VM::MSSMBIOS:
case VM::HKLM_REGISTRIES:
case VM::VPC_INVALID:
case VM::SIDT:
@@ -456,12 +452,10 @@ bool is_unsupported(VM::enum_flags flag) {
case VM::PROCESSOR_NUMBER:
case VM::NUMBER_OF_CORES:
case VM::POWER_CAPABILITIES:
- case VM::SETUPAPI_DISK:
case VM::VIRTUAL_PROCESSORS:
case VM::HYPERV_QUERY:
case VM::BAD_POOLS:
case VM::AMD_THREAD_MISMATCH:
- case VM::NATIVE_VHD:
case VM::VIRTUAL_REGISTRY:
case VM::FIRMWARE:
case VM::UNKNOWN_MANUFACTURER:
@@ -531,20 +525,6 @@ bool is_unsupported(VM::enum_flags flag) {
}
-bool is_gpl(const VM::enum_flags flag) {
- switch (flag) {
- case VM::COMPUTER_NAME:
- case VM::WINE_CHECK:
- case VM::HOSTNAME:
- case VM::KVM_DIRS:
- case VM::QEMU_DIR:
- case VM::POWER_CAPABILITIES:
- case VM::SETUPAPI_DISK: return true;
- default: return false;
- }
-}
-
-
std::bitset settings() {
std::bitset tmp;
@@ -563,7 +543,6 @@ std::bitset settings() {
return tmp;
}
-
// just a simple string replacer
void replace(std::string &text, const std::string &original, const std::string &new_brand) {
size_t start_pos = 0;
@@ -740,7 +719,7 @@ std::string vm_description(const std::string& vm_brand) {
// by the ANY.RUN minifilter driver.
// To patch this detection, I would recommend returning STATUS_OBJECT_NAME_NOT_FOUND
// that is a standard status code for this situation.
- if (status == 0xC000000F) // STATUS_NOT_SUCH_FILE
+ if (static_cast(status) == 0xC000000F) // STATUS_NOT_SUCH_FILE
return true;
// Not actually the case, maybe conflict with other software installation.
@@ -785,7 +764,7 @@ void checker(const VM::enum_flags flag, const char* message) {
}
#endif
- if (is_disabled(flag) || (arg_bitset.test(MIT) && is_gpl(flag))) {
+ if (is_disabled(flag)) {
if (arg_bitset.test(COMPACT)) {
return;
}
@@ -885,27 +864,22 @@ void general() {
checker(VM::HWMON, "hwmon presence");
checker(VM::DLL, "DLLs");
checker(VM::REGISTRY, "registry keys");
- checker(VM::WINE_CHECK, "Wine");
- checker(VM::VM_FILES, "VM files");
+ checker(VM::WINE, "Wine");
+ checker(VM::FILES, "VM files");
checker(VM::HWMODEL, "hw.model");
checker(VM::DISK_SIZE, "disk size");
checker(VM::VBOX_DEFAULT, "VBox default specs");
checker(VM::VBOX_NETWORK, "VBox network provider match");
- checker(VM::COMPUTER_NAME, "computer name");
- checker(VM::HOSTNAME, "hostname");
checker(VM::VM_PROCESSES, "VM processes");
checker(VM::LINUX_USER_HOST, "default Linux user/host");
checker(VM::GAMARUE, "gamarue ransomware technique");
checker(VM::BOCHS_CPU, "BOCHS CPU techniques");
- checker(VM::MSSMBIOS, "MSSMBIOS data");
checker(VM::MAC_MEMSIZE, "MacOS hw.memsize");
checker(VM::MAC_IOKIT, "MacOS registry IO-kit");
checker(VM::IOREG_GREP, "IO registry grep");
checker(VM::MAC_SIP, "MacOS SIP");
- checker(VM::KVM_DIRS, "KVM directories");
checker(VM::HKLM_REGISTRIES, "registry values");
checker(VM::AUDIO, "audio device");
- checker(VM::QEMU_DIR, "QEMU directories");
checker(VM::VPC_INVALID, "VPC invalid instructions");
checker(VM::SIDT, "SIDT");
checker(VM::SGDT, "SGDT");
@@ -955,7 +929,6 @@ void general() {
checker(VM::PROCESSOR_NUMBER, "processor count");
checker(VM::NUMBER_OF_CORES, "CPU core count");
checker(VM::POWER_CAPABILITIES, "Power capabilities");
- checker(VM::SETUPAPI_DISK, "SETUPDI diskdrive");
checker(VM::QEMU_FW_CFG, "QEMU fw_cfg device");
checker(VM::LSHW_QEMU, "QEMU in lshw output");
checker(VM::VIRTUAL_PROCESSORS, "virtual processors");
@@ -963,7 +936,6 @@ void general() {
checker(VM::BAD_POOLS, "bad pools");
checker(VM::AMD_SEV, "AMD-SEV MSR");
checker(VM::AMD_THREAD_MISMATCH, "AMD thread count mismatch");
- checker(VM::NATIVE_VHD, "VHD containers");
checker(VM::VIRTUAL_REGISTRY, "registry emulation");
checker(VM::FIRMWARE, "firmware signatures");
checker(VM::FILE_ACCESS_HISTORY, "low file access count");
diff --git a/src/vmaware.hpp b/src/vmaware.hpp
index 7dd30b5d..2dd2b246 100644
--- a/src/vmaware.hpp
+++ b/src/vmaware.hpp
@@ -23,7 +23,29 @@
* - Repository: https://github.com/kernelwernel/VMAware
* - Docs: https://github.com/kernelwernel/VMAware/docs/documentation.md
* - Full credits: https://github.com/kernelwernel/VMAware#credits-and-contributors-%EF%B8%8F
- * - License: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
+ * - License: MIT
+ *
+ * MIT License
+ *
+ * Copyright (c) 2025 kernelwernel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
*
*
* ============================== SECTIONS ==================================
@@ -210,59 +232,50 @@
#define MSVC 1
#endif
- // shorter and succinct macros
-#if __cplusplus > 202100L
-#define CPP 23
-#ifdef __VMAWARE_DEBUG__
-#pragma message("using post-C++23, set back to C++23 standard")
-#endif
-#elif __cplusplus == 202100L
-#define CPP 23
-#ifdef __VMAWARE_DEBUG__
-#pragma message("using C++23")
-#endif
-#elif __cplusplus == 202002L
-#define CPP 20
-#ifdef __VMAWARE_DEBUG__
-#pragma message("using C++20")
-#endif
-#elif __cplusplus == 201703L
-#define CPP 17
-#ifdef __VMAWARE_DEBUG__
-#pragma message("using C++17")
-#endif
-#elif __cplusplus == 201402L
-#define CPP 14
-#ifdef __VMAWARE_DEBUG__
-#pragma message("using C++14")
-#endif
-#elif __cplusplus == 201103L
-#define CPP 11
-#ifdef __VMAWARE_DEBUG__
-#pragma message("using C++11")
-#endif
-#elif __cplusplus < 201103L
-#define CPP 1
-#ifdef __VMAWARE_DEBUG__
-#pragma message("using pre-C++11")
-#endif
+#if defined(_MSVC_LANG)
+# define VMA_CPLUSPLUS _MSVC_LANG
#else
-#define CPP 0
-#ifdef __VMAWARE_DEBUG__
-#pragma message("Unknown C++ standard")
-#endif
+# define VMA_CPLUSPLUS __cplusplus
+#endif
+
+#if VMA_CPLUSPLUS >= 202300L
+# define CPP 23
+# ifdef __VMAWARE_DEBUG__
+# pragma message("using C++23 or newer")
+# endif
+
+#elif VMA_CPLUSPLUS >= 202002L
+# define CPP 20
+# ifdef __VMAWARE_DEBUG__
+# pragma message("using C++20")
+# endif
+
+#elif VMA_CPLUSPLUS >= 201703L
+# define CPP 17
+# ifdef __VMAWARE_DEBUG__
+# pragma message("using C++17")
+# endif
+
+#elif VMA_CPLUSPLUS >= 201402L
+# define CPP 14
+# ifdef __VMAWARE_DEBUG__
+# pragma message("using C++14")
+# endif
+
+#elif VMA_CPLUSPLUS >= 201103L
+# define CPP 11
+# ifdef __VMAWARE_DEBUG__
+# pragma message("using C++11")
+# endif
+
+#else
+# error "Unsupported C++ standard (pre-C++11 or unknown)."
#endif
#if (CPP < 11 && !WINDOWS)
-#error "VMAware only supports C++11 or above, set your compiler flag to '-std=c++20' for gcc/clang, or '/std:c++20' for MSVC"
+ #error "VMAware only supports C++11 or above, set your compiler flag to '-std=c++20' for gcc/clang, or '/std:c++20' for MSVC"
#endif
-// unused for now, maybe in the future idk
-#if (WINVER == 0x0501) // Windows XP, (0x0701 for Windows 7)
-#define WIN_XP 1
-#else
-#define WIN_XP 0
-#endif
#if defined(__x86_64__) || defined(_M_X64)
#define x86_64 1
@@ -300,16 +313,7 @@
#endif
#if !(defined(WINDOWS) || defined(LINUX) || defined(APPLE))
-#warning "Unknown OS detected, tests will be severely limited"
-#endif
-
-#ifdef _MSC_VER
-#pragma warning(push) // Save current warning state and disable all warnings for external Windows header files
-#pragma warning(disable : 4365)
-#pragma warning(disable : 4668)
-#pragma warning(disable : 4820)
-#pragma warning(disable : 5039)
-#pragma warning(disable : 5204)
+ #warning "Unknown OS detected, tests will be severely limited"
#endif
#if (CPP >= 23)
@@ -351,12 +355,12 @@
#if (WINDOWS)
#include
#include
+#include
#include
#include
#include
#include
#include
-#include
#include
#include
#include
@@ -365,7 +369,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -382,8 +385,10 @@
#pragma comment(lib, "uuid.lib")
#pragma comment(lib, "ntdll.lib")
#pragma comment(lib, "powrprof.lib")
-#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "tbs.lib")
+#if (_WIN32_WINNT >= _WIN32_WINNT_WIN10)
+#pragma comment(lib, "dxgi.lib")
+#endif
#elif (LINUX)
#if (x86)
@@ -409,7 +414,7 @@
#include
#include
#include
-#include
+#include
#elif (APPLE)
#include
#include
@@ -419,38 +424,12 @@
#include
#endif
-#ifdef _MSC_VER
-#pragma warning(pop) // Restore external Windows header file warnings
-#endif
-
-#if (!WINDOWS)
-#define TCHAR char
-#endif
-
#ifdef _UNICODE
#define tregex std::wregex
#else
#define tregex std::regex
#endif
-// macro shortcut to disable MSVC warnings
-#if (WINDOWS)
-#define MSVC_DISABLE_WARNING(...) __pragma(warning(disable : __VA_ARGS__))
-#define MSVC_ENABLE_WARNING(...) __pragma(warning(default : __VA_ARGS__))
-#else
-#define MSVC_DISABLE_WARNING(...)
-#define MSVC_ENABLE_WARNING(...)
-#endif
-
-// MSVC-specific errors
-#define SPECTRE 5045
-#define ASSIGNMENT_OPERATOR 4626
-#define NO_INLINE_FUNC 4514
-#define PADDING 4820
-#define FS_HANDLE 4733
-
-MSVC_DISABLE_WARNING(ASSIGNMENT_OPERATOR NO_INLINE_FUNC SPECTRE)
-
#ifdef __VMAWARE_DEBUG__
#define debug(...) VM::util::debug_msg(__VA_ARGS__)
#define core_debug(...) VM::util::core_debug_msg(__VA_ARGS__)
@@ -573,23 +552,17 @@ struct VM {
HWMON,
DLL,
REGISTRY,
- VM_FILES,
+ FILES,
HWMODEL,
DISK_SIZE,
VBOX_DEFAULT,
VBOX_NETWORK,
-/* GPL */ COMPUTER_NAME,
-/* GPL */ WINE_CHECK,
-/* GPL */ HOSTNAME,
-/* GPL */ KVM_DIRS,
-/* GPL */ QEMU_DIR,
-/* GPL */ POWER_CAPABILITIES,
-/* GPL */ SETUPAPI_DISK,
+ WINE,
+ POWER_CAPABILITIES,
VM_PROCESSES,
LINUX_USER_HOST,
GAMARUE,
BOCHS_CPU,
- MSSMBIOS,
MAC_MEMSIZE,
MAC_IOKIT,
IOREG_GREP,
@@ -649,7 +622,6 @@ struct VM {
BAD_POOLS,
AMD_SEV,
AMD_THREAD_MISMATCH,
- NATIVE_VHD,
VIRTUAL_REGISTRY,
FIRMWARE,
FILE_ACCESS_HISTORY,
@@ -846,50 +818,6 @@ struct VM {
return ((ecx == intel_ecx1) || (ecx == intel_ecx2));
}
- // check for POSSIBILITY of hyperthreading, I don't think there's a
- // full-proof method to detect if you're actually hyperthreading imo.
- [[nodiscard]] static bool has_hyperthreading() {
- u32 unused, ebx, edx;
-
- cpuid(unused, ebx, unused, edx, 1);
- UNUSED(unused);
-
- bool htt_available = (edx & (1 << 28));
-
- if (!htt_available) {
- return false;
- }
-
- u32 logical_cores = ((ebx >> 16) & 0xFF);
- i32 physical_cores = 0;
-
-#if (WINDOWS)
- SYSTEM_INFO sysinfo;
- GetSystemInfo(&sysinfo);
- physical_cores = static_cast(sysinfo.dwNumberOfProcessors);
-#elif (LINUX)
- physical_cores = static_cast(sysconf(_SC_NPROCESSORS_CONF));
-#elif (APPLE)
- // sysctlbyname("hw.physicalcpu", &physical_cores, sizeof(physical_cores), NULL, 0);
- // the code under this is the same as the one commented right above, removed due to non-backwards compatibility
-
- i32 mib[2];
- std::size_t size = sizeof(physical_cores);
-
- mib[0] = CTL_HW; // hardware information
- mib[1] = HW_NCPU; // physical CPU count
-
- if (sysctl(mib, 2, &physical_cores, &size, NULL, 0) != 0) {
- debug("HAS_HYPERTHREADING(): sysctl failed, returned false");
- return false;
- }
-#else
- return false;
-#endif
-
- return (logical_cores > static_cast(physical_cores));
- }
-
// get the CPU product
[[nodiscard]] static std::string get_brand() {
if (memo::cpu_brand::is_cached()) {
@@ -903,26 +831,27 @@ struct VM {
return "Unknown";
}
- std::array buffer{};
- constexpr std::size_t buffer_size = sizeof(i32) * buffer.size();
- std::array charbuffer{};
-
- std::string brand(48, '\0'); // 3 leafs 16 each
+ constexpr std::array ids {{
+ cpu::leaf::brand1,
+ cpu::leaf::brand2,
+ cpu::leaf::brand3
+ }};
- constexpr std::array ids = { { cpu::leaf::brand1, cpu::leaf::brand2, cpu::leaf::brand3 } };
- for (const u32& id : ids) {
- cpu::cpuid(buffer.at(0), buffer.at(1), buffer.at(2), buffer.at(3), id);
+ std::string b(48, '\n');
- std::memcpy(charbuffer.data(), buffer.data(), buffer_size);
+ union Regs {
+ u32 i[4];
+ char c[16];
+ } regs{};
- brand.append(charbuffer.data(), 16);
+ for (auto leaf_id : ids) {
+ cpu::cpuid(regs.i[0], regs.i[1], regs.i[2], regs.i[3], leaf_id);
+ b.append(regs.c, 16);
}
- debug("BRAND: ", "cpu brand = ", brand);
-
- memo::cpu_brand::store(brand);
-
- return brand;
+ memo::cpu_brand::store(b);
+ debug("CPU: ", b);
+ return b;
#endif
}
@@ -1018,183 +947,93 @@ struct VM {
[[nodiscard]] static model_struct get_model() {
const std::string brand = get_brand();
- constexpr const char* intel_i_series_regex = "i[0-9]-[A-Z0-9]{1,7}";
- constexpr const char* intel_xeon_series_regex = "[DEW]-[A-Z0-9]{1,7}";
- constexpr const char* amd_ryzen_regex = "AMD Ryzen ^(PRO)?[A-Z0-9]{1,7}";
-
- std::string match_str = "";
-
- auto match = [&](const char* regex) -> bool {
- std::regex pattern(regex);
+ model_struct result{ false, false, false, false, {} };
- auto words_begin = std::sregex_iterator(brand.begin(), brand.end(), pattern);
- auto words_end = std::sregex_iterator();
-
- for (std::sregex_iterator i = words_begin; i != words_end; ++i) {
- std::smatch match = *i;
- match_str = match.str();
- }
-
- if (!match_str.empty()) {
- return true;
+ if (cpu::is_intel()) {
+ if (brand.find("i") != std::string::npos && brand.find("-") != std::string::npos &&
+ brand.find_first_of("0123456789") != std::string::npos) {
+ result.found = true;
+ result.is_i_series = true;
+ result.string = brand;
+ return result;
}
- return false;
- };
-
- bool found = false;
- bool is_xeon = false;
- bool is_i_series = false;
- bool is_ryzen = false;
-
- if (cpu::is_intel()) {
- if (match(intel_i_series_regex)) {
- found = true;
- is_i_series = true;
- } else if (match(intel_xeon_series_regex)) {
- found = true;
- is_xeon = true;
+ if (brand.find_first_of("DEW") != std::string::npos && brand.find("-") != std::string::npos &&
+ brand.find_first_of("0123456789") != std::string::npos) {
+ result.found = true;
+ result.is_xeon = true;
+ result.string = brand;
+ return result;
}
}
-
- // example: AMD Ryzen 9 3950X 16-Core Processor
- if (cpu::is_amd()) {
- if (match(amd_ryzen_regex)) {
- found = true;
- is_ryzen = true;
+ else if (cpu::is_amd()) {
+ if (brand.find("AMD Ryzen") != std::string::npos) {
+ result.found = true;
+ result.is_ryzen = true;
+ result.string = brand;
+ return result;
}
}
- return model_struct{ found, is_xeon, is_i_series, is_ryzen, match_str };
- };
+ return result;
+ }
-#if (CPP >= 17)
- [[nodiscard]] static bool vmid_template(const u32 p_leaf) {
-#else
- [[nodiscard]] static bool vmid_template(const u32 p_leaf) {
-#endif
-#if (CPP >= 17)
- constexpr std::string_view
-#else
- const std::string
-#endif
- bhyve = "bhyve bhyve ",
- bhyve2 = "BHyVE BHyVE ",
- kvm_hyperv = "Linux KVM Hv",
- qemu = "TCGTCGTCGTCG",
- hyperv = "Microsoft Hv",
- parallels = " prl hyperv ",
- parallels2 = " lrpepyh vr",
- vmware = "VMwareVMware",
- vbox = "VBoxVBoxVBox",
- xen = "XenVMMXenVMM",
- acrn = "ACRNACRNACRN",
- qnx = " QNXQVMBSQG ",
- qnx2 = "QXNQSBMV",
- nvmm = "___ NVMM ___",
- openbsd_vmm = "OpenBSDVMM58",
- intel_haxm = "HAXMHAXMHAXM",
- unisys = "UnisysSpar64",
- lmhs = "SRESRESRESRE",
- jailhouse = "Jailhouse\0\0\0",
- apple_vz = "Apple VZ",
- intel_kgt = "EVMMEVMMEVMM",
- barevisor = "Barevisor!\0\0",
- hyperplatform = "PpyH",
- minivisor = "MiniVisor\0\0\0",
- intel_tdx = "IntelTDX ",
- lkvm = "LKVMLKVMLKVM",
- neko = "Neko Project",
- noir = "NoirVisor ZT";
+ [[nodiscard]] static bool vmid_template(const u32 p_leaf) {
const std::string brand_str = cpu_manufacturer(p_leaf);
-#ifdef __VMAWARE_DEBUG__
- const char* technique_name;
- switch (p_leaf) {
- case 0x40000000:
- technique_name = "VMID_0x4: ";
- break;
- case 0x40000100:
- technique_name = "VMID_0x4 + 0x100: ";
- break;
- case 0x40000001:
- technique_name = "VMID_0x4 + 1: ";
- break;
- default:
- technique_name = "VMID: ";
- break;
- }
- debug(technique_name, brand_str);
-#endif
- // both Hyper-V and VirtualPC have the same string value
- if (brand_str == hyperv) {
+ if (brand_str == "Microsoft Hv") {
if (util::hyper_x() == HYPERV_ARTIFACT_VM) {
return false;
}
return core::add(brands::HYPERV, brands::VPC);
}
- /**
- * this is added because there are inconsistent string
- * values for KVM's manufacturer ID. For example,
- * it gives me "KVMKMVMKV" when I run it under QEMU
- * but the Wikipedia article on CPUID says it's
- * "KVMKVMKVM\0\0\0", like wtf????
- */
if (util::find(brand_str, "KVM")) {
return core::add(brands::KVM);
}
- if (brand_str == vmware) { return core::add(brands::VMWARE); }
- if (brand_str == vbox) { return core::add(brands::VBOX); }
- if (brand_str == qemu) { return core::add(brands::QEMU); }
- if (brand_str == xen) { return core::add(brands::XEN); }
- if (brand_str == kvm_hyperv) { return core::add(brands::KVM_HYPERV); }
- if (brand_str == parallels) { return core::add(brands::PARALLELS); }
- if (brand_str == parallels2) { return core::add(brands::PARALLELS); }
- if (brand_str == bhyve) { return core::add(brands::BHYVE); }
- if (brand_str == bhyve2) { return core::add(brands::BHYVE); }
- if (brand_str == acrn) { return core::add(brands::ACRN); }
- if (brand_str == qnx) { return core::add(brands::QNX); }
- if (brand_str == nvmm) { return core::add(brands::NVMM); }
- if (brand_str == openbsd_vmm) { return core::add(brands::BSD_VMM); }
- if (brand_str == intel_haxm) { return core::add(brands::INTEL_HAXM); }
- if (brand_str == unisys) { return core::add(brands::UNISYS); }
- if (brand_str == lmhs) { return core::add(brands::LMHS); }
- if (brand_str == jailhouse) { return core::add(brands::JAILHOUSE); }
- if (brand_str == intel_kgt) { return core::add(brands::INTEL_KGT); }
- if (brand_str == barevisor) { return core::add(brands::BAREVISOR); }
- if (brand_str == minivisor) { return core::add(brands::MINIVISOR); }
- if (brand_str == intel_tdx) { return core::add(brands::INTEL_TDX); }
- if (brand_str == lkvm) { return core::add(brands::LKVM); }
- if (brand_str == neko) { return core::add(brands::NEKO_PROJECT); }
- if (brand_str == noir) { return core::add(brands::NOIRVISOR); }
+ static const std::unordered_map brand_map = {
+ {"VMwareVMware", brands::VMWARE},
+ {"VBoxVBoxVBox", brands::VBOX},
+ {"TCGTCGTCGTCG", brands::QEMU},
+ {"XenVMMXenVMM", brands::XEN},
+ {"Linux KVM Hv", brands::KVM_HYPERV},
+ {" prl hyperv ", brands::PARALLELS},
+ {" lrpepyh vr", brands::PARALLELS},
+ {"bhyve bhyve ", brands::BHYVE},
+ {"BHyVE BHyVE ", brands::BHYVE},
+ {"ACRNACRNACRN", brands::ACRN},
+ {" QNXQVMBSQG ", brands::QNX},
+ {"___ NVMM ___", brands::NVMM},
+ {"OpenBSDVMM58", brands::BSD_VMM},
+ {"HAXMHAXMHAXM", brands::INTEL_HAXM},
+ {"UnisysSpar64", brands::UNISYS},
+ {"SRESRESRESRE", brands::LMHS},
+ {"Jailhouse\0\0\0", brands::JAILHOUSE},
+ {"EVMMEVMMEVMM", brands::INTEL_KGT},
+ {"Barevisor!\0\0", brands::BAREVISOR},
+ {"MiniVisor\0\0\0", brands::MINIVISOR},
+ {"IntelTDX ", brands::INTEL_TDX},
+ {"LKVMLKVMLKVM", brands::LKVM},
+ {"Neko Project", brands::NEKO_PROJECT},
+ {"NoirVisor ZT", brands::NOIRVISOR}
+ };
- /**
- * i'm honestly not sure about this one,
- * they're supposed to have 12 characters but
- * Wikipedia tells me it these brands have
- * less characters (both 8), so i'm just
- * going to scan for the entire string ig
- */
-#if (CPP >= 17)
- const char* qnx_sample = qnx2.data();
- const char* applevz_sample = apple_vz.data();
-#else
- const char* qnx_sample = qnx2.c_str();
- const char* applevz_sample = apple_vz.c_str();
-#endif
+ const auto it = brand_map.find(brand_str);
+ if (it != brand_map.end()) {
+ return core::add(it->second);
+ }
- if (util::find(brand_str, qnx_sample)) {
+ if (util::find(brand_str, "QXNQSBMV")) {
return core::add(brands::QNX);
}
- if (util::find(brand_str, applevz_sample)) {
+ if (util::find(brand_str, "Apple VZ")) {
return core::add(brands::APPLE_VZ);
}
- if (util::find(brand_str, hyperplatform.data())) {
+ if (util::find(brand_str, "PpyH")) {
return core::add(brands::HYPERPLATFORM);
}
@@ -1390,7 +1229,7 @@ struct VM {
return buffer;
}
- // check if file exists
+
[[nodiscard]] static bool exists(const char* path) {
#if (WINDOWS)
return (GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES) || (GetLastError() != ERROR_FILE_NOT_FOUND);
@@ -1404,16 +1243,6 @@ struct VM {
#endif
}
-#if (WINDOWS) && (defined(UNICODE) || defined(_UNICODE))
- // handle TCHAR conversion
- [[nodiscard]] static bool exists(const TCHAR* path) {
- char c_szText[_MAX_PATH]{};
- size_t convertedChars = 0;
- wcstombs_s(&convertedChars, c_szText, path, _MAX_PATH);
- return exists(c_szText);
- }
-#endif
-
#if (LINUX)
static bool is_directory(const char* path) {
struct stat info;
@@ -1434,7 +1263,7 @@ struct VM {
#endif
}
- // self-explanatory
+
[[nodiscard]] static bool is_admin() noexcept {
#if (LINUX || APPLE)
const uid_t uid = getuid();
@@ -1445,46 +1274,44 @@ struct VM {
(euid == 0)
);
#elif (WINDOWS)
- BOOL is_admin = FALSE;
- HANDLE hToken = NULL;
+ BOOL is_admin = 0;
+ HANDLE hToken = nullptr;
+
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
DWORD dwSize = 0;
- if (!GetTokenInformation(hToken, TokenIntegrityLevel, NULL, 0, &dwSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
- PTOKEN_MANDATORY_LABEL pTIL = (PTOKEN_MANDATORY_LABEL)malloc(dwSize);
- if (pTIL != NULL) {
+ GetTokenInformation(hToken, TokenIntegrityLevel, nullptr, 0, &dwSize);
+
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ auto pTIL = static_cast(malloc(dwSize));
+ if (pTIL != nullptr) {
if (GetTokenInformation(hToken, TokenIntegrityLevel, pTIL, dwSize, &dwSize)) {
- SID* pSID = (SID*)GetSidSubAuthority(pTIL->Label.Sid, (DWORD)(UCHAR)(*GetSidSubAuthorityCount(pTIL->Label.Sid) - 1));
- DWORD dwIntegrityLevel = *GetSidSubAuthority(pTIL->Label.Sid, (DWORD)(UCHAR)(*GetSidSubAuthorityCount(pTIL->Label.Sid) - 1));
+ const DWORD subAuthCount = static_cast(
+ *GetSidSubAuthorityCount(pTIL->Label.Sid));
+ const DWORD dwIntegrityLevel = *GetSidSubAuthority(
+ pTIL->Label.Sid, subAuthCount - 1);
if (dwIntegrityLevel >= SECURITY_MANDATORY_HIGH_RID) {
- is_admin = TRUE;
+ is_admin = 1;
}
-
- UNUSED(pSID);
}
free(pTIL);
}
}
+ CloseHandle(hToken);
}
- CloseHandle(hToken);
-
return is_admin;
#endif
}
- // scan for keyword in string
+
[[nodiscard]] static bool find(const std::string& base_str, const char* keyword) noexcept {
return (base_str.find(keyword) != std::string::npos);
};
- // for debug output
#ifdef __VMAWARE_DEBUG__
#if (CPP < 17)
- // Helper function to handle the recursion
- static inline void print_to_stream(std::ostream&) noexcept {
- // Base case: do nothing
- }
+ static inline void print_to_stream(std::ostream&) noexcept {}
template
static void print_to_stream(std::ostream& os, T&& first, Args&&... args) noexcept {
@@ -1547,199 +1374,133 @@ struct VM {
}
#endif
- // basically std::system but it runs in the background with std::string output
- [[nodiscard]] static std::unique_ptr sys_result(const TCHAR* cmd) {
+
+ [[nodiscard]] static std::unique_ptr sys_result(const char* cmd) {
#if (CPP < 14)
- std::unique_ptr tmp(nullptr);
UNUSED(cmd);
- return tmp;
+ return nullptr;
#else
-#if (LINUX || APPLE)
-#if (ARM)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wignored-attributes"
-#endif
- std::unique_ptr pipe(popen(cmd, "r"), pclose);
-
-#if (ARM)
-#pragma GCC diagnostic pop
-#endif
-
- if (!pipe) {
- return nullptr;
- }
-
- std::string result{};
- std::array buffer{};
-
- while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
- result += buffer.data();
- }
-
- result.pop_back();
-
- return util::make_unique(result);
-#elif (WINDOWS)
- // Set up the structures for creating the process
- STARTUPINFO si = { 0 };
- PROCESS_INFORMATION pi = { 0 };
- si.cb = sizeof(si);
-
- // Create a pipe to capture the command output
- HANDLE hReadPipe, hWritePipe;
- SECURITY_ATTRIBUTES sa;
- sa.nLength = sizeof(SECURITY_ATTRIBUTES);
- sa.bInheritHandle = TRUE;
- sa.lpSecurityDescriptor = NULL;
-
- if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) {
- debug("sys_result: ", "error creating pipe");
-
- return nullptr;
- }
-
- // Set up the startup information with the write end of the pipe as the standard output
- si.hStdError = hWritePipe;
- si.hStdOutput = hWritePipe;
- si.dwFlags |= STARTF_USESTDHANDLES;
-
- // Create the process
- if (!CreateProcess(NULL, const_cast(cmd), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
- debug("sys_result: ", "error creating process");
-
- CloseHandle(hReadPipe);
- CloseHandle(hWritePipe);
- return nullptr;
- }
-
- // Close the write end of the pipe as it's not needed in this process
- CloseHandle(hWritePipe);
+ #if (LINUX || APPLE)
+ struct FileDeleter { void operator()(FILE* f) const noexcept { if (f) pclose(f); } };
+ std::unique_ptr pipe(popen(cmd, "r"), FileDeleter());
+ if (!pipe) {
+ return nullptr;
+ }
- // Read the output from the pipe
- char buffer[4096];
- DWORD bytesRead;
- std::string result;
+ std::string result;
+ char* line = nullptr;
+ size_t len = 0;
+ ssize_t nread;
- while (ReadFile(hReadPipe, buffer, sizeof(buffer), &bytesRead, NULL) && bytesRead > 0) {
- result.append(buffer, bytesRead);
- }
+ while ((nread = getline(&line, &len, pipe.get())) != -1) {
+ result.append(line, static_cast(nread));
+ }
+ free(line);
- // Close handles
- CloseHandle(hReadPipe);
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
+ if (!result.empty() && result.back() == '\n') {
+ result.pop_back();
+ }
- // Return the result as a unique_ptr
- return util::make_unique(result);
-#endif
+ return util::make_unique(std::move(result));
+ #else
+ UNUSED(cmd);
+ return std::make_unique();
+ #endif
#endif
}
- /**
- * @brief Get the disk size in GB
- * @category Linux, Windows
- * @returns Disk size in GB
- */
- [[nodiscard]] static u32 get_disk_size() {
- u32 size = 0;
- constexpr u64 GB = (static_cast(1024) * 1024 * 1024); // Size of 1 GB in bytes
+
+ [[nodiscard]] static u16 get_disk_size() {
+ u16 size = 0;
+ constexpr u64 GB = 1024ull * 1024 * 1024;
+ constexpr u64 U16_MAX = 65535;
#if (LINUX)
struct statvfs stat;
-
if (statvfs("/", &stat) != 0) {
- debug("private util::get_disk_size( function: ", "failed to fetch disk size");
- return 0; // Return 0 to indicate failure
+ debug("util::get_disk_size: ", "failed to fetch disk size");
+ return 0;
+ }
+
+ u64 total_bytes = static_cast(stat.f_blocks) * stat.f_frsize;
+ u64 size_gb = total_bytes / GB;
+
+ if (size_gb > U16_MAX) {
+ size = static_cast(U16_MAX);
+ }
+ else {
+ size = static_cast(size_gb);
}
- // in gigabytes
- size = static_cast((stat.f_blocks * stat.f_frsize) / GB);
#elif (WINDOWS)
ULARGE_INTEGER totalNumberOfBytes;
+ if (GetDiskFreeSpaceExW(L"C:", nullptr, &totalNumberOfBytes, nullptr)) {
+ u64 size_gb = totalNumberOfBytes.QuadPart / GB;
- if (GetDiskFreeSpaceExW(
- L"C:", // Drive or directory path (use wide character string)
- nullptr, // Free bytes available to the caller (not needed for total size)
- &totalNumberOfBytes, // Total number of bytes on the disk
- nullptr // Total number of free bytes on the disk (not needed for total size)
- )) {
- // Convert bytes to GB
- size = static_cast(totalNumberOfBytes.QuadPart / GB);
+ if (size_gb > U16_MAX) {
+ size = static_cast(U16_MAX);
+ }
+ else {
+ size = static_cast(size_gb);
+ }
}
else {
- debug("util::get_disk_size(: ", "failed to fetch size in GB");
+ debug("util::get_disk_size: ", "failed to fetch size in GB");
}
#endif
- if (size == 0)
- return 81;
-
- return size; // Return disk size in GB
+ constexpr u16 fallback_size = 81;
+ return (size == 0) ? fallback_size : size;
}
- // get physical RAM size in GB
- [[nodiscard]] static u64 get_physical_ram_size() {
+
+ [[nodiscard]] static u32 get_physical_ram_size() {
#if (LINUX)
if (!util::is_admin()) {
- debug("private get_physical_ram_size function: ", "not root, returned 0");
+ debug("get_physical_ram_size: ", "not root, returned 0");
return 0;
}
auto result = util::sys_result("dmidecode --type 19 | grep 'Size' | grep '[[:digit:]]*'");
-
- if (result == nullptr) {
- debug("private get_physical_ram_size function: ", "invalid system result from dmidecode, returned 0");
+ if (!result) {
+ debug("get_physical_ram_size: ", "invalid system result, returned 0");
return 0;
}
- const bool MB = (std::regex_search(*result, std::regex("MB")));
- const bool GB = (std::regex_search(*result, std::regex("GB")));
-
- if (!(MB || GB)) {
- debug("private get_physical_ram_size function: ", "neither MB nor GB found, returned 0");
+ bool is_mb = std::regex_search(*result, std::regex("MB"));
+ bool is_gb = std::regex_search(*result, std::regex("GB"));
+ if (!(is_mb || is_gb)) {
+ debug("get_physical_ram_size: ", "unit not found, returned 0");
return 0;
}
std::string number_str;
- bool in_number = false;
-
for (char c : *result) {
- if (std::isdigit(c)) {
- number_str += c;
- in_number = true;
- } else if (in_number) {
- break;
- }
+ if (std::isdigit(c)) number_str += c;
+ else if (!number_str.empty()) break;
}
if (number_str.empty()) {
- debug("private get_physical_ram_size_gb function: ", "string is empty, returned 0");
+ debug("get_physical_ram_size: ", "no digits found, returned 0");
return 0;
}
- u64 number = 0;
-
- number = std::stoull(number_str);
-
- if (MB == true) {
- number = static_cast(std::round(number / 1024));
- }
+ u64 number = std::stoull(number_str);
+ if (is_mb) number = static_cast(std::round(number / 1024.0));
- return number; // in GB
+ return static_cast(std::min(number, std::numeric_limits::max()));
#elif (WINDOWS)
ULONGLONG total_memory_kb = 0;
-
- if (GetPhysicallyInstalledSystemMemory(&total_memory_kb) == ERROR_INVALID_DATA) {
+ if (GetPhysicallyInstalledSystemMemory(&total_memory_kb) == ERROR_INVALID_DATA)
return 0;
- }
- return (total_memory_kb / (static_cast(1024) * 1024)); // MB
+ return static_cast(total_memory_kb / (static_cast(1024) * 1024)); // Return in GB
#else
return 0;
#endif
}
- // Get available memory space
+
[[nodiscard]] static u64 get_memory_space() {
#if (WINDOWS)
MEMORYSTATUSEX statex = { 0 };
@@ -1764,7 +1525,7 @@ struct VM {
#endif
}
- // Check if a process is running
+
[[nodiscard]] static bool is_proc_running(const char* executable) {
#if (LINUX)
#if (CPP >= 17)
@@ -1846,89 +1607,64 @@ struct VM {
#endif
}
- // Returns a list of running process names
+
[[nodiscard]] static std::unordered_set get_running_process_names() {
std::unordered_set processNames;
#if (WINDOWS)
- typedef NTSTATUS(__stdcall* PFN_NtQuerySystemInformation)(
- SYSTEM_INFORMATION_CLASS,
- PVOID,
- ULONG,
- PULONG
- );
-
- static PFN_NtQuerySystemInformation pNtQSI = nullptr;
- static std::vector buffer;
- static std::mutex initMutex;
-
- if (!pNtQSI) {
- std::lock_guard lk(initMutex);
- if (!pNtQSI) {
- const HMODULE hNtdll = GetModuleHandle(_T("ntdll.dll"));
- if (hNtdll) {
-#pragma warning (disable : 4191)
- pNtQSI = reinterpret_cast(GetProcAddress(hNtdll, "NtQuerySystemInformation"));
-#pragma warning (default : 4191)
- }
- if (!pNtQSI) {
- return {};
- }
- }
- }
-
+ static constexpr NTSTATUS STATUS_INFO_LENGTH_MISMATCH = static_cast(0xC0000004);
+ processNames.reserve(256);
+
+ using QSI_t = NTSTATUS(__stdcall*)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
+ static QSI_t NtQSI = nullptr;
+ if (!NtQSI) {
+ HMODULE ntdll = ::GetModuleHandle(_T("ntdll.dll"));
+ if (!ntdll) return {};
+ const char* fn = "NtQuerySystemInformation";
+ void* addr = nullptr;
+ GetFunctionAddresses(ntdll, &fn, &addr, 1);
+ NtQSI = reinterpret_cast(addr);
+ if (!NtQSI) return {};
+ }
+
+ static thread_local std::vector raw;
ULONG needed = 0;
- NTSTATUS status = pNtQSI(SystemProcessInformation, nullptr, 0, &needed);
- if (status != 0) {
- return {};
- }
+ NTSTATUS status = NtQSI(SystemProcessInformation, nullptr, 0, &needed);
+ if (status != STATUS_INFO_LENGTH_MISMATCH) return {};
- if (buffer.size() < needed) {
- buffer.resize(needed);
- }
+ if (raw.size() < needed)
+ raw.resize(static_cast>::size_type>(needed) + 1024);
- status = pNtQSI(
- SystemProcessInformation,
- buffer.data(),
- static_cast(buffer.size()),
- &needed
- );
- if (!NT_SUCCESS(status)) {
- return {};
- }
+ status = NtQSI(SystemProcessInformation, raw.data(), static_cast(raw.size()), &needed);
+ if (!NT_SUCCESS(status)) return {};
- const BYTE* cur = buffer.data();
+ const BYTE* ptr = raw.data();
while (true) {
- auto pi = reinterpret_cast(cur);
- if (pi->ImageName.Buffer && pi->ImageName.Length) {
- int wideChars = static_cast(pi->ImageName.Length / sizeof(WCHAR));
- int utf8Len = WideCharToMultiByte(
+ auto* info = reinterpret_cast(ptr);
+ if (info->ImageName.Buffer && info->ImageName.Length > 0) {
+ const WCHAR* wstr = info->ImageName.Buffer;
+ int wlen = static_cast(info->ImageName.Length / sizeof(WCHAR));
+
+ char utf8buf[1024];
+ int bytes = WideCharToMultiByte(
CP_UTF8, 0,
- pi->ImageName.Buffer, wideChars,
- nullptr, 0,
+ wstr, wlen,
+ utf8buf, sizeof(utf8buf),
nullptr, nullptr
);
- if (utf8Len > 0) {
- std::string name;
- name.resize(static_cast(utf8Len));
- WideCharToMultiByte(
- CP_UTF8, 0,
- pi->ImageName.Buffer, wideChars,
- &name[0], utf8Len,
- nullptr, nullptr
- );
- processNames.insert(std::move(name));
+ if (bytes > 0) {
+ processNames.emplace(utf8buf, static_cast(bytes));
}
}
- if (pi->NextEntryOffset == 0) {
+
+ if (info->NextEntryOffset == 0)
break;
- }
- cur += pi->NextEntryOffset;
+ ptr += info->NextEntryOffset;
}
#endif
return processNames;
}
- // Retrieves the computer name
+
[[nodiscard]] static std::string get_hostname() {
#if (WINDOWS)
char ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
@@ -1950,19 +1686,16 @@ struct VM {
[[nodiscard]] static bool is_running_under_translator() {
- #if (WINDOWS)
- u8 ver = get_windows_version();
- if (ver == 10 || ver == 11) {
- USHORT procMachine = 0, nativeMachine = 0;
- if (IsWow64Process2(GetCurrentProcess(), &procMachine, &nativeMachine)) {
- if (nativeMachine == IMAGE_FILE_MACHINE_ARM64 &&
- (procMachine == IMAGE_FILE_MACHINE_AMD64 ||
- procMachine == IMAGE_FILE_MACHINE_I386))
- {
- return true;
- }
+#if (WINDOWS && _WIN32_WINNT >= _WIN32_WINNT_WIN10)
+ USHORT procMachine = 0, nativeMachine = 0;
+ if (IsWow64Process2(GetCurrentProcess(), &procMachine, &nativeMachine)) {
+ if (nativeMachine == IMAGE_FILE_MACHINE_ARM64 &&
+ (procMachine == IMAGE_FILE_MACHINE_AMD64 ||
+ procMachine == IMAGE_FILE_MACHINE_I386))
+ {
+ return true;
}
- }
+ }
#endif
if (cpu::is_leaf_supported(cpu::leaf::hypervisor)) {
@@ -2025,7 +1758,7 @@ struct VM {
* On Hyper-V virtual machines, the cpuid function reports an EAX value of 11
* This value is tied to the Hyper-V partition model, where each virtual machine runs as a child partition
* These child partitions have limited privileges and access to hypervisor resources,
- * which is reflected in the maximum input value for hypervisor CPUID information as 11.
+ * which is reflected in the maximum input value for hypervisor CPUID information as 11
* Essentially, it indicates that the hypervisor is managing the VM and that the VM is not running directly on hardware but rather in a virtualized environment
*/
auto eax = []() -> u32 {
@@ -2076,55 +1809,45 @@ struct VM {
}
#if (WINDOWS)
- /**
- * @brief Determines if the current process is running under WOW64.
- *
- * WOW64 (Windows-on-Windows 64-bit) is a subsystem that allows 32-bit
- * applications to run on 64-bit Windows. This function checks whether the
- * current process is a 32-bit application running on a 64-bit OS.
- *
- * @return true if the process is running under WOW64, otherwise false.
- */
[[nodiscard]] static bool is_wow64() {
- BOOL isWow64 = FALSE;
+ BOOL isWow64 = 0;
BOOL pbool = IsWow64Process(GetCurrentProcess(), &isWow64);
return (pbool && isWow64);
}
- /**
- * @brief Retrieves the Windows major version using RtlGetVersion.
- *
- * This function queries the ntdll.dll library to obtain the Windows version.
- * It maps the build number to a major Windows version using a predefined map.
- * If the primary method fails, it falls back to get_windows_version_backup().
- *
- * @return The major version of Windows (e.g., 6 for Vista/7, 10 for Windows 10).
- */
[[nodiscard]] static u8 get_windows_version() {
- const std::map windowsVersions = {
- { static_cast(6002), static_cast(6) }, // windows vista
- { static_cast(7601), static_cast(7) },
- { static_cast(9200), static_cast(8) },
- { static_cast(9600), static_cast(8) },
- { static_cast(10240), static_cast(10) },
- { static_cast(10586), static_cast(10) },
- { static_cast(14393), static_cast(10) },
- { static_cast(15063), static_cast(10) },
- { static_cast(16299), static_cast(10) },
- { static_cast(17134), static_cast(10) },
- { static_cast(17763), static_cast(10) },
- { static_cast(18362), static_cast(10) },
- { static_cast(18363), static_cast(10) },
- { static_cast(19041), static_cast(10) },
- { static_cast(19042), static_cast(10) },
- { static_cast(19043), static_cast(10) },
- { static_cast(19044), static_cast(10) },
- { static_cast(19045), static_cast(10) },
- { static_cast(22000), static_cast(11) },
- { static_cast(22621), static_cast(11) },
- { static_cast(22631), static_cast(11) },
- { static_cast(26100), static_cast(11) }
+ struct VersionMapEntry {
+ DWORD build;
+ u8 major;
+ };
+
+ constexpr VersionMapEntry windowsVersions[] = {
+ {6002, 6},
+ {7601, 7},
+
+ {9200, 8},
+ {9600, 8},
+
+ {10240, 10},
+ {10586, 10},
+ {14393, 10},
+ {15063, 10},
+ {16299, 10},
+ {17134, 10},
+ {17763, 10},
+ {18362, 10},
+ {18363, 10},
+ {19041, 10},
+ {19042, 10},
+ {19043, 10},
+ {19044, 10},
+ {19045, 10},
+
+ {22000, 11},
+ {22621, 11},
+ {22631, 11},
+ {26100, 11}
};
const HMODULE ntdll = GetModuleHandle(_T("ntdll.dll"));
@@ -2142,53 +1865,33 @@ struct VM {
RTL_OSVERSIONINFOW osvi{};
osvi.dwOSVersionInfoSize = sizeof(osvi);
-
if (pRtlGetVersion(&osvi) != 0) {
return 0;
}
- u8 major_version = 0;
+ DWORD build = osvi.dwBuildNumber;
+
+ int left = 0;
+ int right = static_cast(sizeof(windowsVersions) / sizeof(windowsVersions[0])) - 1;
- if (windowsVersions.find(osvi.dwBuildNumber) != windowsVersions.end()) {
- major_version = windowsVersions.at(osvi.dwBuildNumber);
+ while (left <= right) {
+ int mid = left + (right - left) / 2;
+ if (windowsVersions[mid].build == build) {
+ return windowsVersions[mid].major;
+ }
+ else if (build < windowsVersions[mid].build) {
+ right = mid - 1;
+ }
+ else {
+ left = mid + 1;
+ }
}
- return major_version;
+ return 0;
}
- /**
- * @brief Retrieves the last error message from the Windows API. Useful for __VMAWARE_DEBUG__
- * @return A std::wstring containing the error message.
- */
- [[nodiscard]] static std::wstring GetLastErrorString() {
- const DWORD error = GetLastError();
- LPWSTR messageBuffer = nullptr;
- size_t size = FormatMessageW(
- FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- nullptr, error, 0, (LPWSTR)&messageBuffer, 0, nullptr
- );
-
- std::wstring message(messageBuffer, size);
- LocalFree(messageBuffer);
- return message;
- }
-
- /**
- * @brief Retrieves the addresses of specified functions from a loaded module using the export directory.
- *
- * This function dynamically resolves the addresses of specified functions in a given module by accessing
- * the export directory of the module. It searches for functions by their names and populates an array of
- * function pointers with the resolved addresses.
- *
- *
- * @param hModule Handle to the loaded module (DLL or EXE) in which to resolve the function addresses.
- * @param names An array of function names (strings) to be resolved in the module.
- * @param functions An array of function pointers where the resolved function addresses will be stored.
- * @param count The number of functions to resolve.
- *
- * @return bool true if all requested function addresses were successfully resolved, false otherwise.
- */
+ // retrieves the addresses of specified functions from a loaded module using the export directory
static void GetFunctionAddresses(const HMODULE hModule, const char* names[], void** functions, size_t count) {
const PIMAGE_DOS_HEADER dosHeader = reinterpret_cast(hModule);
const PIMAGE_NT_HEADERS ntHeaders = reinterpret_cast(
@@ -2245,45 +1948,65 @@ struct VM {
#else
const std::string& brand = cpu::get_brand();
- struct KeywordCheck {
- const char* str;
- std::regex reg;
+ struct CStrView {
+ const char* data;
+ std::size_t size;
+ constexpr CStrView(const char* d, std::size_t s) noexcept
+ : data(d), size(s) {
+ }
};
- static const std::array checks = { {
- {"qemu", std::regex("qemu", std::regex::icase | std::regex::optimize)},
- {"kvm", std::regex("kvm", std::regex::icase | std::regex::optimize)},
- {"vbox", std::regex("vbox", std::regex::icase | std::regex::optimize)},
- {"virtualbox",std::regex("virtualbox",std::regex::icase | std::regex::optimize)},
- {"monitor", std::regex("monitor", std::regex::icase | std::regex::optimize)},
- {"bhyve", std::regex("bhyve", std::regex::icase | std::regex::optimize)},
- {"hypervisor",std::regex("hypervisor",std::regex::icase | std::regex::optimize)},
- {"hvisor", std::regex("hvisor", std::regex::icase | std::regex::optimize)},
- {"parallels", std::regex("parallels", std::regex::icase | std::regex::optimize)},
- {"vmware", std::regex("vmware", std::regex::icase | std::regex::optimize)}
+ static constexpr std::array checks{ {
+ { "qemu", 4 },
+ { "kvm", 3 },
+ { "vbox", 4 },
+ { "virtualbox", 10},
+ { "monitor", 7 },
+ { "bhyve", 5 },
+ { "hypervisor", 10},
+ { "hvisor", 6 },
+ { "parallels", 9 },
+ { "vmware", 6 }
} };
- u8 match_count = 0;
- bool qemu_found = false;
+ for (auto& v : checks) {
+ if (brand.size() < v.size)
+ continue; // too short to match
+
+ if (brand.find(v.data) != std::string::npos) {
+ debug("BRAND_KEYWORDS: match = ", v.data);
- for (const auto& check : checks) {
- if (std::regex_search(brand, check.reg)) {
- debug("BRAND_KEYWORDS: match = ", check.str);
- match_count++;
+ // For these, we only care that it's virtualized:
+ if (v.size == 7 // "monitor"
+ || v.size == 6 && v.data[0] == 'h' // "hvisor"
+ || v.size == 10 && v.data[0] == 'h') // "hypervisor"
+ {
+ return true;
+ }
- if (!qemu_found && (check.str[0] == 'q' || check.str[0] == 'Q')) {
- qemu_found = (std::strcmp(check.str, "qemu") == 0);
+ // Otherwise map to your enums:
+ switch (v.size) {
+ case 4: // "qemu" or "vbox"
+ return core::add(v.data[0] == 'q'
+ ? brands::QEMU
+ : brands::VBOX);
+ case 3: // "kvm"
+ return core::add(brands::KVM);
+ case 5: // "bhyve"
+ return core::add(brands::BHYVE);
+ case 9: // "parallels"
+ return core::add(brands::PARALLELS);
+ case 10: // "virtualbox"
+ return core::add(brands::VBOX);
+ case 6: // "vmware"
+ return core::add(brands::VMWARE);
+ default:
+ return false;
}
}
}
- debug("BRAND_KEYWORDS: matches: ", static_cast(match_count));
-
- if (qemu_found) {
- return core::add(brands::QEMU);
- }
-
- return (match_count > 0);
+ return false;
#endif
}
@@ -2366,7 +2089,6 @@ struct VM {
[[nodiscard]] static bool mac_address_check() {
// C-style array on purpose
u8 mac[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
#if (LINUX)
struct ifreq ifr;
struct ifconf ifc;
@@ -2377,7 +2099,7 @@ struct VM {
if (sock == -1) {
return false;
- };
+ }
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
@@ -2406,71 +2128,83 @@ struct VM {
if (success) {
std::memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
- } else {
+ }
+ else {
debug("MAC: ", "not successful");
}
#elif (WINDOWS)
- DWORD dwBufLen = 0;
- if (GetAdaptersInfo(nullptr, &dwBufLen) != ERROR_BUFFER_OVERFLOW) {
+ ULONG needed = 0;
+ if (GetIfTable(nullptr, &needed, /*order=*/FALSE) != ERROR_INSUFFICIENT_BUFFER) {
return false;
}
- PIP_ADAPTER_INFO AdapterInfo = (PIP_ADAPTER_INFO)std::malloc(dwBufLen);
- if (AdapterInfo == nullptr) {
+ MIB_IFTABLE* table = (MIB_IFTABLE*)std::malloc(needed);
+ if (!table) return false;
+
+ if (GetIfTable(table, &needed, FALSE) != NO_ERROR) {
+ std::free(table);
return false;
}
- if (GetAdaptersInfo(AdapterInfo, &dwBufLen) == NO_ERROR) {
- std::memcpy(mac, AdapterInfo->Address, sizeof(mac));
+ for (DWORD i = 0; i < table->dwNumEntries; ++i) {
+ MIB_IFROW& row = table->table[i];
+ if (row.dwPhysAddrLen == 6
+ && (row.dwOperStatus == IF_OPER_STATUS_OPERATIONAL)
+ && row.dwType != IF_TYPE_SOFTWARE_LOOPBACK)
+ {
+ for (int b = 0; b < 6; ++b) {
+ mac[b] = row.bPhysAddr[b];
+ }
+ break;
+ }
}
- std::free(AdapterInfo);
-#else
- return false;
-#endif
+ std::free(table);
#ifdef __VMAWARE_DEBUG__
- std::stringstream ss;
- ss << std::setw(2) << std::setfill('0') << std::hex
- << static_cast(mac[0]) << ":"
- << static_cast(mac[1]) << ":"
- << static_cast(mac[2]) << ":XX:XX:XX";
- /* removed for privacy reasons, only the first 3 bytes are needed
- << static_cast(mac[3]) << ":"
- << static_cast(mac[4]) << ":"
- << static_cast(mac[5]);
- */
- debug("MAC: ", ss.str());
+ {
+ std::stringstream ss;
+ ss << std::hex << std::setw(2) << std::setfill('0')
+ << static_cast(mac[0]) << ":"
+ << static_cast(mac[1]) << ":"
+ << static_cast(mac[2]) << ":XX:XX:XX";
+ debug("MAC: ", ss.str());
+ }
#endif
- auto compare = [mac](u8 mac1, u8 mac2, u8 mac3) noexcept -> bool {
- return (mac[0] == mac1 && mac[1] == mac2 && mac[2] == mac3);
- };
- // Check for known virtualization MAC address prefixes
- if (compare(0x08, 0x00, 0x27))
- return core::add(brands::VBOX);
+ if ((mac[0] | mac[1] | mac[2]) == 0) {
+ return false;
+ }
- if (compare(0x00, 0x0C, 0x29) ||
- compare(0x00, 0x1C, 0x14) ||
- compare(0x00, 0x50, 0x56) ||
- compare(0x00, 0x05, 0x69))
- {
+ const uint32_t prefix = (uint32_t)mac[0]
+ | ((uint32_t)mac[1] << 8)
+ | ((uint32_t)mac[2] << 16);
+
+ constexpr uint32_t VBOX = 0x270008; // 08:00:27
+ constexpr uint32_t VMW1 = 0x29000C; // 00:0C:29
+ constexpr uint32_t VMW2 = 0x141C00; // 00:1C:14
+ constexpr uint32_t VMW3 = 0x565000; // 00:50:56
+ constexpr uint32_t VMW4 = 0x690500; // 00:05:69
+ constexpr uint32_t XEN = 0xE31600; // 00:16:E3
+ constexpr uint32_t PAR = 0x421C00; // 00:1C:42
+
+ if (prefix == VBOX) {
+ return core::add(brands::VBOX);
+ }
+ else if (prefix == VMW1 || prefix == VMW2
+ || prefix == VMW3 || prefix == VMW4) {
return core::add(brands::VMWARE);
}
-
- if (compare(0x00, 0x16, 0xE3))
+ else if (prefix == XEN) {
return core::add(brands::XEN);
-
- if (compare(0x00, 0x1C, 0x42))
+ }
+ else if (prefix == PAR) {
return core::add(brands::PARALLELS);
+ }
- /*
- see https://github.com/kernelwernel/VMAware/issues/105
- if (compare(0x0A, 0x00, 0x27)) {
- return core::add(brands::HYBRID);
- }
- */
-
return false;
+#else
+ return false;
+#endif
}
@@ -2741,7 +2475,7 @@ struct VM {
#endif
}
__except (EXCEPTION_EXECUTE_HANDLER) {
- return false; // umip
+ return false; // CR4.UMIP
}
// Extract 32-bit base from bytes [2..5]
@@ -2766,7 +2500,7 @@ struct VM {
return false;
#else
static constexpr struct {
- const char* dll_name;
+ const char* dll_name;
const char* brand;
} dll_checks[] = {
{"sbiedll.dll", brands::SANDBOXIE},
@@ -2780,7 +2514,7 @@ struct VM {
};
for (const auto& check : dll_checks) {
- if (GetModuleHandle(_T(check.dll_name)) != nullptr) {
+ if (GetModuleHandleA(check.dll_name) != nullptr) {
debug("DLL: Found ", check.dll_name, " (", check.brand, ")");
return core::add(check.brand);
}
@@ -2936,7 +2670,7 @@ struct VM {
/**
* @brief Find for VM specific files
* @category Windows
- * @implements VM::VM_FILES
+ * @implements VM::FILES
*/
[[nodiscard]] static bool vm_files() {
#if !WINDOWS
@@ -2960,19 +2694,19 @@ struct VM {
}
constexpr std::array vmwareFiles = { {
- "drivers\\Vmmouse.sys",
- "drivers\\Vmusbmouse.sys",
- "drivers\\vm3dgl.dll",
- "drivers\\vmdum.dll",
- "drivers\\VmGuestLibJava.dll",
- "drivers\\vm3dver.dll",
- "drivers\\vmtray.dll",
- "drivers\\VMToolsHook.dll",
- "drivers\\vmGuestLib.dll",
- "drivers\\vmhgfs.dll",
- "vm3dum64_loader.dll",
- "vm3dum64_10.dll"
- } };
+ "drivers\\Vmmouse.sys",
+ "drivers\\Vmusbmouse.sys",
+ "drivers\\vm3dgl.dll",
+ "drivers\\vmdum.dll",
+ "drivers\\VmGuestLibJava.dll",
+ "drivers\\vm3dver.dll",
+ "drivers\\vmtray.dll",
+ "drivers\\VMToolsHook.dll",
+ "drivers\\vmGuestLib.dll",
+ "drivers\\vmhgfs.dll",
+ "vm3dum64_loader.dll",
+ "vm3dum64_10.dll"
+ } };
constexpr std::array vboxFiles = { {
"drivers\\VBoxMouse.sys",
@@ -2992,7 +2726,7 @@ struct VM {
"vboxoglerrorspu.dll",
"vboxoglfeedbackspu.dll",
"vboxoglarrayspu.dll"
- } };
+ } };
constexpr std::array kvmFiles = { {
"drivers\\balloon.sys",
@@ -3027,13 +2761,12 @@ struct VM {
auto checkFiles = [&](const auto& files, u8& count) {
for (const auto& relativePath : files) {
char szPath[MAX_PATH] = { 0 };
- // Combination of the system directory with the relative path
PathCombineA(szPath, szSysDir, relativePath);
if (util::exists(szPath)) {
- count++;
+ ++count;
}
}
- };
+ };
checkFiles(vmwareFiles, vmware);
checkFiles(vboxFiles, vbox);
@@ -3046,27 +2779,80 @@ struct VM {
}
if (util::exists("C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp\\agent.pyw")) {
- debug("VM Files: Found startup agent (agent.pyw), indicating CUCKOO VM.");
+ debug("VM_FILES: Found startup agent (agent.pyw), indicating CUCKOO VM.");
return core::add(brands::CUCKOO);
}
+
+ {
+ char basePath[MAX_PATH];
+ const char* programDir = nullptr;
+ if (util::is_wow64()) {
+ DWORD len = GetEnvironmentVariableA("ProgramW6432", basePath, MAX_PATH);
+ if (len == 0 || len >= MAX_PATH) {}
+ else {
+ programDir = basePath;
+ }
+ }
+ else {
+ if (SHGetFolderPathA(nullptr, CSIDL_PROGRAM_FILES, nullptr, 0, basePath) == S_OK) {
+ programDir = basePath;
+ }
+ }
+ if (programDir) {
+ const char suffix[] = "\\Virtio-Win\\";
+ size_t dirLen = strlen(programDir);
+ size_t suffLen = sizeof(suffix) - 1;
+ if (dirLen + suffLen < MAX_PATH) {
+ memcpy(basePath + dirLen, suffix, suffLen + 1);
+ if (util::exists(basePath)) {
+ debug("VM_FILES: Detected KVM directory at ", basePath);
+ return core::add(brands::KVM);
+ }
+ }
+ }
+ }
+
+ {
+ char szProgramFile[MAX_PATH];
+ char szPath[MAX_PATH] = { 0 };
+ const char* szDirectories[] = {
+ "qemu-ga",
+ "SPICE Guest Tools",
+ };
+ int dirCount = sizeof(szDirectories) / sizeof(szDirectories[0]);
+ for (int i = 0; i < dirCount; ++i) {
+ if (util::is_wow64()) {
+ ExpandEnvironmentStringsA("%ProgramW6432%", szProgramFile, ARRAYSIZE(szProgramFile));
+ }
+ else {
+ SHGetSpecialFolderPathA(nullptr, szProgramFile, CSIDL_PROGRAM_FILES, FALSE);
+ }
+ PathCombineA(szPath, szProgramFile, szDirectories[i]);
+ if (util::exists(szPath)) {
+ debug("VM_FILES: Detected QEMU directory at ", szPath);
+ return core::add(brands::QEMU);
+ }
+ }
+ }
+
if (vbox > vmware && vbox > kvm && vbox > vpc && vbox > parallels) {
- debug("VM Files: Detected VBox files with count ", vbox);
+ debug("VM_FILES: Detected VBox files with count ", vbox);
return core::add(brands::VBOX);
}
if (vmware > vbox && vmware > kvm && vmware > vpc && vmware > parallels) {
- debug("VM Files: Detected VMware files with count ", vmware);
+ debug("VM_FILES: Detected VMware files with count ", vmware);
return core::add(brands::VMWARE);
}
if (kvm > vbox && kvm > vmware && kvm > vpc && kvm > parallels) {
- debug("VM Files: Detected KVM files with count ", kvm);
+ debug("VM_FILES: Detected KVM files with count ", kvm);
return core::add(brands::KVM);
}
if (vpc > vbox && vpc > vmware && vpc > kvm && vpc > parallels) {
- debug("VM Files: Detected VPC files with count ", vpc);
+ debug("VM_FILES: Detected VPC files with count ", vpc);
return core::add(brands::VPC);
}
if (parallels > vbox && parallels > vmware && parallels > kvm && parallels > vpc) {
- debug("VM Files: Detected Parallels files with count ", parallels);
+ debug("VM_FILES: Detected Parallels files with count ", parallels);
return core::add(brands::PARALLELS);
}
@@ -3121,7 +2907,7 @@ struct VM {
#if (!LINUX && !WINDOWS)
return false;
#else
- const u32 size = util::get_disk_size();
+ const u16 size = util::get_disk_size();
debug("DISK_SIZE: size = ", size);
@@ -3147,8 +2933,8 @@ struct VM {
#if (APPLE)
return false;
#else
- const u32 disk = util::get_disk_size();
- const u64 ram = util::get_physical_ram_size();
+ const u16 disk = util::get_disk_size();
+ const u32 ram = util::get_physical_ram_size();
debug("VBOX_DEFAULT: ram = ", ram);
@@ -3233,18 +3019,18 @@ struct VM {
return false;
#else
static const bool isVBoxSF = []() -> bool {
- // Try to open the VBoxSF service key
HKEY hKey = nullptr;
- constexpr LPCSTR kVBoxSFKey =
- "SYSTEM\\CurrentControlSet\\Services\\VBoxSF";
- LONG result = RegOpenKeyExA(
+ constexpr LPCTSTR kVBoxSFKey = _T("SYSTEM\\CurrentControlSet\\Services\\VBoxSF");
+
+ const LONG result = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
kVBoxSFKey,
0,
KEY_READ,
&hKey
);
+
if (result == ERROR_SUCCESS) {
RegCloseKey(hKey);
return true;
@@ -3253,242 +3039,96 @@ struct VM {
}();
return isVBoxSF;
+#endif
+ }
+
+
+ /**
+ * @brief Check if the function "wine_get_unix_file_name is present and if the OS booted from a VHD container
+ * @category Windows
+ * @implements VM::WINE
+ */
+ [[nodiscard]] static bool wine() {
+ #if (!WINDOWS)
+ return false;
+ #else
+ #if (_WIN32_WINNT < _WIN32_WINNT_WIN8)
+ return false;
+ #else
+ BOOL isNativeVhdBoot = 0;
+
+ __try {
+ if (IsNativeVhdBoot(&isNativeVhdBoot)) {
+ return (isNativeVhdBoot == 1);
+ }
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER) {
+ return true;
+ }
+ #endif
+
+ const HMODULE k32 = GetModuleHandle(_T("kernel32.dll"));
+ if (!k32) {
+ return false;
+ }
+
+ const char* names[] = { "wine_get_unix_file_name" };
+ void* functions[1] = { nullptr };
+
+ util::GetFunctionAddresses(k32, names, functions, _countof(names));
+
+ if (functions[0] != nullptr) {
+ return core::add(brands::WINE);
+ }
+
+ return false;
#endif
}
-/* GPL */ // @brief Check if the computer name (not username to be clear) is VM-specific
-/* GPL */ // @category Windows
-/* GPL */ // @author InviZzzible project
-/* GPL */ // @implements VM::COMPUTER_NAME
-/* GPL */ [[nodiscard]] static bool computer_name_match() {
-/* GPL */ #if (!WINDOWS)
-/* GPL */ return false;
-/* GPL */ #else
-/* GPL */ auto out_length = MAX_PATH;
-/* GPL */ std::vector comp_name(static_cast(out_length), 0);
-/* GPL */ GetComputerNameA((LPSTR)comp_name.data(), (LPDWORD)&out_length);
-/* GPL */
-/* GPL */ auto compare = [&](const std::string& s) -> bool {
-/* GPL */ return (std::strcmp((LPCSTR)comp_name.data(), s.c_str()) == 0);
-/* GPL */ };
-/* GPL */
-/* GPL */ debug("COMPUTER_NAME: fetched = ", (LPCSTR)comp_name.data());
-/* GPL */
-/* GPL */ if (compare("InsideTm") || compare("TU-4NH09SMCG1HC")) { // anubis
-/* GPL */ debug("COMPUTER_NAME: detected Anubis");
-/* GPL */ return core::add(brands::ANUBIS);
-/* GPL */ }
-/* GPL */
-/* GPL */ if (compare("klone_x64-pc") || compare("tequilaboomboom")) { // general
-/* GPL */ debug("COMPUTER_NAME: detected general (VM but unknown)");
-/* GPL */ return true;
-/* GPL */ }
-/* GPL */
-/* GPL */ return false;
-/* GPL */ #endif
-/* GPL */ }
-/* GPL */
-/* GPL */
-/* GPL */ // @brief Check wine_get_unix_file_name file for Wine
-/* GPL */ // @author pafish project
-/* GPL */ // @link https://github.com/a0rtega/pafish/blob/master/pafish/wine.c
-/* GPL */ // @category Windows
-/* GPL */ // @implements VM::WINE_CHECK
-/* GPL */ [[nodiscard]] static bool wine() {
-/* GPL */ #if (!WINDOWS)
-/* GPL */ return false;
-/* GPL */ #else
-/* GPL */
-/* GPL */ const HMODULE k32 = GetModuleHandle(_T("kernel32.dll"));
-/* GPL */
-/* GPL */ if (k32 != NULL) {
-/* GPL */ if (GetProcAddress(k32, "wine_get_unix_file_name") != NULL) {
-/* GPL */ return core::add(brands::WINE);
-/* GPL */ }
-/* GPL */ }
-/* GPL */
-/* GPL */ return false;
-/* GPL */ #endif
-/* GPL */ }
-/* GPL */
-/* GPL */
-/* GPL */ // @brief Check if hostname is specific
-/* GPL */ // @author InviZzzible project
-/* GPL */ // @category Windows
-/* GPL */ // @implements VM::HOSTNAME
-/* GPL */ [[nodiscard]] static bool hostname_match() {
-/* GPL */ #if (!WINDOWS)
-/* GPL */ return false;
-/* GPL */ #else
-/* GPL */ auto out_length = MAX_PATH;
-/* GPL */ std::vector dns_host_name(static_cast(out_length), 0);
-/* GPL */ GetComputerNameExA(ComputerNameDnsHostname, (LPSTR)dns_host_name.data(), (LPDWORD)&out_length);
-/* GPL */
-/* GPL */ debug("HOSTNAME: ", (LPCSTR)dns_host_name.data());
-/* GPL */
-/* GPL */ return (!lstrcmpiA((LPCSTR)dns_host_name.data(), "SystemIT"));
-/* GPL */ #endif
-/* GPL */ }
-/* GPL */
-/* GPL */
-/* GPL */ // @brief Check for KVM directory "Virtio-Win"
-/* GPL */ // @category Windows
-/* GPL */ // @author LordNoteWorthy
-/* GPL */ // @note from Al-Khaser project
-/* GPL */ // @link https://github.com/LordNoteworthy/al-khaser/blob/0f31a3866bafdfa703d2ed1ee1a242ab31bf5ef0/al-khaser/AntiVM/KVM.cpp
-/* GPL */ // @implements VM::KVM_DIRS
-/* GPL */ [[nodiscard]] static bool kvm_directories() {
-/* GPL */ #if (!WINDOWS)
-/* GPL */ return false;
-/* GPL */ #else
-/* GPL */ char basePath[MAX_PATH];
-/* GPL */ const char* programDir;
-/* GPL */
-/* GPL */ if (util::is_wow64()) {
-/* GPL */ DWORD len = GetEnvironmentVariable(_T("ProgramW6432"), basePath, MAX_PATH);
-/* GPL */ if (len == 0 || len >= MAX_PATH) return false;
-/* GPL */ programDir = basePath;
-/* GPL */ }
-/* GPL */ else {
-/* GPL */ if (SHGetFolderPath(nullptr, CSIDL_PROGRAM_FILES, nullptr, 0, basePath) != S_OK) {
-/* GPL */ return false;
-/* GPL */ }
-/* GPL */ programDir = basePath;
-/* GPL */ }
-/* GPL */
-/* GPL */ const char suffix[] = "\\Virtio-Win\\";
-/* GPL */ size_t dirLen = strlen(programDir);
-/* GPL */ size_t suffLen = sizeof(suffix) - 1;
-/* GPL */ if (dirLen + suffLen >= MAX_PATH) return false;
-/* GPL */ memcpy(basePath + dirLen, suffix, suffLen + 1);
-/* GPL */
-/* GPL */ return util::exists(basePath);
-/* GPL */ #endif
-/* GPL */ }
-/* GPL */
-/* GPL */
-/* GPL */ // @brief Check for QEMU-specific blacklisted directories
-/* GPL */ // @author LordNoteworthy
-/* GPL */ // @link https://github.com/LordNoteworthy/al-khaser/blob/master/al-khaser/AntiVM/Qemu.cpp
-/* GPL */ // @category Windows
-/* GPL */ // @note from al-khaser project
-/* GPL */ // @implements VM::QEMU_DIR
-/* GPL */ [[nodiscard]] static bool qemu_dir() {
-/* GPL */ #if (!WINDOWS)
-/* GPL */ return false;
-/* GPL */ #else
-/* GPL */ TCHAR szProgramFile[MAX_PATH];
-/* GPL */ TCHAR szPath[MAX_PATH] = _T("");
-/* GPL */
-/* GPL */ const TCHAR* szDirectories[] = {
-/* GPL */ _T("qemu-ga"), // QEMU guest agent.
-/* GPL */ _T("SPICE Guest Tools"), // SPICE guest tools.
-/* GPL */ };
-/* GPL */
-/* GPL */ WORD iLength = sizeof(szDirectories) / sizeof(szDirectories[0]);
-/* GPL */ for (int i = 0; i < iLength; i++) {
-/* GPL */ if (util::is_wow64())
-/* GPL */ ExpandEnvironmentStrings(_T("%ProgramW6432%"), szProgramFile, ARRAYSIZE(szProgramFile));
-/* GPL */ else
-/* GPL */ SHGetSpecialFolderPath(NULL, szProgramFile, CSIDL_PROGRAM_FILES, FALSE);
-/* GPL */
-/* GPL */ PathCombine(szPath, szProgramFile, szDirectories[i]);
-/* GPL */
-/* GPL */ if (util::exists(szPath))
-/* GPL */ return core::add(brands::QEMU);
-/* GPL */ }
-/* GPL */
-/* GPL */ return false;
-/* GPL */ #endif
-/* GPL */ }
-/* GPL */
-/* GPL */
-/* GPL */ // @brief Check what power states are enabled
-/* GPL */ // @category Windows
-/* GPL */ // @author Al-Khaser project
-/* GPL */ // @implements VM::POWER_CAPABILITIES
-/* GPL */ [[nodiscard]] static bool power_capabilities() {
-/* GPL */ #if (!WINDOWS)
-/* GPL */ return false;
-/* GPL */ #else
-/* GPL */ SYSTEM_POWER_CAPABILITIES powerCaps;
-/* GPL */ bool power_stats = false;
-/* GPL */ if (GetPwrCapabilities(&powerCaps) == TRUE)
-/* GPL */ {
-/* GPL */ if ((powerCaps.SystemS1 | powerCaps.SystemS2 | powerCaps.SystemS3 | powerCaps.SystemS4) == FALSE)
-/* GPL */ {
-/* GPL */ power_stats = (powerCaps.ThermalControl == FALSE);
-/* GPL */ }
-/* GPL */
-/* GPL */ }
-/* GPL */
-/* GPL */ return power_stats;
-/* GPL */ #endif
-/* GPL */ }
-/* GPL */
-/* GPL */
-/* GPL */ // @brief Check for virtual machine signatures in disk drive device identifiers
-/* GPL */ // @category Windows
-/* GPL */ // @author Al-Khaser project
-/* GPL */ // @implements VM::SETUPAPI_DISK
-/* GPL */ [[nodiscard]] static bool setupapi_disk() {
-/* GPL */ #if (!WINDOWS)
-/* GPL */ return false;
-/* GPL */ #else
-/* GPL */ HDEVINFO hDevInfo;
-/* GPL */ SP_DEVINFO_DATA DeviceInfoData{};
-/* GPL */ DWORD i;
-/* GPL */
-/* GPL */ hDevInfo = SetupDiGetClassDevs((LPGUID)&GUID_DEVCLASS_DISKDRIVE,
-/* GPL */ 0,
-/* GPL */ 0,
-/* GPL */ DIGCF_PRESENT);
-/* GPL */
-/* GPL */ if (hDevInfo == INVALID_HANDLE_VALUE)
-/* GPL */ return false;
-/* GPL */
-/* GPL */ DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
-/* GPL */ DWORD dwPropertyRegDataType;
-/* GPL */ LPTSTR buffer = NULL;
-/* GPL */ DWORD dwSize = 0;
-/* GPL */
-/* GPL */ for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData); i++)
-/* GPL */ {
-/* GPL */ while (!SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_HARDWAREID,
-/* GPL */ &dwPropertyRegDataType, (PBYTE)buffer, dwSize, &dwSize))
-/* GPL */ {
-/* GPL */ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
-/* GPL */ if (buffer)LocalFree(buffer);
-/* GPL */ buffer = (LPTSTR)LocalAlloc(LPTR, static_cast(dwSize) * 2);
-/* GPL */ if (buffer == NULL)
-/* GPL */ break;
-/* GPL */ }
-/* GPL */ else
-/* GPL */ break;
-/* GPL */
-/* GPL */ }
-/* GPL */
-/* GPL */ if (buffer) {
-/* GPL */ if ((StrStrI(buffer, _T("vbox")) != NULL) ||
-/* GPL */ (StrStrI(buffer, _T("vmware")) != NULL) ||
-/* GPL */ (StrStrI(buffer, _T("qemu")) != NULL) ||
-/* GPL */ (StrStrI(buffer, _T("virtual")) != NULL))
-/* GPL */ {
-/* GPL */ return true;
-/* GPL */ }
-/* GPL */ }
-/* GPL */ }
-/* GPL */
-/* GPL */ if (buffer) LocalFree(buffer);
-/* GPL */ SetupDiDestroyDeviceInfoList(hDevInfo);
-/* GPL */ if (GetLastError() != NO_ERROR && GetLastError() != ERROR_NO_MORE_ITEMS) return false;
-/* GPL */
-/* GPL */ return false;
-/* GPL */ #endif
-/* GPL */ }
-/* GPL */
-/* GPL */
+ /**
+ * @brief Check what power states are enabled
+ * @category Windows
+ * @implements VM::POWER_CAPABILITIES
+ */
+ [[nodiscard]] static bool power_capabilities() {
+#if (!WINDOWS)
+ return false;
+#else
+ const HMODULE ntdll = GetModuleHandle(_T("ntdll.dll"));
+ const char* names[] = { "NtPowerInformation" };
+ void* funcs[1] = { nullptr };
+ util::GetFunctionAddresses(ntdll, names, funcs, _countof(funcs));
+
+ if (!funcs[0])
+ return false;
+
+ using NtPI_t = NTSTATUS(NTAPI*)(POWER_INFORMATION_LEVEL,
+ PVOID, ULONG,
+ PVOID, ULONG);
+ auto NtPowerInformation = reinterpret_cast(funcs[0]);
+
+ SYSTEM_POWER_CAPABILITIES caps = { 0 };
+ NTSTATUS status = NtPowerInformation(
+ SystemPowerCapabilities,
+ nullptr, 0,
+ &caps, sizeof(caps)
+ );
+ if (status != 0)
+ return false;
+
+ const bool no_sleep_states = !(caps.SystemS1 ||
+ caps.SystemS2 ||
+ caps.SystemS3 ||
+ caps.SystemS4);
+ if (no_sleep_states)
+ {
+ return (caps.ThermalControl == FALSE);
+ }
+
+ return false;
+#endif
+ }
/**
@@ -3727,145 +3367,7 @@ struct VM {
return false;
#endif
}
-
-
- /**
- * @brief Check MSSMBIOS registry for VM-specific signatures
- * @category Windows
- * @implements VM::MSSMBIOS
- */
- [[nodiscard]] static bool mssmbios() {
-#if (!WINDOWS)
- return false;
-#else
- struct PatternMeta {
- const char* str;
- size_t length;
- };
-
- struct CheckConfig {
- const char* value_name;
- std::array patterns; // Size for largest pattern set
- const char* debug_prefix;
- size_t actual_pattern_count;
- };
-
- constexpr CheckConfig checks[] = {
- { // SMBiosData check (must come first)
- "SMBiosData",
- {{
- {"INNOTEK GMBH", 12},
- {"VIRTUALBOX", 10},
- {"SUN MICROSYSTEMS", 16},
- {"VBOXVER", 7},
- {"VIRTUAL MACHINE", 15},
- {"VMWARE", 6},
- {"GOOGLE COMPUTE ENGINE", 20}
- }},
- "SMBIOS",
- 7 // Actual number of patterns
- },
- { // AcpiData check
- "AcpiData",
- {{
- {"INNOTEK GMBH", 12},
- {"VBOXAPIC", 8},
- {"SUN MICROSYSTEMS", 16},
- {"VBOXVER", 7},
- {"VIRTUAL MACHINE", 15},
- {"VMWARE", 6},
- {} // Padding
- }},
- "ACPI",
- 6 // Actual number of patterns
- }
- };
-
- HKEY hk = nullptr;
- bool detected = false;
-
- for (const auto& config : checks) {
- LSTATUS ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- _T("SYSTEM\\CurrentControlSet\\Services\\mssmbios\\Data"),
- 0, KEY_READ, &hk);
-
- if (ret != ERROR_SUCCESS) {
- debug(config.debug_prefix, ": Registry open failed");
- continue;
- }
-
- DWORD type = 0;
- DWORD length = 0;
-
- ret = RegQueryValueEx(hk, _T(config.value_name), nullptr, &type, nullptr, &length);
- if (ret != ERROR_SUCCESS || length == 0) {
- RegCloseKey(hk);
- debug(config.debug_prefix, ": Data size query failed");
- continue;
- }
-
- constexpr DWORD kStackThreshold = 4096;
- char stack_buffer[kStackThreshold] = { 0 };
- bool heap_allocated = false;
- char* buffer = nullptr;
-
- if (length <= kStackThreshold) {
- buffer = stack_buffer;
- }
- else {
- buffer = static_cast(LocalAlloc(LPTR, length));
- if (!buffer) {
- RegCloseKey(hk);
- debug(config.debug_prefix, ": Memory allocation failed");
- continue;
- }
- heap_allocated = true;
- }
-
- ret = RegQueryValueEx(hk, _T(config.value_name), nullptr, &type,
- reinterpret_cast(buffer), &length);
-
- if (ret != ERROR_SUCCESS) {
- if (heap_allocated) LocalFree(buffer);
- RegCloseKey(hk);
- debug(config.debug_prefix, ": Data read failed");
- continue;
- }
-
- for (DWORD i = 0; i < length; ++i) {
- buffer[i] = (buffer[i] >= 'a' && buffer[i] <= 'z')
- ? static_cast(buffer[i] - 32)
- : buffer[i];
- }
-
- for (DWORD i = 0; i < length; ++i) {
- const char current = buffer[i];
-
- for (size_t p = 0; p < config.actual_pattern_count; ++p) {
- const auto& pattern = config.patterns[p];
-
- if (current != pattern.str[0]) continue;
- if (i + pattern.length > length) continue;
-
- if (memcmp(buffer + i, pattern.str, pattern.length) == 0) {
- detected = true;
- goto cleanup;
- }
- }
- }
-
- cleanup:
- if (heap_allocated) LocalFree(buffer);
- RegCloseKey(hk);
-
- if (detected && (&config == &checks[0])) break;
- if (detected) return true;
- }
-
- return detected;
-#endif
- }
-
+
/**
* @brief Check if memory is too low for MacOS system
@@ -4081,105 +3583,126 @@ struct VM {
return false;
#else
u8 count = 0;
-
std::unordered_set failedKeys;
- auto check_key = [&failedKeys, &count](const char* p_brand, const char* subKey, const char* valueName, const char* comp_string) {
- if (failedKeys.find(subKey) != failedKeys.end()) {
- return;
- }
+ struct RegCheck {
+ const char* brand;
+ const char* subKey;
+ const char* valueName;
+ const char* compString;
+ };
+ static const std::vector checks = {
+ { brands::BOCHS, "HARDWARE\\Description\\System", "SystemBiosVersion", "BOCHS" },
+ { brands::BOCHS, "HARDWARE\\Description\\System", "VideoBiosVersion", "BOCHS" },
+
+ { brands::ANUBIS, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductID", "76487-337-8429955-22614" },
+ { brands::ANUBIS, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductID", "76487-337-8429955-22614" },
+
+ { brands::CWSANDBOX,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductID", "76487-644-3177037-23510" },
+ { brands::CWSANDBOX,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductID", "76487-644-3177037-23510" },
+
+ { brands::JOEBOX, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductID", "55274-640-2673064-23950" },
+ { brands::JOEBOX, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductID", "55274-640-2673064-23950" },
+
+ { brands::PARALLELS,"HARDWARE\\Description\\System", "SystemBiosVersion", "PARALLELS" },
+ { brands::PARALLELS,"HARDWARE\\Description\\System", "VideoBiosVersion", "PARALLELS" },
+
+ { brands::QEMU, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "QEMU" },
+ { brands::QEMU, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 1\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "QEMU" },
+ { brands::QEMU, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 2\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "QEMU" },
+ { brands::QEMU, "HARDWARE\\Description\\System", "SystemBiosVersion", "QEMU" },
+ { brands::QEMU, "HARDWARE\\Description\\System", "VideoBiosVersion", "QEMU" },
+ { brands::QEMU, "HARDWARE\\Description\\System\\BIOS", "SystemManufacturer", "QEMU" },
+
+ { brands::VBOX, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "VBOX" },
+ { brands::VBOX, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 1\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "VBOX" },
+ { brands::VBOX, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 2\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "VBOX" },
+ { brands::VBOX, "HARDWARE\\Description\\System", "SystemBiosVersion", "VBOX" },
+ { brands::VBOX, "HARDWARE\\DESCRIPTION\\System", "SystemBiosDate", "06/23/99" },
+ { brands::VBOX, "HARDWARE\\Description\\System", "VideoBiosVersion", "VIRTUALBOX" },
+ { brands::VBOX, "HARDWARE\\Description\\System\\BIOS", "SystemProductName", "VIRTUAL" },
+ { brands::VBOX, "SYSTEM\\ControlSet001\\Services\\Disk\\Enum", "DeviceDesc", "VBOX" },
+ { brands::VBOX, "SYSTEM\\ControlSet001\\Services\\Disk\\Enum", "FriendlyName", "VBOX" },
+ { brands::VBOX, "SYSTEM\\ControlSet002\\Services\\Disk\\Enum", "DeviceDesc", "VBOX" },
+ { brands::VBOX, "SYSTEM\\ControlSet002\\Services\\Disk\\Enum", "FriendlyName", "VBOX" },
+ { brands::VBOX, "SYSTEM\\ControlSet003\\Services\\Disk\\Enum", "DeviceDesc", "VBOX" },
+ { brands::VBOX, "SYSTEM\\ControlSet003\\Services\\Disk\\Enum", "FriendlyName", "VBOX" },
+ { brands::VBOX, "SYSTEM\\CurrentControlSet\\Control\\SystemInformation", "SystemProductName", "VIRTUAL" },
+ { brands::VBOX, "SYSTEM\\CurrentControlSet\\Control\\SystemInformation", "SystemProductName", "VIRTUALBOX" },
+
+ { brands::VMWARE, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "VMWARE" },
+ { brands::VMWARE, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 1\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "VMWARE" },
+ { brands::VMWARE, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 2\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "VMWARE" },
+ { brands::VMWARE, "HARDWARE\\Description\\System", "SystemBiosVersion", "VMWARE" },
+ { brands::VMWARE, "HARDWARE\\Description\\System", "SystemBiosVersion", "INTEL - 6040000" },
+ { brands::VMWARE, "HARDWARE\\Description\\System", "VideoBiosVersion", "VMWARE" },
+ { brands::VMWARE, "HARDWARE\\Description\\System\\BIOS", "SystemProductName", "VMware" },
+ { brands::VMWARE, "HARDWARE\\Description\\System\\BIOS", "SystemManufacturer", "VMware, Inc." },
+ { brands::VMWARE, "SYSTEM\\ControlSet001\\Services\\Disk\\Enum", "0", "VMware" },
+ { brands::VMWARE, "SYSTEM\\ControlSet001\\Services\\Disk\\Enum", "1", "VMware" },
+ { brands::VMWARE, "SYSTEM\\ControlSet001\\Services\\Disk\\Enum", "DeviceDesc", "VMware" },
+ { brands::VMWARE, "SYSTEM\\ControlSet001\\Services\\Disk\\Enum", "FriendlyName", "VMware" },
+ { brands::VMWARE, "SYSTEM\\ControlSet002\\Services\\Disk\\Enum", "DeviceDesc", "VMware" },
+ { brands::VMWARE, "SYSTEM\\ControlSet002\\Services\\Disk\\Enum", "FriendlyName", "VMware" },
+ { brands::VMWARE, "SYSTEM\\ControlSet003\\Services\\Disk\\Enum", "DeviceDesc", "VMware" },
+ { brands::VMWARE, "SYSTEM\\ControlSet003\\Services\\Disk\\Enum", "FriendlyName", "VMware" },
+ { brands::VMWARE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", "DisplayName", "vmware tools" },
+ { brands::VMWARE, "SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000", "CoInstallers32", "*vmx*" },
+ { brands::VMWARE, "SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000", "DriverDesc", "VMware*" },
+ { brands::VMWARE, "SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000", "InfSection", "vmx*" },
+ { brands::VMWARE, "SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000", "ProviderName", "VMware*" },
+ { brands::VMWARE, "SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000\\Settings", "Device Description", "VMware*" },
+ { brands::VMWARE, "SYSTEM\\CurrentControlSet\\Control\\SystemInformation", "SystemProductName", "VMWARE" },
+ { brands::VMWARE, "SYSTEM\\CurrentControlSet\\Control\\Video\\{GUID}\\Video", "Service", "vm3dmp" },
+ { brands::VMWARE, "SYSTEM\\CurrentControlSet\\Control\\Video\\{GUID}\\Video", "Service", "vmx_svga" },
+ { brands::VMWARE, "SYSTEM\\CurrentControlSet\\Control\\Video\\{GUID}\\0000", "Device Description", "VMware SVGA*" },
+ { brands::VMWARE, "SYSTEM\\CurrentControlSet\\Services\\Disk\\Enum", "0", "VMWare" },
+ { brands::VMWARE, "HARDWARE\\ACPI\\DSDT\\PTLTD_\\CUSTOM__\\00000000", "00000000", "VMWARE" },
+
+ { brands::XEN, "HARDWARE\\Description\\System\\BIOS", "SystemProductName", "Xen" },
+ };
+
+ std::unordered_map> grouped;
+ grouped.reserve(checks.size());
+ for (const auto& chk : checks) {
+ grouped[chk.subKey].push_back(&chk);
+ }
+
+#if (CPP >= 17)
+ for (auto& [subKey, entries] : grouped) {
+#else
+ for (auto it = grouped.begin(); it != grouped.end(); ++it) {
+ const std::string& subKey = it->first;
+ std::vector& entries = it->second;
+#endif
+ if (failedKeys.count(subKey)) continue;
HKEY hKey;
- DWORD dwType;
- char buffer[1024] = {};
- DWORD bufferSize = sizeof(buffer);
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, subKey.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hKey) != ERROR_SUCCESS) {
+ failedKeys.insert(subKey);
+ continue;
+ }
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(subKey), 0, KEY_READ | KEY_WOW64_64KEY, &hKey) == ERROR_SUCCESS) {
- if (RegQueryValueEx(hKey, _T(valueName), nullptr, &dwType, reinterpret_cast(buffer), &bufferSize) == ERROR_SUCCESS) {
+ for (auto* chk : entries) {
+ DWORD dwType;
+ char buffer[1024] = {};
+ DWORD bufferSize = sizeof(buffer);
+
+ if (RegQueryValueExA(hKey, chk->valueName, nullptr, &dwType,
+ reinterpret_cast(buffer), &bufferSize) == ERROR_SUCCESS) {
if (dwType == REG_SZ || dwType == REG_EXPAND_SZ || dwType == REG_MULTI_SZ) {
- buffer[bufferSize - 1] = '\0';
- if (strstr(buffer, comp_string) != nullptr) {
- debug("HKLM_REGISTRIES: Found ", comp_string, " in ", subKey, " for brand ", p_brand);
- core::add(p_brand);
- count++;
+ buffer[bufferSize ? bufferSize - 1 : 0] = '\0';
+ if (strstr(buffer, chk->compString) != nullptr) {
+ debug("HKLM_REGISTRIES: Found ", chk->compString, " in ", subKey.c_str(), " for brand ", chk->brand);
+ core::add(chk->brand);
+ ++count;
}
}
}
- RegCloseKey(hKey);
- }
- else {
- failedKeys.insert(subKey);
}
- };
- check_key(brands::BOCHS, "HARDWARE\\Description\\System", "SystemBiosVersion", "BOCHS");
- check_key(brands::BOCHS, "HARDWARE\\Description\\System", "VideoBiosVersion", "BOCHS");
-
- check_key(brands::ANUBIS, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductID", "76487-337-8429955-22614");
- check_key(brands::ANUBIS, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductID", "76487-337-8429955-22614");
-
- check_key(brands::CWSANDBOX, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductID", "76487-644-3177037-23510");
- check_key(brands::CWSANDBOX, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductID", "76487-644-3177037-23510");
-
- check_key(brands::JOEBOX, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductID", "55274-640-2673064-23950");
- check_key(brands::JOEBOX, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductID", "55274-640-2673064-23950");
-
- check_key(brands::PARALLELS, "HARDWARE\\Description\\System", "SystemBiosVersion", "PARALLELS");
- check_key(brands::PARALLELS, "HARDWARE\\Description\\System", "VideoBiosVersion", "PARALLELS");
-
- check_key(brands::QEMU, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "QEMU");
- check_key(brands::QEMU, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 1\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "QEMU");
- check_key(brands::QEMU, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 2\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "QEMU");
- check_key(brands::QEMU, "HARDWARE\\Description\\System", "SystemBiosVersion", "QEMU");
- check_key(brands::QEMU, "HARDWARE\\Description\\System", "VideoBiosVersion", "QEMU");
- check_key(brands::QEMU, "HARDWARE\\Description\\System\\BIOS", "SystemManufacturer", "QEMU");
-
- check_key(brands::VBOX, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "VBOX");
- check_key(brands::VBOX, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 1\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "VBOX");
- check_key(brands::VBOX, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 2\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "VBOX");
- check_key(brands::VBOX, "HARDWARE\\Description\\System", "SystemBiosVersion", "VBOX");
- check_key(brands::VBOX, "HARDWARE\\DESCRIPTION\\System", "SystemBiosDate", "06/23/99");
- check_key(brands::VBOX, "HARDWARE\\Description\\System", "VideoBiosVersion", "VIRTUALBOX");
- check_key(brands::VBOX, "HARDWARE\\Description\\System\\BIOS", "SystemProductName", "VIRTUAL");
- check_key(brands::VBOX, "SYSTEM\\ControlSet001\\Services\\Disk\\Enum", "DeviceDesc", "VBOX");
- check_key(brands::VBOX, "SYSTEM\\ControlSet001\\Services\\Disk\\Enum", "FriendlyName", "VBOX");
- check_key(brands::VBOX, "SYSTEM\\ControlSet002\\Services\\Disk\\Enum", "DeviceDesc", "VBOX");
- check_key(brands::VBOX, "SYSTEM\\ControlSet002\\Services\\Disk\\Enum", "FriendlyName", "VBOX");
- check_key(brands::VBOX, "SYSTEM\\ControlSet003\\Services\\Disk\\Enum", "DeviceDesc", "VBOX");
- check_key(brands::VBOX, "SYSTEM\\ControlSet003\\Services\\Disk\\Enum", "FriendlyName", "VBOX");
- check_key(brands::VBOX, "SYSTEM\\CurrentControlSet\\Control\\SystemInformation", "SystemProductName", "VIRTUAL");
- check_key(brands::VBOX, "SYSTEM\\CurrentControlSet\\Control\\SystemInformation", "SystemProductName", "VIRTUALBOX");
-
- check_key(brands::VMWARE, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "VMWARE");
- check_key(brands::VMWARE, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 1\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "VMWARE");
- check_key(brands::VMWARE, "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 2\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0", "Identifier", "VMWARE");
- check_key(brands::VMWARE, "HARDWARE\\Description\\System", "SystemBiosVersion", "VMWARE");
- check_key(brands::VMWARE, "HARDWARE\\Description\\System", "SystemBiosVersion", "INTEL - 6040000");
- check_key(brands::VMWARE, "HARDWARE\\Description\\System", "VideoBiosVersion", "VMWARE");
- check_key(brands::VMWARE, "HARDWARE\\Description\\System\\BIOS", "SystemProductName", "VMware");
- check_key(brands::VMWARE, "HARDWARE\\Description\\System\\BIOS", "SystemManufacturer", "VMware, Inc.");
- check_key(brands::VMWARE, "SYSTEM\\ControlSet001\\Services\\Disk\\Enum", "0", "VMware");
- check_key(brands::VMWARE, "SYSTEM\\ControlSet001\\Services\\Disk\\Enum", "1", "VMware");
- check_key(brands::VMWARE, "SYSTEM\\ControlSet001\\Services\\Disk\\Enum", "DeviceDesc", "VMware");
- check_key(brands::VMWARE, "SYSTEM\\ControlSet001\\Services\\Disk\\Enum", "FriendlyName", "VMware");
- check_key(brands::VMWARE, "SYSTEM\\ControlSet002\\Services\\Disk\\Enum", "DeviceDesc", "VMware");
- check_key(brands::VMWARE, "SYSTEM\\ControlSet002\\Services\\Disk\\Enum", "FriendlyName", "VMware");
- check_key(brands::VMWARE, "SYSTEM\\ControlSet003\\Services\\Disk\\Enum", "DeviceDesc", "VMware");
- check_key(brands::VMWARE, "SYSTEM\\ControlSet003\\Services\\Disk\\Enum", "FriendlyName", "VMware");
- check_key(brands::VMWARE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", "DisplayName", "vmware tools");
- check_key(brands::VMWARE, "SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000", "CoInstallers32", "*vmx*");
- check_key(brands::VMWARE, "SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000", "DriverDesc", "VMware*");
- check_key(brands::VMWARE, "SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000", "InfSection", "vmx*");
- check_key(brands::VMWARE, "SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000", "ProviderName", "VMware*");
- check_key(brands::VMWARE, "SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000\\Settings", "Device Description", "VMware*");
- check_key(brands::VMWARE, "SYSTEM\\CurrentControlSet\\Control\\SystemInformation", "SystemProductName", "VMWARE");
- check_key(brands::VMWARE, "SYSTEM\\CurrentControlSet\\Control\\Video\\{GUID}\\Video", "Service", "vm3dmp");
- check_key(brands::VMWARE, "SYSTEM\\CurrentControlSet\\Control\\Video\\{GUID}\\Video", "Service", "vmx_svga");
- check_key(brands::VMWARE, "SYSTEM\\CurrentControlSet\\Control\\Video\\{GUID}\\0000", "Device Description", "VMware SVGA*");
- check_key(brands::VMWARE, "SYSTEM\\CurrentControlSet\\Services\\Disk\\Enum", "0", "VMWare");
- check_key(brands::VMWARE, "HARDWARE\\ACPI\\DSDT\\PTLTD_\\CUSTOM__\\00000000", "00000000", "VMWARE");
-
- check_key(brands::XEN, "HARDWARE\\Description\\System\\BIOS", "SystemProductName", "Xen");
+ RegCloseKey(hKey);
+ }
return (count > 0);
#endif
@@ -4278,7 +3801,7 @@ struct VM {
#endif
}
__except (EXCEPTION_EXECUTE_HANDLER) {
- return false; // umip
+ return false; // CR4.UMIP
}
// 32-bit base from bytes [2..5]
@@ -4323,7 +3846,7 @@ struct VM {
#endif
}
__except (EXCEPTION_EXECUTE_HANDLER) {
- return false; // umip
+ return false; // CR4.UMIP
}
std::memcpy(&ldt, ldtr_buf, sizeof(ldt));
@@ -4652,98 +4175,61 @@ struct VM {
* @brief Check for odd CPU threads, usually a sign of modification through VM setting because 99% of CPUs have even numbers of threads
* @category x86
* @implements VM::ODD_CPU_THREADS
- */
- [[nodiscard]] static bool odd_cpu_threads() {
-#if (!x86)
- return false;
-#else
- const u32 threads = std::thread::hardware_concurrency();
-
- struct cpu::stepping_struct steps = cpu::fetch_steppings();
-
- debug("ODD_CPU_THREADS: model = ", static_cast(steps.model));
- debug("ODD_CPU_THREADS: family = ", static_cast(steps.family));
- debug("ODD_CPU_THREADS: extmodel = ", static_cast(steps.extmodel));
-
- // check if the microarchitecture was made before 2006, which was around the time multi-core processors were implemented
- auto old_microarchitecture = [&steps]() -> bool {
- constexpr std::array, 32> old_archs = {{
- // 80486
- {{ 0x4, 0x0, 0x1 }},
- {{ 0x4, 0x0, 0x2 }},
- {{ 0x4, 0x0, 0x3 }},
- {{ 0x4, 0x0, 0x4 }},
- {{ 0x4, 0x0, 0x5 }},
- {{ 0x4, 0x0, 0x7 }},
- {{ 0x4, 0x0, 0x8 }},
- {{ 0x4, 0x0, 0x9 }},
-
- // P5
- {{ 0x5, 0x0, 0x1 }},
- {{ 0x5, 0x0, 0x2 }},
- {{ 0x5, 0x0, 0x4 }},
- {{ 0x5, 0x0, 0x7 }},
- {{ 0x5, 0x0, 0x8 }},
-
- // P6
- {{ 0x6, 0x0, 0x1 }},
- {{ 0x6, 0x0, 0x3 }},
- {{ 0x6, 0x0, 0x5 }},
- {{ 0x6, 0x0, 0x6 }},
- {{ 0x6, 0x0, 0x7 }},
- {{ 0x6, 0x0, 0x8 }},
- {{ 0x6, 0x0, 0xA }},
- {{ 0x6, 0x0, 0xB }},
-
- // Netburst
- {{ 0xF, 0x0, 0x6 }},
- {{ 0xF, 0x0, 0x4 }},
- {{ 0xF, 0x0, 0x3 }},
- {{ 0xF, 0x0, 0x2 }},
- {{ 0xF, 0x0, 0x10 }},
-
- {{ 0x6, 0x1, 0x5 }}, // Pentium M (Talopai)
- {{ 0x6, 0x1, 0x6 }}, // Core (Client)
- {{ 0x6, 0x0, 0x9 }}, // Pentium M
- {{ 0x6, 0x0, 0xD }}, // Pentium M
- {{ 0x6, 0x0, 0xE }}, // Modified Pentium M
- {{ 0x6, 0x0, 0xF }} // Core (Client)
- }};
-
- constexpr u8 FAMILY = 0;
- constexpr u8 EXTMODEL = 1;
- constexpr u8 MODEL = 2;
-
- for (const auto& arch : old_archs) {
- if (
- steps.family == arch.at(FAMILY) &&
- steps.extmodel == arch.at(EXTMODEL) &&
- steps.model == arch.at(MODEL)
- ) {
- return true;
- }
- }
+ */
+ [[nodiscard]] static bool odd_cpu_threads() {
+#if (!x86)
+ return false;
+#else
+ const u32 threads = std::thread::hardware_concurrency();
+ auto steps = cpu::fetch_steppings();
+ if (!(cpu::is_intel() || cpu::is_amd()))
return false;
- };
-
- // self-explanatory
- if (!(cpu::is_intel() || cpu::is_amd())) {
+ if (cpu::is_celeron(steps))
return false;
- }
- // intel celeron CPUs are relatively modern, but they can contain a single or odd thread count
- if (cpu::is_celeron(steps)) {
- return false;
- }
+ auto make_id = [](u8 family, u8 extmodel, u8 model) -> u32 {
+ return (static_cast(family) << 16) |
+ (static_cast(extmodel) << 8) |
+ static_cast(model);
+ };
- // CPUs before 2006 had no official multi-core processors
- if (old_microarchitecture()) {
- return false;
+ static constexpr std::array old_microarch_ids = { {
+ // Family 4 (Intel 486): models 1,2,3,4,5,7,8,9
+ make_id(0x4, 0x0, 0x1), make_id(0x4, 0x0, 0x2),
+ make_id(0x4, 0x0, 0x3), make_id(0x4, 0x0, 0x4),
+ make_id(0x4, 0x0, 0x5), make_id(0x4, 0x0, 0x7),
+ make_id(0x4, 0x0, 0x8), make_id(0x4, 0x0, 0x9),
+
+ // Family 5 (Pentium, P5): models 1,2,4,7,8
+ make_id(0x5, 0x0, 0x1), make_id(0x5, 0x0, 0x2),
+ make_id(0x5, 0x0, 0x4), make_id(0x5, 0x0, 0x7),
+ make_id(0x5, 0x0, 0x8),
+
+ // Family 6 (P6/Pentium Pro/Celeron/Pentium II–III): models 1,3,5,6,7,8,9,A,B,D,E,F
+ make_id(0x6, 0x0, 0x1), make_id(0x6, 0x0, 0x3),
+ make_id(0x6, 0x0, 0x5), make_id(0x6, 0x0, 0x6),
+ make_id(0x6, 0x0, 0x7), make_id(0x6, 0x0, 0x8),
+ make_id(0x6, 0x0, 0x9), make_id(0x6, 0x0, 0xA),
+ make_id(0x6, 0x0, 0xB), make_id(0x6, 0x0, 0xD),
+ make_id(0x6, 0x0, 0xE), make_id(0x6, 0x0, 0xF),
+
+ // Family 6 (Yonah/early Core): models 1,2 (extmodel = 1)
+ make_id(0x6, 0x1, 0x5), make_id(0x6, 0x1, 0x6),
+
+ // Family F (Pentium 4): models 2,3,4,6,10
+ make_id(0xF, 0x0, 0x2), make_id(0xF, 0x0, 0x3),
+ make_id(0xF, 0x0, 0x4), make_id(0xF, 0x0, 0x6),
+ make_id(0xF, 0x0, 0x10)
+ } };
+
+ const u32 curId = make_id(steps.family, steps.extmodel, steps.model);
+ for (u32 oldId : old_microarch_ids) {
+ if (curId == oldId)
+ return false;
}
- // is the count odd?
- return (threads & 1);
+ return (threads & 1u) != 0;
#endif
}
@@ -4779,7 +4265,7 @@ struct VM {
}
};
- std::map thread_database = {
+ static const std::map thread_database = {
// i3 series
{ "i3-1000G1", 4 },
{ "i3-1000G4", 4 },
@@ -5735,16 +5221,15 @@ struct VM {
{ "i9-9990XE", 28 }
};
- // if it doesn't exist
- if (thread_database.find(model.string.c_str()) == thread_database.end()) { // < 0.000005 seconds
+ const char* key = model.string.c_str();
+ auto it = thread_database.find(key);
+ if (it == thread_database.end()) {
return false;
}
- const int threads = thread_database.at(model.string.c_str());
-
- debug("INTEL_THREAD_MISMATCH: thread in database = ", static_cast(threads));
+ debug("INTEL_THREAD_MISMATCH: thread in database = ", static_cast(it->second));
- return (std::thread::hardware_concurrency() != static_cast(threads));
+ return std::thread::hardware_concurrency() != static_cast(it->second);
#endif
}
@@ -5763,10 +5248,6 @@ struct VM {
return false;
}
- if (cpu::has_hyperthreading()) {
- return false;
- }
-
const cpu::model_struct model = cpu::get_model();
if (!model.found) {
@@ -5892,7 +5373,6 @@ struct VM {
{ "W-3275M", 56 }
};
- // if it doesn't exist, return false
if (thread_database.find(model.string.c_str()) == thread_database.end()) {
return false;
}
@@ -5917,11 +5397,9 @@ struct VM {
#if (!WINDOWS)
return false;
#else
- const DWORD attrs = GetFileAttributesA("C:\\Cuckoo");
- const bool exists = (attrs != INVALID_FILE_ATTRIBUTES) &&
- (attrs & FILE_ATTRIBUTE_DIRECTORY);
+ const DWORD attrs = GetFileAttributes(_T("C:\\Cuckoo"));
- if (exists) {
+ if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY)) {
return core::add(brands::CUCKOO);
}
@@ -5960,7 +5438,7 @@ struct VM {
/**
- * @brief Check for default Azure hostname format regex (Azure uses Hyper-V as their base VM brand)
+ * @brief Check for default Azure hostname format (Azure uses Hyper-V as their base VM brand)
* @category Windows, Linux
* @implements VM::HYPERV_HOSTNAME
*/
@@ -5972,31 +5450,28 @@ struct VM {
const size_t len = hostname.size();
// most Hyper-V hostnames under Azure have the hostname format of fv-azXXX-XXX where the X is a digit
- if (len < 8) return false; // "fv-az0-0" is minimum length
-
- // Check prefix "fv-az"
- if (!(hostname[0] == 'f' &&
- hostname[1] == 'v' &&
- hostname[2] == '-' &&
- hostname[3] == 'a' &&
- hostname[4] == 'z')) {
+ if (len < 8)
return false;
- }
- const size_t hyphen_pos = hostname.find('-', 5);
+ if (!(hostname.rfind("fv-az", 0) == 0))
+ return false;
- if (hyphen_pos == std::string::npos ||
- hyphen_pos <= 5 ||
- hyphen_pos >= len - 1) {
+ const size_t hyphen_pos = hostname.find('-', 5);
+ if (hyphen_pos == std::string::npos ||
+ hyphen_pos <= 5 ||
+ hyphen_pos >= len - 1)
+ {
return false;
}
for (size_t i = 5; i < hyphen_pos; ++i) {
- if (hostname[i] < '0' || hostname[i] > '9') return false;
+ if (!isdigit(static_cast(hostname[i])))
+ return false;
}
for (size_t i = hyphen_pos + 1; i < len; ++i) {
- if (hostname[i] < '0' || hostname[i] > '9') return false;
+ if (!isdigit(static_cast(hostname[i])))
+ return false;
}
return core::add(brands::AZURE_HYPERV);
@@ -6053,21 +5528,18 @@ struct VM {
#else
RECT desktop;
const HWND hDesktop = GetDesktopWindow();
- GetWindowRect(hDesktop, &desktop);
- const i32 horiz = desktop.right;
- const i32 verti = desktop.bottom;
+ if (!GetWindowRect(hDesktop, &desktop)) {
+ return false;
+ }
+
+ const i16 horiz = static_cast(desktop.right);
+ const i16 verti = static_cast(desktop.bottom);
debug("SCREEN_RESOLUTION: horizontal = ", horiz, ", vertical = ", verti);
- if (
- (horiz == 1024 && verti == 768) ||
+ return (horiz == 1024 && verti == 768) ||
(horiz == 800 && verti == 600) ||
- (horiz == 640 && verti == 480)
- ) {
- return true;
- }
-
- return false;
+ (horiz == 640 && verti == 480);
#endif
}
@@ -6786,13 +6258,14 @@ struct VM {
return false;
#else
bool result = false;
- constexpr DWORD MAX_PHYSICAL_DRIVES = 4;
+ constexpr u8 MAX_PHYSICAL_DRIVES = 4;
- auto is_vbox_serial = [](const char* str, size_t len) -> bool {
- // VirtualBox pattern: VB + 8 hex + - + 8 hex
- if (len != 19) return false;
+ auto is_vbox_serial = [](const char* str, u8 len) -> bool {
+ if (len != 19)
+ return false;
if ((str[0] != 'V' && str[0] != 'v') ||
- (str[1] != 'B' && str[1] != 'b')) return false;
+ (str[1] != 'B' && str[1] != 'b'))
+ return false;
auto is_hex = [](char c) {
return (c >= '0' && c <= '9') ||
@@ -6800,17 +6273,24 @@ struct VM {
(c >= 'a' && c <= 'f');
};
- for (int i : {2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18}) {
- if (!is_hex(str[i])) return false;
+ static constexpr std::array hex_positions = { {
+ 2, 3, 4, 5, 6, 7, 8, 9,
+ 11,12,13,14,15,16,17,18
+ } };
+
+ for (u8 idx : hex_positions) {
+ if (!is_hex(str[idx]))
+ return false;
}
+
return str[10] == '-';
- };
+ };
- for (DWORD drive = 0; drive < MAX_PHYSICAL_DRIVES; drive++) {
+ for (u8 drive = 0; drive < MAX_PHYSICAL_DRIVES; drive++) {
wchar_t path[32];
- swprintf_s(path, L"\\\\.\\PhysicalDrive%lu", drive);
+ swprintf_s(path, L"\\\\.\\PhysicalDrive%u", drive);
- HANDLE hDevice = CreateFileW(path, 0,
+ const HANDLE hDevice = CreateFileW(path, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
OPEN_EXISTING, 0, nullptr);
@@ -6830,7 +6310,7 @@ struct VM {
continue;
}
- BYTE stackBuf[512]{};
+ BYTE stackBuf[512] = { 0 };
BYTE* buffer = nullptr;
if (header.Size <= sizeof(stackBuf)) {
@@ -6855,24 +6335,33 @@ struct VM {
}
auto descriptor = reinterpret_cast(buffer);
- const DWORD serialOffset = descriptor->SerialNumberOffset;
+ const u32 serialOffset = descriptor->SerialNumberOffset;
if (serialOffset > 0 && serialOffset < header.Size) {
- const char* serial = reinterpret_cast(buffer + serialOffset);
- const size_t serialLen = strnlen(serial, header.Size - static_cast(serialOffset));
+ const char* serial =
+ reinterpret_cast(buffer + serialOffset);
+
+ const size_t maxAvail = header.Size - static_cast(serialOffset);
+ const size_t serialLen = strnlen(serial, maxAvail);
- char upperSerial[256] = { 0 };
- const size_t copyLen = (serialLen < sizeof(upperSerial))
- ? serialLen
- : sizeof(upperSerial) - 1;
+ constexpr size_t BUF_SZ = 256;
+ char upperSerial[BUF_SZ] = { 0 };
+
+ size_t copyLen;
+ if (serialLen < (BUF_SZ - 1)) {
+ copyLen = serialLen;
+ }
+ else {
+ copyLen = BUF_SZ - 1;
+ }
- for (size_t i = 0; i < copyLen; i++) {
+ for (size_t i = 0; i < copyLen; ++i) {
char c = serial[i];
- upperSerial[i] = (c >= 'a' && c <= 'z') ? c - 32 : c;
+ upperSerial[i] = (c >= 'a' && c <= 'z') ? char(c - 32) : c;
}
upperSerial[copyLen] = '\0';
- if (is_vbox_serial(upperSerial, copyLen)) {
+ if (is_vbox_serial(upperSerial, static_cast(copyLen))) {
result = core::add(brands::VBOX);
if (buffer != stackBuf) {
LocalFree(buffer);
@@ -6914,7 +6403,7 @@ struct VM {
}
SP_DEVINFO_DATA devInfoData = { sizeof(SP_DEVINFO_DATA) };
- // Check first device only - physical machines typically have multiple. Checking index 0 is sufficient to determine if ANY ports exist
+ // check first device only is sufficient to determine if ANY ports exist, physical machines typically have multiple
const bool hasPorts = SetupDiEnumDeviceInfo(hDevInfo, 0, &devInfoData);
SetupDiDestroyDeviceInfoList(hDevInfo);
@@ -6933,10 +6422,10 @@ struct VM {
#if (!WINDOWS)
return false;
#else
- static const GUID GUID_IVSHMEM_IFACE =
- { 0xdf576976, 0x569d, 0x4672, {0x95,0xa0,0xf5,0x7e,0x4e,0xa0,0xb2,0x10} };
+ constexpr GUID GUID_IVSHMEM_IFACE =
+ { 0xdf576976, 0x569d, 0x4672, {0x95, 0xa0, 0xf5, 0x7e, 0x4e, 0xa0, 0xb2, 0x10} };
- HDEVINFO hDevInfo = SetupDiGetClassDevs(
+ const HDEVINFO hDevInfo = SetupDiGetClassDevs(
&GUID_IVSHMEM_IFACE,
nullptr,
nullptr,
@@ -6946,9 +6435,9 @@ struct VM {
return false;
}
- SP_DEVICE_INTERFACE_DATA ifaceData;
+ SP_DEVICE_INTERFACE_DATA ifaceData = { 0 };
ifaceData.cbSize = sizeof(ifaceData);
- BOOL gotOne = SetupDiEnumDeviceInterfaces(
+ const bool gotOne = SetupDiEnumDeviceInterfaces(
hDevInfo,
nullptr,
&GUID_IVSHMEM_IFACE,
@@ -6958,7 +6447,7 @@ struct VM {
SetupDiDestroyDeviceInfoList(hDevInfo);
- if (gotOne == TRUE) {
+ if (gotOne) {
core::add(brands::HYPERVISOR_PHANTOM);
return true;
}
@@ -7049,48 +6538,58 @@ struct VM {
#if (!WINDOWS)
return false;
#else
- static Microsoft::WRL::ComPtr factory;
- if (!factory) {
+ #if (_WIN32_WINNT < _WIN32_WINNT_WIN10)
+ return false;
+ #else
+ static bool initialized = false;
+ static bool isSoftware = false;
+ if (initialized) return isSoftware;
+ initialized = true;
+
+ Microsoft::WRL::ComPtr factory;
if (FAILED(CreateDXGIFactory2(0, IID_PPV_ARGS(&factory)))) {
debug("GPU_CAPABILITIES: failed to create DXGIFactory2");
- return false;
- }
- }
-
- static HMODULE warpMod = LoadLibrary(_T("dxgi.dll"));
- if (warpMod) {
- static Microsoft::WRL::ComPtr swAdapter;
- if (SUCCEEDED(factory->CreateSoftwareAdapter(warpMod, &swAdapter))) {
- Microsoft::WRL::ComPtr swAdapter1;
- if (SUCCEEDED(swAdapter.As(&swAdapter1))) {
- DXGI_ADAPTER_DESC1 swDesc = {};
- if (SUCCEEDED(swAdapter1->GetDesc1(&swDesc)) &&
- (swDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)) {
- debug("GPU_CAPABILITIES: detected software (WARP) adapter");
- return true;
+ return isSoftware = false;
+ }
+
+ const HMODULE dxgi = LoadLibrary(_T("dxgi.dll"));
+ if (dxgi) {
+ Microsoft::WRL::ComPtr sw;
+ if (SUCCEEDED(factory->CreateSoftwareAdapter(dxgi, &sw))) {
+ Microsoft::WRL::ComPtr sw1;
+ if (SUCCEEDED(sw.As(&sw1))) {
+ DXGI_ADAPTER_DESC1 desc = {};
+ if (SUCCEEDED(sw1->GetDesc1(&desc))
+ && (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE))
+ {
+ debug("GPU_CAPABILITIES: detected software (WARP) adapter");
+ FreeLibrary(dxgi);
+ return isSoftware = true;
+ }
}
}
+ FreeLibrary(dxgi);
}
- }
- Microsoft::WRL::ComPtr hwAdapter1;
- if (FAILED(factory->EnumAdapters1(0, &hwAdapter1))) {
- debug("GPU_CAPABILITIES: no adapters found");
- return false;
- }
+ Microsoft::WRL::ComPtr hw;
+ if (FAILED(factory->EnumAdapters1(0, &hw))) {
+ debug("GPU_CAPABILITIES: no adapters found");
+ return isSoftware = false;
+ }
- DXGI_ADAPTER_DESC1 hwDesc = {};
- if (FAILED(hwAdapter1->GetDesc1(&hwDesc))) {
- debug("GPU_CAPABILITIES: failed to get adapter desc");
- return false;
- }
+ DXGI_ADAPTER_DESC1 hwDesc = {};
+ if (FAILED(hw->GetDesc1(&hwDesc))) {
+ debug("GPU_CAPABILITIES: failed to get adapter desc");
+ return isSoftware = false;
+ }
- if (hwDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
- debug("GPU_CAPABILITIES: primary adapter is software");
- return true;
- }
+ if (hwDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
+ debug("GPU_CAPABILITIES: primary adapter is software");
+ return isSoftware = true;
+ }
- return false;
+ return isSoftware = false;
+ #endif
#endif
}
@@ -7104,12 +6603,12 @@ struct VM {
#if (!WINDOWS)
return false;
#else
- const HANDLE handle1 = CreateFileA(("\\\\.\\VBoxMiniRdrDN"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- const HANDLE handle2 = CreateFileA(("\\\\.\\pipe\\VBoxMiniRdDN"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- const HANDLE handle3 = CreateFileA(("\\\\.\\VBoxTrayIPC"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- const HANDLE handle4 = CreateFileA(("\\\\.\\pipe\\VBoxTrayIPC"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- const HANDLE handle5 = CreateFileA(("\\\\.\\HGFS"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- const HANDLE handle6 = CreateFileA(("\\\\.\\pipe\\cuckoo"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ const HANDLE handle1 = CreateFile(_T("\\\\.\\VBoxMiniRdrDN"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ const HANDLE handle2 = CreateFile(_T("\\\\.\\pipe\\VBoxMiniRdDN"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ const HANDLE handle3 = CreateFile(_T("\\\\.\\VBoxTrayIPC"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ const HANDLE handle4 = CreateFile(_T("\\\\.\\pipe\\VBoxTrayIPC"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ const HANDLE handle5 = CreateFile(_T("\\\\.\\HGFS"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ const HANDLE handle6 = CreateFile(_T("\\\\.\\pipe\\cuckoo"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
bool vbox = false;
@@ -7162,10 +6661,10 @@ struct VM {
return false;
#else
#if (x86_32)
- const PULONG ulNumberProcessors = (PULONG)(__readfsdword(0x30) + 0x64);
+ const PULONG ulNumberProcessors = reinterpret_cast(__readfsdword(0x30) + 0x64);
#else
- const PULONG ulNumberProcessors = (PULONG)(__readgsqword(0x60) + 0xB8);
+ const PULONG ulNumberProcessors = reinterpret_cast(__readgsqword(0x60) + 0xB8);
#endif
if (*ulNumberProcessors < 4)
@@ -7218,19 +6717,25 @@ struct VM {
*/
[[nodiscard]] static bool temperature() {
#if (WINDOWS)
- const GUID GUID_DEVCLASS_THERMALZONE = { 0x4AFA3D51, 0x74A7, 0x11d0, {0xBE, 0x5E, 0x00, 0xA0, 0xC9, 0x06, 0x28, 0x57} };
- HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_THERMALZONE, nullptr, nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+ static constexpr GUID GUID_DEVCLASS_THERMALZONE = {
+ 0x4AFA3D51, 0x74A7, 0x11d0,
+ {0xBE, 0x5E, 0x00, 0xA0, 0xC9, 0x06, 0x28, 0x57}
+ };
+
+ const HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_THERMALZONE, nullptr, nullptr,
+ DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDevInfo == INVALID_HANDLE_VALUE) {
return false;
}
- SP_DEVICE_INTERFACE_DATA deviceInterfaceData{};
+ SP_DEVICE_INTERFACE_DATA deviceInterfaceData = { 0 };
deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
- const bool exists = SetupDiEnumDeviceInterfaces(hDevInfo, nullptr, &GUID_DEVCLASS_THERMALZONE, 0, &deviceInterfaceData);
+ const bool hasThermal = SetupDiEnumDeviceInterfaces(hDevInfo, nullptr, &GUID_DEVCLASS_THERMALZONE, 0, &deviceInterfaceData);
+
SetupDiDestroyDeviceInfoList(hDevInfo);
- return !exists;
+ return !hasThermal;
#elif (LINUX)
return (!util::exists("/sys/class/thermal/thermal_zone0/"));
#else
@@ -7485,7 +6990,7 @@ struct VM {
// actual measurement
constexpr u8 SAMPLE_COUNT = 100;
constexpr u16 SCALE_FACTOR = 1000;
- constexpr u32 THRESHOLD_SCALED = 10 * SCALE_FACTOR; // <10× ratio => VM
+ constexpr u32 THRESHOLD_SCALED = 6 * SCALE_FACTOR; // <6× ratio => VM
u64 samples[SAMPLE_COUNT] = { 0 };
for (int i = 0; i < SAMPLE_COUNT; ++i) {
@@ -7818,7 +7323,7 @@ struct VM {
#if (!WINDOWS)
return false;
#else
-#pragma warning (disable : 4459) // We need to declare our own undocumented internal structure to be able to locate kernel pools
+#pragma warning (disable : 4459)
typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation, // q: SYSTEM_BASIC_INFORMATION
@@ -8056,20 +7561,7 @@ struct VM {
PULONG ReturnLength
);
- NtQuerySystemInformationFunc NtQuerySystemInformation = reinterpret_cast(funcPtrs[0]);
-
- // For example, the pool tag "VM3D" in memory is stored as { 'V', 'M', '3', 'D' } which, on little-endian,
- // corresponds to 0x44334D56
- constexpr DWORD BadPoolDwords[] = {
- 0x44334D56, // "VM3D" (in memory: 0x56, 0x4D, 0x33, 0x44)
- 0x706D6D76, // "vmmp" (in memory: 0x76, 0x6D, 0x6D, 0x70)
- 0x43475443, // "CTGC" (in memory: 0x43, 0x54, 0x47, 0x43) - can be present on baremetal machines
- 0x43434748, // "HGCC" (in memory: 0x48, 0x47, 0x43, 0x43)
- 0x4D4E4748, // "HGNM" (in memory: 0x48, 0x47, 0x4E, 0x4D)
- 0x4C424D56, // "VMBL" (in memory: 0x56, 0x4D, 0x42, 0x4C)
- 0x4D444256, // "VBDM" (in memory: 0x56, 0x42, 0x44, 0x4D)
- 0x41474256 // "VBGA" (in memory: 0x56, 0x42, 0x47, 0x41)
- };
+ const NtQuerySystemInformationFunc NtQuerySystemInformation = reinterpret_cast(funcPtrs[0]);
if (NtQuerySystemInformation)
nt_status = NtQuerySystemInformation(SystemPoolTagInformation, nullptr, 0, &ret_length);
@@ -8086,27 +7578,27 @@ struct VM {
if (!info || info->Count == 0)
return false;
- size_t badCount = 0;
+ u8 badCount = 0;
const auto tagArray = info->TagInfo;
for (ULONG i = 0; i < info->Count && badCount < 2; ++i) {
DWORD tag = *reinterpret_cast(&tagArray[i].Tag);
switch (tag) {
- case 0x44334D56: // VM3D
- case 0x706D6D76: // vmmp
- case 0x43475443: // CTGC
- case 0x43434748: // HGCC
- case 0x4D4E4748: // HGNM
- case 0x4C424D56: // VMBL
- case 0x4D444256: // VBDM
- case 0x41474256: // VBGA
- debug("Bad Pools: Detected bad pool tag: 0x",
- std::hex, tag, std::dec);
- ++badCount;
- break;
- default:
- break;
+ case 0x44334D56: // VM3D
+ case 0x706D6D76: // vmmp
+ case 0x43475443: // CTGC - can be present on baremetal machines
+ case 0x43434748: // HGCC
+ case 0x4D4E4748: // HGNM
+ case 0x4C424D56: // VMBL
+ case 0x4D444256: // VBDM
+ case 0x41474256: // VBGA
+ debug("Bad Pools: Detected bad pool tag: 0x",
+ std::hex, tag, std::dec);
+ ++badCount;
+ break;
+ default:
+ break;
}
}
@@ -8187,10 +7679,6 @@ struct VM {
if (!cpu::is_amd()) {
return false;
}
-
- if (cpu::has_hyperthreading()) {
- return false;
- }
std::string model = cpu::get_brand();
@@ -8778,35 +8266,6 @@ struct VM {
}
- /**
- * @brief Check if the OS was booted from a VHD container
- * @category Windows
- * @implements VM::NATIVE_VHD
- */
- [[nodiscard]] static bool native_vhd() {
-#if (!WINDOWS)
- return false;
-#else
- #if (_WIN32_WINNT < _WIN32_WINNT_WIN8)
- return false;
- #else
- BOOL isNativeVhdBoot = FALSE;
-
- // to detect Wine
- __try {
- if (IsNativeVhdBoot(&isNativeVhdBoot)) {
- return (isNativeVhdBoot == TRUE);
- }
- return false;
- }
- __except (EXCEPTION_EXECUTE_HANDLER) {
- return true;
- }
- #endif
-#endif
- }
-
-
/**
* @brief Check for particular object directory which is present in Sandboxie virtual environment but not in usual host systems
* @category Windows
@@ -8903,7 +8362,7 @@ struct VM {
/**
- * @brief Check for VM signatures in ACPI firmware tables
+ * @brief Check for VM signatures on all firmware tables
* @category Windows
* @credits Requiem, dmfrpro, MegaMax
* @implements VM::FIRMWARE
@@ -8929,11 +8388,53 @@ struct VM {
#pragma warning(default: 4459)
typedef NTSTATUS(__stdcall* PNtQuerySystemInformation)(ULONG, PVOID, ULONG, PULONG);
+
+#if defined(_MSC_VER)
+#define LIKELY(x) (x)
+#define UNLIKELY(x) (x)
+#else
+#define LIKELY(x) __builtin_expect(!!(x), 1)
+#define UNLIKELY(x) __builtin_expect(!!(x), 0)
+#endif
+
+#if defined(_MSC_VER)
+#define BSWAP32(x) _byteswap_ulong(x)
+#else
+#define BSWAP32(x) __builtin_bswap32(x)
+#endif
+
+#if defined(_MSC_VER)
+#define PREFETCH(addr) _mm_prefetch((const char*)(addr), _MM_HINT_T0)
+#else
+#define PREFETCH(addr) __builtin_prefetch(addr)
+#endif
+
constexpr ULONG STATUS_BUFFER_TOO_SMALL = 0xC0000023;
constexpr DWORD ACPI_SIG = 'ACPI';
constexpr DWORD ssdtSig = 'TDSS';
constexpr DWORD facpSig = 'PCAF';
constexpr DWORD dsdtSig = 'DSDT';
+ constexpr DWORD FIRM_SIG = 'FIRM';
+ constexpr DWORD RSMB_SIG = 'RSMB';
+
+ PBYTE qsiBuf = nullptr;
+ ULONG qsiSize = 0;
+
+ auto clear = [&]() noexcept {
+ free(qsiBuf);
+ qsiBuf = nullptr;
+ qsiSize = 0;
+ };
+
+ auto ensure = [&](ULONG need) noexcept -> bool {
+ if (UNLIKELY(qsiSize < need)) {
+ PBYTE tmp = (PBYTE)realloc(qsiBuf, need);
+ if (UNLIKELY(!tmp)) return false;
+ qsiBuf = tmp;
+ qsiSize = need;
+ }
+ return true;
+ };
const HMODULE hNtdll = GetModuleHandle(_T("ntdll.dll"));
if (!hNtdll) return false;
@@ -8946,203 +8447,169 @@ struct VM {
const auto ntqsi = reinterpret_cast(functionPointers[0]);
if (!ntqsi) return false;
- const char* targets[] = {
+ static const char* __restrict targets[] = {
"Parallels Software International","Parallels(R)","innotek",
"Oracle","VirtualBox","vbox","VBOX","VS2005R2",
"VMware, Inc.","VMware","VMWARE",
"S3 Corp.","Virtual Machine","QEMU","WAET","BOCHS","BXPC"
};
+ static const char* __restrict brands_map[] = {
+ brands::PARALLELS, brands::PARALLELS, nullptr,
+ brands::VBOX, brands::VBOX, brands::VBOX, nullptr, nullptr,
+ brands::VMWARE, brands::VMWARE, brands::VMWARE,
+ nullptr, nullptr, brands::QEMU, nullptr, brands::BOCHS, brands::BOCHS
+ };
+ static const size_t targ_count = sizeof(targets) / sizeof(*targets);
- PBYTE qsiBuffer = nullptr;
- ULONG qsiBufferSize = 0;
-
- auto clear_buffer = [&]() {
- if (qsiBuffer) {
- free(qsiBuffer);
- qsiBuffer = nullptr;
- qsiBufferSize = 0;
- }
- };
-
- auto ensure_buffer = [&](ULONG needed) -> bool {
- if (qsiBufferSize < needed) {
- PBYTE newBuf = static_cast(realloc(qsiBuffer, needed));
- if (!newBuf) {
- return false;
- }
- qsiBuffer = newBuf;
- qsiBufferSize = needed;
- }
- return true;
- };
-
- auto query_table = [&](DWORD provider, DWORD tableID, PULONG outSize) -> PSYSTEM_FIRMWARE_TABLE_INFORMATION {
- ULONG header = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
- if (!ensure_buffer(header)) {
- clear_buffer();
- return nullptr;
- }
+ auto query = [&](DWORD provider, DWORD tableID, PULONG outLen) noexcept -> PSYSTEM_FIRMWARE_TABLE_INFORMATION {
+ const ULONG hdrSz = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
+ if (!ensure(hdrSz)) { clear(); return nullptr; }
- auto hdr = reinterpret_cast(qsiBuffer);
+ auto hdr = (PSYSTEM_FIRMWARE_TABLE_INFORMATION)qsiBuf;
hdr->ProviderSignature = provider;
hdr->Action = SystemFirmwareTableEnumerate;
- hdr->TableID = _byteswap_ulong(tableID);
+ hdr->TableID = BSWAP32(tableID);
hdr->TableBufferLength = 0;
- NTSTATUS st = ntqsi(SystemFirmwareTableInformation, hdr, header, outSize);
- if (st != STATUS_BUFFER_TOO_SMALL) {
- clear_buffer();
- return nullptr;
- }
+ NTSTATUS st = ntqsi(SystemFirmwareTableInformation, hdr, hdrSz, outLen);
+ if (static_cast(st) != STATUS_BUFFER_TOO_SMALL) { clear(); return nullptr; }
- ULONG fullSize = *outSize;
- if (!ensure_buffer(fullSize)) {
- clear_buffer();
- return nullptr;
- }
+ const ULONG fullSz = *outLen;
+ if (!ensure(fullSz)) { clear(); return nullptr; }
- hdr = reinterpret_cast(qsiBuffer);
+ hdr = (PSYSTEM_FIRMWARE_TABLE_INFORMATION)qsiBuf;
hdr->ProviderSignature = provider;
hdr->Action = SystemFirmwareTableEnumerate;
- hdr->TableID = _byteswap_ulong(tableID);
- hdr->TableBufferLength = fullSize - header;
+ hdr->TableID = BSWAP32(tableID);
+ hdr->TableBufferLength = fullSz - hdrSz;
- st = ntqsi(SystemFirmwareTableInformation, hdr, fullSize, outSize);
- if (!NT_SUCCESS(st)) {
- clear_buffer();
- return nullptr;
- }
+ PREFETCH(hdr->TableBuffer);
+ st = ntqsi(SystemFirmwareTableInformation, hdr, fullSz, outLen);
+ if (!NT_SUCCESS(st)) { clear(); return nullptr; }
return hdr;
};
- auto check_firmware_table = [&](DWORD sig, DWORD id) -> bool {
- ULONG gotSize = 0;
- auto info = query_table(sig, id, &gotSize);
- if (!info) return false;
+ auto scan_table = [&](DWORD sig, DWORD id)->bool {
+ ULONG got = 0;
+ auto info = query(sig, id, &got);
+ if (UNLIKELY(!info)) return false;
- const UCHAR* buf = info->TableBuffer;
+ const UCHAR* __restrict buf = info->TableBuffer;
size_t len = info->TableBufferLength;
- for (auto target : targets) {
- const size_t tlen = strlen(target);
- if (tlen > len) continue;
-
- for (size_t i = 0; i <= len - tlen; ++i) {
- if (memcmp(buf + i, target, tlen) == 0) {
- const char* brand = nullptr;
-
- if (!strcmp(target, "Parallels Software International") || !strcmp(target, "Parallels(R)"))
- brand = brands::PARALLELS;
- else if (!strcmp(target, "innotek") || !strcmp(target, "VirtualBox") || !strcmp(target, "vbox") || !strcmp(target, "VBOX") || !strcmp(target, "Oracle"))
- brand = brands::VBOX;
- else if (!strcmp(target, "VMware, Inc.") || !strcmp(target, "VMware") || !strcmp(target, "VMWARE"))
- brand = brands::VMWARE;
- else if (!strcmp(target, "QEMU"))
- brand = brands::QEMU;
- else if (!strcmp(target, "BOCHS") || !strcmp(target, "BXPC"))
- brand = brands::BOCHS;
- else {
- clear_buffer();
- return true;
- }
-
- clear_buffer();
- return core::add(brand);
+ for (size_t ti = 0; ti < targ_count; ++ti) {
+ const char* pat = targets[ti];
+ size_t plen = strlen(pat);
+ if (UNLIKELY(plen > len)) continue;
+ for (size_t i = 0; i + plen <= len; ++i) {
+ if (LIKELY(buf[i] == (UCHAR)pat[0] && memcmp(buf + i, pat, plen) == 0)) {
+ clear();
+ const char* brand = brands_map[ti];
+ return (brand ? core::add(brand) : true);
}
}
}
-
- const char marker[] = "777777";
+ static const char marker[] = "777777";
if (len >= sizeof(marker) - 1) {
- for (size_t i = 0; i <= len - (sizeof(marker) - 1); ++i) {
- if (memcmp(buf + i, marker, sizeof(marker) - 1) == 0) {
- clear_buffer();
+ for (size_t i = 0; i + sizeof(marker) - 1 <= len; ++i) {
+ if (LIKELY(memcmp(buf + i, marker, sizeof(marker) - 1) == 0)) {
+ clear();
return core::add(brands::VMWARE_HARD);
}
}
}
-
- clear_buffer();
+ clear();
return false;
};
- ULONG totalLen = 0;
- auto listInfo = query_table(ACPI_SIG, 0, &totalLen);
- if (!listInfo) {
- clear_buffer();
- return false;
- }
-
- const DWORD* tables = reinterpret_cast(listInfo->TableBuffer);
- const ULONG tableCount = listInfo->TableBufferLength / sizeof(DWORD);
- if (tableCount < 4) {
- clear_buffer();
- return true;
- }
-
- ULONG ssdtCount = 0;
- for (ULONG i = 0; i < tableCount; ++i) {
- if (tables[i] == ssdtSig) ++ssdtCount;
- if (ssdtCount == 2) break;
- }
- if (ssdtCount < 2) {
- clear_buffer();
- return true;
- }
-
- for (ULONG i = 0; i < tableCount; ++i) {
- if (tables[i] == facpSig) {
- ULONG fSize = 0;
- auto fadt = query_table(ACPI_SIG, tables[i], &fSize);
- if (fadt && fSize > 45 && fadt->TableBuffer[45] == 0) {
- clear_buffer();
+ ULONG total = 0;
+ auto list = query(ACPI_SIG, 0, &total);
+ if (UNLIKELY(!list)) return false;
+
+ // ACPI table count
+ const DWORD* tables = (DWORD*)list->TableBuffer;
+ const ULONG cnt = list->TableBufferLength / sizeof(DWORD);
+ if (cnt < 4) { clear(); return true; }
+
+ // SSDT count
+ int ssdt_ct = 0;
+ for (ULONG i = 0; i < cnt; ++i) {
+ if (tables[i] == ssdtSig && ++ssdt_ct == 2) break;
+ }
+ if (ssdt_ct < 2) { clear(); return true; }
+
+ for (ULONG i = 0; i < cnt; ++i) {
+ DWORD tbl = tables[i];
+ // FADT PM type check
+ if (tbl == facpSig) {
+ ULONG fsz = 0;
+ auto fadt = query(ACPI_SIG, tbl, &fsz);
+ if (fadt && fsz > 45 && fadt->TableBuffer[45] == 0) {
+ clear();
return true;
}
}
- if (check_firmware_table(ACPI_SIG, tables[i])) {
- clear_buffer();
+ // ACPI scan
+ if (scan_table(ACPI_SIG, tbl)) {
+ clear();
return true;
}
}
- const ULONG dsdtSize = GetSystemFirmwareTable(ACPI_SIG, _byteswap_ulong(dsdtSig), nullptr, 0);
- if (dsdtSize == 0) {
- clear_buffer();
+ // DSDT scan & OSI check
+ clear();
+ const ULONG dsdtSz = GetSystemFirmwareTable(ACPI_SIG, BSWAP32(dsdtSig), nullptr, 0);
+ if (UNLIKELY(dsdtSz == 0)) return false;
+
+ BYTE* dsdt = (BYTE*)malloc(dsdtSz);
+ if (UNLIKELY(!dsdt)) return false;
+
+ if (GetSystemFirmwareTable(ACPI_SIG, BSWAP32(dsdtSig), dsdt, dsdtSz) != dsdtSz) {
+ free(dsdt);
return false;
}
- BYTE* dsdtData = static_cast(malloc(dsdtSize));
- if (!dsdtData) {
- clear_buffer();
- return false;
+ static const char* __restrict osi[] = {
+ "Windows 95","Windows 98","Windows 2000","Windows XP","Windows 2012"
+ };
+ bool found = false;
+ for (auto s : osi) {
+ size_t L = strlen(s);
+ for (ULONG j = 0; j + L <= dsdtSz; ++j) {
+ if (dsdt[j] == (BYTE)s[0] && memcmp(dsdt + j, s, L) == 0) {
+ found = true;
+ break;
+ }
+ }
}
- if (GetSystemFirmwareTable(ACPI_SIG, _byteswap_ulong(dsdtSig), dsdtData, dsdtSize) != dsdtSize) {
- free(dsdtData);
- clear_buffer();
- return false;
+ free(dsdt);
+ if (!found) {
+ return true;
}
- const char* str = reinterpret_cast(dsdtData);
- const char* osi_targets[] = { "Windows 95", "Windows 98", "Windows 2000", "Windows XP", "Windows 2012" };
- bool foundOSI = false;
+ // SMBIOS (RMSB) & FIRM scan
+ const DWORD smbios[] = { FIRM_SIG, RSMB_SIG };
+ for (DWORD provider : smbios) {
+ ULONG totalOther = 0;
+ auto listOther = query(provider, 0, &totalOther);
+ if (!listOther)
+ continue;
- for (auto s : osi_targets) {
- const size_t slen = strlen(s);
- for (ULONG j = 0; j + slen <= dsdtSize; ++j) {
- if (memcmp(str + j, s, slen) == 0) {
- foundOSI = true;
- break;
+ const DWORD* tablesOther = reinterpret_cast(listOther->TableBuffer);
+ const ULONG countOther = listOther->TableBufferLength / sizeof(DWORD);
+ for (ULONG i = 0; i < countOther; ++i) {
+ if (scan_table(provider, tablesOther[i])) {
+ clear();
+ return true;
}
+
}
- if (foundOSI) break;
+ clear();
}
- free(dsdtData);
- clear_buffer();
-
- return !foundOSI;
+ return false;
#elif (LINUX)
// Author: dmfrpro
if (!util::is_admin()) {
@@ -9297,9 +8764,9 @@ struct VM {
return false;
#else
HKEY hKey = nullptr;
- LONG err = RegOpenKeyEx(
+ const LONG err = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
- R"(SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render)",
+ TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\MMDevices\\Audio\\Render"), // Use TEXT macro
0,
KEY_READ | KEY_WOW64_64KEY,
&hKey
@@ -9669,14 +9136,14 @@ struct VM {
case 0x1ec6020f: // Vastai Technologies SG100 vGPU
return true;
- // VirtualBox
+ // VirtualBox
case 0x80ee0021: // USB Tablet
case 0x80ee0022: // multitouch tablet
case 0x80eebeef: // InnoTek Systemberatung GmbH VirtualBox Graphics Adapter
case 0x80eecafe: // InnoTek Systemberatung GmbH VirtualBox Guest Service
return found(brands::VBOX, dev);
- // Hyper-V
+ // Hyper-V
case 0x1f3f9002: // 3SNIC Ltd SSSNIC Ethernet VF Hyper-V
case 0x1f3f9004: // 3SNIC Ltd SSSNIC Ethernet SDI VF Hyper-V
case 0x1f3f9009: // 3SNIC Ltd SSSFC VF Hyper-V
@@ -9687,13 +9154,13 @@ struct VM {
}
return found(brands::HYPERV, dev);
- // Parallels
+ // Parallels
case 0x1ab84000: // Virtual Machine Communication Interface
case 0x1ab84005: // Accelerated Virtual Video Adapter
case 0x1ab84006: // Memory Ballooning Controller
return found(brands::PARALLELS, dev);
- // Xen
+ // Xen
case 0x5853c000: // XenSource, Inc. Citrix XenServer PCI Device for Windows Update
case 0xfffd0101: // XenSource, Inc. PCI Event Channel Controller
case 0x5853c147: // XenSource, Inc. Virtualized Graphics Device
@@ -9702,7 +9169,7 @@ struct VM {
case 0x58530001: // XenSource, Inc. Xen Platform Device
return found(brands::XEN, dev);
- // Connectix (VirtualPC) OHCI USB 1.1 controller
+ // Connectix (VirtualPC) OHCI USB 1.1 controller
case 0x29556e61: return found(brands::VPC, dev);
}
@@ -9736,9 +9203,7 @@ struct VM {
#if (!WINDOWS)
return false;
#else
- // QEMU passthrough location paths
- static const std::wregex busRegex(L"PCIROOT\\(0\\)#PCI\\(0202\\)");
- static const std::wregex acpiSlotRegex(L"#ACPI\\(S[0-9]{2}_\\)");
+ constexpr wchar_t kAcpiSlotPrefix[] = L"#ACPI(S";
HDEVINFO hDevInfo = SetupDiGetClassDevsW(
&GUID_DEVCLASS_DISPLAY,
@@ -9771,14 +9236,31 @@ struct VM {
continue;
const wchar_t* ptr = reinterpret_cast(buffer.data());
- while (*ptr) {
- std::wstring path(ptr);
- if (std::regex_search(path, busRegex) ||
- std::regex_search(path, acpiSlotRegex))
+ while (*ptr)
+ {
+ std::wstring_view path(ptr);
+
+ if (path.substr(0, 17) != L"PCIROOT(0)#PCI(") {
+ ptr += path.size() + 1;
+ continue;
+ }
+
+ auto pos = path.find(kAcpiSlotPrefix);
+ while (pos != std::wstring_view::npos)
{
- SetupDiDestroyDeviceInfoList(hDevInfo);
- return true;
+ if (pos + 10 <= path.size() &&
+ std::iswdigit(path[pos + 7]) &&
+ std::iswdigit(path[pos + 8]) &&
+ path[pos + 9] == '_' &&
+ path[pos + 10] == ')')
+ {
+ SetupDiDestroyDeviceInfoList(hDevInfo);
+ return true;
+ }
+
+ pos = path.find(kAcpiSlotPrefix, pos + 1);
}
+
ptr += path.size() + 1;
}
}
@@ -9806,7 +9288,6 @@ struct VM {
struct core {
- MSVC_DISABLE_WARNING(PADDING)
struct technique {
u8 points = 0; // this is the certainty score between 0 and 100
std::function run; // this is the technique function itself
@@ -9821,7 +9302,6 @@ struct VM {
u16 id;
std::function run;
};
- MSVC_ENABLE_WARNING(PADDING)
// initial technique list, this is where all the techniques are stored
static std::pair technique_list[];
@@ -10338,9 +9818,9 @@ struct VM {
}
#if (CPP >= 17)
-#define VMAWARE_CONSTEXPR constexpr
+ #define VMAWARE_CONSTEXPR constexpr
#else
-#define VMAWARE_CONSTEXPR
+ #define VMAWARE_CONSTEXPR
#endif
public:
@@ -10348,45 +9828,42 @@ struct VM {
// This will then generate a different std::bitset as the
// return value by enabling the bits based on the argument.
template
- static flagset arg_handler(Args&&... args) {
+ static VMAWARE_CONSTEXPR flagset arg_handler(Args&&... args) {
flag_collector.reset();
generate_default(disabled_flag_collector);
- if VMAWARE_CONSTEXPR (is_empty()) {
+ if VMAWARE_CONSTEXPR(is_empty()) {
generate_default(flag_collector);
return flag_collector;
}
+ else {
+ // set the bits in the flag, can take in either an enum value or a std::bitset
+ handleArgs(std::forward(args)...);
- // set the bits in the flag, can take in
- // either an enum value or a std::bitset
- handleArgs(std::forward(args)...);
-
- if (flag_collector.count() == 0) {
- generate_default(flag_collector);
- }
-
-
- const bool setting_no_memo = flag_collector.test(NO_MEMO);
- const bool setting_high_threshold = flag_collector.test(HIGH_THRESHOLD);
- const bool setting_dynamic = flag_collector.test(DYNAMIC);
- const bool setting_multiple = flag_collector.test(MULTIPLE);
- const bool setting_all = flag_collector.test(ALL);
- const bool setting_default = flag_collector.test(DEFAULT);
-
- flag_collector &= disabled_flag_collector;
+ if (flag_collector.count() == 0) {
+ generate_default(flag_collector);
+ }
- flag_collector.set(NO_MEMO, setting_no_memo);
- flag_collector.set(HIGH_THRESHOLD, setting_high_threshold);
- flag_collector.set(DYNAMIC, setting_dynamic);
- flag_collector.set(MULTIPLE, setting_multiple);
- flag_collector.set(ALL, setting_all);
- flag_collector.set(DEFAULT, setting_default);
+ bool no_memo = flag_collector.test(NO_MEMO);
+ bool high_threshold = flag_collector.test(HIGH_THRESHOLD);
+ bool dynamic_flag = flag_collector.test(DYNAMIC);
+ bool multiple = flag_collector.test(MULTIPLE);
+ bool all_flag = flag_collector.test(ALL);
+ bool default_flag = flag_collector.test(DEFAULT);
+ flag_collector &= disabled_flag_collector;
- // handle edgecases
- core::flag_sanitizer(flag_collector);
+ flag_collector.set(NO_MEMO, no_memo);
+ flag_collector.set(HIGH_THRESHOLD, high_threshold);
+ flag_collector.set(DYNAMIC, dynamic_flag);
+ flag_collector.set(MULTIPLE, multiple);
+ flag_collector.set(ALL, all_flag);
+ flag_collector.set(DEFAULT, default_flag);
- return flag_collector;
+ // handle edgecases
+ core::flag_sanitizer(flag_collector);
+ return flag_collector;
+ }
}
// same as above but for VM::disable which only accepts technique flags
@@ -10511,9 +9988,11 @@ struct VM {
const bool is_memoized = (memo_arg != NO_MEMO);
-#if (CPP >= 23)
- [[assume(flag_bit < technique_end)]];
-#endif
+ #if (MSVC)
+ __assume(flag_bit < technique_end);
+ #else
+ __builtin_assume(flag_bit < technique_end);
+ #endif
// if the technique is already cached, return the cached value instead
if (memo::is_cached(flag_bit) && is_memoized) {
@@ -10845,9 +10324,11 @@ struct VM {
// flags above, and get a total score
const u16 points = core::run_all(flags, SHORTCUT);
-#if (CPP >= 23)
- [[assume(points < maximum_points)]];
-#endif
+ #if (MSVC)
+ __assume(points < maximum_points);
+ #else
+ __builtin_assume(points < maximum_points);
+ #endif
u16 threshold = 150;
@@ -10876,9 +10357,11 @@ struct VM {
// flags above, and get a total score
const u16 points = core::run_all(flags, SHORTCUT);
-#if (CPP >= 23)
- [[assume(points < maximum_points)]];
-#endif
+ #if (MSVC)
+ __assume(points < maximum_points);
+ #else
+ __builtin_assume(points < maximum_points);
+ #endif
u8 percent = 0;
u16 threshold = 150;
@@ -10932,9 +10415,11 @@ struct VM {
throw_error("Percentage parameter must be between 0 and 100");
}
-#if (CPP >= 23)
- [[assume(percent > 0 && percent <= 100)]];
-#endif
+ #if (MSVC)
+ __assume(percent > 0 && percent <= 100);
+ #else
+ __builtin_assume(percent > 0 && percent <= 100);
+ #endif
static u16 id = 0;
id++;
@@ -10993,23 +10478,17 @@ struct VM {
case HWMON: return "HWMON";
case DLL: return "DLL";
case REGISTRY: return "REGISTRY";
- case VM_FILES: return "VM_FILES";
+ case FILES: return "VM_FILES";
case HWMODEL: return "HWMODEL";
case DISK_SIZE: return "DISK_SIZE";
case VBOX_DEFAULT: return "VBOX_DEFAULT";
case VBOX_NETWORK: return "VBOX_NETWORK";
-/* GPL */ case COMPUTER_NAME: return "COMPUTER_NAME";
-/* GPL */ case WINE_CHECK: return "WINE_CHECK";
-/* GPL */ case HOSTNAME: return "HOSTNAME";
-/* GPL */ case KVM_DIRS: return "KVM_DIRS";
-/* GPL */ case QEMU_DIR: return "QEMU_DIR";
-/* GPL */ case POWER_CAPABILITIES: return "POWER_CAPABILITIES";
-/* GPL */ case SETUPAPI_DISK: return "SETUPAPI_DISK";
+ case WINE: return "WINE";
+ case POWER_CAPABILITIES: return "POWER_CAPABILITIES";
case VM_PROCESSES: return "VM_PROCESSES";
case LINUX_USER_HOST: return "LINUX_USER_HOST";
case GAMARUE: return "GAMARUE";
case BOCHS_CPU: return "BOCHS_CPU";
- case MSSMBIOS: return "MSSMBIOS";
case MAC_MEMSIZE: return "MAC_MEMSIZE";
case MAC_IOKIT: return "MAC_IOKIT";
case IOREG_GREP: return "IOREG_GREP";
@@ -11069,7 +10548,6 @@ struct VM {
case BAD_POOLS: return "BAD_POOLS";
case AMD_SEV: return "AMD_SEV";
case AMD_THREAD_MISMATCH: return "AMD_THREAD_MISMATCH";
- case NATIVE_VHD: return "NATIVE_VHD";
case VIRTUAL_REGISTRY: return "VIRTUAL_REGISTRY";
case FIRMWARE: return "FIRMWARE";
case FILE_ACCESS_HISTORY: return "FILE_ACCESS_HISTORY";
@@ -11139,9 +10617,11 @@ struct VM {
throw_error("Percentage parameter must be between 0 and 100");
}
-#if (CPP >= 23)
- [[assume(percent <= 100)]];
-#endif
+ #if (MSVC)
+ __assume(percent <= 100);
+ #else
+ __builtin_assume(percent <= 100);
+ #endif
// check if the flag provided is a setting flag, which isn't valid.
if (static_cast(flag) >= technique_end) {
@@ -11409,9 +10889,6 @@ struct VM {
#endif
};
-MSVC_ENABLE_WARNING(ASSIGNMENT_OPERATOR NO_INLINE_FUNC SPECTRE)
-
-
// ============= EXTERNAL DEFINITIONS =============
// These are added here due to warnings related to C++17 inline variables for C++ standards that are under 17.
// It's easier to just group them together rather than having C++17<= preprocessors with inline stuff
@@ -11542,11 +11019,28 @@ std::vector VM::core::custom_table = {
std::pair VM::core::technique_list[] = {
// FORMAT: { VM::, { certainty%, function pointer } },
// START OF TECHNIQUE TABLE
+ std::make_pair(VM::FIRMWARE, VM::core::technique(100, VM::firmware_scan)),
+ std::make_pair(VM::GPU_CAPABILITIES, VM::core::technique(100, VM::gpu_capabilities)),
+ std::make_pair(VM::TIMER, VM::core::technique(45, VM::timer)),
+ std::make_pair(VM::TPM, VM::core::technique(50, VM::tpm)),
+ std::make_pair(VM::PCI_VM_DEVICE_ID, VM::core::technique(90, VM::pci_vm_device_id)),
+ std::make_pair(VM::QEMU_PASSTHROUGH, VM::core::technique(90, VM::qemu_passthrough)),
+ std::make_pair(VM::INTEL_THREAD_MISMATCH, VM::core::technique(95, VM::intel_thread_mismatch)),
+ std::make_pair(VM::AMD_THREAD_MISMATCH, VM::core::technique(95, VM::amd_thread_mismatch)),
+ std::make_pair(VM::XEON_THREAD_MISMATCH, VM::core::technique(95, VM::xeon_thread_mismatch)),
+ std::make_pair(VM::DISK_SERIAL, VM::core::technique(100, VM::disk_serial_number)),
+ std::make_pair(VM::PORT_CONNECTORS, VM::core::technique(25, VM::port_connectors)),
+ std::make_pair(VM::IVSHMEM, VM::core::technique(100, VM::ivshmem)),
+ std::make_pair(VM::GPU_VM_STRINGS, VM::core::technique(100, VM::gpu_vm_strings)),
+ std::make_pair(VM::QEMU_FW_CFG, VM::core::technique(70, VM::qemu_fw_cfg)),
+ std::make_pair(VM::LSHW_QEMU, VM::core::technique(80, VM::lshw_qemu)),
+ std::make_pair(VM::BAD_POOLS, VM::core::technique(80, VM::bad_pools)),
+ std::make_pair(VM::DRIVER_NAMES, VM::core::technique(100, VM::driver_names)),
+ std::make_pair(VM::HKLM_REGISTRIES, VM::core::technique(25, VM::hklm_registries)),
std::make_pair(VM::VMID, VM::core::technique(100, VM::vmid)),
std::make_pair(VM::CPU_BRAND, VM::core::technique(50, VM::cpu_brand)),
std::make_pair(VM::HYPERVISOR_BIT, VM::core::technique(100, VM::hypervisor_bit)),
std::make_pair(VM::HYPERVISOR_STR, VM::core::technique(75, VM::hypervisor_str)),
- std::make_pair(VM::TIMER, VM::core::technique(45, VM::timer)),
std::make_pair(VM::THREADCOUNT, VM::core::technique(35, VM::thread_count)),
std::make_pair(VM::MAC, VM::core::technique(20, VM::mac_address_check)),
std::make_pair(VM::TEMPERATURE, VM::core::technique(15, VM::temperature)),
@@ -11559,28 +11053,21 @@ std::pair VM::core::technique_list[] = {
std::make_pair(VM::HWMON, VM::core::technique(35, VM::hwmon)),
std::make_pair(VM::DLL, VM::core::technique(25, VM::dll_check)),
std::make_pair(VM::REGISTRY, VM::core::technique(50, VM::registry_key)),
- std::make_pair(VM::VM_FILES, VM::core::technique(25, VM::vm_files)),
+ std::make_pair(VM::FILES, VM::core::technique(25, VM::vm_files)),
std::make_pair(VM::HWMODEL, VM::core::technique(100, VM::hwmodel)),
std::make_pair(VM::DISK_SIZE, VM::core::technique(60, VM::disk_size)),
std::make_pair(VM::VBOX_DEFAULT, VM::core::technique(25, VM::vbox_default_specs)),
std::make_pair(VM::VBOX_NETWORK, VM::core::technique(100, VM::vbox_network_share)),
-/* GPL */ std::make_pair(VM::COMPUTER_NAME, VM::core::technique(10, VM::computer_name_match)),
-/* GPL */ std::make_pair(VM::WINE_CHECK, VM::core::technique(100, VM::wine)),
-/* GPL */ std::make_pair(VM::HOSTNAME, VM::core::technique(10, VM::hostname_match)),
-/* GPL */ std::make_pair(VM::KVM_DIRS, VM::core::technique(30, VM::kvm_directories)),
-/* GPL */ std::make_pair(VM::QEMU_DIR, VM::core::technique(30, VM::qemu_dir)),
-/* GPL */ std::make_pair(VM::POWER_CAPABILITIES, VM::core::technique(50, VM::power_capabilities)),
-/* GPL */ std::make_pair(VM::SETUPAPI_DISK, VM::core::technique(100, VM::setupapi_disk)),
+ std::make_pair(VM::WINE, VM::core::technique(100, VM::wine)),
+ std::make_pair(VM::POWER_CAPABILITIES, VM::core::technique(50, VM::power_capabilities)),
std::make_pair(VM::VM_PROCESSES, VM::core::technique(15, VM::vm_processes)),
std::make_pair(VM::LINUX_USER_HOST, VM::core::technique(10, VM::linux_user_host)),
std::make_pair(VM::GAMARUE, VM::core::technique(10, VM::gamarue)),
std::make_pair(VM::BOCHS_CPU, VM::core::technique(100, VM::bochs_cpu)),
- std::make_pair(VM::MSSMBIOS, VM::core::technique(100, VM::mssmbios)),
std::make_pair(VM::MAC_MEMSIZE, VM::core::technique(15, VM::hw_memsize)),
std::make_pair(VM::MAC_IOKIT, VM::core::technique(100, VM::io_kit)),
std::make_pair(VM::IOREG_GREP, VM::core::technique(100, VM::ioreg_grep)),
std::make_pair(VM::MAC_SIP, VM::core::technique(40, VM::mac_sip)),
- std::make_pair(VM::HKLM_REGISTRIES, VM::core::technique(25, VM::hklm_registries)),
std::make_pair(VM::VPC_INVALID, VM::core::technique(75, VM::vpc_invalid)),
std::make_pair(VM::SIDT, VM::core::technique(25, VM::sidt)),
std::make_pair(VM::SGDT, VM::core::technique(30, VM::sgdt)),
@@ -11595,9 +11082,6 @@ std::pair VM::core::technique_list[] = {
std::make_pair(VM::SMSW, VM::core::technique(30, VM::smsw)),
std::make_pair(VM::MUTEX, VM::core::technique(85, VM::mutex)),
std::make_pair(VM::ODD_CPU_THREADS, VM::core::technique(80, VM::odd_cpu_threads)),
- std::make_pair(VM::INTEL_THREAD_MISMATCH, VM::core::technique(95, VM::intel_thread_mismatch)),
- std::make_pair(VM::XEON_THREAD_MISMATCH, VM::core::technique(95, VM::xeon_thread_mismatch)),
- std::make_pair(VM::AMD_THREAD_MISMATCH, VM::core::technique(95, VM::amd_thread_mismatch)),
std::make_pair(VM::CUCKOO_DIR, VM::core::technique(30, VM::cuckoo_dir)),
std::make_pair(VM::CUCKOO_PIPE, VM::core::technique(30, VM::cuckoo_pipe)),
std::make_pair(VM::HYPERV_HOSTNAME, VM::core::technique(30, VM::hyperv_hostname)),
@@ -11620,32 +11104,17 @@ std::pair VM::core::technique_list[] = {
std::make_pair(VM::SMBIOS_VM_BIT, VM::core::technique(50, VM::smbios_vm_bit)),
std::make_pair(VM::PODMAN_FILE, VM::core::technique(5, VM::podman_file)),
std::make_pair(VM::WSL_PROC, VM::core::technique(30, VM::wsl_proc_subdir)),
- std::make_pair(VM::DRIVER_NAMES, VM::core::technique(100, VM::driver_names)),
- std::make_pair(VM::DISK_SERIAL, VM::core::technique(100, VM::disk_serial_number)),
- std::make_pair(VM::PORT_CONNECTORS, VM::core::technique(25, VM::port_connectors)),
- std::make_pair(VM::IVSHMEM, VM::core::technique(100, VM::ivshmem)),
- std::make_pair(VM::GPU_VM_STRINGS, VM::core::technique(100, VM::gpu_vm_strings)),
- std::make_pair(VM::GPU_CAPABILITIES, VM::core::technique(100, VM::gpu_capabilities)),
std::make_pair(VM::VM_DEVICES, VM::core::technique(50, VM::vm_devices)),
std::make_pair(VM::PROCESSOR_NUMBER, VM::core::technique(50, VM::processor_number)),
std::make_pair(VM::NUMBER_OF_CORES, VM::core::technique(50, VM::number_of_cores)),
- std::make_pair(VM::QEMU_FW_CFG, VM::core::technique(70, VM::qemu_fw_cfg)),
- std::make_pair(VM::LSHW_QEMU, VM::core::technique(80, VM::lshw_qemu)),
std::make_pair(VM::VIRTUAL_PROCESSORS, VM::core::technique(50, VM::virtual_processors)),
std::make_pair(VM::HYPERV_QUERY, VM::core::technique(100, VM::hyperv_query)),
- std::make_pair(VM::BAD_POOLS, VM::core::technique(80, VM::bad_pools)),
std::make_pair(VM::AMD_SEV, VM::core::technique(50, VM::amd_sev)),
- std::make_pair(VM::NATIVE_VHD, VM::core::technique(100, VM::native_vhd)),
std::make_pair(VM::VIRTUAL_REGISTRY, VM::core::technique(65, VM::virtual_registry)),
- std::make_pair(VM::FIRMWARE, VM::core::technique(100, VM::firmware_scan)),
std::make_pair(VM::FILE_ACCESS_HISTORY, VM::core::technique(15, VM::file_access_history)),
std::make_pair(VM::AUDIO, VM::core::technique(25, VM::check_audio)),
std::make_pair(VM::UNKNOWN_MANUFACTURER, VM::core::technique(50, VM::unknown_manufacturer)),
std::make_pair(VM::NSJAIL_PID, VM::core::technique(75, VM::nsjail_proc_id)),
- std::make_pair(VM::TPM, VM::core::technique(50, VM::tpm)),
- std::make_pair(VM::PCI_VM_DEVICE_ID, VM::core::technique(90, VM::pci_vm_device_id)),
- std::make_pair(VM::QEMU_PASSTHROUGH, VM::core::technique(90, VM::qemu_passthrough)),
-
// ADD NEW TECHNIQUE STRUCTURE HERE
};
diff --git a/src/vmaware_MIT.hpp b/src/vmaware_MIT.hpp
deleted file mode 100755
index ce2a3d84..00000000
--- a/src/vmaware_MIT.hpp
+++ /dev/null
@@ -1,11729 +0,0 @@
-/**
- * ██╗ ██╗███╗ ███╗ █████╗ ██╗ ██╗ █████╗ ██████╗ ███████╗
- * ██║ ██║████╗ ████║██╔══██╗██║ ██║██╔══██╗██╔══██╗██╔════╝
- * ██║ ██║██╔████╔██║███████║██║ █╗ ██║███████║██████╔╝█████╗
- * ╚██╗ ██╔╝██║╚██╔╝██║██╔══██║██║███╗██║██╔══██║██╔══██╗██╔══╝
- * ╚████╔╝ ██║ ╚═╝ ██║██║ ██║╚███╔███╔╝██║ ██║██║ ██║███████╗
- * ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ 2.3.0 (May 2025)
- *
- * C++ VM detection library
- *
- * - Made by: kernelwernel (https://github.com/kernelwernel)
- * - Co-developed by: Requiem (https://github.com/NotRequiem)
- * - Contributed by:
- * - Alex (https://github.com/greenozon)
- * - Marek Knápek (https://github.com/MarekKnapek)
- * - Vladyslav Miachkov (https://github.com/fameowner99)
- * - Alan Tse (https://github.com/alandtse)
- * - Georgii Gennadev (https://github.com/D00Movenok)
- * - utoshu (https://github.com/utoshu)
- * - Jyd (https://github.com/jyd519)
- * - dmfrpro (https://github.com/dmfrpro)
- * - Pierre-Étienne Messier (https://github.com/pemessier)
- * - Repository: https://github.com/kernelwernel/VMAware
- * - Docs: https://github.com/kernelwernel/VMAware/docs/documentation.md
- * - Full credits: https://github.com/kernelwernel/VMAware#credits-and-contributors-%EF%B8%8F
- * - License: MIT
- *
- * MIT License
- *
- * Copyright (c) 2025 kernelwernel
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- *
- * ============================== SECTIONS ==================================
- * - enums for publicly accessible techniques => line 579
- * - struct for internal cpu operations => line 758
- * - struct for internal memoization => line 1224
- * - struct for internal utility functions => line 1352
- * - struct for internal core components => line 9885
- * - start of VM detection technique list => line 2465
- * - start of public VM detection functions => line 10542
- * - start of externally defined variables => line 11486
- *
- *
- * ============================== EXAMPLE ===================================
- * #include "vmaware.hpp"
- * #include
- *
- * int main() {
- * if (VM::detect()) {
- * std::cout << "Virtual machine detected!" << "\n";
- * } else {
- * std::cout << "Running on baremetal" << "\n";
- * }
- *
- * std::cout << "VM name: " << VM::brand() << "\n";
- * std::cout << "VM type: " << VM::type() << "\n";
- * std::cout << "VM certainty: " << (int)VM::percentage() << "%" << "\n";
- * }
- *
- *
- * ========================== CODE DOCUMENTATION =============================
- *
- * Welcome! This is just a preliminary text to lay the context of how it works,
- * how it's structured, and guide anybody who's trying to understand the whole code.
- * Reading over 12k+ lines of other people's C++ code is obviously not an easy task,
- * and that's perfectly understandable. I'd struggle as well if I was in your position
- * while not even knowing where to start. So here's a more human-friendly explanation:
- *
- *
- * Firstly, the lib is completely static, meaning that there's no need for struct
- * constructors to be initiated (unless you're using the VM::vmaware struct).
- * The main focus of the lib are the tables:
- * - the TECHNIQUE table stores all the VM detection technique information in a std::map
- *
- * - the BRAND table stores every VM brand as a std::map as well, but as a scoreboard.
- * This means that if a VM detection has detected a VM brand, that brand will have an
- * incremented score. After every technique is run, the brand with the highest score
- * is chosen as the officially detected brand.
- *
- * The techniques are all static functions, which all return a boolean. There are a few
- * categories of techniques that target vastly different things such as OS queries, CPU
- * values, other hardware values, firmware data, and system files just to name a few.
- *
- *
- * Secondly, there are multiple modules in the lib that are combined to integrate with
- * the functionalities needed:
- * - core module:
- * This contains many important components such as the aforementioned tables,
- * the standard structure for how VM techniques are organised, functionalities
- * to run all the techniques in the technique table, functionalities to run
- * custom-made techniques by the user, and an argument handler based on the
- * arguments inputted by the user.
- *
- * - cpu module:
- * As the name suggests, this contains functionalities for the CPU. There are
- * many techniques that utilise some kind of low-level CPU interaction, so
- * this module was added to further standardise it.
- *
- * - memo module:
- * This contains functionalities for memoizing technique results (not to be
- * confused with "memorization"). More specifically, this allows us to cache
- * a technique result in a table where each entry contains a technique and its
- * result. This allows us to avoid re-running techniques which happens a lot
- * internally. Some techniques are costlier than others in terms of
- * performance, so this is a crucial module that allows us to save a lot of
- * time. Additionally, it contains other memoization caches for various other
- * things for convenience purposes.
- *
- * - util module:
- * This contains many utility functionalities to be used by the techniques.
- * Examples of functionalities include file I/O, registries, permission
- * checks, system commands, HDD sizes, RAM sizes, debugs, process checking,
- * OS queries, Hyper-X, and so on. (It should be mentioned that this is
- * probably the least enjoyable part of the lib to read, since it's really messy)
- *
- *
- * Thirdly, I'll explain in this section how all of these facets of the lib interact with
- * each other. Let's take an example with VM::detect(), where it returns a boolean true or
- * false if a VM has been detected or not. The chain of steps it takes goes like this:
- * 1. The function tries to handle the user arguments (if there's
- * any), and generates a std::bitset. This bitset has a length of
- * every VM detection technique + settings, where each bit
- * corresponds to whether this technique will be run or not,
- * and which settings were selected.
- *
- * 2. After the bitset has been generated, this information is then
- * passed to the core module of the lib. It analyses the bitset,
- * and runs every VM detection technique that has been selected,
- * while ignoring the ones that weren't selected (by default most
- * of them are already selected anyway). The function that does
- * this mechanism is core::run_all()
- *
- * 3. While the core::run_all() function is being ran, it checks if
- * each technique has already been memoized or not. If it has,
- * retrieve the result from the cache and move to the next technique.
- * If it hasn't, run the technique and cache the result to the
- * cache table.
- *
- * 4. After every technique has been executed, this generates a
- * uint16_t score. Every technique has a score value between 0 to
- * 100, and if they are detected then this score is accumulated to
- * a total score. If the total is above 150, that means it's a VM[1].
- *
- *
- * There are other functions such as VM::brand(), which returns a std::string of the most
- * likely brand that your system is running on. It has a bit of a different mechanism:
- * 1. Same as step 1 in VM::detect()
- *
- * 2. Check if the majority of techniques have been run already and stored
- * in the cache. If not, invoke core::run_all(). The reason why this is
- * important is because a lot of techniques increment a point for its
- * respected brand that was detected. For example, if the VM::QEMU_USB
- * technique has detected a VM, it'll add a score to the QEMU brand in
- * the scoreboard. If no technique has been run, then there's no way to
- * populate the scoreboard with any points. After every VM detection
- * technique has been invoked/retrieved, the brand scoreboard is now
- * ready to be analysed.
- *
- * 3. Create a filter for the scoreboard, where every brand that has a score
- * of 0 are erased for abstraction purposes. Now the scoreboard is only
- * populated with relevant brands where they all have at least a single
- * point. These are the contenders for which brand will be outputted.
- *
- * 4. Merge certain brand combinations together. For example, Azure's cloud
- * is based on Hyper-V, but Hyper-V may have a higher score due to the
- * prevalence of it in a practical setting, which will put Azure to the
- * side. In reality, there should be an indication that Azure is involved
- * since it's a better idea to let the user know that the brand is "Azure
- * Hyper-V" instead of just "Hyper-V". So what this step does is "merge"
- * the brands together to form a more accurate idea of the brand(s) involved.
- *
- * 5. After all of this, the scoreboard is sorted in descending order, where
- * the brands with the highest points are now selected as the official
- * output of the VM::brand() function.
- *
- * 6. The result is then cached to the memo module, so if another function
- * invokes VM:brand() again, "the result is retrieved from the cache
- * without needing to run all of the previous steps again.
- *
- * (NOTE: it's a bit more complicated than this, but that's the gist of how this function works)
- *
- * Most of the functions provided usually depend on the 2 techniques covered.
- * And they serve as a functionality base for other components of the lib.
- *
- *
- * [1]: If the user has provided a setting argument called VM::HIGH_THRESHOLD,
- * the threshold becomes 300 instead of 150.
- */
-
-#pragma once
-
-#if defined(_WIN32) || defined(_WIN64)
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#define WINDOWS 1
-#define LINUX 0
-#define APPLE 0
-#elif (defined(__linux__))
-#define WINDOWS 0
-#define LINUX 1
-#define APPLE 0
-#elif (defined(__APPLE__) || defined(__APPLE_CPP__) || defined(__MACH__) || defined(__DARWIN))
-#define WINDOWS 0
-#define LINUX 0
-#define APPLE 1
-#else
-#define WINDOWS 0
-#define LINUX 0
-#define APPLE 0
-#endif
-
-#ifdef _MSC_VER
-#define MSVC 1
-#endif
-
- // shorter and succinct macros
-#if __cplusplus > 202100L
-#define CPP 23
-#ifdef __VMAWARE_DEBUG__
-#pragma message("using post-C++23, set back to C++23 standard")
-#endif
-#elif __cplusplus == 202100L
-#define CPP 23
-#ifdef __VMAWARE_DEBUG__
-#pragma message("using C++23")
-#endif
-#elif __cplusplus == 202002L
-#define CPP 20
-#ifdef __VMAWARE_DEBUG__
-#pragma message("using C++20")
-#endif
-#elif __cplusplus == 201703L
-#define CPP 17
-#ifdef __VMAWARE_DEBUG__
-#pragma message("using C++17")
-#endif
-#elif __cplusplus == 201402L
-#define CPP 14
-#ifdef __VMAWARE_DEBUG__
-#pragma message("using C++14")
-#endif
-#elif __cplusplus == 201103L
-#define CPP 11
-#ifdef __VMAWARE_DEBUG__
-#pragma message("using C++11")
-#endif
-#elif __cplusplus < 201103L
-#define CPP 1
-#ifdef __VMAWARE_DEBUG__
-#pragma message("using pre-C++11")
-#endif
-#else
-#define CPP 0
-#ifdef __VMAWARE_DEBUG__
-#pragma message("Unknown C++ standard")
-#endif
-#endif
-
-#if (CPP < 11 && !WINDOWS)
-#error "VMAware only supports C++11 or above, set your compiler flag to '-std=c++20' for gcc/clang, or '/std:c++20' for MSVC"
-#endif
-
-// unused for now, maybe in the future idk
-#if (WINVER == 0x0501) // Windows XP, (0x0701 for Windows 7)
-#define WIN_XP 1
-#else
-#define WIN_XP 0
-#endif
-
-#if defined(__x86_64__) || defined(_M_X64)
-#define x86_64 1
-#else
-#define x86_64 0
-#endif
-
-#if defined(__i386__) || defined(_M_IX86)
-#define x86_32 1
-#else
-#define x86_32 0
-#endif
-
-#if x86_32 || x86_64
-#define x86 1
-#else
-#define x86 0
-#endif
-
-#if (defined(__arm__) || defined(__ARM_LINUX_COMPILER__) || defined(__aarch64__) || defined(_M_ARM64))
-#define ARM 1
-#else
-#define ARM 0
-#endif
-
-#if defined(__clang__)
-#define GCC 0
-#define CLANG 1
-#elif defined(__GNUC__)
-#define GCC 1
-#define CLANG 0
-#else
-#define GCC 0
-#define CLANG 0
-#endif
-
-#if !(defined(WINDOWS) || defined(LINUX) || defined(APPLE))
-#warning "Unknown OS detected, tests will be severely limited"
-#endif
-
-#ifdef _MSC_VER
-#pragma warning(push) // Save current warning state and disable all warnings for external Windows header files
-#pragma warning(disable : 4365)
-#pragma warning(disable : 4668)
-#pragma warning(disable : 4820)
-#pragma warning(disable : 5039)
-#pragma warning(disable : 5204)
-#endif
-
-#if (CPP >= 23)
-#include
-#endif
-#if (CPP >= 20)
-#include
-#include
-#include
-#endif
-#if (CPP >= 17)
-#include
-#endif
-#ifdef __VMAWARE_DEBUG__
-#include
-#include
-#include
-#include
-#endif
-
-#include
-#include