diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d544331b..8715720b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -53,3 +53,116 @@ jobs: - name: CMake Test run: cd build/${{matrix.preset}} && ctest --verbose + + build-linux-gcc: + name: Build Linux GCC + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + configuration: + - Debug + - Release + include: + - configuration: Debug + preset: debug + - configuration: Release + preset: release + steps: + - name: Checkout Source + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Ninja + uses: seanmiddleditch/gha-setup-ninja@v5 + + - name: CMake Build + run: cmake --workflow --preset=${{matrix.preset}} + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: Linux GCC ${{matrix.configuration}} Artifacts + path: | + build/${{matrix.preset}}/artifacts/* + + build-linux-clang: + name: Build Linux Clang + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + configuration: + - Debug + - Release + include: + - configuration: Debug + preset: debug + - configuration: Release + preset: release + steps: + - name: Checkout Source + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Ninja + uses: seanmiddleditch/gha-setup-ninja@v5 + + - name: Install Clang + run: | + sudo apt update + sudo apt install -y wget gnupg software-properties-common + wget https://apt.llvm.org/llvm-snapshot.gpg.key -O- | sudo gpg --dearmor -o /usr/share/keyrings/llvm-archive-keyring.gpg + echo "deb [signed-by=/usr/share/keyrings/llvm-archive-keyring.gpg] https://apt.llvm.org/$(lsb_release -sc)/ llvm-toolchain-$(lsb_release -sc)-18 main" | sudo tee /etc/apt/sources.list.d/llvm.list + sudo apt update + sudo apt install -y clang-18 lld-18 + sudo update-alternatives --install /usr/bin/cc cc /usr/bin/clang-18 100 + sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-18 100 + sudo update-alternatives --set cc /usr/bin/clang-18 + sudo update-alternatives --set c++ /usr/bin/clang++-18 + + - name: CMake Build + run: cmake --workflow --preset=${{matrix.preset}} + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: Linux Clang ${{matrix.configuration}} Artifacts + path: | + build/${{matrix.preset}}/artifacts/* + + build-mac: + name: Build macOS + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + configuration: + - Debug + - Release + include: + - configuration: Debug + preset: debug + - configuration: Release + preset: release + steps: + - name: Checkout Source + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Dependencies + run: | + brew install ninja + + - name: CMake Build + run: cmake --workflow --preset=${{matrix.preset}} + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: macOS ${{matrix.configuration}} Artifacts + path: | + build/${{matrix.preset}}/artifacts/* diff --git a/.gitmodules b/.gitmodules index c6814e54..21cf3d31 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,10 +3,6 @@ url = ../unicorn.git shallow = true branch = dev -[submodule "deps/phnt"] - path = deps/phnt - url = ../phnt.git - shallow = true [submodule "deps/reflect"] path = deps/reflect url = https://github.com/qlibs/reflect.git diff --git a/cmake/utils.cmake b/cmake/utils.cmake index 3d026088..9c67459f 100644 --- a/cmake/utils.cmake +++ b/cmake/utils.cmake @@ -209,7 +209,9 @@ function(momo_target_set_warnings_as_errors target) return() endif() - set(compile_options) + set(compile_options -Wall -Wextra + #-Wconversion + -pedantic -Werror -Wno-comment) if(MSVC) set(compile_options /W4 /WX) @@ -315,6 +317,8 @@ function(momo_strip_target target) endif() if(NOT MSVC) + # TODO: detect LLVM IR bitcode and abort + return() if(NOT DEFINED STRIP_COMMAND) set(STRIP_COMMAND strip) endif() diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 9217618b..8d55e778 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -1,7 +1,6 @@ set(UNICORN_ARCH "x86" CACHE STRING "") add_subdirectory(unicorn) -add_subdirectory(phnt) ########################################## diff --git a/deps/mini-gdbstub b/deps/mini-gdbstub index 25b60f54..2b8a5aad 160000 --- a/deps/mini-gdbstub +++ b/deps/mini-gdbstub @@ -1 +1 @@ -Subproject commit 25b60f545bd9aa4ecdd392b7da959fff7237449b +Subproject commit 2b8a5aade45b9553c7359d32ca98def0a6670f0c diff --git a/deps/phnt b/deps/phnt deleted file mode 160000 index a218107e..00000000 --- a/deps/phnt +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a218107e7a0eb16052a2124219778b3722e3681c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1565e612..ea61b41b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,6 +5,8 @@ add_subdirectory(windows-emulator) add_subdirectory(analyzer) add_subdirectory(fuzzing-engine) add_subdirectory(fuzzer) -add_subdirectory(bad-sample) -add_subdirectory(test-sample) +if(WIN32) + add_subdirectory(bad-sample) + add_subdirectory(test-sample) +endif() add_subdirectory(windows-emulator-test) diff --git a/src/analyzer/main.cpp b/src/analyzer/main.cpp index c9a8b256..0c3c0476 100644 --- a/src/analyzer/main.cpp +++ b/src/analyzer/main.cpp @@ -15,20 +15,25 @@ namespace void watch_system_objects(windows_emulator& win_emu, const bool cache_logging) { + (void)win_emu; + (void)cache_logging; + +#ifdef OS_WINDOWS watch_object(win_emu, *win_emu.current_thread().teb, cache_logging); watch_object(win_emu, win_emu.process().peb, cache_logging); - watch_object(win_emu, emulator_object{win_emu.emu(), kusd_mmio::address()}, cache_logging); + watch_object(win_emu, emulator_object{win_emu.emu(), kusd_mmio::address()}, cache_logging); + auto* params_hook = watch_object(win_emu, win_emu.process().process_params, cache_logging); - win_emu.emu().hook_memory_write(win_emu.process().peb.value() + offsetof(PEB, ProcessParameters), 0x8, + win_emu.emu().hook_memory_write(win_emu.process().peb.value() + offsetof(PEB64, ProcessParameters), 0x8, [&, cache_logging](const uint64_t address, size_t, const uint64_t value) { const auto target_address = win_emu.process().peb.value() + offsetof( - PEB, ProcessParameters); + PEB64, ProcessParameters); if (address == target_address) { - const emulator_object obj{ + const emulator_object obj{ win_emu.emu(), value }; @@ -36,6 +41,7 @@ namespace params_hook = watch_object(win_emu, obj, cache_logging); } }); +#endif } void run_emulation(windows_emulator& win_emu, const analysis_options& options) @@ -57,13 +63,14 @@ namespace } catch (const std::exception& e) { - win_emu.log.print(color::red, "Emulation failed at: 0x%llX - %s\n", - win_emu.emu().read_instruction_pointer(), e.what()); + win_emu.log.print(color::red, "Emulation failed at: 0x%" PRIx64 " - %s\n", + win_emu.emu().read_instruction_pointer(), e.what()); throw; } catch (...) { - win_emu.log.print(color::red, "Emulation failed at: 0x%llX\n", win_emu.emu().read_instruction_pointer()); + win_emu.log.print(color::red, "Emulation failed at: 0x%" PRIx64 "\n", + win_emu.emu().read_instruction_pointer()); throw; } @@ -78,9 +85,9 @@ namespace } } - std::vector parse_arguments(const std::span args) + std::vector parse_arguments(const std::span args) { - std::vector wide_args{}; + std::vector wide_args{}; wide_args.reserve(args.size() - 1); for (size_t i = 1; i < args.size(); ++i) @@ -140,7 +147,7 @@ namespace win_emu.log.print( color::green, - "Reading from executable section %s at 0x%llX via 0x%llX\n", + "Reading from executable section %s at 0x%" PRIx64 " via 0x%" PRIx64 "\n", section.name.c_str(), address, rip); }; @@ -161,7 +168,7 @@ namespace win_emu.log.print( color::blue, - "Writing to executable section %s at 0x%llX via 0x%llX\n", + "Writing to executable section %s at 0x%" PRIx64 " via 0x%" PRIx64 "\n", section.name.c_str(), address, rip); }; diff --git a/src/analyzer/object_watching.hpp b/src/analyzer/object_watching.hpp index 25bfcdcc..f382de81 100644 --- a/src/analyzer/object_watching.hpp +++ b/src/analyzer/object_watching.hpp @@ -31,10 +31,10 @@ emulator_hook* watch_object(windows_emulator& emu, emulator_object object, co const auto offset = address - object.value(); emu.log.print(is_main_access ? color::green : color::dark_gray, - "Object access: %s - 0x%llX (%s) at 0x%llX (%s)\n", - i.get_type_name().c_str(), - offset, - i.get_member_name(offset).c_str(), rip, - mod ? mod->name.c_str() : ""); + "Object access: %s - 0x%llX (%s) at 0x%llX (%s)\n", + i.get_type_name().c_str(), + offset, + i.get_member_name(offset).c_str(), rip, + mod ? mod->name.c_str() : ""); }); } diff --git a/src/analyzer/reflect_type_info.hpp b/src/analyzer/reflect_type_info.hpp index fa943337..2d03cb7c 100644 --- a/src/analyzer/reflect_type_info.hpp +++ b/src/analyzer/reflect_type_info.hpp @@ -1,8 +1,17 @@ #pragma once +#ifndef OS_WINDOWS +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + #include "reflect_extension.hpp" #include +#ifndef OS_WINDOWS +#pragma GCC diagnostic pop +#endif + template class reflect_type_info { diff --git a/src/analyzer/std_include.hpp b/src/analyzer/std_include.hpp index 05e56c34..43df7c99 100644 --- a/src/analyzer/std_include.hpp +++ b/src/analyzer/std_include.hpp @@ -1,37 +1,5 @@ #pragma once -#ifdef _WIN32 -#pragma warning(push) -#pragma warning(disable: 4005) -#pragma warning(disable: 4127) -#pragma warning(disable: 4201) -#pragma warning(disable: 4244) -#pragma warning(disable: 4245) -#pragma warning(disable: 4324) -#pragma warning(disable: 4458) -#pragma warning(disable: 4471) -#pragma warning(disable: 4505) -#pragma warning(disable: 4702) -#pragma warning(disable: 4996) -#pragma warning(disable: 5054) -#pragma warning(disable: 6011) -#pragma warning(disable: 6297) -#pragma warning(disable: 6385) -#pragma warning(disable: 6386) -#pragma warning(disable: 6387) -#pragma warning(disable: 26110) -#pragma warning(disable: 26451) -#pragma warning(disable: 26444) -#pragma warning(disable: 26451) -#pragma warning(disable: 26489) -#pragma warning(disable: 26495) -#pragma warning(disable: 26498) -#pragma warning(disable: 26812) -#pragma warning(disable: 28020) - -#define WIN32_LEAN_AND_MEAN -#define NOMINMAX - #include #include #include @@ -57,23 +25,6 @@ #include -#define NTDDI_WIN11_GE 0 -#define PHNT_VERSION PHNT_WIN11 -#include -#include -#include - -#ifdef _WIN32 -#pragma warning(pop) -#endif - -#ifdef max -#undef max -#endif - -#ifdef min -#undef min -#endif -#endif +#include using namespace std::literals; diff --git a/src/bad-sample/CMakeLists.txt b/src/bad-sample/CMakeLists.txt index 93e997ae..2e6e2502 100644 --- a/src/bad-sample/CMakeLists.txt +++ b/src/bad-sample/CMakeLists.txt @@ -7,5 +7,6 @@ file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS list(SORT SRC_FILES) add_executable(bad-sample ${SRC_FILES}) +target_link_libraries(bad-sample PRIVATE common) momo_assign_source_group(${SRC_FILES}) diff --git a/src/bad-sample/bad.cpp b/src/bad-sample/bad.cpp index 50aa3646..adabd48b 100644 --- a/src/bad-sample/bad.cpp +++ b/src/bad-sample/bad.cpp @@ -1,10 +1,11 @@ #include #include -#include +#include +#include #define THE_SIZE 30 -extern "C" __declspec(noinline) __declspec(dllexport) +extern "C" NO_INLINE EXPORT_SYMBOL void vulnerable(const uint8_t* data, const size_t size) { if (size < 10) diff --git a/src/common/network/address.cpp b/src/common/network/address.cpp index 837a6381..1737804e 100644 --- a/src/common/network/address.cpp +++ b/src/common/network/address.cpp @@ -57,7 +57,7 @@ namespace network this->address4_ = addr; } - address::address(const sockaddr* addr, const int length) + address::address(const sockaddr* addr, const socklen_t length) : address() { this->set_address(addr, length); @@ -109,7 +109,7 @@ namespace network this->address6_.sin6_addr = addr; } - void address::set_address(const sockaddr* addr, const int length) + void address::set_address(const sockaddr* addr, const socklen_t length) { if (static_cast(length) >= sizeof(sockaddr_in) && addr->sa_family == AF_INET) { @@ -250,29 +250,29 @@ namespace network return this->address6_; } - int address::get_size() const + socklen_t address::get_size() const { switch (this->address_.sa_family) { case AF_INET: - return static_cast(sizeof(this->address4_)); + return static_cast(sizeof(this->address4_)); case AF_INET6: - return static_cast(sizeof(this->address6_)); + return static_cast(sizeof(this->address6_)); default: - return static_cast(sizeof(this->address_)); + return static_cast(sizeof(this->address_)); } } - int address::get_max_size() const + socklen_t address::get_max_size() const { - const auto s = sizeof(this->address_); - const auto s4 = sizeof(this->address4_); - const auto s6 = sizeof(this->address6_); - const auto sstore = sizeof(this->storage_); - const auto max_size = std::max(sstore, std::max(s, std::max(s4, s6))); + constexpr auto s = sizeof(this->address_); + constexpr auto s4 = sizeof(this->address4_); + constexpr auto s6 = sizeof(this->address6_); + constexpr auto sstore = sizeof(this->storage_); + constexpr auto max_size = std::max(sstore, std::max(s, std::max(s4, s6))); static_assert(max_size == sstore); - return max_size; + return static_cast(max_size); } bool address::is_ipv4() const @@ -339,7 +339,7 @@ namespace network addrinfo* result = nullptr; if (!getaddrinfo(hostname.data(), nullptr, nullptr, &result)) { - const auto _2 = utils::finally([&result]() + const auto _2 = utils::finally([&result] { freeaddrinfo(result); }); @@ -349,7 +349,7 @@ namespace network if (i->ai_family == AF_INET || i->ai_family == AF_INET6) { address a{}; - a.set_address(i->ai_addr, static_cast(i->ai_addrlen)); + a.set_address(i->ai_addr, static_cast(i->ai_addrlen)); results.emplace_back(std::move(a)); } } diff --git a/src/common/network/address.hpp b/src/common/network/address.hpp index d7a5ab0f..1351f198 100644 --- a/src/common/network/address.hpp +++ b/src/common/network/address.hpp @@ -30,6 +30,7 @@ #include #ifdef _WIN32 +using socklen_t = int; #pragma comment(lib, "ws2_32.lib") #endif @@ -44,12 +45,12 @@ namespace network address(const std::string& addr, const std::optional& family = {}); address(const sockaddr_in& addr); address(const sockaddr_in6& addr); - address(const sockaddr* addr, int length); + address(const sockaddr* addr, socklen_t length); void set_ipv4(uint32_t ip); void set_ipv4(const in_addr& addr); void set_ipv6(const in6_addr& addr); - void set_address(const sockaddr* addr, int length); + void set_address(const sockaddr* addr, socklen_t length); void set_port(unsigned short port); [[nodiscard]] unsigned short get_port() const; @@ -62,8 +63,8 @@ namespace network const sockaddr_in& get_in_addr() const; const sockaddr_in6& get_in6_addr() const; - int get_size() const; - int get_max_size() const; + socklen_t get_size() const; + socklen_t get_max_size() const; bool is_ipv4() const; bool is_ipv6() const; diff --git a/src/common/network/socket.cpp b/src/common/network/socket.cpp index 7f385df1..45991ff3 100644 --- a/src/common/network/socket.cpp +++ b/src/common/network/socket.cpp @@ -68,10 +68,10 @@ namespace network bool socket::send(const address& target, const void* data, const size_t size) const { - const int res = sendto(this->socket_, static_cast(data), static_cast(size), 0, - &target.get_addr(), - target.get_size()); - return res == static_cast(size); + const auto res = sendto(this->socket_, static_cast(data), static_cast(size), 0, + &target.get_addr(), + target.get_size()); + return static_cast(res) == size; } bool socket::send(const address& target, const std::string& data) const @@ -82,7 +82,7 @@ namespace network bool socket::receive(address& source, std::string& data) const { char buffer[0x2000]; - socklen_t len = source.get_max_size(); + auto len = source.get_max_size(); const auto result = recvfrom(this->socket_, buffer, static_cast(sizeof(buffer)), 0, &source.get_addr(), &len); diff --git a/src/common/network/socket.hpp b/src/common/network/socket.hpp index 7c8cded9..ef8f1d35 100644 --- a/src/common/network/socket.hpp +++ b/src/common/network/socket.hpp @@ -6,12 +6,13 @@ #include #ifdef _WIN32 -using socklen_t = int; +using send_size = int; #define GET_SOCKET_ERROR() (WSAGetLastError()) #define poll WSAPoll #define SOCK_WOULDBLOCK WSAEWOULDBLOCK #else using SOCKET = int; +using send_size = size_t; #define INVALID_SOCKET (SOCKET)(~0) #define SOCKET_ERROR (-1) #define GET_SOCKET_ERROR() (errno) diff --git a/src/common/platform/compiler.hpp b/src/common/platform/compiler.hpp new file mode 100644 index 00000000..b8fca2ef --- /dev/null +++ b/src/common/platform/compiler.hpp @@ -0,0 +1,44 @@ +#pragma once + +#if defined(_WIN32) || defined(_WIN64) +#define OS_WINDOWS +#elif defined(__APPLE__) || defined(__MACH__) + #define OS_MAC +#elif defined(__linux__) +#define OS_LINUX +#else +#error "Unsupported platform" +#endif + +#ifdef OS_WINDOWS +#define EXPORT_SYMBOL __declspec(dllexport) +#define IMPORT_SYMBOL __declspec(dllimport) +#define NO_INLINE __declspec(noinline) + +#define DECLSPEC_ALIGN(n) __declspec(align(n)) + +#define RESTRICTED_POINTER + +#else +#include + +#define EXPORT_SYMBOL __attribute__((visibility("default"))) +#define IMPORT_SYMBOL +#define NO_INLINE __attribute__((noinline)) + +#define DECLSPEC_ALIGN(n) alignas(n) +#define fopen_s fopen + +#define RESTRICTED_POINTER __restrict + +#ifdef OS_MAC +#define _fseeki64 fseeko +#define _ftelli64 ftello +#define _stat64 stat +#else +#define _fseeki64 fseeko64 +#define _ftelli64 ftello64 +#define _stat64 stat64 +#endif + +#endif diff --git a/src/common/platform/file_management.hpp b/src/common/platform/file_management.hpp new file mode 100644 index 00000000..57e6d403 --- /dev/null +++ b/src/common/platform/file_management.hpp @@ -0,0 +1,383 @@ +#pragma once + +#define ACCESS_MASK DWORD +#define DEVICE_TYPE DWORD + +#define FILE_DEVICE_DISK 0x00000007 +#define FILE_DEVICE_CONSOLE 0x00000050 + +#define FILE_SUPERSEDE 0x00000000 +#define FILE_OPEN 0x00000001 +#define FILE_CREATE 0x00000002 +#define FILE_OPEN_IF 0x00000003 +#define FILE_OVERWRITE 0x00000004 +#define FILE_OVERWRITE_IF 0x00000005 +#define FILE_MAXIMUM_DISPOSITION 0x00000005 + +#ifndef OS_WINDOWS +#define GENERIC_READ 0x80000000 +#define GENERIC_WRITE 0x40000000 +#define GENERIC_EXECUTE 0x20000000 +#define GENERIC_ALL 0x10000000 + +#undef DELETE +#define DELETE 0x00010000 +#define READ_CONTROL 0x00020000 +#define WRITE_DAC 0x00040000 +#define WRITE_OWNER 0x00080000 +#define SYNCHRONIZE 0x00100000 +#define STANDARD_RIGHTS_REQUIRED 0x000f0000 + +#define FILE_READ_DATA 0x0001 /* file & pipe */ +#define FILE_LIST_DIRECTORY 0x0001 /* directory */ +#define FILE_WRITE_DATA 0x0002 /* file & pipe */ +#define FILE_ADD_FILE 0x0002 /* directory */ +#define FILE_APPEND_DATA 0x0004 /* file */ +#define FILE_ADD_SUBDIRECTORY 0x0004 /* directory */ +#define FILE_CREATE_PIPE_INSTANCE 0x0004 /* named pipe */ +#define FILE_READ_EA 0x0008 /* file & directory */ +#define FILE_READ_PROPERTIES FILE_READ_EA +#define FILE_WRITE_EA 0x0010 /* file & directory */ +#define FILE_WRITE_PROPERTIES FILE_WRITE_EA +#define FILE_EXECUTE 0x0020 /* file */ +#define FILE_TRAVERSE 0x0020 /* directory */ +#define FILE_DELETE_CHILD 0x0040 /* directory */ +#define FILE_READ_ATTRIBUTES 0x0080 /* all */ +#define FILE_WRITE_ATTRIBUTES 0x0100 /* all */ +#define FILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x1ff) + +#endif + +#define FILE_DIRECTORY_FILE 0x00000001 +#define FILE_WRITE_THROUGH 0x00000002 +#define FILE_SEQUENTIAL_ONLY 0x00000004 +#define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008 + +#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010 +#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 +#define FILE_NON_DIRECTORY_FILE 0x00000040 +#define FILE_CREATE_TREE_CONNECTION 0x00000080 + +#define FILE_ATTRIBUTE_NORMAL 0x00000080 + +#define PS_ATTRIBUTE_NUMBER_MASK 0x0000ffff +#define PS_ATTRIBUTE_THREAD 0x00010000 // may be used with thread creation +#define PS_ATTRIBUTE_INPUT 0x00020000 // input only +#define PS_ATTRIBUTE_ADDITIVE 0x00040000 // "accumulated" e.g. bitmasks, counters, etc. + +#define SL_RESTART_SCAN 0x01 +#define SL_RETURN_SINGLE_ENTRY 0x02 +#define SL_NO_CURSOR_UPDATE 0x10 + +#define SEC_IMAGE 0x01000000 + +typedef enum _FSINFOCLASS +{ + FileFsVolumeInformation = 1, // q: FILE_FS_VOLUME_INFORMATION + FileFsLabelInformation, // s: FILE_FS_LABEL_INFORMATION (requires FILE_WRITE_DATA to volume) + FileFsSizeInformation, // q: FILE_FS_SIZE_INFORMATION + FileFsDeviceInformation, // q: FILE_FS_DEVICE_INFORMATION + FileFsAttributeInformation, // q: FILE_FS_ATTRIBUTE_INFORMATION + FileFsControlInformation, + // q, s: FILE_FS_CONTROL_INFORMATION (q: requires FILE_READ_DATA; s: requires FILE_WRITE_DATA to volume) + FileFsFullSizeInformation, // q: FILE_FS_FULL_SIZE_INFORMATION + FileFsObjectIdInformation, // q; s: FILE_FS_OBJECTID_INFORMATION (s: requires FILE_WRITE_DATA to volume) + FileFsDriverPathInformation, // q: FILE_FS_DRIVER_PATH_INFORMATION + FileFsVolumeFlagsInformation, + // q; s: FILE_FS_VOLUME_FLAGS_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES to volume) // 10 + FileFsSectorSizeInformation, // q: FILE_FS_SECTOR_SIZE_INFORMATION // since WIN8 + FileFsDataCopyInformation, // q: FILE_FS_DATA_COPY_INFORMATION + FileFsMetadataSizeInformation, // q: FILE_FS_METADATA_SIZE_INFORMATION // since THRESHOLD + FileFsFullSizeInformationEx, // q: FILE_FS_FULL_SIZE_INFORMATION_EX // since REDSTONE5 + FileFsGuidInformation, // q: FILE_FS_GUID_INFORMATION // since 23H2 + FileFsMaximumInformation +} FSINFOCLASS, *PFSINFOCLASS; + +typedef enum _FSINFOCLASS FS_INFORMATION_CLASS; + +typedef enum _FILE_INFORMATION_CLASS +{ + FileDirectoryInformation = 1, + // q: FILE_DIRECTORY_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) + FileFullDirectoryInformation, + // q: FILE_FULL_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) + FileBothDirectoryInformation, + // q: FILE_BOTH_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) + FileBasicInformation, + // q; s: FILE_BASIC_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) + FileStandardInformation, // q: FILE_STANDARD_INFORMATION, FILE_STANDARD_INFORMATION_EX + FileInternalInformation, // q: FILE_INTERNAL_INFORMATION + FileEaInformation, // q: FILE_EA_INFORMATION + FileAccessInformation, // q: FILE_ACCESS_INFORMATION + FileNameInformation, // q: FILE_NAME_INFORMATION + FileRenameInformation, // s: FILE_RENAME_INFORMATION (requires DELETE) // 10 + FileLinkInformation, // s: FILE_LINK_INFORMATION + FileNamesInformation, // q: FILE_NAMES_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) + FileDispositionInformation, // s: FILE_DISPOSITION_INFORMATION (requires DELETE) + FilePositionInformation, // q; s: FILE_POSITION_INFORMATION + FileFullEaInformation, // FILE_FULL_EA_INFORMATION + FileModeInformation, // q; s: FILE_MODE_INFORMATION + FileAlignmentInformation, // q: FILE_ALIGNMENT_INFORMATION + FileAllInformation, // q: FILE_ALL_INFORMATION (requires FILE_READ_ATTRIBUTES) + FileAllocationInformation, // s: FILE_ALLOCATION_INFORMATION (requires FILE_WRITE_DATA) + FileEndOfFileInformation, // s: FILE_END_OF_FILE_INFORMATION (requires FILE_WRITE_DATA) // 20 + FileAlternateNameInformation, // q: FILE_NAME_INFORMATION + FileStreamInformation, // q: FILE_STREAM_INFORMATION + FilePipeInformation, + // q; s: FILE_PIPE_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) + FilePipeLocalInformation, // q: FILE_PIPE_LOCAL_INFORMATION (requires FILE_READ_ATTRIBUTES) + FilePipeRemoteInformation, + // q; s: FILE_PIPE_REMOTE_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) + FileMailslotQueryInformation, // q: FILE_MAILSLOT_QUERY_INFORMATION + FileMailslotSetInformation, // s: FILE_MAILSLOT_SET_INFORMATION + FileCompressionInformation, // q: FILE_COMPRESSION_INFORMATION + FileObjectIdInformation, // q: FILE_OBJECTID_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) + FileCompletionInformation, // s: FILE_COMPLETION_INFORMATION // 30 + FileMoveClusterInformation, // s: FILE_MOVE_CLUSTER_INFORMATION (requires FILE_WRITE_DATA) + FileQuotaInformation, // q: FILE_QUOTA_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) + FileReparsePointInformation, + // q: FILE_REPARSE_POINT_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) + FileNetworkOpenInformation, // q: FILE_NETWORK_OPEN_INFORMATION (requires FILE_READ_ATTRIBUTES) + FileAttributeTagInformation, // q: FILE_ATTRIBUTE_TAG_INFORMATION (requires FILE_READ_ATTRIBUTES) + FileTrackingInformation, // s: FILE_TRACKING_INFORMATION (requires FILE_WRITE_DATA) + FileIdBothDirectoryInformation, + // q: FILE_ID_BOTH_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) + FileIdFullDirectoryInformation, + // q: FILE_ID_FULL_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) + FileValidDataLengthInformation, + // s: FILE_VALID_DATA_LENGTH_INFORMATION (requires FILE_WRITE_DATA and/or SeManageVolumePrivilege) + FileShortNameInformation, // s: FILE_NAME_INFORMATION (requires DELETE) // 40 + FileIoCompletionNotificationInformation, + // q; s: FILE_IO_COMPLETION_NOTIFICATION_INFORMATION (q: requires FILE_READ_ATTRIBUTES) // since VISTA + FileIoStatusBlockRangeInformation, // s: FILE_IOSTATUSBLOCK_RANGE_INFORMATION (requires SeLockMemoryPrivilege) + FileIoPriorityHintInformation, + // q; s: FILE_IO_PRIORITY_HINT_INFORMATION, FILE_IO_PRIORITY_HINT_INFORMATION_EX (q: requires FILE_READ_DATA) + FileSfioReserveInformation, // q; s: FILE_SFIO_RESERVE_INFORMATION (q: requires FILE_READ_DATA) + FileSfioVolumeInformation, // q: FILE_SFIO_VOLUME_INFORMATION (requires FILE_READ_ATTRIBUTES) + FileHardLinkInformation, // q: FILE_LINKS_INFORMATION + FileProcessIdsUsingFileInformation, // q: FILE_PROCESS_IDS_USING_FILE_INFORMATION (requires FILE_READ_ATTRIBUTES) + FileNormalizedNameInformation, // q: FILE_NAME_INFORMATION + FileNetworkPhysicalNameInformation, // q: FILE_NETWORK_PHYSICAL_NAME_INFORMATION + FileIdGlobalTxDirectoryInformation, + // q: FILE_ID_GLOBAL_TX_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) // since WIN7 // 50 + FileIsRemoteDeviceInformation, // q: FILE_IS_REMOTE_DEVICE_INFORMATION (requires FILE_READ_ATTRIBUTES) + FileUnusedInformation, + FileNumaNodeInformation, // q: FILE_NUMA_NODE_INFORMATION + FileStandardLinkInformation, // q: FILE_STANDARD_LINK_INFORMATION + FileRemoteProtocolInformation, // q: FILE_REMOTE_PROTOCOL_INFORMATION + FileRenameInformationBypassAccessCheck, // (kernel-mode only); s: FILE_RENAME_INFORMATION // since WIN8 + FileLinkInformationBypassAccessCheck, // (kernel-mode only); s: FILE_LINK_INFORMATION + FileVolumeNameInformation, // q: FILE_VOLUME_NAME_INFORMATION + FileIdInformation, // q: FILE_ID_INFORMATION + FileIdExtdDirectoryInformation, + // q: FILE_ID_EXTD_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) // 60 + FileReplaceCompletionInformation, // s: FILE_COMPLETION_INFORMATION // since WINBLUE + FileHardLinkFullIdInformation, // q: FILE_LINK_ENTRY_FULL_ID_INFORMATION // FILE_LINKS_FULL_ID_INFORMATION + FileIdExtdBothDirectoryInformation, + // q: FILE_ID_EXTD_BOTH_DIR_INFORMATION (requires FILE_LIST_DIRECTORY) (NtQueryDirectoryFile[Ex]) // since THRESHOLD + FileDispositionInformationEx, // s: FILE_DISPOSITION_INFO_EX (requires DELETE) // since REDSTONE + FileRenameInformationEx, // s: FILE_RENAME_INFORMATION_EX + FileRenameInformationExBypassAccessCheck, // (kernel-mode only); s: FILE_RENAME_INFORMATION_EX + FileDesiredStorageClassInformation, + // q; s: FILE_DESIRED_STORAGE_CLASS_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) // since REDSTONE2 + FileStatInformation, // q: FILE_STAT_INFORMATION (requires FILE_READ_ATTRIBUTES) + FileMemoryPartitionInformation, // s: FILE_MEMORY_PARTITION_INFORMATION // since REDSTONE3 + FileStatLxInformation, + // q: FILE_STAT_LX_INFORMATION (requires FILE_READ_ATTRIBUTES and FILE_READ_EA) // since REDSTONE4 // 70 + FileCaseSensitiveInformation, + // q; s: FILE_CASE_SENSITIVE_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) + FileLinkInformationEx, // s: FILE_LINK_INFORMATION_EX // since REDSTONE5 + FileLinkInformationExBypassAccessCheck, // (kernel-mode only); s: FILE_LINK_INFORMATION_EX + FileStorageReserveIdInformation, + // q; s: FILE_STORAGE_RESERVE_ID_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) + FileCaseSensitiveInformationForceAccessCheck, // q; s: FILE_CASE_SENSITIVE_INFORMATION + FileKnownFolderInformation, + // q; s: FILE_KNOWN_FOLDER_INFORMATION (q: requires FILE_READ_ATTRIBUTES; s: requires FILE_WRITE_ATTRIBUTES) // since WIN11 + FileStatBasicInformation, // since 23H2 + FileId64ExtdDirectoryInformation, // FILE_ID_64_EXTD_DIR_INFORMATION + FileId64ExtdBothDirectoryInformation, // FILE_ID_64_EXTD_BOTH_DIR_INFORMATION + FileIdAllExtdDirectoryInformation, // FILE_ID_ALL_EXTD_DIR_INFORMATION + FileIdAllExtdBothDirectoryInformation, // FILE_ID_ALL_EXTD_BOTH_DIR_INFORMATION + FileStreamReservationInformation, // FILE_STREAM_RESERVATION_INFORMATION // since 24H2 + FileMupProviderInfo, // MUP_PROVIDER_INFORMATION + FileMaximumInformation +} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; + +typedef enum _OBJECT_INFORMATION_CLASS +{ + ObjectBasicInformation, // q: OBJECT_BASIC_INFORMATION + ObjectNameInformation, // q: OBJECT_NAME_INFORMATION + ObjectTypeInformation, // q: OBJECT_TYPE_INFORMATION + ObjectTypesInformation, // q: OBJECT_TYPES_INFORMATION + ObjectHandleFlagInformation, // qs: OBJECT_HANDLE_FLAG_INFORMATION + ObjectSessionInformation, // s: void // change object session // (requires SeTcbPrivilege) + ObjectSessionObjectInformation, // s: void // change object session // (requires SeTcbPrivilege) + MaxObjectInfoClass +} OBJECT_INFORMATION_CLASS; + +typedef enum _HARDERROR_RESPONSE_OPTION +{ + OptionAbortRetryIgnore, + OptionOk, + OptionOkCancel, + OptionRetryCancel, + OptionYesNo, + OptionYesNoCancel, + OptionShutdownSystem, + OptionOkNoWait, + OptionCancelTryContinue +} HARDERROR_RESPONSE_OPTION; + +typedef enum _HARDERROR_RESPONSE +{ + ResponseReturnToCaller, + ResponseNotHandled, + ResponseAbort, + ResponseCancel, + ResponseIgnore, + ResponseNo, + ResponseOk, + ResponseRetry, + ResponseYes, + ResponseTryAgain, + ResponseContinue +} HARDERROR_RESPONSE; + +typedef USHORT RTL_ATOM; + +template +struct IO_STATUS_BLOCK +{ + union + { + NTSTATUS Status; + typename Traits::PVOID Pointer; + }; + + typename Traits::ULONG_PTR Information; +}; + +template +struct OBJECT_ATTRIBUTES +{ + ULONG Length; + typename Traits::HANDLE RootDirectory; + EMULATOR_CAST(typename Traits::PVOID, UNICODE_STRING*) ObjectName; + ULONG Attributes; + typename Traits::PVOID SecurityDescriptor; // PSECURITY_DESCRIPTOR; + typename Traits::PVOID SecurityQualityOfService; // PSECURITY_QUALITY_OF_SERVICE +}; + +typedef struct _FILE_FS_DEVICE_INFORMATION +{ + DEVICE_TYPE DeviceType; + ULONG Characteristics; +} FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION; + +typedef struct _FILE_POSITION_INFORMATION +{ + LARGE_INTEGER CurrentByteOffset; +} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION; + +typedef struct _FILE_STANDARD_INFORMATION +{ + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG NumberOfLinks; + BOOLEAN DeletePending; + BOOLEAN Directory; +} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION; + +typedef struct _FILE_NAME_INFORMATION +{ + ULONG FileNameLength; + char16_t FileName[1]; +} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; + +typedef struct _FILE_BASIC_INFORMATION +{ + LARGE_INTEGER CreationTime; // Specifies the time that the file was created. + LARGE_INTEGER LastAccessTime; // Specifies the time that the file was last accessed. + LARGE_INTEGER LastWriteTime; // Specifies the time that the file was last written to. + LARGE_INTEGER ChangeTime; // Specifies the last time the file was changed. + ULONG FileAttributes; // Specifies one or more FILE_ATTRIBUTE_XXX flags. +} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; + +typedef struct _FILE_DIRECTORY_INFORMATION +{ + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + char16_t FileName[1]; +} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION; + +typedef struct _FILE_FULL_DIR_INFORMATION +{ + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + char16_t FileName[1]; +} FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION; + +typedef struct _FILE_BOTH_DIR_INFORMATION +{ + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + char ShortNameLength; + char16_t ShortName[12]; + char16_t FileName[1]; +} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION; + +#ifndef OS_WINDOWS +typedef BOOLEAN SECURITY_CONTEXT_TRACKING_MODE, + * PSECURITY_CONTEXT_TRACKING_MODE; +typedef struct _SECURITY_QUALITY_OF_SERVICE +{ + DWORD Length; + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; + SECURITY_CONTEXT_TRACKING_MODE ContextTrackingMode; + BOOLEAN EffectiveOnly; +} SECURITY_QUALITY_OF_SERVICE, *P_SECURITY_QUALITY_OF_SERVICE; + +#endif + +typedef struct _PORT_VIEW64 +{ + ULONG Length; + EMULATOR_CAST(std::uint64_t, HANDLE) SectionHandle; + ULONG SectionOffset; + EMULATOR_CAST(std::int64_t, SIZE_T) ViewSize; + EmulatorTraits::PVOID ViewBase; + EmulatorTraits::PVOID ViewRemoteBase; +} PORT_VIEW64, *PPORT_VIEW64; + +typedef struct _REMOTE_PORT_VIEW64 +{ + ULONG Length; + EMULATOR_CAST(std::int64_t, SIZE_T) ViewSize; + EmulatorTraits::PVOID ViewBase; +} REMOTE_PORT_VIEW64, *PREMOTE_PORT_VIEW64; diff --git a/src/common/platform/kernel_mapped.hpp b/src/common/platform/kernel_mapped.hpp new file mode 100644 index 00000000..eba0cb63 --- /dev/null +++ b/src/common/platform/kernel_mapped.hpp @@ -0,0 +1,886 @@ +#pragma once + +#include + +#define PROCESSOR_FEATURE_MAX 64 +#define GDI_HANDLE_BUFFER_SIZE64 60 +#define RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_RELEASE_ON_DEACTIVATION 0x00000001 +#define RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NO_DEACTIVATE 0x00000002 +#define RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ON_FREE_LIST 0x00000004 +#define RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED 0x00000008 +#define RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED 0x00000010 +#define ACTIVATION_CONTEXT_STACK_FLAG_QUERIES_DISABLED 0x00000001 +#define GDI_BATCH_BUFFER_SIZE 310 +#define WIN32_CLIENT_INFO_LENGTH 62 +#define STATIC_UNICODE_BUFFER_LENGTH 261 +#define TLS_MINIMUM_AVAILABLE 64 + +typedef struct _EMU_NT_TIB64 +{ + struct _EXCEPTION_REGISTRATION_RECORD* ExceptionList; + std::uint64_t* StackBase; + std::uint64_t* StackLimit; + std::uint64_t* SubSystemTib; + std::uint64_t* FibreData; + std::uint64_t* ArbitraryUserPointer; + struct _EMU_NT_TIB64* Self; +} EMU_NT_TIB64; + +typedef EMU_NT_TIB64* PEMU_NT_TIB64; + +union PEB_BITFIELD_UNION +{ + BOOLEAN BitField; + + struct + { + BOOLEAN ImageUsesLargePages : 1; + BOOLEAN IsProtectedProcess : 1; + BOOLEAN IsImageDynamicallyRelocated : 1; + BOOLEAN SkipPatchingUser32Forwarders : 1; + BOOLEAN IsPackagedProcess : 1; + BOOLEAN IsAppContainer : 1; + BOOLEAN IsProtectedProcessLight : 1; + BOOLEAN IsLongPathAwareProcess : 1; + }; +}; + +#ifndef OS_WINDOWS + +typedef struct _LIST_ENTRY64 +{ + struct _LIST_ENTRY *Flink; + struct _LIST_ENTRY *Blink; +} LIST_ENTRY64, *PLIST_ENTRY64, *RESTRICTED_POINTER PRLIST_ENTRY64; + +#endif + +typedef struct _PEB_LDR_DATA64 +{ + ULONG Length; + BOOLEAN Initialized; + EmulatorTraits::HANDLE SsHandle; + LIST_ENTRY64 InLoadOrderModuleList; + LIST_ENTRY64 InMemoryOrderModuleList; + LIST_ENTRY64 InInitializationOrderModuleList; + std::uint64_t* EntryInProgress; + BOOLEAN ShutdownInProgress; + EmulatorTraits::HANDLE ShutdownThreadId; +} PEB_LDR_DATA64, *PPEB_LDR_DATA64; + +typedef struct _STRING64 +{ + USHORT Length; + USHORT MaximumLength; + char16_t* Buffer; +} STRING64, *PSTRING64, ANSI_STRING64, *PANSI_STRING64, OEM_STRING64, *POEM_STRING64; + +typedef struct _RTL_DRIVE_LETTER_CURDIR64 +{ + USHORT Flags; + USHORT Length; + ULONG TimeStamp; + STRING64 DosPath; +} RTL_DRIVE_LETTER_CURDIR64, *PRTL_DRIVE_LETTER_CURDIR64; + +#define RTL_MAX_DRIVE_LETTERS 32 +#define RTL_DRIVE_LETTER_VALID (USHORT)0x0001 + +template +struct ARRAY_CONTAINER +{ + T arr[Size]; +}; + +typedef struct _CURDIR64 +{ + UNICODE_STRING> DosPath; + EmulatorTraits::HANDLE Handle; +} CURDIR64, *PCURDIR64; + +typedef struct _RTL_USER_PROCESS_PARAMETERS64 +{ + ULONG MaximumLength; + ULONG Length; + + ULONG Flags; + ULONG DebugFlags; + + EmulatorTraits::HANDLE ConsoleHandle; + ULONG ConsoleFlags; + EmulatorTraits::HANDLE StandardInput; + EmulatorTraits::HANDLE StandardOutput; + EmulatorTraits::HANDLE StandardError; + + CURDIR64 CurrentDirectory; + UNICODE_STRING> DllPath; + UNICODE_STRING> ImagePathName; + UNICODE_STRING> CommandLine; + std::uint64_t* Environment; + + ULONG StartingX; + ULONG StartingY; + ULONG CountX; + ULONG CountY; + ULONG CountCharsX; + ULONG CountCharsY; + ULONG FillAttribute; + + ULONG WindowFlags; + ULONG ShowWindowFlags; + UNICODE_STRING> WindowTitle; + UNICODE_STRING> DesktopInfo; + UNICODE_STRING> ShellInfo; + UNICODE_STRING> RuntimeData; + ARRAY_CONTAINER CurrentDirectories; + + std::uint64_t* EnvironmentSize; + std::uint64_t* EnvironmentVersion; + + std::uint64_t* PackageDependencyData; + ULONG ProcessGroupId; + ULONG LoaderThreads; + + UNICODE_STRING> RedirectionDllName; // REDSTONE4 + UNICODE_STRING> HeapPartitionName; // 19H1 + std::uint64_t* DefaultThreadpoolCpuSetMasks; + ULONG DefaultThreadpoolCpuSetMaskCount; + ULONG DefaultThreadpoolThreadMaximum; + ULONG HeapMemoryTypeMask; // WIN11 +} RTL_USER_PROCESS_PARAMETERS64, *PRTL_USER_PROCESS_PARAMETERS64; + +union PEB_CROSS_PROCESS_FLAGS_UNION +{ + ULONG CrossProcessFlags; + + struct + { + ULONG ProcessInJob : 1; + ULONG ProcessInitializing : 1; + ULONG ProcessUsingVEH : 1; + ULONG ProcessUsingVCH : 1; + ULONG ProcessUsingFTH : 1; + ULONG ProcessPreviouslyThrottled : 1; + ULONG ProcessCurrentlyThrottled : 1; + ULONG ProcessImagesHotPatched : 1; // REDSTONE5 + ULONG ReservedBits0 : 24; + }; +}; + +union PEB_KERNEL_CALLBACK_TABLE_UNION64 +{ + void* KernelCallbackTable; + void* UserSharedInfoPtr; +}; + +typedef struct _API_SET_NAMESPACE +{ + ULONG Version; + ULONG Size; + ULONG Flags; + ULONG Count; + ULONG EntryOffset; + ULONG HashOffset; + ULONG HashFactor; +} API_SET_NAMESPACE, *PAPI_SET_NAMESPACE; + +union PEB_CONTEXT_DATA_UNION64 +{ + void* pContextData; // WIN7 + void* pUnused; // WIN10 + void* EcCodeBitMap; // WIN11 +}; + +union PEB_TRACING_FLAGS_UNION +{ + ULONG TracingFlags; + + struct + { + ULONG HeapTracingEnabled : 1; + ULONG CritSecTracingEnabled : 1; + ULONG LibLoaderTracingEnabled : 1; + ULONG SpareTracingBits : 29; + }; +}; + +union PEB_LEAP_SECONDS_FLAG_UNION +{ + ULONG LeapSecondFlags; + + struct + { + ULONG SixtySecondEnabled : 1; + ULONG Reserved : 31; + }; +}; + +typedef struct _PEB64 +{ + BOOLEAN InheritedAddressSpace; + BOOLEAN ReadImageFileExecOptions; + BOOLEAN BeingDebugged; + PEB_BITFIELD_UNION BitField; + + EmulatorTraits::HANDLE Mutant; + + std::uint64_t* ImageBaseAddress; + PPEB_LDR_DATA64 Ldr; + PRTL_USER_PROCESS_PARAMETERS64 ProcessParameters; + std::uint64_t* SubSystemData; + std::uint64_t* ProcessHeap; + EMULATOR_CAST(void*, PRTL_CRITICAL_SECTION) FastPebLock; + EMULATOR_CAST(void*, PSLIST_HEADER) AtlThunkSListPtr; + std::uint64_t* IFEOKey; + PEB_CROSS_PROCESS_FLAGS_UNION CrossProcessFlags; + PEB_KERNEL_CALLBACK_TABLE_UNION64 KernelCallbackTable; + + ULONG SystemReserved; + ULONG AtlThunkSListPtr32; + PAPI_SET_NAMESPACE ApiSetMap; + ULONG TlsExpansionCounter; + EMULATOR_CAST(void*, PRTL_BITMAP) TlsBitmap; + + ARRAY_CONTAINER TlsBitmapBits; // TLS_MINIMUM_AVAILABLE + void* ReadOnlySharedMemoryBase; + EMULATOR_CAST(void*, PSILO_USER_SHARED_DATA) SharedData; // HotpatchInformation + std::uint64_t** ReadOnlyStaticServerData; + + std::uint64_t* AnsiCodePageData; // PCPTABLEINFO + std::uint64_t* OemCodePageData; // PCPTABLEINFO + std::uint64_t* UnicodeCaseTableData; // PNLSTABLEINFO + + ULONG NumberOfProcessors; + ULONG NtGlobalFlag; + + ULARGE_INTEGER CriticalSectionTimeout; + EMULATOR_CAST(std::int64_t, SIZE_T) HeapSegmentReserve; + EMULATOR_CAST(std::int64_t, SIZE_T) HeapSegmentCommit; + EMULATOR_CAST(std::int64_t, SIZE_T) HeapDeCommitTotalFreeThreshold; + EMULATOR_CAST(std::int64_t, SIZE_T) HeapDeCommitFreeBlockThreshold; + + ULONG NumberOfHeaps; + ULONG MaximumNumberOfHeaps; + std::uint64_t** ProcessHeaps; // PHEAP + + std::uint64_t* GdiSharedHandleTable; // PGDI_SHARED_MEMORY + std::uint64_t* ProcessStarterHelper; + ULONG GdiDCAttributeList; + + EMULATOR_CAST(void*, PRTL_CRITICAL_SECTION) LoaderLock; + + ULONG OSMajorVersion; + ULONG OSMinorVersion; + USHORT OSBuildNumber; + USHORT OSCSDVersion; + ULONG OSPlatformId; + ULONG ImageSubsystem; + ULONG ImageSubsystemMajorVersion; + ULONG ImageSubsystemMinorVersion; + EMULATOR_CAST(std::uint64_t, KAFFINITY) ActiveProcessAffinityMask; + ARRAY_CONTAINER GdiHandleBuffer; + std::uint64_t* PostProcessInitRoutine; + + EMULATOR_CAST(void*, PRTL_BITMAP) TlsExpansionBitmap; + ARRAY_CONTAINER TlsExpansionBitmapBits; // TLS_EXPANSION_SLOTS + + ULONG SessionId; + + ULARGE_INTEGER AppCompatFlags; // KACF_* + ULARGE_INTEGER AppCompatFlagsUser; + std::uint64_t* pShimData; + std::uint64_t* AppCompatInfo; // APPCOMPAT_EXE_DATA + + UNICODE_STRING> CSDVersion; + + EMULATOR_CAST(void*, PACTIVATION_CONTEXT_DATA) ActivationContextData; + EMULATOR_CAST(void*, PASSEMBLY_STORAGE_MAP) ProcessAssemblyStorageMap; + EMULATOR_CAST(void*, PACTIVATION_CONTEXT_DATA) SystemDefaultActivationContextData; + EMULATOR_CAST(void*, PASSEMBLY_STORAGE_MAP) SystemAssemblyStorageMap; + + EMULATOR_CAST(std::int64_t, SIZE_T) MinimumStackCommit; + + ARRAY_CONTAINER SparePointers; // 19H1 (previously FlsCallback to FlsHighIndex) + std::uint64_t* PatchLoaderData; + std::uint64_t* ChpeV2ProcessInfo; // _CHPEV2_PROCESS_INFO + + ULONG AppModelFeatureState; + ARRAY_CONTAINER SpareUlongs; + + USHORT ActiveCodePage; + USHORT OemCodePage; + USHORT UseCaseMapping; + USHORT UnusedNlsField; + + std::uint64_t* WerRegistrationData; + std::uint64_t* WerShipAssertPtr; + + PEB_CONTEXT_DATA_UNION64 ContextData; + + std::uint64_t* pImageHeaderHash; + PEB_TRACING_FLAGS_UNION TracingFlags; + + ULONGLONG CsrServerReadOnlySharedMemoryBase; + EMULATOR_CAST(void*, PRTL_CRITICAL_SECTION) TppWorkerpListLock; + LIST_ENTRY64 TppWorkerpList; + ARRAY_CONTAINER WaitOnAddressHashTable; + EMULATOR_CAST(void*, PTELEMETRY_COVERAGE_HEADER) TelemetryCoverageHeader; // REDSTONE3 + ULONG CloudFileFlags; + ULONG CloudFileDiagFlags; // REDSTONE4 + CHAR PlaceholderCompatibilityMode; + ARRAY_CONTAINER PlaceholderCompatibilityModeReserved; + EMULATOR_CAST(void*, PLEAP_SECOND_DATA) LeapSecondData; // REDSTONE5 + PEB_LEAP_SECONDS_FLAG_UNION LeapSecondFlags; + + ULONG NtGlobalFlag2; + ULONGLONG ExtendedFeatureDisableMask; // since WIN11 +} PEB64, *PPEB64; + +typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME64 +{ + struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME* Previous; + EMULATOR_CAST(void*, ACTIVATION_CONTEXT) ActivationContext; + ULONG Flags; // RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_* +} RTL_ACTIVATION_CONTEXT_STACK_FRAME64, *PRTL_ACTIVATION_CONTEXT_STACK_FRAME64; + +typedef struct _ACTIVATION_CONTEXT_STACK64 +{ + PRTL_ACTIVATION_CONTEXT_STACK_FRAME64 ActiveFrame; + LIST_ENTRY64 FrameListCache; + ULONG Flags; // ACTIVATION_CONTEXT_STACK_FLAG_* + ULONG NextCookieSequenceNumber; + ULONG StackId; +} ACTIVATION_CONTEXT_STACK64, *PACTIVATION_CONTEXT_STACK64; + +typedef struct _GDI_TEB_BATCH64 +{ + ULONG Offset; + std::uint64_t* HDC; + ULONG Buffer[GDI_BATCH_BUFFER_SIZE]; +} GDI_TEB_BATCH64, *PGDI_TEB_BATCH64; + +#ifndef OS_WINDOWS +typedef struct _GUID +{ + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +} GUID; + +typedef struct _PROCESSOR_NUMBER +{ + WORD Group; + BYTE Number; + BYTE Reserved; +} PROCESSOR_NUMBER, *PPROCESSOR_NUMBER; + +#endif + +union TEB_CURRENT_IDEAL_PROCESSOR_UNION +{ + PROCESSOR_NUMBER CurrentIdealProcessor; + ULONG IdealProcessorValue; + + struct + { + UCHAR ReservedPad0; + UCHAR ReservedPad1; + UCHAR ReservedPad2; + UCHAR IdealProcessor; + }; +}; + + +union TEB_CROSS_TEB_FLAGS_UNION +{ + USHORT CrossTebFlags; + USHORT SpareCrossTebBits : 16; +}; + +union TEB_SAME_TEB_FLAGS_UNION +{ + USHORT SameTebFlags; + + struct + { + USHORT SafeThunkCall : 1; + USHORT InDebugPrint : 1; + USHORT HasFiberData : 1; + USHORT SkipThreadAttach : 1; + USHORT WerInShipAssertCode : 1; + USHORT RanProcessInit : 1; + USHORT ClonedThread : 1; + USHORT SuppressDebugMsg : 1; + USHORT DisableUserStackWalk : 1; + USHORT RtlExceptionAttached : 1; + USHORT InitialThread : 1; + USHORT SessionAware : 1; + USHORT LoadOwner : 1; + USHORT LoaderWorker : 1; + USHORT SkipLoaderInit : 1; + USHORT SkipFileAPIBrokering : 1; + }; +}; + +#ifndef OS_WINDOWS +using LCID = DWORD; +#endif + +typedef struct _TEB64 +{ + EMU_NT_TIB64 NtTib; + + std::uint64_t* EnvironmentPointer; + CLIENT_ID64 ClientId; + std::uint64_t* ActiveRpcHandle; + std::uint64_t* ThreadLocalStoragePointer; + PPEB64 ProcessEnvironmentBlock; + + ULONG LastErrorValue; + ULONG CountOfOwnedCriticalSections; + std::uint64_t* CsrClientThread; + std::uint64_t* Win32ThreadInfo; + ARRAY_CONTAINER User32Reserved; + ARRAY_CONTAINER UserReserved; + std::uint64_t* WOW32Reserved; + LCID CurrentLocale; + ULONG FpSoftwareStatusRegister; + ARRAY_CONTAINER ReservedForDebuggerInstrumentation; + ARRAY_CONTAINER SystemReserved1; + std::uint64_t* HeapFlsData; + ARRAY_CONTAINER RngState; + CHAR PlaceholderCompatibilityMode; + BOOLEAN PlaceholderHydrationAlwaysExplicit; + ARRAY_CONTAINER PlaceholderReserved; + + ULONG ProxiedProcessId; + ACTIVATION_CONTEXT_STACK64 ActivationStack; + + ARRAY_CONTAINER WorkingOnBehalfTicket; + + NTSTATUS ExceptionCode; + + PACTIVATION_CONTEXT_STACK64 ActivationContextStackPointer; + std::uint64_t* InstrumentationCallbackSp; + std::uint64_t* InstrumentationCallbackPreviousPc; + std::uint64_t* InstrumentationCallbackPreviousSp; + ULONG TxFsContext; + BOOLEAN InstrumentationCallbackDisabled; + BOOLEAN UnalignedLoadStoreExceptions; + GDI_TEB_BATCH64 GdiTebBatch; + CLIENT_ID64 RealClientId; + EmulatorTraits::HANDLE GdiCachedProcessHandle; + ULONG GdiClientPID; + ULONG GdiClientTID; + std::uint64_t* GdiThreadLocalInfo; + ARRAY_CONTAINER Win32ClientInfo; + + ARRAY_CONTAINER glDispatchTable; + ARRAY_CONTAINER glReserved1; + std::uint64_t* glReserved2; + std::uint64_t* glSectionInfo; + std::uint64_t* glSection; + std::uint64_t* glTable; + std::uint64_t* glCurrentRC; + std::uint64_t* glContext; + + NTSTATUS LastStatusValue; + + UNICODE_STRING> StaticUnicodeString; + ARRAY_CONTAINER StaticUnicodeBuffer; + + std::uint64_t* DeallocationStack; + + ARRAY_CONTAINER TlsSlots; + LIST_ENTRY64 TlsLinks; + + std::uint64_t* Vdm; + std::uint64_t* ReservedForNtRpc; + ARRAY_CONTAINER DbgSsReserved; + + ULONG HardErrorMode; + ARRAY_CONTAINER Instrumentation; + GUID ActivityId; + + std::uint64_t* SubProcessTag; + std::uint64_t* PerflibData; + std::uint64_t* EtwTraceData; + std::uint64_t* WinSockData; + ULONG GdiBatchCount; + + TEB_CURRENT_IDEAL_PROCESSOR_UNION CurrentIdealProcessor; + + ULONG GuaranteedStackBytes; + std::uint64_t* ReservedForPerf; + std::uint64_t* ReservedForOle; // tagSOleTlsData + ULONG WaitingOnLoaderLock; + std::uint64_t* SavedPriorityState; + std::uint64_t* ReservedForCodeCoverage; + std::uint64_t* ThreadPoolData; + std::uint64_t** TlsExpansionSlots; + std::uint64_t* ChpeV2CpuAreaInfo; // CHPEV2_CPUAREA_INFO // previously DeallocationBStore + std::uint64_t* Unused; // previously BStoreLimit + ULONG MuiGeneration; + ULONG IsImpersonating; + std::uint64_t* NlsCache; + std::uint64_t* pShimData; + ULONG HeapData; + EmulatorTraits::HANDLE CurrentTransactionHandle; + EMULATOR_CAST(void*, PTEB_ACTIVE_FRAME) ActiveFrame; + std::uint64_t* FlsData; + + std::uint64_t* PreferredLanguages; + std::uint64_t* UserPrefLanguages; + std::uint64_t* MergedPrefLanguages; + ULONG MuiImpersonation; + + TEB_CROSS_TEB_FLAGS_UNION CrossTebFlags; + TEB_SAME_TEB_FLAGS_UNION SameTebFlags; + + std::uint64_t* TxnScopeEnterCallback; + std::uint64_t* TxnScopeExitCallback; + std::uint64_t* TxnScopeContext; + ULONG LockCount; + LONG WowTebOffset; + std::uint64_t* ResourceRetValue; + std::uint64_t* ReservedForWdf; + ULONGLONG ReservedForCrt; + GUID EffectiveContainerId; + ULONGLONG LastSleepCounter; // Win11 + ULONG SpinCallCount; + ULONGLONG ExtendedFeatureDisableMask; + std::uint64_t* SchedulerSharedDataSlot; // 24H2 + std::uint64_t* HeapWalkContext; + EMU_GROUP_AFFINITY64 PrimaryGroupAffinity; + ARRAY_CONTAINER Rcu; +} TEB64, *PTEB64; + +#ifdef OS_WINDOWS +inline TEB64* NtCurrentTeb64(VOID) +{ + return (TEB64*)__readgsqword(FIELD_OFFSET(EMU_NT_TIB64, Self)); +} +#endif + +#pragma pack(push, 4) +typedef struct _KSYSTEM_TIME +{ + ULONG LowPart; + LONG High1Time; + LONG High2Time; +} KSYSTEM_TIME, *PKSYSTEM_TIME; +#pragma pack(pop) + +typedef enum _NT_PRODUCT_TYPE +{ + NtProductWinNt = 1, + NtProductLanManNt, + NtProductServer +} NT_PRODUCT_TYPE, *PNT_PRODUCT_TYPE; + +typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE +{ + StandardDesign, + NEC98x86, + EndAlternatives +} ALTERNATIVE_ARCHITECTURE_TYPE; + +union KUSD_SHARED_DATA_FLAGS_UNION +{ + ULONG SharedDataFlags; + + struct + { + // + // The following bit fields are for the debugger only. Do not use. + // Use the bit definitions instead. + // + + ULONG DbgErrorPortPresent : 1; + ULONG DbgElevationEnabled : 1; + ULONG DbgVirtEnabled : 1; + ULONG DbgInstallerDetectEnabled : 1; + ULONG DbgLkgEnabled : 1; + ULONG DbgDynProcessorEnabled : 1; + ULONG DbgConsoleBrokerEnabled : 1; + ULONG DbgSecureBootEnabled : 1; + ULONG DbgMultiSessionSku : 1; + ULONG DbgMultiUsersInSessionSku : 1; + ULONG DbgStateSeparationEnabled : 1; + ULONG DbgSplitTokenEnabled : 1; + ULONG DbgShadowAdminEnabled : 1; + ULONG SpareBits : 19; + }; +}; + +union KUSD_TICK_COUNT_UNION +{ + volatile KSYSTEM_TIME TickCount; + volatile std::uint64_t TickCountQuad; + + struct + { + ULONG ReservedTickCountOverlay[3]; + ULONG TickCountPad[1]; + }; +}; + +union KUSD_VIRTUALIZATION_FLAGS_UNION +{ + UCHAR VirtualizationFlags; +}; + +union KUSD_MITIGATION_POLICIES_UNION +{ + UCHAR MitigationPolicies; + + struct + { + UCHAR NXSupportPolicy : 2; + UCHAR SEHValidationPolicy : 2; + UCHAR CurDirDevicesSkippedForDlls : 2; + UCHAR Reserved : 2; + }; +}; + +union KUSD_QPC_DATA_UNION +{ + USHORT QpcData; + + struct + { + volatile UCHAR QpcBypassEnabled; + UCHAR QpcReserved; + }; +}; + +#ifndef OS_WINDOWS +#define MAXIMUM_XSTATE_FEATURES 64 + +typedef struct _XSTATE_FEATURE { + ULONG Offset; + ULONG Size; +} XSTATE_FEATURE; + +typedef struct _XSTATE_CONFIGURATION { + std::uint64_t EnabledFeatures; + std::uint64_t EnabledVolatileFeatures; + ULONG Size; + union { + ULONG ControlFlags; + struct { + ULONG OptimizedSave : 1; + ULONG CompactionEnabled : 1; + ULONG Reserved1 : 30; + }; + }; + XSTATE_FEATURE Features[MAXIMUM_XSTATE_FEATURES]; + std::uint64_t EnabledSupervisorFeatures; + std::uint64_t AlignedFeatures; + std::uint64_t AllFeatureSize; + ULONG AllFeatures[MAXIMUM_XSTATE_FEATURES]; +} XSTATE_CONFIGURATION, *PXSTATE_CONFIGURATION; + +#endif + +typedef struct _KUSER_SHARED_DATA64 +{ + ULONG TickCountLowDeprecated; + ULONG TickCountMultiplier; + volatile KSYSTEM_TIME InterruptTime; + volatile KSYSTEM_TIME SystemTime; + volatile KSYSTEM_TIME TimeZoneBias; + USHORT ImageNumberLow; + USHORT ImageNumberHigh; + ARRAY_CONTAINER NtSystemRoot; + ULONG MaxStackTraceDepth; + ULONG CryptoExponent; + ULONG TimeZoneId; + ULONG LargePageMinimum; + ULONG AitSamplingValue; + ULONG AppCompatFlag; + ULONGLONG RNGSeedVersion; + ULONG GlobalValidationRunlevel; + volatile LONG TimeZoneBiasStamp; + ULONG NtBuildNumber; + NT_PRODUCT_TYPE NtProductType; + BOOLEAN ProductTypeIsValid; + BOOLEAN Reserved0; + USHORT NativeProcessorArchitecture; + ULONG NtMajorVersion; + ULONG NtMinorVersion; + ARRAY_CONTAINER ProcessorFeatures; + ULONG Reserved1; + ULONG Reserved3; + volatile ULONG TimeSlip; + ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture; + ULONG BootId; + LARGE_INTEGER SystemExpirationDate; + ULONG SuiteMask; + BOOLEAN KdDebuggerEnabled; + KUSD_MITIGATION_POLICIES_UNION MitigationPolicies; + USHORT CyclesPerYield; + volatile ULONG ActiveConsoleId; + volatile ULONG DismountCount; + ULONG ComPlusPackage; + ULONG LastSystemRITEventTickCount; + ULONG NumberOfPhysicalPages; + BOOLEAN SafeBootMode; + KUSD_VIRTUALIZATION_FLAGS_UNION VirtualizationFlags; + ARRAY_CONTAINER Reserved12; + KUSD_SHARED_DATA_FLAGS_UNION SharedDataFlags; + ULONG DataFlagsPad; + ULONGLONG TestRetInstruction; + LONGLONG QpcFrequency; + ULONG SystemCall; + ULONG Reserved2; + ULONGLONG FullNumberOfPhysicalPages; + ULONGLONG SystemCallPad; + KUSD_TICK_COUNT_UNION TickCount; + ULONG Cookie; + ULONG CookiePad; + LONGLONG ConsoleSessionForegroundProcessId; + ULONGLONG TimeUpdateLock; + ULONGLONG BaselineSystemTimeQpc; + ULONGLONG BaselineInterruptTimeQpc; + ULONGLONG QpcSystemTimeIncrement; + ULONGLONG QpcInterruptTimeIncrement; + UCHAR QpcSystemTimeIncrementShift; + UCHAR QpcInterruptTimeIncrementShift; + USHORT UnparkedProcessorCount; + ARRAY_CONTAINER EnclaveFeatureMask; + ULONG TelemetryCoverageRound; + ARRAY_CONTAINER UserModeGlobalLogger; + ULONG ImageFileExecutionOptions; + ULONG LangGenerationCount; + ULONGLONG Reserved4; + volatile ULONGLONG InterruptTimeBias; + volatile ULONGLONG QpcBias; + ULONG ActiveProcessorCount; + volatile UCHAR ActiveGroupCount; + UCHAR Reserved9; + KUSD_QPC_DATA_UNION QpcData; + LARGE_INTEGER TimeZoneBiasEffectiveStart; + LARGE_INTEGER TimeZoneBiasEffectiveEnd; + XSTATE_CONFIGURATION XState; + KSYSTEM_TIME FeatureConfigurationChangeStamp; + ULONG Spare; + std::uint64_t UserPointerAuthMask; + ARRAY_CONTAINER Reserved10; +} KUSER_SHARED_DATA64, *PKUSER_SHARED_DATA64; + +typedef struct _API_SET_NAMESPACE_ENTRY +{ + ULONG Flags; + ULONG NameOffset; + ULONG NameLength; + ULONG HashedLength; + ULONG ValueOffset; + ULONG ValueCount; +} API_SET_NAMESPACE_ENTRY, *PAPI_SET_NAMESPACE_ENTRY; + +typedef struct _API_SET_HASH_ENTRY +{ + ULONG Hash; + ULONG Index; +} API_SET_HASH_ENTRY, *PAPI_SET_HASH_ENTRY; + +typedef struct _API_SET_VALUE_ENTRY +{ + ULONG Flags; + ULONG NameOffset; + ULONG NameLength; + ULONG ValueOffset; + ULONG ValueLength; +} API_SET_VALUE_ENTRY, *PAPI_SET_VALUE_ENTRY; + +template +struct PS_ATTRIBUTE +{ + typename Traits::ULONG_PTR Attribute; + typename Traits::SIZE_T Size; + + union + { + typename Traits::ULONG_PTR Value; + typename Traits::PVOID ValuePtr; + }; + + typename Traits::SIZE_T* ReturnLength; +}; + +template +struct PS_ATTRIBUTE_LIST +{ + typename Traits::SIZE_T TotalLength; + PS_ATTRIBUTE Attributes[1]; +}; + +typedef struct _SYSTEM_TIMEOFDAY_INFORMATION64 +{ + LARGE_INTEGER BootTime; + LARGE_INTEGER CurrentTime; + LARGE_INTEGER TimeZoneBias; + ULONG TimeZoneId; + ULONG Reserved; + ULONGLONG BootTimeBias; + ULONGLONG SleepTimeBias; +} SYSTEM_TIMEOFDAY_INFORMATION64, *PSYSTEM_TIMEOFDAY_INFORMATION64; + +typedef struct _PROCESS_BASIC_INFORMATION64 +{ + NTSTATUS ExitStatus; + PPEB64 PebBaseAddress; + EMULATOR_CAST(std::uint64_t, KAFFINITY) AffinityMask; + EMULATOR_CAST(std::uint32_t, KPRIORITY) BasePriority; + EMULATOR_CAST(std::uint64_t, HANDLE) UniqueProcessId; + EMULATOR_CAST(std::uint64_t, HANDLE) InheritedFromUniqueProcessId; +} PROCESS_BASIC_INFORMATION64, *PPROCESS_BASIC_INFORMATION64; + +typedef struct _KERNEL_USER_TIMES +{ + LARGE_INTEGER CreateTime; + LARGE_INTEGER ExitTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; +} KERNEL_USER_TIMES, *PKERNEL_USER_TIMES; + +struct THREAD_TLS_INFO +{ + ULONG Flags; + + union + { + EmulatorTraits::PVOID* TlsVector; + EmulatorTraits::PVOID TlsModulePointer; + }; + + EMULATOR_CAST(std::uint64_t, ULONG_PTR) ThreadId; +}; + +static_assert(sizeof(THREAD_TLS_INFO) == 0x18); + +typedef enum _PROCESS_TLS_INFORMATION_TYPE +{ + ProcessTlsReplaceIndex, + ProcessTlsReplaceVector, + MaxProcessTlsOperation +} PROCESS_TLS_INFORMATION_TYPE, *PPROCESS_TLS_INFORMATION_TYPE; + +struct PROCESS_TLS_INFO +{ + ULONG Unknown; + PROCESS_TLS_INFORMATION_TYPE TlsRequest; + ULONG ThreadDataCount; + + union + { + ULONG TlsIndex; + ULONG TlsVectorLength; + }; + + THREAD_TLS_INFO ThreadData[1]; +}; + +static_assert(sizeof(PROCESS_TLS_INFO) - sizeof(THREAD_TLS_INFO) == 0x10); diff --git a/src/common/platform/memory.hpp b/src/common/platform/memory.hpp new file mode 100644 index 00000000..8d8758c0 --- /dev/null +++ b/src/common/platform/memory.hpp @@ -0,0 +1,131 @@ +#pragma once + +#define PAGE_EXECUTE 0x10 +#define PAGE_EXECUTE_READ 0x20 +#define PAGE_EXECUTE_READWRITE 0x40 +#define PAGE_EXECUTE_WRITECOPY 0x80 + +#define PAGE_NOACCESS 0x01 +#define PAGE_READONLY 0x02 +#define PAGE_READWRITE 0x04 +#define PAGE_WRITECOPY 0x08 + +#define PAGE_TARGETS_INVALID 0x40000000 +#define PAGE_TARGETS_NO_UPDATE 0x40000000 + +#define PAGE_GUARD 0x100 +#define PAGE_NOCACHE 0x200 +#define PAGE_WRITECOMBINE 0x400 + +#define MEM_COMMIT 0x00001000 +#define MEM_RESERVE 0x00002000 +#define MEM_DECOMMIT 0x00004000 +#define MEM_RELEASE 0x00008000 +#define MEM_FREE 0x00010000 +#define MEM_PRIVATE 0x00020000 +#define MEM_MAPPED 0x00040000 +#define MEM_RESET 0x00080000 +#define MEM_TOP_DOWN 0x00100000 +#define MEM_WRITE_WATCH 0x00200000 +#define MEM_PHYSICAL 0x00400000 +#define MEM_ROTATE 0x00800000 +#define MEM_DIFFERENT_IMAGE_BASE_OK 0x00800000 +#define MEM_RESET_UNDO 0x01000000 +#define MEM_LARGE_PAGES 0x20000000 +#define MEM_DOS_LIM 0x40000000 +#define MEM_4MB_PAGES 0x80000000 +#define MEM_64K_PAGES (MEM_LARGE_PAGES | MEM_PHYSICAL) + +typedef enum _MEMORY_INFORMATION_CLASS +{ + MemoryBasicInformation, // q: MEMORY_BASIC_INFORMATION + MemoryWorkingSetInformation, // q: MEMORY_WORKING_SET_INFORMATION + MemoryMappedFilenameInformation, // q: UNICODE_STRING + MemoryRegionInformation, // q: MEMORY_REGION_INFORMATION + MemoryWorkingSetExInformation, // q: MEMORY_WORKING_SET_EX_INFORMATION // since VISTA + MemorySharedCommitInformation, // q: MEMORY_SHARED_COMMIT_INFORMATION // since WIN8 + MemoryImageInformation, // q: MEMORY_IMAGE_INFORMATION + MemoryRegionInformationEx, // MEMORY_REGION_INFORMATION + MemoryPrivilegedBasicInformation, // MEMORY_BASIC_INFORMATION + MemoryEnclaveImageInformation, // MEMORY_ENCLAVE_IMAGE_INFORMATION // since REDSTONE3 + MemoryBasicInformationCapped, // 10 + MemoryPhysicalContiguityInformation, // MEMORY_PHYSICAL_CONTIGUITY_INFORMATION // since 20H1 + MemoryBadInformation, // since WIN11 + MemoryBadInformationAllProcesses, // since 22H1 + MemoryImageExtensionInformation, // since 24H2 + MaxMemoryInfoClass +} MEMORY_INFORMATION_CLASS; + +typedef enum _SECTION_INHERIT +{ + ViewShare = 1, + ViewUnmap = 2 +} SECTION_INHERIT; + + +typedef struct DECLSPEC_ALIGN(16) _EMU_MEMORY_BASIC_INFORMATION64 +{ + void* BaseAddress; + void* AllocationBase; + DWORD AllocationProtect; + WORD PartitionId; + std::int64_t RegionSize; + DWORD State; + DWORD Protect; + DWORD Type; +} EMU_MEMORY_BASIC_INFORMATION64, *PEMU_MEMORY_BASIC_INFORMATION64; + + +typedef struct _MEMORY_IMAGE_INFORMATION64 +{ + void* ImageBase; + std::int64_t SizeOfImage; + + union + { + ULONG ImageFlags; + + struct + { + ULONG ImagePartialMap : 1; + ULONG ImageNotExecutable : 1; + ULONG ImageSigningLevel : 4; // REDSTONE3 + ULONG ImageExtensionPresent : 1; // since 24H2 + ULONG Reserved : 25; + }; + }; +} MEMORY_IMAGE_INFORMATION64, *PMEMORY_IMAGE_INFORMATION64; + +typedef struct _MEMORY_REGION_INFORMATION +{ + void* AllocationBase; + ULONG AllocationProtect; + + union + { + ULONG RegionType; + + struct + { + ULONG Private : 1; + ULONG MappedDataFile : 1; + ULONG MappedImage : 1; + ULONG MappedPageFile : 1; + ULONG MappedPhysical : 1; + ULONG DirectMapped : 1; + ULONG SoftwareEnclave : 1; // REDSTONE3 + ULONG PageSize64K : 1; + ULONG PlaceholderReservation : 1; // REDSTONE4 + ULONG MappedAwe : 1; // 21H1 + ULONG MappedWriteWatch : 1; + ULONG PageSizeLarge : 1; + ULONG PageSizeHuge : 1; + ULONG Reserved : 19; + }; + }; + + std::int64_t RegionSize; + std::int64_t CommitSize; + DWORD64 PartitionId; // 19H1 + DWORD64 NodePreference; // 20H1 +} MEMORY_REGION_INFORMATION64, *PMEMORY_REGION_INFORMATION64; diff --git a/src/common/platform/network.hpp b/src/common/platform/network.hpp new file mode 100644 index 00000000..2e14c0a5 --- /dev/null +++ b/src/common/platform/network.hpp @@ -0,0 +1,8 @@ +#pragma once + +template +struct EMU_WSABUF +{ + ULONG len; + EMULATOR_CAST(typename Traits::PVOID, CHAR*) buf; +}; diff --git a/src/common/platform/platform.hpp b/src/common/platform/platform.hpp new file mode 100644 index 00000000..a8730fd9 --- /dev/null +++ b/src/common/platform/platform.hpp @@ -0,0 +1,46 @@ +#pragma once + +#ifdef _WIN32 +#pragma warning(push) +#pragma warning(disable: 4201) // nameless struct/union +#pragma warning(disable: 4702) // unreachable code +#else +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + +#include "compiler.hpp" +#include "primitives.hpp" +#include "traits.hpp" +#include "unicode.hpp" +#include "status.hpp" +#include "process.hpp" +#include "kernel_mapped.hpp" +#include "memory.hpp" +#include "file_management.hpp" +#include "win_pefile.hpp" +#include "synchronisation.hpp" +#include "registry.hpp" +#include "network.hpp" +#include "threading.hpp" + +#ifdef OS_WINDOWS +#pragma comment(lib, "ntdll") + +extern "C" { +NTSYSCALLAPI +NTSTATUS +NTAPI +NtQuerySystemInformationEx( + _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, + _In_reads_bytes_(InputBufferLength) PVOID InputBuffer, + _In_ ULONG InputBufferLength, + _Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation, + _In_ ULONG SystemInformationLength, + _Out_opt_ PULONG ReturnLength +); +} +#pragma warning(pop) +#else +#pragma GCC diagnostic pop +#endif diff --git a/src/common/platform/primitives.hpp b/src/common/platform/primitives.hpp new file mode 100644 index 00000000..3fdb937d --- /dev/null +++ b/src/common/platform/primitives.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include + +#ifdef OS_WINDOWS + +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include +#include "winnt.h" + +#else + +#define DWORD std::uint32_t +using LONG = std::int32_t; +using ULONG = DWORD; +using DWORD64 = std::uint64_t; +using ULONGLONG = DWORD64; +using LONGLONG = std::int64_t; + +typedef union _ULARGE_INTEGER +{ + struct + { + DWORD LowPart; + DWORD HighPart; + }; + + ULONGLONG QuadPart; +} ULARGE_INTEGER; + +typedef union _LARGE_INTEGER +{ + struct + { + DWORD LowPart; + LONG HighPart; + }; + + LONGLONG QuadPart; +} LARGE_INTEGER; + +using BYTE = std::uint8_t; +#define CHAR BYTE +#endif + + +using WORD = std::uint16_t; + +#define UCHAR unsigned char + +#define BOOLEAN bool +using CSHORT = short; +using USHORT = WORD; + + +#define DUMMYSTRUCTNAME + +#ifndef TRUE +#define TRUE true +#define FALSE false +#endif diff --git a/src/common/platform/process.hpp b/src/common/platform/process.hpp new file mode 100644 index 00000000..f4333648 --- /dev/null +++ b/src/common/platform/process.hpp @@ -0,0 +1,890 @@ +#pragma once + +#define CONTEXT_X86_MAIN 0x00010000 +#define CONTEXT_AMD64_MAIN 0x100000 +#define CONTEXT_CONTROL_32 (CONTEXT_X86_MAIN | 0x1L) +#define CONTEXT_CONTROL_64 (CONTEXT_AMD64_MAIN | 0x1L) +#define CONTEXT_INTEGER_32 (CONTEXT_X86_MAIN | 0x2L) +#define CONTEXT_INTEGER_64 (CONTEXT_AMD64_MAIN | 0x2L) +#define CONTEXT_SEGMENTS_32 (CONTEXT_X86_MAIN | 0x4L) +#define CONTEXT_SEGMENTS_64 (CONTEXT_AMD64_MAIN | 0x4L) +#define CONTEXT_FLOATING_POINT_32 (CONTEXT_X86_MAIN | 0x8L) +#define CONTEXT_FLOATING_POINT_64 (CONTEXT_AMD64_MAIN | 0x8L) +#define CONTEXT_DEBUG_REGISTERS_32 (CONTEXT_X86_MAIN | 0x10L) +#define CONTEXT_DEBUG_REGISTERS_64 (CONTEXT_AMD64_MAIN | 0x10L) +#define CONTEXT_XSTATE_32 (CONTEXT_X86_MAIN | 0x20L) +#define CONTEXT_XSTATE_64 (CONTEXT_AMD64_MAIN | 0x20L) + +#define CONTEXT64_ALL (CONTEXT_CONTROL_64 | CONTEXT_INTEGER_64 | CONTEXT_SEGMENTS_64 | \ + CONTEXT_FLOATING_POINT_64 | CONTEXT_DEBUG_REGISTERS_64) + + +typedef enum _SYSTEM_INFORMATION_CLASS +{ + SystemBasicInformation, // q: SYSTEM_BASIC_INFORMATION + SystemProcessorInformation, // q: SYSTEM_PROCESSOR_INFORMATION + SystemPerformanceInformation, // q: SYSTEM_PERFORMANCE_INFORMATION + SystemTimeOfDayInformation, // q: SYSTEM_TIMEOFDAY_INFORMATION + SystemPathInformation, // not implemented + SystemProcessInformation, // q: SYSTEM_PROCESS_INFORMATION + SystemCallCountInformation, // q: SYSTEM_CALL_COUNT_INFORMATION + SystemDeviceInformation, // q: SYSTEM_DEVICE_INFORMATION + SystemProcessorPerformanceInformation, // q: SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION (EX in: USHORT ProcessorGroup) + SystemFlagsInformation, // q: SYSTEM_FLAGS_INFORMATION + SystemCallTimeInformation, // not implemented // SYSTEM_CALL_TIME_INFORMATION // 10 + SystemModuleInformation, // q: RTL_PROCESS_MODULES + SystemLocksInformation, // q: RTL_PROCESS_LOCKS + SystemStackTraceInformation, // q: RTL_PROCESS_BACKTRACES + SystemPagedPoolInformation, // not implemented + SystemNonPagedPoolInformation, // not implemented + SystemHandleInformation, // q: SYSTEM_HANDLE_INFORMATION + SystemObjectInformation, // q: SYSTEM_OBJECTTYPE_INFORMATION mixed with SYSTEM_OBJECT_INFORMATION + SystemPageFileInformation, // q: SYSTEM_PAGEFILE_INFORMATION + SystemVdmInstemulInformation, // q: SYSTEM_VDM_INSTEMUL_INFO + SystemVdmBopInformation, // not implemented // 20 + SystemFileCacheInformation, + // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (info for WorkingSetTypeSystemCache) + SystemPoolTagInformation, // q: SYSTEM_POOLTAG_INFORMATION + SystemInterruptInformation, // q: SYSTEM_INTERRUPT_INFORMATION (EX in: USHORT ProcessorGroup) + SystemDpcBehaviorInformation, + // q: SYSTEM_DPC_BEHAVIOR_INFORMATION; s: SYSTEM_DPC_BEHAVIOR_INFORMATION (requires SeLoadDriverPrivilege) + SystemFullMemoryInformation, // not implemented // SYSTEM_MEMORY_USAGE_INFORMATION + SystemLoadGdiDriverInformation, // s (kernel-mode only) + SystemUnloadGdiDriverInformation, // s (kernel-mode only) + SystemTimeAdjustmentInformation, + // q: SYSTEM_QUERY_TIME_ADJUST_INFORMATION; s: SYSTEM_SET_TIME_ADJUST_INFORMATION (requires SeSystemtimePrivilege) + SystemSummaryMemoryInformation, // not implemented // SYSTEM_MEMORY_USAGE_INFORMATION + SystemMirrorMemoryInformation, + // s (requires license value "Kernel-MemoryMirroringSupported") (requires SeShutdownPrivilege) // 30 + SystemPerformanceTraceInformation, // q; s: (type depends on EVENT_TRACE_INFORMATION_CLASS) + SystemObsolete0, // not implemented + SystemExceptionInformation, // q: SYSTEM_EXCEPTION_INFORMATION + SystemCrashDumpStateInformation, // s: SYSTEM_CRASH_DUMP_STATE_INFORMATION (requires SeDebugPrivilege) + SystemKernelDebuggerInformation, // q: SYSTEM_KERNEL_DEBUGGER_INFORMATION + SystemContextSwitchInformation, // q: SYSTEM_CONTEXT_SWITCH_INFORMATION + SystemRegistryQuotaInformation, // q: SYSTEM_REGISTRY_QUOTA_INFORMATION; s (requires SeIncreaseQuotaPrivilege) + SystemExtendServiceTableInformation, // s (requires SeLoadDriverPrivilege) // loads win32k only + SystemPrioritySeperation, // s (requires SeTcbPrivilege) + SystemVerifierAddDriverInformation, // s (requires SeDebugPrivilege) // 40 + SystemVerifierRemoveDriverInformation, // s (requires SeDebugPrivilege) + SystemProcessorIdleInformation, // q: SYSTEM_PROCESSOR_IDLE_INFORMATION (EX in: USHORT ProcessorGroup) + SystemLegacyDriverInformation, // q: SYSTEM_LEGACY_DRIVER_INFORMATION + SystemCurrentTimeZoneInformation, // q; s: RTL_TIME_ZONE_INFORMATION + SystemLookasideInformation, // q: SYSTEM_LOOKASIDE_INFORMATION + SystemTimeSlipNotification, // s: HANDLE (NtCreateEvent) (requires SeSystemtimePrivilege) + SystemSessionCreate, // not implemented + SystemSessionDetach, // not implemented + SystemSessionInformation, // not implemented (SYSTEM_SESSION_INFORMATION) + SystemRangeStartInformation, // q: SYSTEM_RANGE_START_INFORMATION // 50 + SystemVerifierInformation, // q: SYSTEM_VERIFIER_INFORMATION; s (requires SeDebugPrivilege) + SystemVerifierThunkExtend, // s (kernel-mode only) + SystemSessionProcessInformation, // q: SYSTEM_SESSION_PROCESS_INFORMATION + SystemLoadGdiDriverInSystemSpace, + // s: SYSTEM_GDI_DRIVER_INFORMATION (kernel-mode only) (same as SystemLoadGdiDriverInformation) + SystemNumaProcessorMap, // q: SYSTEM_NUMA_INFORMATION + SystemPrefetcherInformation, // q; s: PREFETCHER_INFORMATION // PfSnQueryPrefetcherInformation + SystemExtendedProcessInformation, // q: SYSTEM_PROCESS_INFORMATION + SystemRecommendedSharedDataAlignment, // q: ULONG // KeGetRecommendedSharedDataAlignment + SystemComPlusPackage, // q; s: ULONG + SystemNumaAvailableMemory, // q: SYSTEM_NUMA_INFORMATION // 60 + SystemProcessorPowerInformation, // q: SYSTEM_PROCESSOR_POWER_INFORMATION (EX in: USHORT ProcessorGroup) + SystemEmulationBasicInformation, // q: SYSTEM_BASIC_INFORMATION + SystemEmulationProcessorInformation, // q: SYSTEM_PROCESSOR_INFORMATION + SystemExtendedHandleInformation, // q: SYSTEM_HANDLE_INFORMATION_EX + SystemLostDelayedWriteInformation, // q: ULONG + SystemBigPoolInformation, // q: SYSTEM_BIGPOOL_INFORMATION + SystemSessionPoolTagInformation, // q: SYSTEM_SESSION_POOLTAG_INFORMATION + SystemSessionMappedViewInformation, // q: SYSTEM_SESSION_MAPPED_VIEW_INFORMATION + SystemHotpatchInformation, // q; s: SYSTEM_HOTPATCH_CODE_INFORMATION + SystemObjectSecurityMode, // q: ULONG // 70 + SystemWatchdogTimerHandler, // s: SYSTEM_WATCHDOG_HANDLER_INFORMATION // (kernel-mode only) + SystemWatchdogTimerInformation, // q: SYSTEM_WATCHDOG_TIMER_INFORMATION // (kernel-mode only) + SystemLogicalProcessorInformation, // q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION (EX in: USHORT ProcessorGroup) + SystemWow64SharedInformationObsolete, // not implemented + SystemRegisterFirmwareTableInformationHandler, // s: SYSTEM_FIRMWARE_TABLE_HANDLER // (kernel-mode only) + SystemFirmwareTableInformation, // SYSTEM_FIRMWARE_TABLE_INFORMATION + SystemModuleInformationEx, // q: RTL_PROCESS_MODULE_INFORMATION_EX + SystemVerifierTriageInformation, // not implemented + SystemSuperfetchInformation, // q; s: SUPERFETCH_INFORMATION // PfQuerySuperfetchInformation + SystemMemoryListInformation, + // q: SYSTEM_MEMORY_LIST_INFORMATION; s: SYSTEM_MEMORY_LIST_COMMAND (requires SeProfileSingleProcessPrivilege) // 80 + SystemFileCacheInformationEx, + // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (same as SystemFileCacheInformation) + SystemThreadPriorityClientIdInformation, + // s: SYSTEM_THREAD_CID_PRIORITY_INFORMATION (requires SeIncreaseBasePriorityPrivilege) + SystemProcessorIdleCycleTimeInformation, + // q: SYSTEM_PROCESSOR_IDLE_CYCLE_TIME_INFORMATION[] (EX in: USHORT ProcessorGroup) + SystemVerifierCancellationInformation, + // SYSTEM_VERIFIER_CANCELLATION_INFORMATION // name:wow64:whNT32QuerySystemVerifierCancellationInformation + SystemProcessorPowerInformationEx, // not implemented + SystemRefTraceInformation, // q; s: SYSTEM_REF_TRACE_INFORMATION // ObQueryRefTraceInformation + SystemSpecialPoolInformation, + // q; s: SYSTEM_SPECIAL_POOL_INFORMATION (requires SeDebugPrivilege) // MmSpecialPoolTag, then MmSpecialPoolCatchOverruns != 0 + SystemProcessIdInformation, // q: SYSTEM_PROCESS_ID_INFORMATION + SystemErrorPortInformation, // s (requires SeTcbPrivilege) + SystemBootEnvironmentInformation, // q: SYSTEM_BOOT_ENVIRONMENT_INFORMATION // 90 + SystemHypervisorInformation, // q: SYSTEM_HYPERVISOR_QUERY_INFORMATION + SystemVerifierInformationEx, // q; s: SYSTEM_VERIFIER_INFORMATION_EX + SystemTimeZoneInformation, // q; s: RTL_TIME_ZONE_INFORMATION (requires SeTimeZonePrivilege) + SystemImageFileExecutionOptionsInformation, + // s: SYSTEM_IMAGE_FILE_EXECUTION_OPTIONS_INFORMATION (requires SeTcbPrivilege) + SystemCoverageInformation, + // q: COVERAGE_MODULES s: COVERAGE_MODULE_REQUEST // ExpCovQueryInformation (requires SeDebugPrivilege) + SystemPrefetchPatchInformation, // SYSTEM_PREFETCH_PATCH_INFORMATION + SystemVerifierFaultsInformation, // s: SYSTEM_VERIFIER_FAULTS_INFORMATION (requires SeDebugPrivilege) + SystemSystemPartitionInformation, // q: SYSTEM_SYSTEM_PARTITION_INFORMATION + SystemSystemDiskInformation, // q: SYSTEM_SYSTEM_DISK_INFORMATION + SystemProcessorPerformanceDistribution, + // q: SYSTEM_PROCESSOR_PERFORMANCE_DISTRIBUTION (EX in: USHORT ProcessorGroup) // 100 + SystemNumaProximityNodeInformation, // q; s: SYSTEM_NUMA_PROXIMITY_MAP + SystemDynamicTimeZoneInformation, // q; s: RTL_DYNAMIC_TIME_ZONE_INFORMATION (requires SeTimeZonePrivilege) + SystemCodeIntegrityInformation, // q: SYSTEM_CODEINTEGRITY_INFORMATION // SeCodeIntegrityQueryInformation + SystemProcessorMicrocodeUpdateInformation, // s: SYSTEM_PROCESSOR_MICROCODE_UPDATE_INFORMATION + SystemProcessorBrandString, // q: CHAR[] // HaliQuerySystemInformation -> HalpGetProcessorBrandString, info class 23 + SystemVirtualAddressInformation, + // q: SYSTEM_VA_LIST_INFORMATION[]; s: SYSTEM_VA_LIST_INFORMATION[] (requires SeIncreaseQuotaPrivilege) // MmQuerySystemVaInformation + SystemLogicalProcessorAndGroupInformation, + // q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX (EX in: LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType) // since WIN7 // KeQueryLogicalProcessorRelationship + SystemProcessorCycleTimeInformation, // q: SYSTEM_PROCESSOR_CYCLE_TIME_INFORMATION[] (EX in: USHORT ProcessorGroup) + SystemStoreInformation, + // q; s: SYSTEM_STORE_INFORMATION (requires SeProfileSingleProcessPrivilege) // SmQueryStoreInformation + SystemRegistryAppendString, // s: SYSTEM_REGISTRY_APPEND_STRING_PARAMETERS // 110 + SystemAitSamplingValue, // s: ULONG (requires SeProfileSingleProcessPrivilege) + SystemVhdBootInformation, // q: SYSTEM_VHD_BOOT_INFORMATION + SystemCpuQuotaInformation, // q; s: PS_CPU_QUOTA_QUERY_INFORMATION + SystemNativeBasicInformation, // q: SYSTEM_BASIC_INFORMATION + SystemErrorPortTimeouts, // SYSTEM_ERROR_PORT_TIMEOUTS + SystemLowPriorityIoInformation, // q: SYSTEM_LOW_PRIORITY_IO_INFORMATION + SystemTpmBootEntropyInformation, // q: TPM_BOOT_ENTROPY_NT_RESULT // ExQueryTpmBootEntropyInformation + SystemVerifierCountersInformation, // q: SYSTEM_VERIFIER_COUNTERS_INFORMATION + SystemPagedPoolInformationEx, + // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (info for WorkingSetTypePagedPool) + SystemSystemPtesInformationEx, + // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (info for WorkingSetTypeSystemPtes) // 120 + SystemNodeDistanceInformation, // q: USHORT[4*NumaNodes] // (EX in: USHORT NodeNumber) + SystemAcpiAuditInformation, + // q: SYSTEM_ACPI_AUDIT_INFORMATION // HaliQuerySystemInformation -> HalpAuditQueryResults, info class 26 + SystemBasicPerformanceInformation, + // q: SYSTEM_BASIC_PERFORMANCE_INFORMATION // name:wow64:whNtQuerySystemInformation_SystemBasicPerformanceInformation + SystemQueryPerformanceCounterInformation, // q: SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION // since WIN7 SP1 + SystemSessionBigPoolInformation, // q: SYSTEM_SESSION_POOLTAG_INFORMATION // since WIN8 + SystemBootGraphicsInformation, // q; s: SYSTEM_BOOT_GRAPHICS_INFORMATION (kernel-mode only) + SystemScrubPhysicalMemoryInformation, // q; s: MEMORY_SCRUB_INFORMATION + SystemBadPageInformation, // SYSTEM_BAD_PAGE_INFORMATION + SystemProcessorProfileControlArea, // q; s: SYSTEM_PROCESSOR_PROFILE_CONTROL_AREA + SystemCombinePhysicalMemoryInformation, + // s: MEMORY_COMBINE_INFORMATION, MEMORY_COMBINE_INFORMATION_EX, MEMORY_COMBINE_INFORMATION_EX2 // 130 + SystemEntropyInterruptTimingInformation, // q; s: SYSTEM_ENTROPY_TIMING_INFORMATION + SystemConsoleInformation, // q; s: SYSTEM_CONSOLE_INFORMATION + SystemPlatformBinaryInformation, // q: SYSTEM_PLATFORM_BINARY_INFORMATION (requires SeTcbPrivilege) + SystemPolicyInformation, // q: SYSTEM_POLICY_INFORMATION (Warbird/Encrypt/Decrypt/Execute) + SystemHypervisorProcessorCountInformation, // q: SYSTEM_HYPERVISOR_PROCESSOR_COUNT_INFORMATION + SystemDeviceDataInformation, // q: SYSTEM_DEVICE_DATA_INFORMATION + SystemDeviceDataEnumerationInformation, // q: SYSTEM_DEVICE_DATA_INFORMATION + SystemMemoryTopologyInformation, // q: SYSTEM_MEMORY_TOPOLOGY_INFORMATION + SystemMemoryChannelInformation, // q: SYSTEM_MEMORY_CHANNEL_INFORMATION + SystemBootLogoInformation, // q: SYSTEM_BOOT_LOGO_INFORMATION // 140 + SystemProcessorPerformanceInformationEx, + // q: SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_EX // (EX in: USHORT ProcessorGroup) // since WINBLUE + SystemCriticalProcessErrorLogInformation, + SystemSecureBootPolicyInformation, // q: SYSTEM_SECUREBOOT_POLICY_INFORMATION + SystemPageFileInformationEx, // q: SYSTEM_PAGEFILE_INFORMATION_EX + SystemSecureBootInformation, // q: SYSTEM_SECUREBOOT_INFORMATION + SystemEntropyInterruptTimingRawInformation, + SystemPortableWorkspaceEfiLauncherInformation, // q: SYSTEM_PORTABLE_WORKSPACE_EFI_LAUNCHER_INFORMATION + SystemFullProcessInformation, + // q: SYSTEM_PROCESS_INFORMATION with SYSTEM_PROCESS_INFORMATION_EXTENSION (requires admin) + SystemKernelDebuggerInformationEx, // q: SYSTEM_KERNEL_DEBUGGER_INFORMATION_EX + SystemBootMetadataInformation, // 150 + SystemSoftRebootInformation, // q: ULONG + SystemElamCertificateInformation, // s: SYSTEM_ELAM_CERTIFICATE_INFORMATION + SystemOfflineDumpConfigInformation, // q: OFFLINE_CRASHDUMP_CONFIGURATION_TABLE_V2 + SystemProcessorFeaturesInformation, // q: SYSTEM_PROCESSOR_FEATURES_INFORMATION + SystemRegistryReconciliationInformation, // s: NULL (requires admin) (flushes registry hives) + SystemEdidInformation, // q: SYSTEM_EDID_INFORMATION + SystemManufacturingInformation, // q: SYSTEM_MANUFACTURING_INFORMATION // since THRESHOLD + SystemEnergyEstimationConfigInformation, // q: SYSTEM_ENERGY_ESTIMATION_CONFIG_INFORMATION + SystemHypervisorDetailInformation, // q: SYSTEM_HYPERVISOR_DETAIL_INFORMATION + SystemProcessorCycleStatsInformation, + // q: SYSTEM_PROCESSOR_CYCLE_STATS_INFORMATION (EX in: USHORT ProcessorGroup) // 160 + SystemVmGenerationCountInformation, + SystemTrustedPlatformModuleInformation, // q: SYSTEM_TPM_INFORMATION + SystemKernelDebuggerFlags, // SYSTEM_KERNEL_DEBUGGER_FLAGS + SystemCodeIntegrityPolicyInformation, // q; s: SYSTEM_CODEINTEGRITYPOLICY_INFORMATION + SystemIsolatedUserModeInformation, // q: SYSTEM_ISOLATED_USER_MODE_INFORMATION + SystemHardwareSecurityTestInterfaceResultsInformation, + SystemSingleModuleInformation, // q: SYSTEM_SINGLE_MODULE_INFORMATION + SystemAllowedCpuSetsInformation, // s: SYSTEM_WORKLOAD_ALLOWED_CPU_SET_INFORMATION + SystemVsmProtectionInformation, // q: SYSTEM_VSM_PROTECTION_INFORMATION (previously SystemDmaProtectionInformation) + SystemInterruptCpuSetsInformation, // q: SYSTEM_INTERRUPT_CPU_SET_INFORMATION // 170 + SystemSecureBootPolicyFullInformation, // q: SYSTEM_SECUREBOOT_POLICY_FULL_INFORMATION + SystemCodeIntegrityPolicyFullInformation, + SystemAffinitizedInterruptProcessorInformation, // (requires SeIncreaseBasePriorityPrivilege) + SystemRootSiloInformation, // q: SYSTEM_ROOT_SILO_INFORMATION + SystemCpuSetInformation, // q: SYSTEM_CPU_SET_INFORMATION // since THRESHOLD2 + SystemCpuSetTagInformation, // q: SYSTEM_CPU_SET_TAG_INFORMATION + SystemWin32WerStartCallout, + SystemSecureKernelProfileInformation, // q: SYSTEM_SECURE_KERNEL_HYPERGUARD_PROFILE_INFORMATION + SystemCodeIntegrityPlatformManifestInformation, + // q: SYSTEM_SECUREBOOT_PLATFORM_MANIFEST_INFORMATION // since REDSTONE + SystemInterruptSteeringInformation, + // q: in: SYSTEM_INTERRUPT_STEERING_INFORMATION_INPUT, out: SYSTEM_INTERRUPT_STEERING_INFORMATION_OUTPUT // NtQuerySystemInformationEx // 180 + SystemSupportedProcessorArchitectures, + // p: in opt: HANDLE, out: SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION[] // NtQuerySystemInformationEx + SystemMemoryUsageInformation, // q: SYSTEM_MEMORY_USAGE_INFORMATION + SystemCodeIntegrityCertificateInformation, // q: SYSTEM_CODEINTEGRITY_CERTIFICATE_INFORMATION + SystemPhysicalMemoryInformation, // q: SYSTEM_PHYSICAL_MEMORY_INFORMATION // since REDSTONE2 + SystemControlFlowTransition, // (Warbird/Encrypt/Decrypt/Execute) + SystemKernelDebuggingAllowed, // s: ULONG + SystemActivityModerationExeState, // SYSTEM_ACTIVITY_MODERATION_EXE_STATE + SystemActivityModerationUserSettings, // SYSTEM_ACTIVITY_MODERATION_USER_SETTINGS + SystemCodeIntegrityPoliciesFullInformation, + SystemCodeIntegrityUnlockInformation, // SYSTEM_CODEINTEGRITY_UNLOCK_INFORMATION // 190 + SystemIntegrityQuotaInformation, + SystemFlushInformation, // q: SYSTEM_FLUSH_INFORMATION + SystemProcessorIdleMaskInformation, // q: ULONG_PTR[ActiveGroupCount] // since REDSTONE3 + SystemSecureDumpEncryptionInformation, + SystemWriteConstraintInformation, // SYSTEM_WRITE_CONSTRAINT_INFORMATION + SystemKernelVaShadowInformation, // SYSTEM_KERNEL_VA_SHADOW_INFORMATION + SystemHypervisorSharedPageInformation, // SYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION // since REDSTONE4 + SystemFirmwareBootPerformanceInformation, + SystemCodeIntegrityVerificationInformation, // SYSTEM_CODEINTEGRITYVERIFICATION_INFORMATION + SystemFirmwarePartitionInformation, // SYSTEM_FIRMWARE_PARTITION_INFORMATION // 200 + SystemSpeculationControlInformation, + // SYSTEM_SPECULATION_CONTROL_INFORMATION // (CVE-2017-5715) REDSTONE3 and above. + SystemDmaGuardPolicyInformation, // SYSTEM_DMA_GUARD_POLICY_INFORMATION + SystemEnclaveLaunchControlInformation, // SYSTEM_ENCLAVE_LAUNCH_CONTROL_INFORMATION + SystemWorkloadAllowedCpuSetsInformation, // SYSTEM_WORKLOAD_ALLOWED_CPU_SET_INFORMATION // since REDSTONE5 + SystemCodeIntegrityUnlockModeInformation, // SYSTEM_CODEINTEGRITY_UNLOCK_INFORMATION + SystemLeapSecondInformation, // SYSTEM_LEAP_SECOND_INFORMATION + SystemFlags2Information, // q: SYSTEM_FLAGS_INFORMATION + SystemSecurityModelInformation, // SYSTEM_SECURITY_MODEL_INFORMATION // since 19H1 + SystemCodeIntegritySyntheticCacheInformation, + SystemFeatureConfigurationInformation, + // q: in: SYSTEM_FEATURE_CONFIGURATION_QUERY, out: SYSTEM_FEATURE_CONFIGURATION_INFORMATION; s: SYSTEM_FEATURE_CONFIGURATION_UPDATE // NtQuerySystemInformationEx // since 20H1 // 210 + SystemFeatureConfigurationSectionInformation, + // q: in: SYSTEM_FEATURE_CONFIGURATION_SECTIONS_REQUEST, out: SYSTEM_FEATURE_CONFIGURATION_SECTIONS_INFORMATION // NtQuerySystemInformationEx + SystemFeatureUsageSubscriptionInformation, + // q: SYSTEM_FEATURE_USAGE_SUBSCRIPTION_DETAILS; s: SYSTEM_FEATURE_USAGE_SUBSCRIPTION_UPDATE + SystemSecureSpeculationControlInformation, // SECURE_SPECULATION_CONTROL_INFORMATION + SystemSpacesBootInformation, // since 20H2 + SystemFwRamdiskInformation, // SYSTEM_FIRMWARE_RAMDISK_INFORMATION + SystemWheaIpmiHardwareInformation, + SystemDifSetRuleClassInformation, // SYSTEM_DIF_VOLATILE_INFORMATION + SystemDifClearRuleClassInformation, + SystemDifApplyPluginVerificationOnDriver, // SYSTEM_DIF_PLUGIN_DRIVER_INFORMATION + SystemDifRemovePluginVerificationOnDriver, // SYSTEM_DIF_PLUGIN_DRIVER_INFORMATION // 220 + SystemShadowStackInformation, // SYSTEM_SHADOW_STACK_INFORMATION + SystemBuildVersionInformation, + // q: in: ULONG (LayerNumber), out: SYSTEM_BUILD_VERSION_INFORMATION // NtQuerySystemInformationEx // 222 + SystemPoolLimitInformation, // SYSTEM_POOL_LIMIT_INFORMATION (requires SeIncreaseQuotaPrivilege) + SystemCodeIntegrityAddDynamicStore, + SystemCodeIntegrityClearDynamicStores, + SystemDifPoolTrackingInformation, + SystemPoolZeroingInformation, // q: SYSTEM_POOL_ZEROING_INFORMATION + SystemDpcWatchdogInformation, // q; s: SYSTEM_DPC_WATCHDOG_CONFIGURATION_INFORMATION + SystemDpcWatchdogInformation2, // q; s: SYSTEM_DPC_WATCHDOG_CONFIGURATION_INFORMATION_V2 + SystemSupportedProcessorArchitectures2, + // q: in opt: HANDLE, out: SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION[] // NtQuerySystemInformationEx // 230 + SystemSingleProcessorRelationshipInformation, + // q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX // (EX in: PROCESSOR_NUMBER Processor) + SystemXfgCheckFailureInformation, // q: SYSTEM_XFG_FAILURE_INFORMATION + SystemIommuStateInformation, // SYSTEM_IOMMU_STATE_INFORMATION // since 22H1 + SystemHypervisorMinrootInformation, // SYSTEM_HYPERVISOR_MINROOT_INFORMATION + SystemHypervisorBootPagesInformation, // SYSTEM_HYPERVISOR_BOOT_PAGES_INFORMATION + SystemPointerAuthInformation, // SYSTEM_POINTER_AUTH_INFORMATION + SystemSecureKernelDebuggerInformation, + SystemOriginalImageFeatureInformation, + // q: in: SYSTEM_ORIGINAL_IMAGE_FEATURE_INFORMATION_INPUT, out: SYSTEM_ORIGINAL_IMAGE_FEATURE_INFORMATION_OUTPUT // NtQuerySystemInformationEx + SystemMemoryNumaInformation, // SYSTEM_MEMORY_NUMA_INFORMATION_INPUT, SYSTEM_MEMORY_NUMA_INFORMATION_OUTPUT + SystemMemoryNumaPerformanceInformation, + // SYSTEM_MEMORY_NUMA_PERFORMANCE_INFORMATION_INPUTSYSTEM_MEMORY_NUMA_PERFORMANCE_INFORMATION_INPUT, SYSTEM_MEMORY_NUMA_PERFORMANCE_INFORMATION_OUTPUT // since 24H2 // 240 + SystemCodeIntegritySignedPoliciesFullInformation, + SystemSecureSecretsInformation, + SystemTrustedAppsRuntimeInformation, // SYSTEM_TRUSTEDAPPS_RUNTIME_INFORMATION + SystemBadPageInformationEx, // SYSTEM_BAD_PAGE_INFORMATION + SystemResourceDeadlockTimeout, // ULONG + SystemBreakOnContextUnwindFailureInformation, // ULONG (requires SeDebugPrivilege) + SystemOslRamdiskInformation, // SYSTEM_OSL_RAMDISK_INFORMATION + MaxSystemInfoClass +} SYSTEM_INFORMATION_CLASS; + +#ifndef OS_WINDOWS +typedef enum _TOKEN_INFORMATION_CLASS +{ + TokenUser = 1, // q: TOKEN_USER, SE_TOKEN_USER + TokenGroups, // q: TOKEN_GROUPS + TokenPrivileges, // q: TOKEN_PRIVILEGES + TokenOwner, // q; s: TOKEN_OWNER + TokenPrimaryGroup, // q; s: TOKEN_PRIMARY_GROUP + TokenDefaultDacl, // q; s: TOKEN_DEFAULT_DACL + TokenSource, // q: TOKEN_SOURCE + TokenType, // q: TOKEN_TYPE + TokenImpersonationLevel, // q: SECURITY_IMPERSONATION_LEVEL + TokenStatistics, // q: TOKEN_STATISTICS // 10 + TokenRestrictedSids, // q: TOKEN_GROUPS + TokenSessionId, // q; s: ULONG (requires SeTcbPrivilege) + TokenGroupsAndPrivileges, // q: TOKEN_GROUPS_AND_PRIVILEGES + TokenSessionReference, // s: ULONG (requires SeTcbPrivilege) + TokenSandBoxInert, // q: ULONG + TokenAuditPolicy, // q; s: TOKEN_AUDIT_POLICY (requires SeSecurityPrivilege/SeTcbPrivilege) + TokenOrigin, // q; s: TOKEN_ORIGIN (requires SeTcbPrivilege) + TokenElevationType, // q: TOKEN_ELEVATION_TYPE + TokenLinkedToken, // q; s: TOKEN_LINKED_TOKEN (requires SeCreateTokenPrivilege) + TokenElevation, // q: TOKEN_ELEVATION // 20 + TokenHasRestrictions, // q: ULONG + TokenAccessInformation, // q: TOKEN_ACCESS_INFORMATION + TokenVirtualizationAllowed, // q; s: ULONG (requires SeCreateTokenPrivilege) + TokenVirtualizationEnabled, // q; s: ULONG + TokenIntegrityLevel, // q; s: TOKEN_MANDATORY_LABEL + TokenUIAccess, // q; s: ULONG (requires SeTcbPrivilege) + TokenMandatoryPolicy, // q; s: TOKEN_MANDATORY_POLICY (requires SeTcbPrivilege) + TokenLogonSid, // q: TOKEN_GROUPS + TokenIsAppContainer, // q: ULONG // since WIN8 + TokenCapabilities, // q: TOKEN_GROUPS // 30 + TokenAppContainerSid, // q: TOKEN_APPCONTAINER_INFORMATION + TokenAppContainerNumber, // q: ULONG + TokenUserClaimAttributes, // q: CLAIM_SECURITY_ATTRIBUTES_INFORMATION + TokenDeviceClaimAttributes, // q: CLAIM_SECURITY_ATTRIBUTES_INFORMATION + TokenRestrictedUserClaimAttributes, // q: CLAIM_SECURITY_ATTRIBUTES_INFORMATION + TokenRestrictedDeviceClaimAttributes, // q: CLAIM_SECURITY_ATTRIBUTES_INFORMATION + TokenDeviceGroups, // q: TOKEN_GROUPS + TokenRestrictedDeviceGroups, // q: TOKEN_GROUPS + TokenSecurityAttributes, // q; s: TOKEN_SECURITY_ATTRIBUTES_[AND_OPERATION_]INFORMATION (requires SeTcbPrivilege) + TokenIsRestricted, // q: ULONG // 40 + TokenProcessTrustLevel, // q: TOKEN_PROCESS_TRUST_LEVEL // since WINBLUE + TokenPrivateNameSpace, // q; s: ULONG (requires SeTcbPrivilege) // since THRESHOLD + TokenSingletonAttributes, // q: TOKEN_SECURITY_ATTRIBUTES_INFORMATION // since REDSTONE + TokenBnoIsolation, // q: TOKEN_BNO_ISOLATION_INFORMATION // since REDSTONE2 + TokenChildProcessFlags, // s: ULONG (requires SeTcbPrivilege) // since REDSTONE3 + TokenIsLessPrivilegedAppContainer, // q: ULONG // since REDSTONE5 + TokenIsSandboxed, // q: ULONG // since 19H1 + TokenIsAppSilo, // q: ULONG // since WIN11 22H2 // previously TokenOriginatingProcessTrustLevel // q: TOKEN_PROCESS_TRUST_LEVEL + TokenLoggingInformation, // TOKEN_LOGGING_INFORMATION // since 24H2 + MaxTokenInfoClass +} TOKEN_INFORMATION_CLASS, *PTOKEN_INFORMATION_CLASS; + +#endif + +typedef enum _PROCESSINFOCLASS +{ + ProcessBasicInformation, // q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION + ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX + ProcessIoCounters, // q: IO_COUNTERS + ProcessVmCounters, // q: VM_COUNTERS, VM_COUNTERS_EX, VM_COUNTERS_EX2 + ProcessTimes, // q: KERNEL_USER_TIMES + ProcessBasePriority, // s: KPRIORITY + ProcessRaisePriority, // s: ULONG + ProcessDebugPort, // q: HANDLE + ProcessExceptionPort, // s: PROCESS_EXCEPTION_PORT (requires SeTcbPrivilege) + ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN + ProcessLdtInformation, // qs: PROCESS_LDT_INFORMATION // 10 + ProcessLdtSize, // s: PROCESS_LDT_SIZE + ProcessDefaultHardErrorMode, // qs: ULONG + ProcessIoPortHandlers, // (kernel-mode only) // s: PROCESS_IO_PORT_HANDLER_INFORMATION + ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS + ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void + ProcessUserModeIOPL, // qs: ULONG (requires SeTcbPrivilege) + ProcessEnableAlignmentFaultFixup, // s: BOOLEAN + ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS + ProcessWx86Information, // qs: ULONG (requires SeTcbPrivilege) (VdmAllowed) + ProcessHandleCount, // q: ULONG, PROCESS_HANDLE_INFORMATION // 20 + ProcessAffinityMask, // (q >WIN7)s: KAFFINITY, qs: GROUP_AFFINITY + ProcessPriorityBoost, // qs: ULONG + ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX + ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION + ProcessForegroundInformation, // s: PROCESS_FOREGROUND_BACKGROUND + ProcessWow64Information, // q: ULONG_PTR + ProcessImageFileName, // q: UNICODE_STRING + ProcessLUIDDeviceMapsEnabled, // q: ULONG + ProcessBreakOnTermination, // qs: ULONG + ProcessDebugObjectHandle, // q: HANDLE // 30 + ProcessDebugFlags, // qs: ULONG + ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: PROCESS_HANDLE_TRACING_ENABLE[_EX] or void to disable + ProcessIoPriority, // qs: IO_PRIORITY_HINT + ProcessExecuteFlags, // qs: ULONG (MEM_EXECUTE_OPTION_*) + ProcessTlsInformation, // PROCESS_TLS_INFORMATION // ProcessResourceManagement + ProcessCookie, // q: ULONG + ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION + ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION // since VISTA + ProcessPagePriority, // qs: PAGE_PRIORITY_INFORMATION + ProcessInstrumentationCallback, // s: PVOID or PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION // 40 + ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX + ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[]; s: void + ProcessImageFileNameWin32, // q: UNICODE_STRING + ProcessImageFileMapping, // q: HANDLE (input) + ProcessAffinityUpdateMode, // qs: PROCESS_AFFINITY_UPDATE_MODE + ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE + ProcessGroupInformation, // q: USHORT[] + ProcessTokenVirtualizationEnabled, // s: ULONG + ProcessConsoleHostProcess, // qs: ULONG_PTR // ProcessOwnerInformation + ProcessWindowInformation, // q: PROCESS_WINDOW_INFORMATION // 50 + ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8 + ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION + ProcessDynamicFunctionTableInformation, // s: PROCESS_DYNAMIC_FUNCTION_TABLE_INFORMATION + ProcessHandleCheckingMode, // qs: ULONG; s: 0 disables, otherwise enables + ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION + ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION + ProcessWorkingSetControl, // s: PROCESS_WORKING_SET_CONTROL (requires SeDebugPrivilege) + ProcessHandleTable, // q: ULONG[] // since WINBLUE + ProcessCheckStackExtentsMode, // qs: ULONG // KPROCESS->CheckStackExtents (CFG) + ProcessCommandLineInformation, // q: UNICODE_STRING // 60 + ProcessProtectionInformation, // q: PS_PROTECTION + ProcessMemoryExhaustion, // s: PROCESS_MEMORY_EXHAUSTION_INFO // since THRESHOLD + ProcessFaultInformation, // s: PROCESS_FAULT_INFORMATION + ProcessTelemetryIdInformation, // q: PROCESS_TELEMETRY_ID_INFORMATION + ProcessCommitReleaseInformation, // qs: PROCESS_COMMIT_RELEASE_INFORMATION + ProcessDefaultCpuSetsInformation, // qs: SYSTEM_CPU_SET_INFORMATION[5] + ProcessAllowedCpuSetsInformation, // qs: SYSTEM_CPU_SET_INFORMATION[5] + ProcessSubsystemProcess, + ProcessJobMemoryInformation, // q: PROCESS_JOB_MEMORY_INFO + ProcessInPrivate, // q: BOOLEAN; s: void // ETW // since THRESHOLD2 // 70 + ProcessRaiseUMExceptionOnInvalidHandleClose, // qs: ULONG; s: 0 disables, otherwise enables + ProcessIumChallengeResponse, + ProcessChildProcessInformation, // q: PROCESS_CHILD_PROCESS_INFORMATION + ProcessHighGraphicsPriorityInformation, // qs: BOOLEAN (requires SeTcbPrivilege) + ProcessSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2 + ProcessEnergyValues, // q: PROCESS_ENERGY_VALUES, PROCESS_EXTENDED_ENERGY_VALUES + ProcessPowerThrottlingState, // qs: POWER_THROTTLING_PROCESS_STATE + ProcessReserved3Information, // ProcessActivityThrottlePolicy // PROCESS_ACTIVITY_THROTTLE_POLICY + ProcessWin32kSyscallFilterInformation, // q: WIN32K_SYSCALL_FILTER + ProcessDisableSystemAllowedCpuSets, // s: BOOLEAN // 80 + ProcessWakeInformation, // q: PROCESS_WAKE_INFORMATION + ProcessEnergyTrackingState, // qs: PROCESS_ENERGY_TRACKING_STATE + ProcessManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3 + ProcessCaptureTrustletLiveDump, + ProcessTelemetryCoverage, // q: TELEMETRY_COVERAGE_HEADER; s: TELEMETRY_COVERAGE_POINT + ProcessEnclaveInformation, + ProcessEnableReadWriteVmLogging, // qs: PROCESS_READWRITEVM_LOGGING_INFORMATION + ProcessUptimeInformation, // q: PROCESS_UPTIME_INFORMATION + ProcessImageSection, // q: HANDLE + ProcessDebugAuthInformation, // since REDSTONE4 // 90 + ProcessSystemResourceManagement, // s: PROCESS_SYSTEM_RESOURCE_MANAGEMENT + ProcessSequenceNumber, // q: ULONGLONG + ProcessLoaderDetour, // since REDSTONE5 + ProcessSecurityDomainInformation, // q: PROCESS_SECURITY_DOMAIN_INFORMATION + ProcessCombineSecurityDomainsInformation, // s: PROCESS_COMBINE_SECURITY_DOMAINS_INFORMATION + ProcessEnableLogging, // qs: PROCESS_LOGGING_INFORMATION + ProcessLeapSecondInformation, // qs: PROCESS_LEAP_SECOND_INFORMATION + ProcessFiberShadowStackAllocation, // s: PROCESS_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION // since 19H1 + ProcessFreeFiberShadowStackAllocation, // s: PROCESS_FREE_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION + ProcessAltSystemCallInformation, // s: PROCESS_SYSCALL_PROVIDER_INFORMATION // since 20H1 // 100 + ProcessDynamicEHContinuationTargets, // s: PROCESS_DYNAMIC_EH_CONTINUATION_TARGETS_INFORMATION + ProcessDynamicEnforcedCetCompatibleRanges, // s: PROCESS_DYNAMIC_ENFORCED_ADDRESS_RANGE_INFORMATION // since 20H2 + ProcessCreateStateChange, // since WIN11 + ProcessApplyStateChange, + ProcessEnableOptionalXStateFeatures, // s: ULONG64 // optional XState feature bitmask + ProcessAltPrefetchParam, // qs: OVERRIDE_PREFETCH_PARAMETER // App Launch Prefetch (ALPF) // since 22H1 + ProcessAssignCpuPartitions, + ProcessPriorityClassEx, // s: PROCESS_PRIORITY_CLASS_EX + ProcessMembershipInformation, // q: PROCESS_MEMBERSHIP_INFORMATION + ProcessEffectiveIoPriority, // q: IO_PRIORITY_HINT // 110 + ProcessEffectivePagePriority, // q: ULONG + ProcessSchedulerSharedData, // since 24H2 + ProcessSlistRollbackInformation, + ProcessNetworkIoCounters, // q: PROCESS_NETWORK_COUNTERS + ProcessFindFirstThreadByTebValue, // PROCESS_TEB_VALUE_INFORMATION + MaxProcessInfoClass +} PROCESSINFOCLASS; + +typedef enum _PS_ATTRIBUTE_NUM +{ + PsAttributeParentProcess, // in HANDLE + PsAttributeDebugObject, // in HANDLE + PsAttributeToken, // in HANDLE + PsAttributeClientId, // out PCLIENT_ID + PsAttributeTebAddress, // out PTEB * + PsAttributeImageName, // in PWSTR + PsAttributeImageInfo, // out PSECTION_IMAGE_INFORMATION + PsAttributeMemoryReserve, // in PPS_MEMORY_RESERVE + PsAttributePriorityClass, // in UCHAR + PsAttributeErrorMode, // in ULONG + PsAttributeStdHandleInfo, // 10, in PPS_STD_HANDLE_INFO + PsAttributeHandleList, // in HANDLE[] + PsAttributeGroupAffinity, // in PGROUP_AFFINITY + PsAttributePreferredNode, // in PUSHORT + PsAttributeIdealProcessor, // in PPROCESSOR_NUMBER + PsAttributeUmsThread, // ? in PUMS_CREATE_THREAD_ATTRIBUTES + PsAttributeMitigationOptions, // in PPS_MITIGATION_OPTIONS_MAP (PROCESS_CREATION_MITIGATION_POLICY_*) // since WIN8 + PsAttributeProtectionLevel, // in PS_PROTECTION // since WINBLUE + PsAttributeSecureProcess, // in PPS_TRUSTLET_CREATE_ATTRIBUTES, since THRESHOLD + PsAttributeJobList, // in HANDLE[] + PsAttributeChildProcessPolicy, // 20, in PULONG (PROCESS_CREATION_CHILD_PROCESS_*) // since THRESHOLD2 + PsAttributeAllApplicationPackagesPolicy, + // in PULONG (PROCESS_CREATION_ALL_APPLICATION_PACKAGES_*) // since REDSTONE + PsAttributeWin32kFilter, // in PWIN32K_SYSCALL_FILTER + PsAttributeSafeOpenPromptOriginClaim, // in SE_SAFE_OPEN_PROMPT_RESULTS + PsAttributeBnoIsolation, // in PPS_BNO_ISOLATION_PARAMETERS // since REDSTONE2 + PsAttributeDesktopAppPolicy, // in PULONG (PROCESS_CREATION_DESKTOP_APP_*) + PsAttributeChpe, // in BOOLEAN // since REDSTONE3 + PsAttributeMitigationAuditOptions, + // in PPS_MITIGATION_AUDIT_OPTIONS_MAP (PROCESS_CREATION_MITIGATION_AUDIT_POLICY_*) // since 21H1 + PsAttributeMachineType, // in USHORT // since 21H2 + PsAttributeComponentFilter, + PsAttributeEnableOptionalXStateFeatures, // since WIN11 + PsAttributeSupportedMachines, // since 24H2 + PsAttributeSveVectorLength, // PPS_PROCESS_CREATION_SVE_VECTOR_LENGTH + PsAttributeMax +} PS_ATTRIBUTE_NUM; + +struct SYSTEM_PROCESSOR_INFORMATION64 +{ + USHORT ProcessorArchitecture; + USHORT ProcessorLevel; + USHORT ProcessorRevision; + USHORT MaximumProcessors; + ULONG ProcessorFeatureBits; +}; + +#ifndef OS_WINDOWS + +typedef struct _M128A { + ULONGLONG Low; + LONGLONG High; +} M128A, *PM128A; + +typedef struct _XMM_SAVE_AREA32 { + WORD ControlWord; + WORD StatusWord; + BYTE TagWord; + BYTE Reserved1; + WORD ErrorOpcode; + DWORD ErrorOffset; + WORD ErrorSelector; + WORD Reserved2; + DWORD DataOffset; + WORD DataSelector; + WORD Reserved3; + DWORD MxCsr; + DWORD MxCsr_Mask; + M128A FloatRegisters[8]; + M128A XmmRegisters[16]; + BYTE Reserved4[96]; +} XMM_SAVE_AREA32, *PXMM_SAVE_AREA32; + +#endif + +typedef struct _NEON128 +{ + ULONGLONG Low; + LONGLONG High; +} NEON128; + +typedef struct DECLSPEC_ALIGN(16) _CONTEXT64 +{ + DWORD64 P1Home; + DWORD64 P2Home; + DWORD64 P3Home; + DWORD64 P4Home; + DWORD64 P5Home; + DWORD64 P6Home; + DWORD ContextFlags; + DWORD MxCsr; + WORD SegCs; + WORD SegDs; + WORD SegEs; + WORD SegFs; + WORD SegGs; + WORD SegSs; + DWORD EFlags; + DWORD64 Dr0; + DWORD64 Dr1; + DWORD64 Dr2; + DWORD64 Dr3; + DWORD64 Dr6; + DWORD64 Dr7; + DWORD64 Rax; + DWORD64 Rcx; + DWORD64 Rdx; + DWORD64 Rbx; + DWORD64 Rsp; + DWORD64 Rbp; + DWORD64 Rsi; + DWORD64 Rdi; + DWORD64 R8; + DWORD64 R9; + DWORD64 R10; + DWORD64 R11; + DWORD64 R12; + DWORD64 R13; + DWORD64 R14; + DWORD64 R15; + DWORD64 Rip; + + union + { + XMM_SAVE_AREA32 FltSave; + NEON128 Q[16]; + ULONGLONG D[32]; + + struct + { + M128A Header[2]; + M128A Legacy[8]; + M128A Xmm0; + M128A Xmm1; + M128A Xmm2; + M128A Xmm3; + M128A Xmm4; + M128A Xmm5; + M128A Xmm6; + M128A Xmm7; + M128A Xmm8; + M128A Xmm9; + M128A Xmm10; + M128A Xmm11; + M128A Xmm12; + M128A Xmm13; + M128A Xmm14; + M128A Xmm15; + }; + + DWORD S[32]; + }; + + M128A VectorRegister[26]; + DWORD64 VectorControl; + DWORD64 DebugControl; + DWORD64 LastBranchToRip; + DWORD64 LastBranchFromRip; + DWORD64 LastExceptionToRip; + DWORD64 LastExceptionFromRip; +} CONTEXT64, *PCONTEXT64; + +template +struct EMU_EXCEPTION_RECORD +{ + DWORD ExceptionCode; + DWORD ExceptionFlags; + EMULATOR_CAST(typename Traits::PVOID, struct EMU_EXCEPTION_RECORD *) ExceptionRecord; + typename Traits::PVOID ExceptionAddress; + DWORD NumberParameters; + typename Traits::ULONG_PTR ExceptionInformation[15]; +}; + +template +struct EMU_EXCEPTION_POINTERS +{ + EMULATOR_CAST(typename Traits::PVOID, EMU_EXCEPTION_RECORD*) ExceptionRecord; + EMULATOR_CAST(typename Traits::PVOID, CONTEXT64* or CONTEXT32*) ContextRecord; +}; + +#define MAXIMUM_NODE_COUNT64 0x40 +#define MAXIMUM_NODE_COUNT32 0x10 + +struct EMU_GROUP_AFFINITY64 +{ + EMULATOR_CAST(std::uint64_t, KAFFINITY) Mask; + WORD Group; + WORD Reserved[3]; +}; + +typedef struct _SYSTEM_NUMA_INFORMATION64 +{ + ULONG HighestNodeNumber; + ULONG Reserved; + + union + { + EMU_GROUP_AFFINITY64 ActiveProcessorsGroupAffinity[MAXIMUM_NODE_COUNT64]; + ULONGLONG AvailableMemory[MAXIMUM_NODE_COUNT64]; + ULONGLONG Pad[MAXIMUM_NODE_COUNT64 * 2]; + }; +} SYSTEM_NUMA_INFORMATION64, *PSYSTEM_NUMA_INFORMATION64; + +typedef struct _SYSTEM_ERROR_PORT_TIMEOUTS +{ + ULONG StartTimeout; + ULONG CommTimeout; +} SYSTEM_ERROR_PORT_TIMEOUTS, *PSYSTEM_ERROR_PORT_TIMEOUTS; + +typedef struct _SYSTEM_BASIC_INFORMATION64 +{ + ULONG Reserved; + ULONG TimerResolution; + ULONG PageSize; + ULONG NumberOfPhysicalPages; + ULONG LowestPhysicalPageNumber; + ULONG HighestPhysicalPageNumber; + ULONG AllocationGranularity; + EMULATOR_CAST(EmulatorTraits::PVOID, ULONG_PTR) MinimumUserModeAddress; + EMULATOR_CAST(EmulatorTraits::PVOID, ULONG_PTR) MaximumUserModeAddress; + EMULATOR_CAST(EmulatorTraits::PVOID, KAFFINITY) ActiveProcessorsAffinityMask; + char NumberOfProcessors; +} SYSTEM_BASIC_INFORMATION64, *PSYSTEM_BASIC_INFORMATION64; + +typedef struct _SYSTEM_RANGE_START_INFORMATION64 +{ + EmulatorTraits::SIZE_T SystemRangeStart; +} SYSTEM_RANGE_START_INFORMATION64, *PSYSTEM_RANGE_START_INFORMATION64; + +struct SID_AND_ATTRIBUTES64 +{ + EMULATOR_CAST(EmulatorTraits::PVOID, PSID) Sid; + DWORD Attributes; +}; + +struct TOKEN_USER64 +{ + SID_AND_ATTRIBUTES64 User; +}; + +struct TOKEN_BNO_ISOLATION_INFORMATION64 +{ + EmulatorTraits::PVOID IsolationPrefix; + BOOLEAN IsolationEnabled; +}; + +struct TOKEN_MANDATORY_LABEL64 +{ + SID_AND_ATTRIBUTES64 Label; +}; + +#ifndef OS_WINDOWS + +typedef enum _TOKEN_TYPE { + TokenPrimary = 1, + TokenImpersonation +} TOKEN_TYPE; +typedef TOKEN_TYPE* PTOKEN_TYPE; + +typedef struct _TOKEN_ELEVATION { + DWORD TokenIsElevated; +} TOKEN_ELEVATION, * PTOKEN_ELEVATION; + +typedef enum _SECURITY_IMPERSONATION_LEVEL { + SecurityAnonymous, + SecurityIdentification, + SecurityImpersonation, + SecurityDelegation +} SECURITY_IMPERSONATION_LEVEL, *PSECURITY_IMPERSONATION_LEVEL; + + +typedef struct _LUID { + DWORD LowPart; + LONG HighPart; +} LUID, *PLUID; + +typedef struct _TOKEN_STATISTICS { + LUID TokenId; + LUID AuthenticationId; + LARGE_INTEGER ExpirationTime; + TOKEN_TYPE TokenType; + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; + DWORD DynamicCharged; + DWORD DynamicAvailable; + DWORD GroupCount; + DWORD PrivilegeCount; + LUID ModifiedId; +} TOKEN_STATISTICS, *PTOKEN_STATISTICS; + +#endif + +typedef struct _TOKEN_SECURITY_ATTRIBUTES_INFORMATION +{ + USHORT Version; + USHORT Reserved; + ULONG AttributeCount; + + union + { + EmulatorTraits::PVOID pAttributeV1; + } Attribute; +} TOKEN_SECURITY_ATTRIBUTES_INFORMATION, *PTOKEN_SECURITY_ATTRIBUTES_INFORMATION; + +struct GDI_HANDLE_ENTRY64 +{ + union + { + EmulatorTraits::PVOID Object; + EmulatorTraits::PVOID NextFree; + }; + + union + { + struct + { + USHORT ProcessId; + USHORT Lock : 1; + USHORT Count : 15; + }; + + ULONG Value; + } Owner; + + USHORT Unique; + UCHAR Type; + UCHAR Flags; + EmulatorTraits::PVOID UserPointer; +}; + +#define GDI_MAX_HANDLE_COUNT 0xFFFF // 0x4000 + +struct GDI_SHARED_MEMORY64 +{ + GDI_HANDLE_ENTRY64 Handles[GDI_MAX_HANDLE_COUNT]; +}; + +struct CLIENT_ID64 +{ + DWORD64 UniqueProcess; + DWORD64 UniqueThread; +}; + +struct PORT_MESSAGE64 +{ + union + { + struct + { + CSHORT DataLength; + CSHORT TotalLength; + } s1; + + ULONG Length; + } u1; + + union + { + struct + { + CSHORT Type; + CSHORT DataInfoOffset; + } s2; + + ULONG ZeroInit; + } u2; + + union + { + CLIENT_ID64 ClientId; + double DoNotUseThisField; + }; + + ULONG MessageId; + + union + { + EmulatorTraits::SIZE_T ClientViewSize; // only valid for LPC_CONNECTION_REQUEST messages + ULONG CallbackId; // only valid for LPC_REQUEST messages + }; +}; + +struct ALPC_MESSAGE_ATTRIBUTES +{ + ULONG AllocatedAttributes; + ULONG ValidAttributes; +}; + +template +struct PORT_DATA_ENTRY +{ + typename Traits::PVOID Base; + ULONG Size; +}; + +template +struct EMU_RTL_SRWLOCK +{ + typename Traits::PVOID Ptr; +}; diff --git a/src/common/platform/registry.hpp b/src/common/platform/registry.hpp new file mode 100644 index 00000000..f77dd5d4 --- /dev/null +++ b/src/common/platform/registry.hpp @@ -0,0 +1,64 @@ +#pragma once + +typedef enum _KEY_INFORMATION_CLASS +{ + KeyBasicInformation, // KEY_BASIC_INFORMATION + KeyNodeInformation, // KEY_NODE_INFORMATION + KeyFullInformation, // KEY_FULL_INFORMATION + KeyNameInformation, // KEY_NAME_INFORMATION + KeyCachedInformation, // KEY_CACHED_INFORMATION + KeyFlagsInformation, // KEY_FLAGS_INFORMATION + KeyVirtualizationInformation, // KEY_VIRTUALIZATION_INFORMATION + KeyHandleTagsInformation, // KEY_HANDLE_TAGS_INFORMATION + KeyTrustInformation, // KEY_TRUST_INFORMATION + KeyLayerInformation, // KEY_LAYER_INFORMATION + MaxKeyInfoClass +} KEY_INFORMATION_CLASS; + +typedef enum _KEY_VALUE_INFORMATION_CLASS +{ + KeyValueBasicInformation, // KEY_VALUE_BASIC_INFORMATION + KeyValueFullInformation, // KEY_VALUE_FULL_INFORMATION + KeyValuePartialInformation, // KEY_VALUE_PARTIAL_INFORMATION + KeyValueFullInformationAlign64, + KeyValuePartialInformationAlign64, // KEY_VALUE_PARTIAL_INFORMATION_ALIGN64 + KeyValueLayerInformation, // KEY_VALUE_LAYER_INFORMATION + MaxKeyValueInfoClass +} KEY_VALUE_INFORMATION_CLASS; + +struct KEY_NAME_INFORMATION +{ + std::uint32_t NameLength; + char16_t Name[1]; +}; + +struct KEY_HANDLE_TAGS_INFORMATION +{ + ULONG HandleTags; +}; + +struct KEY_VALUE_BASIC_INFORMATION +{ + ULONG TitleIndex; + ULONG Type; + ULONG NameLength; + char16_t Name[1]; +}; + +struct KEY_VALUE_PARTIAL_INFORMATION +{ + ULONG TitleIndex; + ULONG Type; + ULONG DataLength; + UCHAR Data[1]; +}; + +struct KEY_VALUE_FULL_INFORMATION +{ + ULONG TitleIndex; + ULONG Type; + ULONG DataOffset; + ULONG DataLength; + ULONG NameLength; + char16_t Name[1]; +}; diff --git a/src/common/platform/status.hpp b/src/common/platform/status.hpp new file mode 100644 index 00000000..82b7e6dc --- /dev/null +++ b/src/common/platform/status.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include + +using NTSTATUS = std::uint32_t; + +#ifndef OS_WINDOWS +#define STATUS_WAIT_0 ((NTSTATUS)0x00000000L) +#define STATUS_TIMEOUT ((NTSTATUS)0x00000102L) + +#define STATUS_ACCESS_VIOLATION ((NTSTATUS)0xC0000005L) +#define STATUS_INVALID_HANDLE ((NTSTATUS)0xC0000008L) +#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL) + +#define STATUS_PENDING ((DWORD)0x00000103L) +#endif + +#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) +#define STATUS_WAIT_1 ((NTSTATUS)0x00000001L) + +#define STATUS_UNSUCCESSFUL ((NTSTATUS)0x00000001L) +#define STATUS_ALERTED ((NTSTATUS)0x00000101L) + +#define STATUS_OBJECT_NAME_EXISTS ((NTSTATUS)0x40000000L) + +#define STATUS_NO_MORE_FILES ((NTSTATUS)0x80000006L) + +#define STATUS_ILLEGAL_INSTRUCTION ((DWORD )0xC000001DL) +#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) +#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L) +#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034L) +#define STATUS_NO_TOKEN ((NTSTATUS)0xC000007CL) +#define STATUS_FILE_INVALID ((NTSTATUS)0xC0000098L) +#define STATUS_MEMORY_NOT_ALLOCATED ((NTSTATUS)0xC00000A0L) +#define STATUS_FILE_IS_A_DIRECTORY ((NTSTATUS)0xC00000BAL) +#define STATUS_NOT_SUPPORTED ((NTSTATUS)0xC00000BBL) +#define STATUS_INVALID_ADDRESS ((NTSTATUS)0xC0000141L) +#define STATUS_NOT_FOUND ((NTSTATUS)0xC0000225L) +#define STATUS_CONNECTION_REFUSED ((NTSTATUS)0xC0000236L) +#define STATUS_ADDRESS_ALREADY_ASSOCIATED ((NTSTATUS)0xC0000328L) + +#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L) + + +#define FILE_DEVICE_NETWORK 0x00000012 +#define FSCTL_AFD_BASE FILE_DEVICE_NETWORK diff --git a/src/common/platform/synchronisation.hpp b/src/common/platform/synchronisation.hpp new file mode 100644 index 00000000..8fc51aa8 --- /dev/null +++ b/src/common/platform/synchronisation.hpp @@ -0,0 +1,16 @@ +#pragma once + +typedef enum _EVENT_TYPE +{ + NotificationEvent, + SynchronizationEvent +} EVENT_TYPE; + +typedef enum _WAIT_TYPE +{ + WaitAll, + WaitAny, + WaitNotification, + WaitDequeue, + WaitDpc, +} WAIT_TYPE; diff --git a/src/common/platform/threading.hpp b/src/common/platform/threading.hpp new file mode 100644 index 00000000..244994df --- /dev/null +++ b/src/common/platform/threading.hpp @@ -0,0 +1,83 @@ +#pragma once + +typedef enum _THREADINFOCLASS +{ + ThreadBasicInformation, // q: THREAD_BASIC_INFORMATION + ThreadTimes, // q: KERNEL_USER_TIMES + ThreadPriority, // s: KPRIORITY (requires SeIncreaseBasePriorityPrivilege) + ThreadBasePriority, // s: KPRIORITY + ThreadAffinityMask, // s: KAFFINITY + ThreadImpersonationToken, // s: HANDLE + ThreadDescriptorTableEntry, // q: DESCRIPTOR_TABLE_ENTRY (or WOW64_DESCRIPTOR_TABLE_ENTRY) + ThreadEnableAlignmentFaultFixup, // s: BOOLEAN + ThreadEventPair, + ThreadQuerySetWin32StartAddress, // q: ULONG_PTR + ThreadZeroTlsCell, // s: ULONG // TlsIndex // 10 + ThreadPerformanceCount, // q: LARGE_INTEGER + ThreadAmILastThread, // q: ULONG + ThreadIdealProcessor, // s: ULONG + ThreadPriorityBoost, // qs: ULONG + ThreadSetTlsArrayAddress, // s: ULONG_PTR // Obsolete + ThreadIsIoPending, // q: ULONG + ThreadHideFromDebugger, // q: BOOLEAN; s: void + ThreadBreakOnTermination, // qs: ULONG + ThreadSwitchLegacyState, // s: void // NtCurrentThread // NPX/FPU + ThreadIsTerminated, // q: ULONG // 20 + ThreadLastSystemCall, // q: THREAD_LAST_SYSCALL_INFORMATION + ThreadIoPriority, // qs: IO_PRIORITY_HINT (requires SeIncreaseBasePriorityPrivilege) + ThreadCycleTime, // q: THREAD_CYCLE_TIME_INFORMATION + ThreadPagePriority, // qs: PAGE_PRIORITY_INFORMATION + ThreadActualBasePriority, // s: LONG (requires SeIncreaseBasePriorityPrivilege) + ThreadTebInformation, // q: THREAD_TEB_INFORMATION (requires THREAD_GET_CONTEXT + THREAD_SET_CONTEXT) + ThreadCSwitchMon, // Obsolete + ThreadCSwitchPmu, + ThreadWow64Context, // qs: WOW64_CONTEXT, ARM_NT_CONTEXT since 20H1 + ThreadGroupInformation, // qs: GROUP_AFFINITY // 30 + ThreadUmsInformation, // q: THREAD_UMS_INFORMATION // Obsolete + ThreadCounterProfiling, // q: BOOLEAN; s: THREAD_PROFILING_INFORMATION? + ThreadIdealProcessorEx, // qs: PROCESSOR_NUMBER; s: previous PROCESSOR_NUMBER on return + ThreadCpuAccountingInformation, // q: BOOLEAN; s: HANDLE (NtOpenSession) // NtCurrentThread // since WIN8 + ThreadSuspendCount, // q: ULONG // since WINBLUE + ThreadHeterogeneousCpuPolicy, // q: KHETERO_CPU_POLICY // since THRESHOLD + ThreadContainerId, // q: GUID + ThreadNameInformation, // qs: THREAD_NAME_INFORMATION + ThreadSelectedCpuSets, + ThreadSystemThreadInformation, // q: SYSTEM_THREAD_INFORMATION // 40 + ThreadActualGroupAffinity, // q: GROUP_AFFINITY // since THRESHOLD2 + ThreadDynamicCodePolicyInfo, // q: ULONG; s: ULONG (NtCurrentThread) + ThreadExplicitCaseSensitivity, // qs: ULONG; s: 0 disables, otherwise enables + ThreadWorkOnBehalfTicket, // RTL_WORK_ON_BEHALF_TICKET_EX + ThreadSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2 + ThreadDbgkWerReportActive, // s: ULONG; s: 0 disables, otherwise enables + ThreadAttachContainer, // s: HANDLE (job object) // NtCurrentThread + ThreadManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3 + ThreadPowerThrottlingState, // POWER_THROTTLING_THREAD_STATE // since REDSTONE3 (set), WIN11 22H2 (query) + ThreadWorkloadClass, // THREAD_WORKLOAD_CLASS // since REDSTONE5 // 50 + ThreadCreateStateChange, // since WIN11 + ThreadApplyStateChange, + ThreadStrongerBadHandleChecks, // since 22H1 + ThreadEffectiveIoPriority, // q: IO_PRIORITY_HINT + ThreadEffectivePagePriority, // q: ULONG + ThreadUpdateLockOwnership, // since 24H2 + ThreadSchedulerSharedDataSlot, // SCHEDULER_SHARED_DATA_SLOT_INFORMATION + ThreadTebInformationAtomic, // THREAD_TEB_INFORMATION + ThreadIndexInformation, // THREAD_INDEX_INFORMATION + MaxThreadInfoClass +} THREADINFOCLASS; + + +template +struct THREAD_NAME_INFORMATION +{ + UNICODE_STRING ThreadName; +}; + +typedef struct _THREAD_BASIC_INFORMATION64 +{ + NTSTATUS ExitStatus; + PTEB64 TebBaseAddress; + CLIENT_ID64 ClientId; + EMULATOR_CAST(std::uint64_t, KAFFINITY) AffinityMask; + EMULATOR_CAST(std::uint32_t, KPRIORITY) Priority; + EMULATOR_CAST(std::uint32_t, KPRIORITY) BasePriority; +} THREAD_BASIC_INFORMATION64, *PTHREAD_BASIC_INFORMATION64; \ No newline at end of file diff --git a/src/common/platform/traits.hpp b/src/common/platform/traits.hpp new file mode 100644 index 00000000..758e641a --- /dev/null +++ b/src/common/platform/traits.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include + +// used to retain original type "x" +#define EMULATOR_CAST(T, x) T + +struct Emu32 +{ +}; + +struct Emu64 +{ +}; + +template +struct EmulatorTraits; + +template <> +struct EmulatorTraits +{ + using PVOID = std::uint32_t; + using ULONG_PTR = std::uint32_t; + using SIZE_T = std::uint32_t; + using UNICODE = char16_t; + using HANDLE = std::uint32_t; +}; + +template <> +struct EmulatorTraits +{ + using PVOID = std::uint64_t; + using ULONG_PTR = std::uint64_t; + using SIZE_T = std::uint64_t; + using UNICODE = char16_t; + using HANDLE = std::uint64_t; +}; diff --git a/src/common/platform/unicode.hpp b/src/common/platform/unicode.hpp new file mode 100644 index 00000000..644d9c43 --- /dev/null +++ b/src/common/platform/unicode.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include + +template +struct UNICODE_STRING +{ + USHORT Length; + USHORT MaximumLength; + EMULATOR_CAST(typename Traits::PVOID, char16_t*) Buffer; +}; + +inline std::string u16_to_u8(const std::u16string_view u16_view) +{ + std::string utf8_str; + utf8_str.reserve(u16_view.size() * 2); + for (const char16_t ch : u16_view) + { + if (ch <= 0x7F) + { + utf8_str.push_back(static_cast(ch)); + } + else if (ch <= 0x7FF) + { + utf8_str.push_back(static_cast(0xC0 | (ch >> 6))); + utf8_str.push_back(static_cast(0x80 | (ch & 0x3F))); + } + else + { + utf8_str.push_back(static_cast(0xE0 | (ch >> 12))); + utf8_str.push_back(static_cast(0x80 | ((ch >> 6) & 0x3F))); + utf8_str.push_back(static_cast(0x80 | (ch & 0x3F))); + } + } + return utf8_str; +} + +inline std::string w_to_u8(const std::wstring_view w_view) +{ + std::string utf8_str; + utf8_str.reserve(w_view.size() * 2); + for (const wchar_t w_ch : w_view) + { + const auto ch = static_cast(w_ch); + if (ch <= 0x7F) + { + utf8_str.push_back(static_cast(ch)); + } + else if (ch <= 0x7FF) + { + utf8_str.push_back(static_cast(0xC0 | (ch >> 6))); + utf8_str.push_back(static_cast(0x80 | (ch & 0x3F))); + } + else + { + utf8_str.push_back(static_cast(0xE0 | (ch >> 12))); + utf8_str.push_back(static_cast(0x80 | ((ch >> 6) & 0x3F))); + utf8_str.push_back(static_cast(0x80 | (ch & 0x3F))); + } + } + return utf8_str; +} + +#ifndef OS_WINDOWS +inline int open_unicode(FILE** handle, const std::u16string& fileName, const std::u16string& mode) +{ + *handle = fopen(u16_to_u8(fileName).c_str(), u16_to_u8(mode).c_str()); + return errno; +} +#else +inline std::wstring u16_to_w(const std::u16string& u16str) +{ + return std::wstring(reinterpret_cast(u16str.data()), u16str.size()); +} + +inline auto open_unicode(FILE** handle, const std::u16string& fileName, const std::u16string& mode) +{ + return _wfopen_s(handle, u16_to_w(fileName).c_str(), u16_to_w(mode).c_str()); +} +#endif diff --git a/src/common/platform/win_pefile.hpp b/src/common/platform/win_pefile.hpp new file mode 100644 index 00000000..41ca0e61 --- /dev/null +++ b/src/common/platform/win_pefile.hpp @@ -0,0 +1,340 @@ +#pragma once + +#include + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory +// IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage) +#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP +#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory +#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers +#define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table +#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors +#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor + +#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 // Section contains extended relocations. +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded. +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable. +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable. +#define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable. +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable. +#define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable. +#define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable. + +#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code. +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data. +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data. + +#define IMAGE_REL_BASED_ABSOLUTE 0 +#define IMAGE_REL_BASED_HIGH 1 +#define IMAGE_REL_BASED_LOW 2 +#define IMAGE_REL_BASED_HIGHLOW 3 +#define IMAGE_REL_BASED_HIGHADJ 4 +#define IMAGE_REL_BASED_MIPS_JMPADDR 5 +#define IMAGE_REL_BASED_ARM_MOV32A 5 +#define IMAGE_REL_BASED_ARM_MOV32 5 +#define IMAGE_REL_BASED_SECTION 6 +#define IMAGE_REL_BASED_REL 7 +#define IMAGE_REL_BASED_ARM_MOV32T 7 +#define IMAGE_REL_BASED_THUMB_MOV32 7 +#define IMAGE_REL_BASED_MIPS_JMPADDR16 9 +#define IMAGE_REL_BASED_IA64_IMM64 9 +#define IMAGE_REL_BASED_DIR64 10 +#define IMAGE_REL_BASED_HIGH3ADJ 11 + +#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040 +#define IMAGE_FILE_DLL 0x2000 + +#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_AMD64 0x8664 + +#define PROCESSOR_ARCHITECTURE_AMD64 9 + +enum class PEMachineType : std::uint16_t +{ + UNKNOWN = 0, + I386 = 0x014c, // Intel 386. + R3000 = 0x0162, // MIPS little-endian, 0x160 big-endian + R4000 = 0x0166, // MIPS little-endian + R10000 = 0x0168, // MIPS little-endian + WCEMIPSV2 = 0x0169, // MIPS little-endian WCE v2 + ALPHA = 0x0184, // Alpha_AXP + SH3 = 0x01a2, // SH3 little-endian + SH3DSP = 0x01a3, + SH3E = 0x01a4, // SH3E little-endian + SH4 = 0x01a6, // SH4 little-endian + SH5 = 0x01a8, // SH5 + ARM = 0x01c0, // ARM Little-Endian + THUMB = 0x01c2, // ARM Thumb/Thumb-2 Little-Endian + ARMNT = 0x01c4, // ARM Thumb-2 Little-Endian + AM33 = 0x01d3, + POWERPC = 0x01F0, // IBM PowerPC Little-Endian + POWERPCFP = 0x01f1, + IA64 = 0x0200, // Intel 64 + MIPS16 = 0x0266, // MIPS + ALPHA64 = 0x0284, // ALPHA64 + MIPSFPU = 0x0366, // MIPS + MIPSFPU16 = 0x0466, // MIPS + AXP64 = ALPHA64, + TRICORE = 0x0520, // Infineon + CEF = 0x0CEF, + EBC = 0x0EBC, // EFI Byte Code + AMD64 = 0x8664, // AMD64 (K8) + M32R = 0x9041, // M32R little-endian + CEE = 0xC0EE, +}; + + +#pragma pack(push, 4) + +template +struct PEOptionalHeaderBasePart2_t +{ +}; + +template <> +struct PEOptionalHeaderBasePart2_t +{ + std::uint32_t BaseOfData; + std::uint32_t ImageBase; +}; + +template <> +struct PEOptionalHeaderBasePart2_t +{ + std::uint64_t ImageBase; +}; + +template +struct PEOptionalHeaderBasePart1_t +{ + enum + { + k_NumberOfDataDirectors = 16 + }; + + uint16_t Magic; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; + uint32_t SizeOfCode; + uint32_t SizeOfInitializedData; + uint32_t SizeOfUninitializedData; + uint32_t AddressOfEntryPoint; + uint32_t BaseOfCode; +}; + + +struct PEDirectory_t2 +{ + std::uint32_t VirtualAddress; + std::uint32_t Size; +}; + +template +struct PEOptionalHeaderBasePart3_t : PEOptionalHeaderBasePart1_t, PEOptionalHeaderBasePart2_t +{ + uint32_t SectionAlignment; + uint32_t FileAlignment; + uint16_t MajorOperatingSystemVersion; + uint16_t MinorOperatingSystemVersion; + uint16_t MajorImageVersion; + uint16_t MinorImageVersion; + uint16_t MajorSubsystemVersion; + uint16_t MinorSubsystemVersion; + uint32_t Win32VersionValue; + uint32_t SizeOfImage; + uint32_t SizeOfHeaders; + uint32_t CheckSum; + uint16_t Subsystem; + uint16_t DllCharacteristics; + T SizeOfStackReserve; + T SizeOfStackCommit; + T SizeOfHeapReserve; + T SizeOfHeapCommit; + uint32_t LoaderFlags; + uint32_t NumberOfRvaAndSizes; + PEDirectory_t2 DataDirectory[PEOptionalHeaderBasePart1_t::k_NumberOfDataDirectors]; +}; + +template +struct PEOptionalHeader_t +{ +}; + +template <> +struct PEOptionalHeader_t : PEOptionalHeaderBasePart3_t +{ + enum + { + k_Magic = 0x10b, // IMAGE_NT_OPTIONAL_HDR32_MAGIC + }; +}; + +template <> +struct PEOptionalHeader_t : PEOptionalHeaderBasePart3_t +{ + enum + { + k_Magic = 0x20b, // IMAGE_NT_OPTIONAL_HDR64_MAGIC + }; +}; + +struct PEFileHeader_t +{ + PEMachineType Machine; + std::uint16_t NumberOfSections; + std::uint32_t TimeDateStamp; + std::uint32_t PointerToSymbolTable; + std::uint32_t NumberOfSymbols; + std::uint16_t SizeOfOptionalHeader; + std::uint16_t Characteristics; +}; + +template +struct PENTHeaders_t +{ + enum + { + k_Signature = 0x00004550, // IMAGE_NT_SIGNATURE + }; + + uint32_t Signature; + PEFileHeader_t FileHeader; + PEOptionalHeader_t OptionalHeader; +}; + +struct PEDosHeader_t +{ + enum + { + k_Magic = 0x5A4D + }; + + std::uint16_t e_magic; // Magic number ( k_Magic ) + std::uint16_t e_cblp; // Bytes on last page of file + std::uint16_t e_cp; // Pages in file + std::uint16_t e_crlc; // Relocations + std::uint16_t e_cparhdr; // Size of header in paragraphs + std::uint16_t e_minalloc; // Minimum extra paragraphs needed + std::uint16_t e_maxalloc; // Maximum extra paragraphs needed + std::uint16_t e_ss; // Initial (relative) SS value + std::uint16_t e_sp; // Initial SP value + std::uint16_t e_csum; // Checksum + std::uint16_t e_ip; // Initial IP value + std::uint16_t e_cs; // Initial (relative) CS value + std::uint16_t e_lfarlc; // File address of relocation table + std::uint16_t e_ovno; // Overlay number + std::uint16_t e_res[4]; // Reserved words + std::uint16_t e_oemid; // OEM identifier (for e_oeminfo) + std::uint16_t e_oeminfo; // OEM information; e_oemid specific + std::uint16_t e_res2[10]; // Reserved words + std::uint32_t e_lfanew; // File address of new exe header +}; + +#pragma pack(pop) + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +#ifndef OS_WINDOWS +typedef struct _IMAGE_SECTION_HEADER +{ + std::uint8_t Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + std:: uint32_t PhysicalAddress; + std::uint32_t VirtualSize; + } Misc; + std::uint32_t VirtualAddress; + std::uint32_t SizeOfRawData; + std::uint32_t PointerToRawData; + std::uint32_t PointerToRelocations; + std::uint32_t PointerToLinenumbers; + std::uint16_t NumberOfRelocations; + std::uint16_t NumberOfLinenumbers; + std::uint32_t Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +typedef struct _IMAGE_EXPORT_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + DWORD Name; + DWORD Base; + DWORD NumberOfFunctions; + DWORD NumberOfNames; + DWORD AddressOfFunctions; + DWORD AddressOfNames; + DWORD AddressOfNameOrdinals; +} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; + +typedef struct _IMAGE_BASE_RELOCATION { + DWORD VirtualAddress; + DWORD SizeOfBlock; + WORD TypeOffset[1]; +} IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION; + +#endif + +template +struct SECTION_IMAGE_INFORMATION +{ + typename Traits::PVOID TransferAddress; + ULONG ZeroBits; + typename Traits::SIZE_T MaximumStackSize; + typename Traits::SIZE_T CommittedStackSize; + ULONG SubSystemType; + + union + { + struct + { + USHORT SubSystemMinorVersion; + USHORT SubSystemMajorVersion; + }; + + ULONG SubSystemVersion; + }; + + union + { + struct + { + USHORT MajorOperatingSystemVersion; + USHORT MinorOperatingSystemVersion; + }; + + ULONG OperatingSystemVersion; + }; + + USHORT ImageCharacteristics; + USHORT DllCharacteristics; + PEMachineType Machine; + BOOLEAN ImageContainsCode; + + union + { + UCHAR ImageFlags; + + struct + { + UCHAR ComPlusNativeReady : 1; + UCHAR ComPlusILOnly : 1; + UCHAR ImageDynamicallyRelocated : 1; + UCHAR ImageMappedFlat : 1; + UCHAR BaseBelow4gb : 1; + UCHAR ComPlusPrefer32bit : 1; + UCHAR Reserved : 2; + }; + }; + + ULONG LoaderFlags; + ULONG ImageFileSize; + ULONG CheckSum; +}; diff --git a/src/common/utils/finally.hpp b/src/common/utils/finally.hpp index 8d30b150..94489e59 100644 --- a/src/common/utils/finally.hpp +++ b/src/common/utils/finally.hpp @@ -13,8 +13,8 @@ namespace utils { public: static_assert(!std::is_reference::value && !std::is_const::value && - !std::is_volatile::value, - "Final_action should store its callable by value"); + !std::is_volatile::value, + "Final_action should store its callable by value"); explicit final_action(F f) noexcept : f_(std::move(f)) { @@ -52,4 +52,4 @@ namespace utils return final_action::type>::type>( std::forward(f)); } -} \ No newline at end of file +} diff --git a/src/common/utils/io.cpp b/src/common/utils/io.cpp index fb151bb0..e7258219 100644 --- a/src/common/utils/io.cpp +++ b/src/common/utils/io.cpp @@ -28,12 +28,12 @@ namespace utils::io io::create_directory(file.parent_path()); } - std::basic_ofstream stream( + std::ofstream stream( file, std::ios::binary | std::ofstream::out | (append ? std::ofstream::app : std::ofstream::out)); if (stream.is_open()) { - stream.write(data.data(), static_cast(data.size())); + stream.write(reinterpret_cast(data.data()), static_cast(data.size())); stream.close(); return true; } diff --git a/src/common/utils/nt_handle.hpp b/src/common/utils/nt_handle.hpp index 0545027e..fc97f925 100644 --- a/src/common/utils/nt_handle.hpp +++ b/src/common/utils/nt_handle.hpp @@ -1,5 +1,7 @@ #pragma once +#ifdef WIN32 + #define NOMINMAX #define WIN32_LEAN_AND_MEAN #include @@ -83,3 +85,5 @@ namespace utils::nt HANDLE handle_{InvalidHandleFunction()}; }; } + +#endif diff --git a/src/common/utils/string.hpp b/src/common/utils/string.hpp index a03d7b45..dac98317 100644 --- a/src/common/utils/string.hpp +++ b/src/common/utils/string.hpp @@ -11,6 +11,16 @@ namespace utils::string return static_cast(std::tolower(static_cast(val))); } + inline char16_t char_to_lower(const char16_t val) + { + if (val >= u'A' && val <= u'Z') + { + return val + 32; + } + + return val; + } + inline wchar_t char_to_lower(const wchar_t val) { return std::towlower(val); diff --git a/src/common/utils/timer.hpp b/src/common/utils/timer.hpp index b5a21553..3fd09722 100644 --- a/src/common/utils/timer.hpp +++ b/src/common/utils/timer.hpp @@ -21,6 +21,6 @@ namespace utils } private: - typename Clock::time_point point_{ Clock::now() }; + typename Clock::time_point point_{Clock::now()}; }; } diff --git a/src/emulator/emulator.hpp b/src/emulator/emulator.hpp index 2c54cd4b..b20b0925 100644 --- a/src/emulator/emulator.hpp +++ b/src/emulator/emulator.hpp @@ -42,7 +42,8 @@ using instruction_hook_callback = std::function using interrupt_hook_callback = std::function; using simple_memory_hook_callback = std::function; -using complex_memory_hook_callback = std::function; +using complex_memory_hook_callback = std::function; using memory_violation_hook_callback = std::function; @@ -140,7 +141,8 @@ private: { assert((static_cast(operation) & (static_cast(operation) - 1)) == 0); return this->hook_memory_access(address, size, operation, - [c = std::move(callback)](const uint64_t a, const size_t s, const uint64_t value, + [c = std::move(callback)](const uint64_t a, const size_t s, + const uint64_t value, memory_operation) { c(a, s, value); diff --git a/src/emulator/memory_manager.cpp b/src/emulator/memory_manager.cpp index 1f076c33..abd5405f 100644 --- a/src/emulator/memory_manager.cpp +++ b/src/emulator/memory_manager.cpp @@ -63,30 +63,33 @@ namespace } } -static void serialize(utils::buffer_serializer& buffer, const memory_manager::committed_region& region) +namespace utils { - buffer.write(region.length); - buffer.write(region.pemissions); -} + static void serialize(buffer_serializer& buffer, const memory_manager::committed_region& region) + { + buffer.write(region.length); + buffer.write(region.pemissions); + } -static void deserialize(utils::buffer_deserializer& buffer, memory_manager::committed_region& region) -{ - region.length = static_cast(buffer.read()); - region.pemissions = buffer.read(); -} + static void deserialize(buffer_deserializer& buffer, memory_manager::committed_region& region) + { + region.length = static_cast(buffer.read()); + region.pemissions = buffer.read(); + } -static void serialize(utils::buffer_serializer& buffer, const memory_manager::reserved_region& region) -{ - buffer.write(region.is_mmio); - buffer.write(region.length); - buffer.write_map(region.committed_regions); -} + static void serialize(buffer_serializer& buffer, const memory_manager::reserved_region& region) + { + buffer.write(region.is_mmio); + buffer.write(region.length); + buffer.write_map(region.committed_regions); + } -static void deserialize(utils::buffer_deserializer& buffer, memory_manager::reserved_region& region) -{ - buffer.read(region.is_mmio); - region.length = static_cast(buffer.read()); - buffer.read_map(region.committed_regions); + static void deserialize(buffer_deserializer& buffer, memory_manager::reserved_region& region) + { + buffer.read(region.is_mmio); + region.length = static_cast(buffer.read()); + buffer.read_map(region.committed_regions); + } } void memory_manager::serialize_memory_state(utils::buffer_serializer& buffer, const bool is_snapshot) const @@ -243,7 +246,7 @@ bool memory_manager::allocate_memory(const uint64_t address, const size_t size, return false; } - const auto entry = this->reserved_regions_.try_emplace(address, size).first; + const auto entry = this->reserved_regions_.try_emplace(address, reserved_region{.length = size,}).first; if (!reserve_only) { diff --git a/src/emulator/memory_region.hpp b/src/emulator/memory_region.hpp index 71729a8d..880f3666 100644 --- a/src/emulator/memory_region.hpp +++ b/src/emulator/memory_region.hpp @@ -1,14 +1,15 @@ -#pragma once -#include "memory_permission.hpp" - -struct basic_memory_region -{ - uint64_t start{}; - size_t length{}; - memory_permission permissions{}; -}; - -struct memory_region : basic_memory_region -{ - bool committed{}; -}; +#pragma once +#include "memory_permission.hpp" +#include + +struct basic_memory_region +{ + uint64_t start{}; + size_t length{}; + memory_permission permissions{}; +}; + +struct memory_region : basic_memory_region +{ + bool committed{}; +}; diff --git a/src/emulator/serialization.hpp b/src/emulator/serialization.hpp index d18f5c25..e86894db 100644 --- a/src/emulator/serialization.hpp +++ b/src/emulator/serialization.hpp @@ -38,8 +38,8 @@ namespace utils }; template - struct has_serialize_function(), - std::declval&>()) + struct has_serialize_function(), + std::declval&>()) )>> : std::true_type { @@ -51,7 +51,7 @@ namespace utils }; template - struct has_deserialize_function(), std::declval&>()))>> : std::true_type @@ -97,6 +97,7 @@ namespace utils const std::span result(this->buffer_.data() + this->offset_, length); this->offset_ += length; + (void)this->no_debugging_; #ifndef NDEBUG if (!this->no_debugging_) @@ -137,7 +138,7 @@ namespace utils } else if constexpr (detail::has_deserialize_function::value) { - ::deserialize(*this, object); + deserialize(*this, object); } else if constexpr (is_trivially_copyable) { @@ -360,7 +361,7 @@ namespace utils } else if constexpr (detail::has_serialize_function::value) { - ::serialize(*this, object); + serialize(*this, object); } else if constexpr (is_trivially_copyable) { @@ -465,6 +466,12 @@ namespace utils object = this->read_string(); } + template <> + inline void buffer_deserializer::read(std::u16string& object) + { + object = this->read_string(); + } + template <> inline void buffer_serializer::write(const bool& object) { @@ -482,4 +489,10 @@ namespace utils { this->write_string(object); } + + template <> + inline void buffer_serializer::write(const std::u16string& object) + { + this->write_string(object); + } } diff --git a/src/emulator/serialization_helper.hpp b/src/emulator/serialization_helper.hpp index 6af6e0f0..0d6f58d2 100644 --- a/src/emulator/serialization_helper.hpp +++ b/src/emulator/serialization_helper.hpp @@ -5,40 +5,43 @@ #include #include -inline void serialize(utils::buffer_serializer& buffer, const std::chrono::steady_clock::time_point& tp) +namespace utils { - buffer.write(tp.time_since_epoch().count()); -} - -inline void deserialize(utils::buffer_deserializer& buffer, std::chrono::steady_clock::time_point& tp) -{ - using time_point = std::chrono::steady_clock::time_point; - using duration = time_point::duration; - - const auto count = buffer.read(); - tp = time_point{duration{count}}; -} - -inline void serialize(utils::buffer_serializer& buffer, const std::chrono::system_clock::time_point& tp) -{ - buffer.write(tp.time_since_epoch().count()); -} - -inline void deserialize(utils::buffer_deserializer& buffer, std::chrono::system_clock::time_point& tp) -{ - using time_point = std::chrono::system_clock::time_point; - using duration = time_point::duration; - - const auto count = buffer.read(); - tp = time_point{duration{count}}; -} - -inline void serialize(utils::buffer_serializer& buffer, const std::filesystem::path& path) -{ - buffer.write_string(path.wstring()); -} - -inline void deserialize(utils::buffer_deserializer& buffer, std::filesystem::path& path) -{ - path = buffer.read_string(); + inline void serialize(buffer_serializer& buffer, const std::chrono::steady_clock::time_point& tp) + { + buffer.write(tp.time_since_epoch().count()); + } + + inline void deserialize(buffer_deserializer& buffer, std::chrono::steady_clock::time_point& tp) + { + using time_point = std::chrono::steady_clock::time_point; + using duration = time_point::duration; + + const auto count = buffer.read(); + tp = time_point{duration{count}}; + } + + inline void serialize(buffer_serializer& buffer, const std::chrono::system_clock::time_point& tp) + { + buffer.write(tp.time_since_epoch().count()); + } + + inline void deserialize(buffer_deserializer& buffer, std::chrono::system_clock::time_point& tp) + { + using time_point = std::chrono::system_clock::time_point; + using duration = time_point::duration; + + const auto count = buffer.read(); + tp = time_point{duration{count}}; + } + + inline void serialize(buffer_serializer& buffer, const std::filesystem::path& path) + { + buffer.write_string(path.u16string()); + } + + inline void deserialize(buffer_deserializer& buffer, std::filesystem::path& path) + { + path = buffer.read_string(); + } } diff --git a/src/fuzzer/main.cpp b/src/fuzzer/main.cpp index 8a652d84..7179d79f 100644 --- a/src/fuzzer/main.cpp +++ b/src/fuzzer/main.cpp @@ -24,7 +24,8 @@ namespace catch (...) { win_emu.log.disable_output(false); - win_emu.log.print(color::red, "Emulation failed at: 0x%llX\n", win_emu.emu().read_instruction_pointer()); + win_emu.log.print(color::red, "Emulation failed at: 0x%" PRIx64 "\n", + win_emu.emu().read_instruction_pointer()); throw; } @@ -90,7 +91,7 @@ namespace restore_emulator(); - const auto memory = emu.emu().allocate_memory(page_align_up(std::max(data.size(), 1ULL)), + const auto memory = emu.emu().allocate_memory(page_align_up(std::max(data.size(), size_t(1))), memory_permission::read_write); emu.emu().write_memory(memory, data.data(), data.size()); @@ -109,12 +110,12 @@ namespace } }; - struct my_fuzzer_handler : fuzzer::handler + struct my_fuzzing_handler : fuzzer::fuzzing_handler { std::vector emulator_state{}; std::atomic_bool stop_fuzzing{false}; - my_fuzzer_handler(std::vector emulator_state) + my_fuzzing_handler(std::vector emulator_state) : emulator_state(std::move(emulator_state)) { } @@ -137,7 +138,7 @@ namespace utils::buffer_serializer serializer{}; base_emulator.serialize(serializer); - my_fuzzer_handler handler{serializer.move_buffer()}; + my_fuzzing_handler handler{serializer.move_buffer()}; fuzzer::run(handler, concurrency); } diff --git a/src/fuzzer/std_include.hpp b/src/fuzzer/std_include.hpp index 05e56c34..43df7c99 100644 --- a/src/fuzzer/std_include.hpp +++ b/src/fuzzer/std_include.hpp @@ -1,37 +1,5 @@ #pragma once -#ifdef _WIN32 -#pragma warning(push) -#pragma warning(disable: 4005) -#pragma warning(disable: 4127) -#pragma warning(disable: 4201) -#pragma warning(disable: 4244) -#pragma warning(disable: 4245) -#pragma warning(disable: 4324) -#pragma warning(disable: 4458) -#pragma warning(disable: 4471) -#pragma warning(disable: 4505) -#pragma warning(disable: 4702) -#pragma warning(disable: 4996) -#pragma warning(disable: 5054) -#pragma warning(disable: 6011) -#pragma warning(disable: 6297) -#pragma warning(disable: 6385) -#pragma warning(disable: 6386) -#pragma warning(disable: 6387) -#pragma warning(disable: 26110) -#pragma warning(disable: 26451) -#pragma warning(disable: 26444) -#pragma warning(disable: 26451) -#pragma warning(disable: 26489) -#pragma warning(disable: 26495) -#pragma warning(disable: 26498) -#pragma warning(disable: 26812) -#pragma warning(disable: 28020) - -#define WIN32_LEAN_AND_MEAN -#define NOMINMAX - #include #include #include @@ -57,23 +25,6 @@ #include -#define NTDDI_WIN11_GE 0 -#define PHNT_VERSION PHNT_WIN11 -#include -#include -#include - -#ifdef _WIN32 -#pragma warning(pop) -#endif - -#ifdef max -#undef max -#endif - -#ifdef min -#undef min -#endif -#endif +#include using namespace std::literals; diff --git a/src/fuzzing-engine/fuzzer.cpp b/src/fuzzing-engine/fuzzer.cpp index c207eca1..f6338403 100644 --- a/src/fuzzing-engine/fuzzer.cpp +++ b/src/fuzzing-engine/fuzzer.cpp @@ -1,4 +1,6 @@ #include "fuzzer.hpp" +#include + #include "input_generator.hpp" namespace fuzzer @@ -8,7 +10,7 @@ namespace fuzzer class fuzzing_context { public: - fuzzing_context(input_generator& generator, handler& handler) + fuzzing_context(input_generator& generator, fuzzing_handler& handler) : generator(generator) , handler(handler) { @@ -36,7 +38,7 @@ namespace fuzzer } input_generator& generator; - handler& handler; + fuzzing_handler& handler; std::atomic_uint64_t executions{0}; private: @@ -110,7 +112,7 @@ namespace fuzzer }; } - void run(handler& handler, const size_t concurrency) + void run(fuzzing_handler& handler, const size_t concurrency) { input_generator generator{}; fuzzing_context context{generator, handler}; @@ -123,7 +125,8 @@ namespace fuzzer const auto executions = context.executions.exchange(0); const auto highest_scorer = context.generator.get_highest_scorer(); const auto avg_score = context.generator.get_average_score(); - printf("Executions/s: %lld - Score: %llX - Avg: %.3f\n", executions, highest_scorer.score, avg_score); + printf("Executions/s: %" PRIu64 " - Score: %" PRIx64 " - Avg: %.3f\n", executions, highest_scorer.score, + avg_score); } } } diff --git a/src/fuzzing-engine/fuzzer.hpp b/src/fuzzing-engine/fuzzer.hpp index bebfb4f8..900a0f83 100644 --- a/src/fuzzing-engine/fuzzer.hpp +++ b/src/fuzzing-engine/fuzzer.hpp @@ -20,12 +20,12 @@ namespace fuzzer virtual ~executer() = default; virtual execution_result execute(std::span data, - const std::function& coverage_handler) = 0; + const std::function& coverage_handler) = 0; }; - struct handler + struct fuzzing_handler { - virtual ~handler() = default; + virtual ~fuzzing_handler() = default; virtual std::unique_ptr make_executer() = 0; @@ -35,5 +35,5 @@ namespace fuzzer } }; - void run(handler& handler, size_t concurrency = std::thread::hardware_concurrency()); + void run(fuzzing_handler& handler, size_t concurrency = std::thread::hardware_concurrency()); } diff --git a/src/fuzzing-engine/random_generator.cpp b/src/fuzzing-engine/random_generator.cpp index 985f052e..9985840b 100644 --- a/src/fuzzing-engine/random_generator.cpp +++ b/src/fuzzing-engine/random_generator.cpp @@ -1,4 +1,5 @@ #include "random_generator.hpp" +#include namespace fuzzer { diff --git a/src/fuzzing-engine/random_generator.hpp b/src/fuzzing-engine/random_generator.hpp index 357c5eb5..37a61689 100644 --- a/src/fuzzing-engine/random_generator.hpp +++ b/src/fuzzing-engine/random_generator.hpp @@ -2,6 +2,7 @@ #include #include #include +#include namespace fuzzer { diff --git a/src/unicorn-emulator/CMakeLists.txt b/src/unicorn-emulator/CMakeLists.txt index a6bedb3a..3b473f3b 100644 --- a/src/unicorn-emulator/CMakeLists.txt +++ b/src/unicorn-emulator/CMakeLists.txt @@ -13,4 +13,4 @@ target_include_directories(unicorn-emulator INTERFACE ) target_link_libraries(unicorn-emulator PUBLIC emulator) -target_link_libraries(unicorn-emulator PRIVATE unicorn) +target_link_libraries(unicorn-emulator PRIVATE unicorn common) diff --git a/src/unicorn-emulator/unicorn.hpp b/src/unicorn-emulator/unicorn.hpp index 20ee619a..e93d3631 100644 --- a/src/unicorn-emulator/unicorn.hpp +++ b/src/unicorn-emulator/unicorn.hpp @@ -1,7 +1,9 @@ #pragma once +#ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4505) +#endif #ifdef __clang__ #pragma GCC diagnostic push @@ -15,7 +17,9 @@ #pragma GCC diagnostic pop #endif +#ifdef _MSC_VER #pragma warning(pop) +#endif #include diff --git a/src/unicorn-emulator/unicorn_x64_emulator.cpp b/src/unicorn-emulator/unicorn_x64_emulator.cpp index bbcb2a8e..4bac8420 100644 --- a/src/unicorn-emulator/unicorn_x64_emulator.cpp +++ b/src/unicorn-emulator/unicorn_x64_emulator.cpp @@ -5,6 +5,7 @@ #include "unicorn_hook.hpp" #include "function_wrapper.hpp" +#include namespace unicorn { @@ -127,8 +128,17 @@ namespace unicorn throw std::runtime_error("Memory saving not supported atm"); } +#ifndef OS_WINDOWS +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + uc_ctl_context_mode(uc, UC_CTL_CONTEXT_CPU | (in_place ? UC_CTL_CONTEXT_MEMORY : 0)); +#ifndef OS_WINDOWS +#pragma GCC diagnostic pop +#endif + this->size_ = uc_context_size(uc); uce(uc_context_alloc(uc, &this->context_)); } @@ -242,7 +252,17 @@ namespace unicorn unicorn_x64_emulator() { uce(uc_open(UC_ARCH_X86, UC_MODE_64, &this->uc_)); + +#ifndef OS_WINDOWS +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + uce(uc_ctl_set_tcg_buffer_size(this->uc_, 2 << 30 /* 2 gb */)); + +#ifndef OS_WINDOWS +#pragma GCC diagnostic pop +#endif } ~unicorn_x64_emulator() override @@ -316,15 +336,17 @@ namespace unicorn mmio_write_callback write_cb) override { mmio_callbacks cb{ - .read = [c = std::move(read_cb)](uc_engine*, const uint64_t addr, const uint32_t s) - { - return c(addr, s); - }, - .write = [c = std::move(write_cb)](uc_engine*, const uint64_t addr, const uint32_t s, - const uint64_t value) - { - c(addr, s, value); - } + .read = mmio_callbacks::read_wrapper( + [c = std::move(read_cb)](uc_engine*, const uint64_t addr, const uint32_t s) + { + return c(addr, s); + }), + .write = mmio_callbacks::write_wrapper( + [c = std::move(write_cb)](uc_engine*, const uint64_t addr, const uint32_t s, + const uint64_t value) + { + c(addr, s, value); + }) }; uce(uc_mmio_map(*this, address, size, cb.read.get_c_function(), cb.read.get_user_data(), diff --git a/src/unicorn-emulator/unicorn_x64_emulator.hpp b/src/unicorn-emulator/unicorn_x64_emulator.hpp index f349cf53..ca57015b 100644 --- a/src/unicorn-emulator/unicorn_x64_emulator.hpp +++ b/src/unicorn-emulator/unicorn_x64_emulator.hpp @@ -2,11 +2,12 @@ #include #include +#include "platform/platform.hpp" #ifdef UNICORN_EMULATOR_IMPL -#define UNICORN_EMULATOR_DLL_STORAGE __declspec(dllexport) +#define UNICORN_EMULATOR_DLL_STORAGE EXPORT_SYMBOL #else -#define UNICORN_EMULATOR_DLL_STORAGE __declspec(dllimport) +#define UNICORN_EMULATOR_DLL_STORAGE IMPORT_SYMBOL #endif namespace unicorn diff --git a/src/windows-emulator-test/CMakeLists.txt b/src/windows-emulator-test/CMakeLists.txt index 01ccf136..42f1934b 100644 --- a/src/windows-emulator-test/CMakeLists.txt +++ b/src/windows-emulator-test/CMakeLists.txt @@ -16,7 +16,9 @@ target_link_libraries(windows-emulator-test PRIVATE windows-emulator ) -add_dependencies(windows-emulator-test test-sample) +if(WIN32) + add_dependencies(windows-emulator-test test-sample) +endif() add_test(NAME windows-emulator-test COMMAND windows-emulator-test diff --git a/src/windows-emulator-test/main.cpp b/src/windows-emulator-test/main.cpp index 0194ab6e..cdf4fb81 100644 --- a/src/windows-emulator-test/main.cpp +++ b/src/windows-emulator-test/main.cpp @@ -2,6 +2,6 @@ int main(int argc, char* argv[]) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); } diff --git a/src/windows-emulator-test/time_test.cpp b/src/windows-emulator-test/time_test.cpp index 6e114205..70f1971d 100644 --- a/src/windows-emulator-test/time_test.cpp +++ b/src/windows-emulator-test/time_test.cpp @@ -6,8 +6,8 @@ namespace test { std::string output_buffer{}; - emulator_settings settings{ - .arguments = {L"-time"}, + const emulator_settings settings{ + .arguments = {u"-time"}, .stdout_callback = [&output_buffer](const std::string_view data) { output_buffer.append(data); diff --git a/src/windows-emulator/CMakeLists.txt b/src/windows-emulator/CMakeLists.txt index 7948efc7..0fb26ae9 100644 --- a/src/windows-emulator/CMakeLists.txt +++ b/src/windows-emulator/CMakeLists.txt @@ -20,7 +20,6 @@ target_link_libraries(windows-emulator PRIVATE target_link_libraries(windows-emulator PUBLIC emulator - phnt::phnt ) target_include_directories(windows-emulator INTERFACE diff --git a/src/windows-emulator/context_frame.cpp b/src/windows-emulator/context_frame.cpp index 3f9d7a02..3ca0c9d4 100644 --- a/src/windows-emulator/context_frame.cpp +++ b/src/windows-emulator/context_frame.cpp @@ -3,9 +3,9 @@ namespace context_frame { - void restore(x64_emulator& emu, const CONTEXT& context) + void restore(x64_emulator& emu, const CONTEXT64& context) { - if (context.ContextFlags & CONTEXT_DEBUG_REGISTERS) + if (context.ContextFlags & CONTEXT_DEBUG_REGISTERS_64) { emu.reg(x64_register::dr0, context.Dr0); emu.reg(x64_register::dr1, context.Dr1); @@ -15,7 +15,7 @@ namespace context_frame emu.reg(x64_register::dr7, context.Dr7); } - if (context.ContextFlags & CONTEXT_CONTROL) + if (context.ContextFlags & CONTEXT_CONTROL_64) { emu.reg(x64_register::ss, context.SegSs); emu.reg(x64_register::cs, context.SegCs); @@ -26,7 +26,7 @@ namespace context_frame emu.reg(x64_register::eflags, context.EFlags); } - if (context.ContextFlags & CONTEXT_INTEGER) + if (context.ContextFlags & CONTEXT_INTEGER_64) { emu.reg(x64_register::rax, context.Rax); emu.reg(x64_register::rbx, context.Rbx); @@ -53,7 +53,7 @@ namespace context_frame emu.reg(x64_register::gs, context.SegGs); }*/ - if (context.ContextFlags & CONTEXT_FLOATING_POINT) + if (context.ContextFlags & CONTEXT_FLOATING_POINT_64) { emu.reg(x64_register::fpcw, context.FltSave.ControlWord); emu.reg(x64_register::fpsw, context.FltSave.StatusWord); @@ -66,7 +66,7 @@ namespace context_frame } } - if (context.ContextFlags & CONTEXT_XSTATE) + if (context.ContextFlags & CONTEXT_XSTATE_64) { emu.reg(x64_register::mxcsr, context.MxCsr); @@ -78,9 +78,9 @@ namespace context_frame } } - void save(x64_emulator& emu, CONTEXT& context) + void save(x64_emulator& emu, CONTEXT64& context) { - if (context.ContextFlags & CONTEXT_DEBUG_REGISTERS) + if (context.ContextFlags & CONTEXT_DEBUG_REGISTERS_64) { context.Dr0 = emu.reg(x64_register::dr0); context.Dr1 = emu.reg(x64_register::dr1); @@ -90,7 +90,7 @@ namespace context_frame context.Dr7 = emu.reg(x64_register::dr7); } - if (context.ContextFlags & CONTEXT_CONTROL) + if (context.ContextFlags & CONTEXT_CONTROL_64) { context.SegSs = emu.reg(x64_register::ss); context.SegCs = emu.reg(x64_register::cs); @@ -99,7 +99,7 @@ namespace context_frame context.EFlags = emu.reg(x64_register::eflags); } - if (context.ContextFlags & CONTEXT_INTEGER) + if (context.ContextFlags & CONTEXT_INTEGER_64) { context.Rax = emu.reg(x64_register::rax); context.Rbx = emu.reg(x64_register::rbx); @@ -118,7 +118,7 @@ namespace context_frame context.R15 = emu.reg(x64_register::r15); } - if (context.ContextFlags & CONTEXT_SEGMENTS) + if (context.ContextFlags & CONTEXT_SEGMENTS_64) { context.SegDs = emu.reg(x64_register::ds); context.SegEs = emu.reg(x64_register::es); @@ -126,7 +126,7 @@ namespace context_frame context.SegGs = emu.reg(x64_register::gs); } - if (context.ContextFlags & CONTEXT_FLOATING_POINT) + if (context.ContextFlags & CONTEXT_FLOATING_POINT_64) { context.FltSave.ControlWord = emu.reg(x64_register::fpcw); context.FltSave.StatusWord = emu.reg(x64_register::fpsw); @@ -138,7 +138,7 @@ namespace context_frame } } - if (context.ContextFlags & CONTEXT_XSTATE) + if (context.ContextFlags & CONTEXT_XSTATE_64) { context.MxCsr = emu.reg(x64_register::mxcsr); for (int i = 0; i < 16; i++) diff --git a/src/windows-emulator/context_frame.hpp b/src/windows-emulator/context_frame.hpp index 63f3e36b..9f922446 100644 --- a/src/windows-emulator/context_frame.hpp +++ b/src/windows-emulator/context_frame.hpp @@ -3,6 +3,6 @@ namespace context_frame { - void save(x64_emulator& emu, CONTEXT& context); - void restore(x64_emulator& emu, const CONTEXT& context); + void save(x64_emulator& emu, CONTEXT64& context); + void restore(x64_emulator& emu, const CONTEXT64& context); } diff --git a/src/windows-emulator/debugging/gdb_stub.hpp b/src/windows-emulator/debugging/gdb_stub.hpp index 4248737e..82dbae58 100644 --- a/src/windows-emulator/debugging/gdb_stub.hpp +++ b/src/windows-emulator/debugging/gdb_stub.hpp @@ -35,4 +35,5 @@ struct gdb_stub_handler virtual void on_interrupt() = 0; }; -bool run_gdb_stub(gdb_stub_handler& handler, std::string target_description, size_t register_count, std::string bind_address); +bool run_gdb_stub(gdb_stub_handler& handler, std::string target_description, size_t register_count, + std::string bind_address); diff --git a/src/windows-emulator/devices/afd_endpoint.cpp b/src/windows-emulator/devices/afd_endpoint.cpp index 9cff970f..8b9766ce 100644 --- a/src/windows-emulator/devices/afd_endpoint.cpp +++ b/src/windows-emulator/devices/afd_endpoint.cpp @@ -32,23 +32,23 @@ namespace return win_emu.emu().read_memory(data.buffer); } - std::pair> get_poll_info( + std::pair> get_poll_info( windows_emulator& win_emu, const io_device_context& c) { - constexpr auto info_size = offsetof(AFD_POLL_INFO, Handles); + constexpr auto info_size = offsetof(AFD_POLL_INFO64, Handles); if (!c.input_buffer || c.input_buffer_length < info_size) { throw std::runtime_error("Bad AFD poll data"); } - AFD_POLL_INFO poll_info{}; + AFD_POLL_INFO64 poll_info{}; win_emu.emu().read_memory(c.input_buffer, &poll_info, info_size); - std::vector handle_info{}; + std::vector handle_info{}; - const emulator_object handle_info_obj{win_emu.emu(), c.input_buffer + info_size}; + const emulator_object handle_info_obj{win_emu.emu(), c.input_buffer + info_size}; - if (c.input_buffer_length < (info_size + sizeof(AFD_POLL_HANDLE_INFO) * poll_info.NumberOfHandles)) + if (c.input_buffer_length < (info_size + sizeof(AFD_POLL_HANDLE_INFO64) * poll_info.NumberOfHandles)) { throw std::runtime_error("Bad AFD poll handle data"); } @@ -126,7 +126,7 @@ namespace NTSTATUS perform_poll(windows_emulator& win_emu, const io_device_context& c, const std::span endpoints, - const std::span handles) + const std::span handles) { std::vector poll_data{}; poll_data.resize(endpoints.size()); @@ -147,8 +147,8 @@ namespace return STATUS_PENDING; } - constexpr auto info_size = offsetof(AFD_POLL_INFO, Handles); - const emulator_object handle_info_obj{win_emu.emu(), c.input_buffer + info_size}; + constexpr auto info_size = offsetof(AFD_POLL_INFO64, Handles); + const emulator_object handle_info_obj{win_emu.emu(), c.input_buffer + info_size}; size_t current_index = 0; @@ -170,7 +170,7 @@ namespace assert(current_index == static_cast(count)); - emulator_object{win_emu.emu(), c.input_buffer}.access([&](AFD_POLL_INFO& info) + emulator_object{win_emu.emu(), c.input_buffer}.access([&](AFD_POLL_INFO64& info) { info.NumberOfHandles = static_cast(current_index); }); @@ -354,7 +354,7 @@ namespace } const auto* address = reinterpret_cast(data.data() + address_offset); - const auto address_size = static_cast(data.size() - address_offset); + const auto address_size = static_cast(data.size() - address_offset); const network::address addr(address, address_size); @@ -367,7 +367,7 @@ namespace } static std::vector resolve_endpoints(windows_emulator& win_emu, - const std::span handles) + const std::span handles) { auto& proc = win_emu.process(); @@ -376,7 +376,7 @@ namespace for (const auto& handle : handles) { - auto* device = proc.devices.get(reinterpret_cast(handle.Handle)); + auto* device = proc.devices.get(handle.Handle); if (!device) { throw std::runtime_error("Bad device!"); @@ -428,17 +428,17 @@ namespace { auto& emu = win_emu.emu(); - if (c.input_buffer_length < sizeof(AFD_RECV_DATAGRAM_INFO)) + if (c.input_buffer_length < sizeof(AFD_RECV_DATAGRAM_INFO>)) { return STATUS_BUFFER_TOO_SMALL; } - const auto receive_info = emu.read_memory(c.input_buffer); - const auto buffer = emu.read_memory(receive_info.BufferArray); + const auto receive_info = emu.read_memory>>(c.input_buffer); + const auto buffer = emu.read_memory>>(receive_info.BufferArray); std::vector address{}; - ULONG address_length = 0x1000; + unsigned long address_length = 0x1000; if (receive_info.AddressLength) { address_length = emu.read_memory(receive_info.AddressLength); @@ -451,12 +451,12 @@ namespace return STATUS_INVALID_PARAMETER; } - int fromlength = static_cast(address.size()); + auto fromlength = static_cast(address.size()); std::vector data{}; data.resize(buffer.len); - const auto recevied_data = recvfrom(*this->s_, data.data(), static_cast(data.size()), 0, + const auto recevied_data = recvfrom(*this->s_, data.data(), static_cast(data.size()), 0, reinterpret_cast(address.data()), &fromlength); if (recevied_data < 0) @@ -482,7 +482,7 @@ namespace if (c.io_status_block) { - IO_STATUS_BLOCK block{}; + IO_STATUS_BLOCK> block{}; block.Information = static_cast(recevied_data); c.io_status_block.write(block); } @@ -494,24 +494,24 @@ namespace { const auto& emu = win_emu.emu(); - if (c.input_buffer_length < sizeof(AFD_SEND_DATAGRAM_INFO)) + if (c.input_buffer_length < sizeof(AFD_SEND_DATAGRAM_INFO>)) { return STATUS_BUFFER_TOO_SMALL; } - const auto send_info = emu.read_memory(c.input_buffer); - const auto buffer = emu.read_memory(send_info.BufferArray); + const auto send_info = emu.read_memory>>(c.input_buffer); + const auto buffer = emu.read_memory>>(send_info.BufferArray); const auto address = emu.read_memory(send_info.TdiConnInfo.RemoteAddress, - send_info.TdiConnInfo.RemoteAddressLength); + static_cast(send_info.TdiConnInfo.RemoteAddressLength)); const network::address target(reinterpret_cast(address.data()), - static_cast(address.size())); + static_cast(address.size())); const auto data = emu.read_memory(buffer.buf, buffer.len); const auto sent_data = sendto(*this->s_, reinterpret_cast(data.data()), - static_cast(data.size()), 0 /* ? */, &target.get_addr(), + static_cast(data.size()), 0 /* ? */, &target.get_addr(), target.get_size()); if (sent_data < 0) @@ -528,7 +528,7 @@ namespace if (c.io_status_block) { - IO_STATUS_BLOCK block{}; + IO_STATUS_BLOCK> block{}; block.Information = static_cast(sent_data); c.io_status_block.write(block); } diff --git a/src/windows-emulator/devices/afd_types.hpp b/src/windows-emulator/devices/afd_types.hpp index 944ae5e4..55310bce 100644 --- a/src/windows-emulator/devices/afd_types.hpp +++ b/src/windows-emulator/devices/afd_types.hpp @@ -3,87 +3,93 @@ #include "../std_include.hpp" typedef LONG TDI_STATUS; -typedef PVOID CONNECTION_CONTEXT; -typedef struct _TDI_CONNECTION_INFORMATION +template +struct TDI_CONNECTION_INFORMATION { LONG UserDataLength; - PVOID UserData; + typename Traits::PVOID UserData; LONG OptionsLength; - PVOID Options; + typename Traits::PVOID Options; LONG RemoteAddressLength; - PVOID RemoteAddress; -} TDI_CONNECTION_INFORMATION, *PTDI_CONNECTION_INFORMATION; + typename Traits::PVOID RemoteAddress; +}; -typedef struct _TDI_REQUEST +template +struct TDI_REQUEST { union { - HANDLE AddressHandle; - CONNECTION_CONTEXT ConnectionContext; - HANDLE ControlChannel; + typename Traits::HANDLE AddressHandle; + EMULATOR_CAST(typename Traits::PVOID, CONNECTION_CONTEXT) ConnectionContext; + typename Traits::HANDLE ControlChannel; } Handle; - PVOID RequestNotifyObject; - PVOID RequestContext; + typename Traits::PVOID RequestNotifyObject; + typename Traits::PVOID RequestContext; TDI_STATUS TdiStatus; -} TDI_REQUEST, *PTDI_REQUEST; +}; -typedef struct _TDI_REQUEST_SEND_DATAGRAM +template +struct TDI_REQUEST_SEND_DATAGRAM { - TDI_REQUEST Request; - PTDI_CONNECTION_INFORMATION SendDatagramInformation; -} TDI_REQUEST_SEND_DATAGRAM, *PTDI_REQUEST_SEND_DATAGRAM; + TDI_REQUEST Request; + EMULATOR_CAST(typename Traits::PVOID, PTDI_CONNECTION_INFORMATION) SendDatagramInformation; +}; -typedef struct _AFD_SEND_INFO +template +struct AFD_SEND_INFO { - LPWSABUF BufferArray; + EMULATOR_CAST(typename Traits::PVOID, LPWSABUF) BufferArray; ULONG BufferCount; ULONG AfdFlags; ULONG TdiFlags; -} AFD_SEND_INFO, *PAFD_SEND_INFO; +}; -typedef struct _AFD_SEND_DATAGRAM_INFO +template +struct AFD_SEND_DATAGRAM_INFO { - LPWSABUF BufferArray; + EMULATOR_CAST(typename Traits::PVOID, LPWSABUF) BufferArray; ULONG BufferCount; ULONG AfdFlags; - TDI_REQUEST_SEND_DATAGRAM TdiRequest; - TDI_CONNECTION_INFORMATION TdiConnInfo; -} AFD_SEND_DATAGRAM_INFO, *PAFD_SEND_DATAGRAM_INFO; + TDI_REQUEST_SEND_DATAGRAM TdiRequest; + TDI_CONNECTION_INFORMATION TdiConnInfo; +}; -typedef struct _AFD_RECV_INFO +template +struct AFD_RECV_INFO { - LPWSABUF BufferArray; + EMULATOR_CAST(typename Traits::PVOID, LPWSABUF) BufferArray; ULONG BufferCount; ULONG AfdFlags; ULONG TdiFlags; -} AFD_RECV_INFO, *PAFD_RECV_INFO; +}; -typedef struct _AFD_RECV_DATAGRAM_INFO +template +struct AFD_RECV_DATAGRAM_INFO { - LPWSABUF BufferArray; + EMULATOR_CAST(typename Traits::PVOID, LPWSABUF) BufferArray; ULONG BufferCount; ULONG AfdFlags; ULONG TdiFlags; - PVOID Address; - PULONG AddressLength; -} AFD_RECV_DATAGRAM_INFO, *PAFD_RECV_DATAGRAM_INFO; + typename Traits::PVOID Address; + EMULATOR_CAST(typename Traits::PVOID, PULONG) AddressLength; +}; -typedef struct _AFD_POLL_HANDLE_INFO +struct AFD_POLL_HANDLE_INFO64 { - HANDLE Handle; + EmulatorTraits::HANDLE Handle; ULONG PollEvents; NTSTATUS Status; -} AFD_POLL_HANDLE_INFO, *PAFD_POLL_HANDLE_INFO; +}; -typedef struct _AFD_POLL_INFO +struct AFD_POLL_INFO64 { LARGE_INTEGER Timeout; ULONG NumberOfHandles; BOOLEAN Unique; - AFD_POLL_HANDLE_INFO Handles[1]; -} AFD_POLL_INFO, *PAFD_POLL_INFO; + AFD_POLL_HANDLE_INFO64 Handles[1]; +}; #define AFD_POLL_RECEIVE_BIT 0 #define AFD_POLL_RECEIVE (1 << AFD_POLL_RECEIVE_BIT) diff --git a/src/windows-emulator/emulator_utils.hpp b/src/windows-emulator/emulator_utils.hpp index bfa448a3..c151761b 100644 --- a/src/windows-emulator/emulator_utils.hpp +++ b/src/windows-emulator/emulator_utils.hpp @@ -140,6 +140,8 @@ private: uint64_t address_{}; }; + +// TODO: warning emulator_utils is hardcoded for 64bit unicode_string usage class emulator_allocator { public: @@ -179,14 +181,15 @@ public: return emulator_object(*this->emu_, potential_start); } - wchar_t* copy_string(const std::wstring_view str) + + char16_t* copy_string(const std::u16string_view str) { - UNICODE_STRING uc_str{}; + UNICODE_STRING> uc_str{}; this->make_unicode_string(uc_str, str); - return uc_str.Buffer; + return reinterpret_cast(uc_str.Buffer); } - void make_unicode_string(UNICODE_STRING& result, const std::wstring_view str) + void make_unicode_string(UNICODE_STRING>& result, const std::u16string_view str) { constexpr auto element_size = sizeof(str[0]); constexpr auto required_alignment = alignof(decltype(str[0])); @@ -199,16 +202,16 @@ public: constexpr std::array nullbyte{}; this->emu_->write_memory(string_buffer + total_length, nullbyte.data(), nullbyte.size()); - result.Buffer = reinterpret_cast(string_buffer); + result.Buffer = string_buffer; result.Length = static_cast(total_length); result.MaximumLength = static_cast(total_length + element_size); } - emulator_object make_unicode_string(const std::wstring_view str) + emulator_object>> make_unicode_string(const std::u16string_view str) { - const auto unicode_string = this->reserve(); + const auto unicode_string = this->reserve>>(); - unicode_string.access([&](UNICODE_STRING& unicode_str) + unicode_string.access([&](UNICODE_STRING>& unicode_str) { this->make_unicode_string(unicode_str, str); }); @@ -267,29 +270,31 @@ private: uint64_t active_address_{0}; }; -inline std::wstring read_unicode_string(const emulator& emu, const UNICODE_STRING ucs) -{ - static_assert(offsetof(UNICODE_STRING, Length) == 0); - static_assert(offsetof(UNICODE_STRING, MaximumLength) == 2); - static_assert(offsetof(UNICODE_STRING, Buffer) == 8); - static_assert(sizeof(UNICODE_STRING) == 16); - std::wstring result{}; +inline std::u16string read_unicode_string(const emulator& emu, const UNICODE_STRING> ucs) +{ + static_assert(offsetof(UNICODE_STRING>, Length) == 0); + static_assert(offsetof(UNICODE_STRING>, MaximumLength) == 2); + static_assert(offsetof(UNICODE_STRING>, Buffer) == 8); + static_assert(sizeof(UNICODE_STRING>) == 16); + + std::u16string result{}; result.resize(ucs.Length / 2); - emu.read_memory(reinterpret_cast(ucs.Buffer), result.data(), ucs.Length); + emu.read_memory(ucs.Buffer, result.data(), ucs.Length); return result; } -inline std::wstring read_unicode_string(const emulator& emu, const emulator_object uc_string) +inline std::u16string read_unicode_string(const emulator& emu, + const emulator_object>> uc_string) { const auto ucs = uc_string.read(); return read_unicode_string(emu, ucs); } -inline std::wstring read_unicode_string(emulator& emu, const UNICODE_STRING* uc_string) +inline std::u16string read_unicode_string(emulator& emu, const UNICODE_STRING>* uc_string) { - return read_unicode_string(emu, emulator_object{emu, uc_string}); + return read_unicode_string(emu, emulator_object>>{emu, uc_string}); } diff --git a/src/windows-emulator/handles.hpp b/src/windows-emulator/handles.hpp index 08ed0831..35362a4f 100644 --- a/src/windows-emulator/handles.hpp +++ b/src/windows-emulator/handles.hpp @@ -34,21 +34,25 @@ struct handle_value static_assert(sizeof(handle_value) == 8); +// TODO: this is a concrete 64bit handle union handle { handle_value value; uint64_t bits; - HANDLE h; + std::uint64_t h; }; -inline void serialize(utils::buffer_serializer& buffer, const handle& h) +namespace utils { - buffer.write(h.bits); -} + inline void serialize(buffer_serializer& buffer, const handle& h) + { + buffer.write(h.bits); + } -inline void deserialize(utils::buffer_deserializer& buffer, handle& h) -{ - buffer.read(h.bits); + inline void deserialize(buffer_deserializer& buffer, handle& h) + { + buffer.read(h.bits); + } } inline bool operator==(const handle& h1, const handle& h2) diff --git a/src/windows-emulator/io_device.cpp b/src/windows-emulator/io_device.cpp index e3eb0669..00374b39 100644 --- a/src/windows-emulator/io_device.cpp +++ b/src/windows-emulator/io_device.cpp @@ -12,21 +12,21 @@ namespace }; } -std::unique_ptr create_device(const std::wstring_view device) +std::unique_ptr create_device(const std::u16string_view device) { - if (device == L"CNG" - || device == L"KsecDD" - || device == L"PcwDrv" - || device == L"DeviceApi\\CMApi" - || device == L"ConDrv\\Server") + if (device == u"CNG" + || device == u"KsecDD" + || device == u"PcwDrv" + || device == u"DeviceApi\\CMApi" + || device == u"ConDrv\\Server") { return std::make_unique(); } - if (device == L"Afd\\Endpoint") + if (device == u"Afd\\Endpoint") { return create_afd_endpoint(); } - throw std::runtime_error("Unsupported device: " + std::string(device.begin(), device.end())); + throw std::runtime_error("Unsupported device: " + u16_to_u8(device)); } diff --git a/src/windows-emulator/io_device.hpp b/src/windows-emulator/io_device.hpp index 5b1ab9a1..965d1da3 100644 --- a/src/windows-emulator/io_device.hpp +++ b/src/windows-emulator/io_device.hpp @@ -15,7 +15,7 @@ struct io_device_context handle event{}; emulator_pointer /*PIO_APC_ROUTINE*/ apc_routine{}; emulator_pointer apc_context{}; - emulator_object io_status_block; + emulator_object>> io_status_block; ULONG io_control_code{}; emulator_pointer input_buffer{}; ULONG input_buffer_length{}; @@ -65,11 +65,12 @@ struct io_device_creation_data uint32_t length; }; -inline void write_io_status(const emulator_object io_status_block, const NTSTATUS status) +inline void write_io_status(const emulator_object>> io_status_block, + const NTSTATUS status) { if (io_status_block) { - io_status_block.access([&](IO_STATUS_BLOCK& status_block) + io_status_block.access([&](IO_STATUS_BLOCK>& status_block) { status_block.Status = status; }); @@ -131,14 +132,14 @@ struct stateless_device : io_device } }; -std::unique_ptr create_device(std::wstring_view device); +std::unique_ptr create_device(std::u16string_view device); class io_device_container : public io_device { public: io_device_container() = default; - io_device_container(std::wstring device, windows_emulator& win_emu, const io_device_creation_data& data) + io_device_container(std::u16string device, windows_emulator& win_emu, const io_device_creation_data& data) : device_name_(std::move(device)) { this->setup(); @@ -182,7 +183,7 @@ public: } private: - std::wstring device_name_{}; + std::u16string device_name_{}; std::unique_ptr device_{}; void setup() diff --git a/src/windows-emulator/kusd_mmio.cpp b/src/windows-emulator/kusd_mmio.cpp index 83fdb0e4..b88e2d23 100644 --- a/src/windows-emulator/kusd_mmio.cpp +++ b/src/windows-emulator/kusd_mmio.cpp @@ -5,14 +5,14 @@ #include constexpr auto KUSD_ADDRESS = 0x7ffe0000ULL; -constexpr auto KUSD_SIZE = sizeof(KUSER_SHARED_DATA); +constexpr auto KUSD_SIZE = sizeof(KUSER_SHARED_DATA64); constexpr auto KUSD_BUFFER_SIZE = page_align_up(KUSD_SIZE); namespace { - void setup_kusd(KUSER_SHARED_DATA& kusd, const bool use_relative_time) + void setup_kusd(KUSER_SHARED_DATA64& kusd, const bool use_relative_time) { - memset(&kusd, 0, sizeof(kusd)); + memset(reinterpret_cast(&kusd), 0, sizeof(kusd)); kusd.TickCountMultiplier = 0x0fa00000; kusd.InterruptTime.LowPart = 0x17bd9547; @@ -88,15 +88,18 @@ namespace } } -inline void serialize(utils::buffer_serializer& buffer, const KUSER_SHARED_DATA& kusd) +namespace utils { - static_assert(KUSD_SIZE == sizeof(kusd)); - buffer.write(&kusd, KUSD_SIZE); -} + inline void serialize(buffer_serializer& buffer, const KUSER_SHARED_DATA64& kusd) + { + static_assert(KUSD_SIZE == sizeof(kusd)); + buffer.write(&kusd, KUSD_SIZE); + } -inline void deserialize(utils::buffer_deserializer& buffer, KUSER_SHARED_DATA& kusd) -{ - buffer.read(&kusd, KUSD_SIZE); + inline void deserialize(buffer_deserializer& buffer, KUSER_SHARED_DATA64& kusd) + { + buffer.read(&kusd, KUSD_SIZE); + } } kusd_mmio::kusd_mmio(x64_emulator& emu, process_context& process) @@ -154,7 +157,7 @@ uint64_t kusd_mmio::read(const uint64_t addr, const size_t size) } const auto end = addr + size; - const auto valid_end = std::min(end, KUSD_SIZE); + const auto valid_end = std::min(end, static_cast(KUSD_SIZE)); const auto real_size = valid_end - addr; if (real_size > sizeof(result)) @@ -180,7 +183,7 @@ void kusd_mmio::update() if (this->use_relative_time_) { const auto passed_time = this->process_->executed_instructions; - const auto clock_frequency = this->kusd_.QpcFrequency; + const auto clock_frequency = static_cast(this->kusd_.QpcFrequency); using duration = std::chrono::system_clock::duration; time += duration(passed_time * duration::period::den / clock_frequency); @@ -206,7 +209,7 @@ void kusd_mmio::register_mmio() [this](const uint64_t addr, const size_t size) { return this->read(addr, size); - }, [this](const uint64_t, const size_t, const uint64_t) + }, [](const uint64_t, const size_t, const uint64_t) { // Writing not supported! }); diff --git a/src/windows-emulator/kusd_mmio.hpp b/src/windows-emulator/kusd_mmio.hpp index 97548ceb..fc7c2adc 100644 --- a/src/windows-emulator/kusd_mmio.hpp +++ b/src/windows-emulator/kusd_mmio.hpp @@ -24,12 +24,12 @@ public: void serialize(utils::buffer_serializer& buffer) const; void deserialize(utils::buffer_deserializer& buffer); - KUSER_SHARED_DATA& get() + KUSER_SHARED_DATA64& get() { return this->kusd_; } - const KUSER_SHARED_DATA& get() const + const KUSER_SHARED_DATA64& get() const { return this->kusd_; } @@ -45,7 +45,7 @@ private: bool registered_{}; bool use_relative_time_{}; - KUSER_SHARED_DATA kusd_{}; + KUSER_SHARED_DATA64 kusd_{}; std::chrono::system_clock::time_point start_time_{}; uint64_t read(uint64_t addr, size_t size); diff --git a/src/windows-emulator/logger.cpp b/src/windows-emulator/logger.cpp index ebb32146..b38e94de 100644 --- a/src/windows-emulator/logger.cpp +++ b/src/windows-emulator/logger.cpp @@ -75,6 +75,12 @@ namespace return {buffer, static_cast(count)}; } +#define format_to_string(msg, str)\ + va_list ap;\ + va_start(ap, msg);\ + const auto str = format(&ap, msg);\ + va_end(ap); + void print_colored(const std::string_view& line, const color_type base_color) { const auto _ = utils::finally(&reset_color); @@ -83,18 +89,48 @@ namespace } } -void logger::print(const color c, const char* message, ...) const +void logger::print(const color c, const std::string_view message) const { if (this->disable_output_) { return; } - va_list ap; - va_start(ap, message); - - const auto data = format(&ap, message); - print_colored(data, get_color_type(c)); - - va_end(ap); + print_colored(message, get_color_type(c)); +} + +void logger::print(const color c, const char* message, ...) const +{ + format_to_string(message, data); + this->print(c, data); +} + +void logger::info(const char* message, ...) const +{ + format_to_string(message, data); + this->print(color::cyan, data); +} + +void logger::warn(const char* message, ...) const +{ + format_to_string(message, data); + this->print(color::yellow, data); +} + +void logger::error(const char* message, ...) const +{ + format_to_string(message, data); + this->print(color::red, data); +} + +void logger::success(const char* message, ...) const +{ + format_to_string(message, data); + this->print(color::green, data); +} + +void logger::log(const char* message, ...) const +{ + format_to_string(message, data); + this->print(color::gray, data); } diff --git a/src/windows-emulator/logger.hpp b/src/windows-emulator/logger.hpp index 139d0a1d..734e1ef6 100644 --- a/src/windows-emulator/logger.hpp +++ b/src/windows-emulator/logger.hpp @@ -1,5 +1,11 @@ #pragma once +#ifdef OS_WINDOWS +#define FORMAT_ATTRIBUTE(fmt_pos, var_pos) +#else +#define FORMAT_ATTRIBUTE(fmt_pos, var_pos) __attribute__((format( printf, fmt_pos, var_pos))) +#endif + enum class color { black, @@ -17,37 +23,13 @@ enum class color class logger { public: - void print(color c, const char* message, ...) const; - - template - void info(const char* message, Args... args) - { - this->print(color::cyan, message, args...); - } - - template - void warn(const char* message, Args... args) - { - this->print(color::yellow, message, args...); - } - - template - void error(const char* message, Args... args) - { - this->print(color::red, message, args...); - } - - template - void success(const char* message, Args... args) - { - this->print(color::green, message, args...); - } - - template - void log(const char* message, Args... args) - { - this->print(color::gray, message, args...); - } + void print(color c, std::string_view message) const; + void print(color c, const char* message, ...) const FORMAT_ATTRIBUTE(3, 4); + void info(const char* message, ...) const FORMAT_ATTRIBUTE(2, 3); + void warn(const char* message, ...) const FORMAT_ATTRIBUTE(2, 3); + void error(const char* message, ...) const FORMAT_ATTRIBUTE(2, 3); + void success(const char* message, ...) const FORMAT_ATTRIBUTE(2, 3); + void log(const char* message, ...) const FORMAT_ATTRIBUTE(2, 3); void disable_output(const bool value) { diff --git a/src/windows-emulator/memory_utils.hpp b/src/windows-emulator/memory_utils.hpp index 40fbcf58..30d36851 100644 --- a/src/windows-emulator/memory_utils.hpp +++ b/src/windows-emulator/memory_utils.hpp @@ -21,7 +21,7 @@ inline std::string get_permission_string(const memory_permission permission) inline memory_permission map_nt_to_emulator_protection(uint32_t nt_protection) { - nt_protection &= ~PAGE_GUARD; // TODO: Implement that + nt_protection &= ~static_cast(PAGE_GUARD); // TODO: Implement that switch (nt_protection) { diff --git a/src/windows-emulator/module/module_manager.cpp b/src/windows-emulator/module/module_manager.cpp index f487b1f0..881be43e 100644 --- a/src/windows-emulator/module/module_manager.cpp +++ b/src/windows-emulator/module/module_manager.cpp @@ -19,46 +19,49 @@ namespace } } -static void serialize(utils::buffer_serializer& buffer, const exported_symbol& sym) +namespace utils { - buffer.write(sym.name); - buffer.write(sym.ordinal); - buffer.write(sym.rva); - buffer.write(sym.address); -} + static void serialize(buffer_serializer& buffer, const exported_symbol& sym) + { + buffer.write(sym.name); + buffer.write(sym.ordinal); + buffer.write(sym.rva); + buffer.write(sym.address); + } -static void deserialize(utils::buffer_deserializer& buffer, exported_symbol& sym) -{ - buffer.read(sym.name); - buffer.read(sym.ordinal); - buffer.read(sym.rva); - buffer.read(sym.address); -} + static void deserialize(buffer_deserializer& buffer, exported_symbol& sym) + { + buffer.read(sym.name); + buffer.read(sym.ordinal); + buffer.read(sym.rva); + buffer.read(sym.address); + } -static void serialize(utils::buffer_serializer& buffer, const mapped_module& mod) -{ - buffer.write_string(mod.name); - buffer.write_string(mod.path.wstring()); + static void serialize(buffer_serializer& buffer, const mapped_module& mod) + { + buffer.write_string(mod.name); + buffer.write(mod.path.u16string()); - buffer.write(mod.image_base); - buffer.write(mod.size_of_image); - buffer.write(mod.entry_point); + buffer.write(mod.image_base); + buffer.write(mod.size_of_image); + buffer.write(mod.entry_point); - buffer.write_vector(mod.exports); - buffer.write_map(mod.address_names); -} + buffer.write_vector(mod.exports); + buffer.write_map(mod.address_names); + } -static void deserialize(utils::buffer_deserializer& buffer, mapped_module& mod) -{ - mod.name = buffer.read_string(); - mod.path = buffer.read_string(); + static void deserialize(buffer_deserializer& buffer, mapped_module& mod) + { + mod.name = buffer.read_string(); + mod.path = buffer.read_string(); - buffer.read(mod.image_base); - buffer.read(mod.size_of_image); - buffer.read(mod.entry_point); + buffer.read(mod.image_base); + buffer.read(mod.size_of_image); + buffer.read(mod.entry_point); - buffer.read_vector(mod.exports); - buffer.read_map(mod.address_names); + buffer.read_vector(mod.exports); + buffer.read_map(mod.address_names); + } } module_manager::module_manager(emulator& emu) @@ -82,7 +85,7 @@ mapped_module* module_manager::map_module(const std::filesystem::path& file, log { auto mod = map_module_from_file(*this->emu_, std::move(canonical_file)); - logger.log("Mapped %s at 0x%llX\n", mod.path.generic_string().c_str(), mod.image_base); + logger.log("Mapped %s at 0x%" PRIx64 "\n", mod.path.generic_string().c_str(), mod.image_base); const auto image_base = mod.image_base; const auto entry = this->modules_.try_emplace(image_base, std::move(mod)); diff --git a/src/windows-emulator/module/module_mapping.cpp b/src/windows-emulator/module/module_mapping.cpp index d9adb256..8d1577b1 100644 --- a/src/windows-emulator/module/module_mapping.cpp +++ b/src/windows-emulator/module/module_mapping.cpp @@ -7,9 +7,15 @@ namespace { - uint64_t get_first_section_offset(const IMAGE_NT_HEADERS& nt_headers, const uint64_t nt_headers_offset) + uint64_t get_first_section_offset(const PENTHeaders_t& nt_headers, const uint64_t nt_headers_offset) { - const auto first_section_absolute = reinterpret_cast(IMAGE_FIRST_SECTION(&nt_headers)); + const uint8_t* nt_headers_addr = reinterpret_cast(&nt_headers); + size_t optional_header_offset = reinterpret_cast(&(nt_headers.OptionalHeader)) - reinterpret_cast< + uintptr_t>(&nt_headers); + size_t optional_header_size = nt_headers.FileHeader.SizeOfOptionalHeader; + const uint8_t* first_section_addr = nt_headers_addr + optional_header_offset + optional_header_size; + + const auto first_section_absolute = reinterpret_cast(first_section_addr); const auto absolute_base = reinterpret_cast(&nt_headers); return nt_headers_offset + (first_section_absolute - absolute_base); } @@ -24,7 +30,7 @@ namespace } void collect_exports(mapped_module& binary, const utils::safe_buffer_accessor buffer, - const IMAGE_OPTIONAL_HEADER& optional_header) + const PEOptionalHeader_t& optional_header) { auto& export_directory_entry = optional_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; if (export_directory_entry.VirtualAddress == 0 || export_directory_entry.Size == 0) @@ -75,7 +81,7 @@ namespace } void apply_relocations(const mapped_module& binary, const utils::safe_buffer_accessor buffer, - const IMAGE_OPTIONAL_HEADER& optional_header) + const PEOptionalHeader_t& optional_header) { const auto delta = binary.image_base - optional_header.ImageBase; if (delta == 0) @@ -113,7 +119,7 @@ namespace const auto entry = entries.get(i); const int type = entry >> 12; - const int offset = entry & 0xfff; + const auto offset = static_cast(entry & 0xfff); const auto total_offset = relocation.VirtualAddress + offset; switch (type) @@ -138,7 +144,7 @@ namespace void map_sections(emulator& emu, mapped_module& binary, const utils::safe_buffer_accessor buffer, - const IMAGE_NT_HEADERS& nt_headers, const uint64_t nt_headers_offset) + const PENTHeaders_t& nt_headers, const uint64_t nt_headers_offset) { const auto first_section_offset = get_first_section_offset(nt_headers, nt_headers_offset); const auto sections = buffer.as(first_section_offset); @@ -200,13 +206,13 @@ mapped_module map_module_from_data(emulator& emu, const std::span utils::safe_buffer_accessor buffer{data}; - const auto dos_header = buffer.as(0).get(); + const auto dos_header = buffer.as(0).get(); const auto nt_headers_offset = dos_header.e_lfanew; - const auto nt_headers = buffer.as(nt_headers_offset).get(); + const auto nt_headers = buffer.as>(nt_headers_offset).get(); auto& optional_header = nt_headers.OptionalHeader; - if (nt_headers.FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) + if (nt_headers.FileHeader.Machine != PEMachineType::AMD64) { throw std::runtime_error("Unsupported architecture!"); } diff --git a/src/windows-emulator/module/module_mapping.hpp b/src/windows-emulator/module/module_mapping.hpp index 8d69db80..f0802b4c 100644 --- a/src/windows-emulator/module/module_mapping.hpp +++ b/src/windows-emulator/module/module_mapping.hpp @@ -4,7 +4,7 @@ #include "mapped_module.hpp" mapped_module map_module_from_data(emulator& emu, std::span data, - std::filesystem::path file); + std::filesystem::path file); mapped_module map_module_from_file(emulator& emu, std::filesystem::path file); bool unmap_module(emulator& emu, const mapped_module& mod); diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index 7ff7cffa..eb6cbbe2 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -51,7 +51,7 @@ struct event : ref_counted_object { bool signaled{}; EVENT_TYPE type{}; - std::wstring name{}; + std::u16string name{}; bool is_signaled() { @@ -88,7 +88,7 @@ struct mutant : ref_counted_object { uint32_t locked_count{0}; uint32_t owning_thread_id{}; - std::wstring name{}; + std::u16string name{}; bool try_lock(const uint32_t thread_id) { @@ -176,7 +176,7 @@ struct file_enumeration_state struct file { utils::file_handle handle{}; - std::wstring name{}; + std::u16string name{}; std::optional enumeration_state{}; bool is_file() const @@ -206,8 +206,8 @@ struct file struct section { - std::wstring name{}; - std::wstring file_name{}; + std::u16string name{}; + std::u16string file_name{}; uint64_t maximum_size{}; uint32_t section_page_protection{}; uint32_t allocation_attributes{}; @@ -238,7 +238,7 @@ struct section struct semaphore : ref_counted_object { - std::wstring name{}; + std::u16string name{}; volatile uint32_t current_count{}; uint32_t max_count{}; @@ -263,7 +263,7 @@ struct semaphore : ref_counted_object struct port { - std::wstring name{}; + std::u16string name{}; uint64_t view_base{}; void serialize(utils::buffer_serializer& buffer) const @@ -356,7 +356,7 @@ public: uint32_t id{}; - std::wstring name{}; + std::u16string name{}; std::optional exit_status{}; std::vector await_objects{}; @@ -368,7 +368,7 @@ public: std::optional pending_status{}; std::optional gs_segment; - std::optional> teb; + std::optional> teb; std::vector last_registers{}; @@ -466,7 +466,7 @@ public: buffer.read_optional(this->await_time); buffer.read_optional(this->pending_status); buffer.read_optional(this->gs_segment, [this] { return emulator_allocator(*this->emu_ptr); }); - buffer.read_optional(this->teb, [this] { return emulator_object(*this->emu_ptr); }); + buffer.read_optional(this->teb, [this] { return emulator_object(*this->emu_ptr); }); buffer.read_vector(this->last_registers); } @@ -522,8 +522,8 @@ struct process_context emulator_allocator base_allocator; - emulator_object peb; - emulator_object process_params; + emulator_object peb; + emulator_object process_params; kusd_mmio kusd; module_manager mod_manager; diff --git a/src/windows-emulator/registry/hive_parser.cpp b/src/windows-emulator/registry/hive_parser.cpp index a71f7b2f..d5d6d293 100644 --- a/src/windows-emulator/registry/hive_parser.cpp +++ b/src/windows-emulator/registry/hive_parser.cpp @@ -10,45 +10,45 @@ namespace struct offset_entry_t { - long offset; - long hash; + int32_t offset; + int32_t hash; }; struct offsets_t { - long block_size; + int32_t block_size; char block_type[2]; - short count; + int16_t count; offset_entry_t entries[1]; }; struct key_block_t { - long block_size; + int32_t block_size; char block_type[2]; - char dummya[18]; - int subkey_count; - char dummyb[4]; - int subkeys; - char dummyc[4]; - int value_count; - int offsets; - char dummyd[28]; - short len; - short du; + uint8_t dummya[18]; + int32_t subkey_count; + uint8_t dummyb[4]; + int32_t subkeys; + uint8_t dummyc[4]; + int32_t value_count; + int32_t offsets; + uint8_t dummyd[28]; + int16_t len; + int16_t du; char name[255]; }; struct value_block_t { - long block_size; + int32_t block_size; char block_type[2]; - short name_len; - long size; - long offset; - long value_type; - short flags; - short dummy; + int16_t name_len; + int32_t size; + int32_t offset; + int32_t value_type; + int16_t flags; + int16_t dummy; char name[255]; }; @@ -206,7 +206,7 @@ void hive_key::parse(std::ifstream& file) const auto subkey_block_offset = MAIN_ROOT_OFFSET + offset_entry.offset; const auto subkey = read_file_object(file, subkey_block_offset); - std::string subkey_name(subkey.name, std::min(subkey.len, static_cast(sizeof(subkey.name)))); + std::string subkey_name(subkey.name, std::min(subkey.len, static_cast(sizeof(subkey.name)))); utils::string::to_lower_inplace(subkey_name); this->sub_keys_.emplace(std::move(subkey_name), hive_key{subkey.subkeys, subkey.value_count, subkey.offsets}); diff --git a/src/windows-emulator/registry/hive_parser.hpp b/src/windows-emulator/registry/hive_parser.hpp index 462557d9..5746e389 100644 --- a/src/windows-emulator/registry/hive_parser.hpp +++ b/src/windows-emulator/registry/hive_parser.hpp @@ -1,6 +1,9 @@ #pragma once +#include #include +#include + #include struct hive_value diff --git a/src/windows-emulator/registry/registry_manager.hpp b/src/windows-emulator/registry/registry_manager.hpp index af672148..aed43c16 100644 --- a/src/windows-emulator/registry/registry_manager.hpp +++ b/src/windows-emulator/registry/registry_manager.hpp @@ -2,8 +2,7 @@ #include "../std_include.hpp" #include - -class hive_parser; +#include "hive_parser.hpp" struct registry_key { diff --git a/src/windows-emulator/std_include.hpp b/src/windows-emulator/std_include.hpp index e2fe6334..a82acdab 100644 --- a/src/windows-emulator/std_include.hpp +++ b/src/windows-emulator/std_include.hpp @@ -28,9 +28,8 @@ #pragma warning(disable: 26498) #pragma warning(disable: 26812) #pragma warning(disable: 28020) - -#define WIN32_LEAN_AND_MEAN -#define NOMINMAX +#pragma warning(pop) +#endif #include #include @@ -56,25 +55,9 @@ #include #include +#include +#include -#define NTDDI_WIN11_GE 0 -#define PHNT_VERSION PHNT_WIN11 -#include -#include -#include -#include - -#ifdef _WIN32 -#pragma warning(pop) -#endif - -#ifdef max -#undef max -#endif - -#ifdef min -#undef min -#endif -#endif +#include "platform/platform.hpp" using namespace std::literals; diff --git a/src/windows-emulator/syscall_dispatcher.cpp b/src/windows-emulator/syscall_dispatcher.cpp index 10e1e49a..6237ffdc 100644 --- a/src/windows-emulator/syscall_dispatcher.cpp +++ b/src/windows-emulator/syscall_dispatcher.cpp @@ -93,10 +93,10 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu) const auto* mod = context.mod_manager.find_by_address(address); if (mod != context.ntdll && mod != context.win32u) { - win_emu.log.print(color::blue, "Executing inline syscall: %s (0x%X) at 0x%llX (%s)\n", - entry->second.name.c_str(), - syscall_id, - address, mod ? mod->name.c_str() : ""); + win_emu.log.print(color::blue, "Executing inline syscall: %s (0x%X) at 0x%" PRIx64 " (%s)\n", + entry->second.name.c_str(), + syscall_id, + address, mod ? mod->name.c_str() : ""); } else { @@ -106,19 +106,21 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu) const auto return_address = c.emu.read_memory(rsp); const auto* mod_name = context.mod_manager.find_name(return_address); - win_emu.log.print(color::dark_gray, "Executing syscall: %s (0x%X) at 0x%llX via 0x%llX (%s) %lld\n", - entry->second.name.c_str(), - syscall_id, address, return_address, mod_name, c.proc.executed_instructions); + win_emu.log.print(color::dark_gray, + "Executing syscall: %s (0x%X) at 0x%" PRIx64 " via 0x%" PRIx64 " (%s)\n", + entry->second.name.c_str(), + syscall_id, address, return_address, mod_name); } else { const auto* previous_mod = context.mod_manager.find_by_address(context.previous_ip); win_emu.log.print(color::blue, - "Crafted out-of-line syscall: %s (0x%X) at 0x%llX (%s) via 0x%llX (%s)\n", - entry->second.name.c_str(), - syscall_id, - address, mod ? mod->name.c_str() : "", context.previous_ip, - previous_mod ? previous_mod->name.c_str() : ""); + "Crafted out-of-line syscall: %s (0x%X) at 0x%" PRIx64 " (%s) via 0x%" PRIx64 + " (%s)\n", + entry->second.name.c_str(), + syscall_id, + address, mod ? mod->name.c_str() : "", context.previous_ip, + previous_mod ? previous_mod->name.c_str() : ""); } } @@ -126,13 +128,13 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu) } catch (std::exception& e) { - printf("Syscall threw an exception: %X (0x%llX) - %s\n", syscall_id, address, e.what()); + printf("Syscall threw an exception: %X (0x%" PRIx64 ") - %s\n", syscall_id, address, e.what()); emu.reg(x64_register::rax, STATUS_UNSUCCESSFUL); emu.stop(); } catch (...) { - printf("Syscall threw an unknown exception: %X (0x%llX)\n", syscall_id, address); + printf("Syscall threw an unknown exception: %X (0x%" PRIx64 ")\n", syscall_id, address); emu.reg(x64_register::rax, STATUS_UNSUCCESSFUL); emu.stop(); } diff --git a/src/windows-emulator/syscall_utils.hpp b/src/windows-emulator/syscall_utils.hpp index 902ecebb..41819729 100644 --- a/src/windows-emulator/syscall_utils.hpp +++ b/src/windows-emulator/syscall_utils.hpp @@ -1,6 +1,7 @@ #pragma once #include "windows_emulator.hpp" +#include struct syscall_context { @@ -173,6 +174,8 @@ void forward_syscall(const syscall_context& c, NTSTATUS (*handler)(const syscall resolve_indexed_argument>>(c.emu, index)... }; + (void)index; + const auto ret = std::apply(handler, std::move(func_args)); write_status(c, ret, ip); } @@ -186,12 +189,12 @@ syscall_handler make_syscall_handler() }; } -template -void write_attribute(emulator& emu, const PS_ATTRIBUTE& attribute, const T& value) +template +void write_attribute(emulator& emu, const PS_ATTRIBUTE& attribute, const T& value) { if (attribute.ReturnLength) { - emulator_object{emu, attribute.ReturnLength}.write(sizeof(T)); + emulator_object{emu, attribute.ReturnLength}.write(sizeof(T)); } if (attribute.Size >= sizeof(T)) @@ -269,6 +272,10 @@ inline std::chrono::system_clock::time_point convert_from_ksystem_time(const vol return convert_from_ksystem_time(*const_cast(&time)); } +#ifndef OS_WINDOWS +using __time64_t = int64_t; +#endif + inline LARGE_INTEGER convert_unix_to_windows_time(const __time64_t unix_time) { LARGE_INTEGER windows_time{}; diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index dd17505c..32c8a9ee 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -5,11 +5,15 @@ #include "syscall_utils.hpp" #include +#include #include +#include #include #include #include +#include + namespace { NTSTATUS handle_NtQueryPerformanceCounter(const syscall_context& c, @@ -61,23 +65,25 @@ namespace NTSTATUS handle_NtOpenKey(const syscall_context& c, const emulator_object key_handle, const ACCESS_MASK /*desired_access*/, - const emulator_object object_attributes) + const emulator_object>> object_attributes) { const auto attributes = object_attributes.read(); - auto key = read_unicode_string(c.emu, attributes.ObjectName); + auto key = read_unicode_string( + c.emu, reinterpret_cast>*>(attributes.ObjectName)); if (attributes.RootDirectory) { - const auto* parent_handle = c.proc.registry_keys.get(reinterpret_cast(attributes.RootDirectory)); + const auto* parent_handle = c.proc.registry_keys.get(attributes.RootDirectory); if (!parent_handle) { return STATUS_INVALID_HANDLE; } - key = parent_handle->hive / parent_handle->path / key; + const std::filesystem::path full_path = parent_handle->hive / parent_handle->path / key; + key = full_path.u16string(); } - c.win_emu.log.print(color::dark_gray, "--> Registry key: %S\n", key.c_str()); + c.win_emu.log.print(color::dark_gray, "--> Registry key: %s\n", u16_to_u8(key).c_str()); auto entry = c.proc.registry.get_key(key); if (!entry.has_value()) @@ -93,7 +99,7 @@ namespace NTSTATUS handle_NtOpenKeyEx(const syscall_context& c, const emulator_object key_handle, const ACCESS_MASK desired_access, - const emulator_object object_attributes, + const emulator_object>> object_attributes, ULONG /*open_options*/) { return handle_NtOpenKey(c, key_handle, desired_access, object_attributes); @@ -166,7 +172,7 @@ namespace } NTSTATUS handle_NtQueryValueKey(const syscall_context& c, const handle key_handle, - const emulator_object value_name, + const emulator_object>> value_name, const KEY_VALUE_INFORMATION_CLASS key_value_information_class, const uint64_t key_value_information, const ULONG length, const emulator_object result_length) @@ -178,9 +184,8 @@ namespace } const auto query_name = read_unicode_string(c.emu, value_name); - const std::string name(query_name.begin(), query_name.end()); - const auto value = c.proc.registry.get_value(*key, name); + const auto value = c.proc.registry.get_value(*key, u16_to_u8(query_name)); if (!value) { return STATUS_OBJECT_NAME_NOT_FOUND; @@ -317,16 +322,17 @@ namespace if (info_class == ThreadNameInformation) { - if (thread_information_length != sizeof(THREAD_NAME_INFORMATION)) + if (thread_information_length != sizeof(THREAD_NAME_INFORMATION>)) { return STATUS_BUFFER_OVERFLOW; } - const emulator_object info{c.emu, thread_information}; + const emulator_object>> info{c.emu, thread_information}; const auto i = info.read(); thread->name = read_unicode_string(c.emu, i.ThreadName); - c.win_emu.log.print(color::blue, "Setting thread (%d) name: %S\n", thread->id, thread->name.c_str()); + c.win_emu.log.print(color::blue, "Setting thread (%d) name: %s\n", thread->id, + u16_to_u8(thread->name).c_str()); return STATUS_SUCCESS; } @@ -354,7 +360,7 @@ namespace const auto tls_index = c.emu.read_memory(thread_information); const auto teb = thread->teb->read(); - auto* tls_vector = static_cast(teb.ThreadLocalStoragePointer); + auto* tls_vector = teb.ThreadLocalStoragePointer; c.emu.write_memory(tls_vector + tls_index, nullptr); return STATUS_SUCCESS; @@ -460,16 +466,17 @@ namespace NTSTATUS handle_NtCreateMutant(const syscall_context& c, const emulator_object mutant_handle, const ACCESS_MASK /*desired_access*/, - const emulator_object object_attributes, + const emulator_object>> object_attributes, const BOOLEAN initial_owner) { - std::wstring name{}; + std::u16string name{}; if (object_attributes) { const auto attributes = object_attributes.read(); if (attributes.ObjectName) { - name = read_unicode_string(c.emu, attributes.ObjectName); + name = read_unicode_string( + c.emu, emulator_object>>{c.emu, attributes.ObjectName}); } } @@ -500,16 +507,17 @@ namespace NTSTATUS handle_NtCreateEvent(const syscall_context& c, const emulator_object event_handle, const ACCESS_MASK /*desired_access*/, - const emulator_object object_attributes, + const emulator_object>> object_attributes, const EVENT_TYPE event_type, const BOOLEAN initial_state) { - std::wstring name{}; + std::u16string name{}; if (object_attributes) { const auto attributes = object_attributes.read(); if (attributes.ObjectName) { - name = read_unicode_string(c.emu, attributes.ObjectName); + name = read_unicode_string( + c.emu, reinterpret_cast>*>(attributes.ObjectName)); } } @@ -540,10 +548,11 @@ namespace NTSTATUS handle_NtOpenEvent(const syscall_context& c, const emulator_object event_handle, const ACCESS_MASK /*desired_access*/, - const emulator_object object_attributes) + const emulator_object>> object_attributes) { const auto attributes = object_attributes.read(); - const auto name = read_unicode_string(c.emu, attributes.ObjectName); + const auto name = read_unicode_string( + c.emu, reinterpret_cast>*>(attributes.ObjectName)); for (auto& entry : c.proc.events) { @@ -590,20 +599,21 @@ namespace NTSTATUS handle_NtOpenSection(const syscall_context& c, const emulator_object section_handle, const ACCESS_MASK /*desired_access*/, - const emulator_object object_attributes) + const emulator_object>> object_attributes) { const auto attributes = object_attributes.read(); - auto filename = read_unicode_string(c.emu, attributes.ObjectName); - c.win_emu.log.print(color::dark_gray, "--> Opening section: %S\n", filename.c_str()); + auto filename = read_unicode_string( + c.emu, reinterpret_cast>*>(attributes.ObjectName)); + c.win_emu.log.print(color::dark_gray, "--> Opening section: %s\n", u16_to_u8(filename).c_str()); - if (filename == L"\\Windows\\SharedSection") + if (filename == u"\\Windows\\SharedSection") { section_handle.write(SHARED_SECTION); return STATUS_SUCCESS; } - if (reinterpret_cast(attributes.RootDirectory) != KNOWN_DLLS_DIRECTORY) + if (attributes.RootDirectory != KNOWN_DLLS_DIRECTORY) { puts("Unsupported section"); c.emu.stop(); @@ -626,9 +636,11 @@ namespace NTSTATUS handle_NtMapViewOfSection(const syscall_context& c, const handle section_handle, const handle process_handle, const emulator_object base_address, - const ULONG_PTR /*zero_bits*/, const SIZE_T /*commit_size*/, + const EMULATOR_CAST(EmulatorTraits::ULONG_PTR, ULONG_PTR) /*zero_bits*/, + const EMULATOR_CAST(EmulatorTraits::SIZE_T, SIZE_T) /*commit_size*/, const emulator_object /*section_offset*/, - const emulator_object view_size, + const emulator_object::SIZE_T, SIZE_T)> + view_size, const SECTION_INHERIT /*inherit_disposition*/, const ULONG /*allocation_type*/, const ULONG /*win32_protect*/) { @@ -644,7 +656,7 @@ namespace const auto address = c.emu.find_free_allocation_base(shared_section_size); c.emu.allocate_memory(address, shared_section_size, memory_permission::read_write); - const std::wstring_view windows_dir = c.proc.kusd.get().NtSystemRoot.arr; + const std::u16string_view windows_dir = c.proc.kusd.get().NtSystemRoot.arr; const auto windows_dir_size = windows_dir.size() * 2; constexpr auto windows_dir_offset = 0x10; @@ -652,29 +664,34 @@ namespace const auto obj_address = address + windows_dir_offset; - const emulator_object windir_obj{c.emu, obj_address}; - windir_obj.access([&](UNICODE_STRING& ucs) + const emulator_object>> windir_obj{c.emu, obj_address}; + windir_obj.access([&](UNICODE_STRING>& ucs) { - const auto dir_address = kusd_mmio::address() + offsetof(KUSER_SHARED_DATA, NtSystemRoot); + const auto dir_address = kusd_mmio::address() + offsetof(KUSER_SHARED_DATA64, NtSystemRoot); - ucs.Buffer = reinterpret_cast(dir_address - obj_address); + ucs.Buffer = dir_address - obj_address; ucs.Length = static_cast(windows_dir_size); ucs.MaximumLength = ucs.Length; }); - const emulator_object sysdir_obj{c.emu, windir_obj.value() + windir_obj.size()}; - sysdir_obj.access([&](UNICODE_STRING& ucs) + const emulator_object>> sysdir_obj{ + c.emu, windir_obj.value() + windir_obj.size() + }; + sysdir_obj.access([&](UNICODE_STRING>& ucs) + { - c.proc.base_allocator.make_unicode_string(ucs, L"C:\\WINDOWS\\System32"); - ucs.Buffer = reinterpret_cast(reinterpret_cast(ucs.Buffer) - obj_address); + c.proc.base_allocator.make_unicode_string(ucs, u"C:\\WINDOWS\\System32"); + ucs.Buffer = ucs.Buffer - obj_address; }); - const emulator_object base_dir_obj{c.emu, sysdir_obj.value() + sysdir_obj.size()}; - base_dir_obj.access([&](UNICODE_STRING& ucs) + const emulator_object>> base_dir_obj{ + c.emu, sysdir_obj.value() + sysdir_obj.size() + }; + base_dir_obj.access([&](UNICODE_STRING>& ucs) { - c.proc.base_allocator.make_unicode_string(ucs, L"\\Sessions\\1\\BaseNamedObjects"); - ucs.Buffer = reinterpret_cast(reinterpret_cast(ucs.Buffer) - obj_address); + c.proc.base_allocator.make_unicode_string(ucs, u"\\Sessions\\1\\BaseNamedObjects"); + ucs.Buffer = ucs.Buffer - obj_address; }); if (view_size) @@ -701,7 +718,7 @@ namespace return STATUS_FILE_INVALID; } - std::wstring wide_name(binary->name.begin(), binary->name.end()); + std::u16string wide_name(binary->name.begin(), binary->name.end()); section_entry->name = utils::string::to_lower_consume(wide_name); if (view_size.value()) @@ -747,7 +764,8 @@ namespace NTSTATUS handle_NtCreateIoCompletion(const syscall_context& c, const emulator_object event_handle, const ACCESS_MASK desired_access, - const emulator_object object_attributes, + const emulator_object>> + object_attributes, const uint32_t /*number_of_concurrent_threads*/) { return handle_NtCreateEvent(c, event_handle, desired_access, object_attributes, NotificationEvent, FALSE); @@ -755,7 +773,8 @@ namespace NTSTATUS handle_NtCreateWaitCompletionPacket(const syscall_context& c, const emulator_object event_handle, const ACCESS_MASK desired_access, - const emulator_object object_attributes) + const emulator_object>> + object_attributes) { return handle_NtCreateEvent(c, event_handle, desired_access, object_attributes, NotificationEvent, FALSE); } @@ -780,17 +799,17 @@ namespace { if (return_length) { - return_length.write(sizeof(MEMORY_BASIC_INFORMATION)); + return_length.write(sizeof(EMU_MEMORY_BASIC_INFORMATION64)); } - if (memory_information_length != sizeof(MEMORY_BASIC_INFORMATION)) + if (memory_information_length != sizeof(EMU_MEMORY_BASIC_INFORMATION64)) { return STATUS_BUFFER_OVERFLOW; } - const emulator_object info{c.emu, memory_information}; + const emulator_object info{c.emu, memory_information}; - info.access([&](MEMORY_BASIC_INFORMATION& image_info) + info.access([&](EMU_MEMORY_BASIC_INFORMATION64& image_info) { const auto region_info = c.emu.get_region_info(base_address); @@ -817,10 +836,10 @@ namespace { if (return_length) { - return_length.write(sizeof(MEMORY_IMAGE_INFORMATION)); + return_length.write(sizeof(MEMORY_IMAGE_INFORMATION64)); } - if (memory_information_length != sizeof(MEMORY_IMAGE_INFORMATION)) + if (memory_information_length != sizeof(MEMORY_IMAGE_INFORMATION64)) { return STATUS_BUFFER_OVERFLOW; } @@ -828,13 +847,13 @@ namespace const auto mod = c.proc.mod_manager.find_by_address(base_address); if (!mod) { - printf("Bad address for memory image request: 0x%llX\n", base_address); + printf("Bad address for memory image request: 0x%" PRIx64 "\n", base_address); return STATUS_INVALID_ADDRESS; } - const emulator_object info{c.emu, memory_information}; + const emulator_object info{c.emu, memory_information}; - info.access([&](MEMORY_IMAGE_INFORMATION& image_info) + info.access([&](MEMORY_IMAGE_INFORMATION64& image_info) { image_info.ImageBase = reinterpret_cast(mod->image_base); image_info.SizeOfImage = mod->size_of_image; @@ -848,10 +867,10 @@ namespace { if (return_length) { - return_length.write(sizeof(MEMORY_REGION_INFORMATION)); + return_length.write(sizeof(MEMORY_REGION_INFORMATION64)); } - if (memory_information_length != sizeof(MEMORY_REGION_INFORMATION)) + if (memory_information_length != sizeof(MEMORY_REGION_INFORMATION64)) { return STATUS_BUFFER_OVERFLOW; } @@ -862,9 +881,9 @@ namespace return STATUS_INVALID_ADDRESS; } - const emulator_object info{c.emu, memory_information}; + const emulator_object info{c.emu, memory_information}; - info.access([&](MEMORY_REGION_INFORMATION& image_info) + info.access([&](MEMORY_REGION_INFORMATION64& image_info) { memset(&image_info, 0, sizeof(image_info)); @@ -900,17 +919,17 @@ namespace { if (return_length) { - return_length.write(sizeof(SYSTEM_TIMEOFDAY_INFORMATION)); + return_length.write(sizeof(SYSTEM_TIMEOFDAY_INFORMATION64)); } - if (system_information_length != sizeof(SYSTEM_TIMEOFDAY_INFORMATION)) + if (system_information_length != sizeof(SYSTEM_TIMEOFDAY_INFORMATION64)) { return STATUS_BUFFER_TOO_SMALL; } - const emulator_object info_obj{c.emu, system_information}; + const emulator_object info_obj{c.emu, system_information}; - info_obj.access([&](SYSTEM_TIMEOFDAY_INFORMATION& info) + info_obj.access([&](SYSTEM_TIMEOFDAY_INFORMATION64& info) { info.BootTime.QuadPart = 0; // TODO: Fill @@ -923,17 +942,17 @@ namespace { if (return_length) { - return_length.write(sizeof(SYSTEM_RANGE_START_INFORMATION)); + return_length.write(sizeof(SYSTEM_RANGE_START_INFORMATION64)); } - if (system_information_length != sizeof(SYSTEM_RANGE_START_INFORMATION)) + if (system_information_length != sizeof(SYSTEM_RANGE_START_INFORMATION64)) { return STATUS_BUFFER_TOO_SMALL; } - const emulator_object info_obj{c.emu, system_information}; + const emulator_object info_obj{c.emu, system_information}; - info_obj.access([&](SYSTEM_RANGE_START_INFORMATION& info) + info_obj.access([&](SYSTEM_RANGE_START_INFORMATION64& info) { info.SystemRangeStart = 0xFFFF800000000000; }); @@ -945,17 +964,17 @@ namespace { if (return_length) { - return_length.write(sizeof(SYSTEM_PROCESSOR_INFORMATION)); + return_length.write(sizeof(SYSTEM_PROCESSOR_INFORMATION64)); } - if (system_information_length != sizeof(SYSTEM_PROCESSOR_INFORMATION)) + if (system_information_length != sizeof(SYSTEM_PROCESSOR_INFORMATION64)) { return STATUS_BUFFER_TOO_SMALL; } - const emulator_object info_obj{c.emu, system_information}; + const emulator_object info_obj{c.emu, system_information}; - info_obj.access([&](SYSTEM_PROCESSOR_INFORMATION& info) + info_obj.access([&](SYSTEM_PROCESSOR_INFORMATION64& info) { memset(&info, 0, sizeof(info)); info.MaximumProcessors = 2; @@ -969,17 +988,17 @@ namespace { if (return_length) { - return_length.write(sizeof(SYSTEM_NUMA_INFORMATION)); + return_length.write(sizeof(SYSTEM_NUMA_INFORMATION64)); } - if (system_information_length != sizeof(SYSTEM_NUMA_INFORMATION)) + if (system_information_length != sizeof(SYSTEM_NUMA_INFORMATION64)) { return STATUS_BUFFER_TOO_SMALL; } - const emulator_object info_obj{c.emu, system_information}; + const emulator_object info_obj{c.emu, system_information}; - info_obj.access([&](SYSTEM_NUMA_INFORMATION& info) + info_obj.access([&](SYSTEM_NUMA_INFORMATION64& info) { memset(&info, 0, sizeof(info)); info.ActiveProcessorsGroupAffinity->Mask = 0xFFF; @@ -1022,17 +1041,17 @@ namespace if (return_length) { - return_length.write(sizeof(SYSTEM_BASIC_INFORMATION)); + return_length.write(sizeof(SYSTEM_BASIC_INFORMATION64)); } - if (system_information_length != sizeof(SYSTEM_BASIC_INFORMATION)) + if (system_information_length != sizeof(SYSTEM_BASIC_INFORMATION64)) { return STATUS_BUFFER_TOO_SMALL; } - const emulator_object info{c.emu, system_information}; + const emulator_object info{c.emu, system_information}; - info.access([&](SYSTEM_BASIC_INFORMATION& basic_info) + info.access([&](SYSTEM_BASIC_INFORMATION64& basic_info) { basic_info.Reserved = 0; basic_info.TimerResolution = 0x0002625a; @@ -1095,10 +1114,16 @@ namespace return_length.access([&](uint32_t& len) { + (void)len; +#ifdef OS_WINDOWS code = NtQuerySystemInformationEx(static_cast(info_class), buffer, input_buffer_length, res_buff, system_information_length, reinterpret_cast(&len)); +#else + // TODO: unsupported + code = STATUS_SUCCESS; +#endif }); if (code == 0) @@ -1121,17 +1146,17 @@ namespace if (return_length) { - return_length.write(sizeof(SYSTEM_BASIC_INFORMATION)); + return_length.write(sizeof(SYSTEM_BASIC_INFORMATION64)); } - if (system_information_length != sizeof(SYSTEM_BASIC_INFORMATION)) + if (system_information_length != sizeof(SYSTEM_BASIC_INFORMATION64)) { return STATUS_BUFFER_TOO_SMALL; } - const emulator_object info{c.emu, system_information}; + const emulator_object info{c.emu, system_information}; - info.access([&](SYSTEM_BASIC_INFORMATION& basic_info) + info.access([&](SYSTEM_BASIC_INFORMATION64& basic_info) { basic_info.Reserved = 0; basic_info.TimerResolution = 0x0002625a; @@ -1162,29 +1187,31 @@ namespace { if (return_length) { - return_length.write(sizeof(SECTION_IMAGE_INFORMATION)); + return_length.write(sizeof(SECTION_IMAGE_INFORMATION>)); } - if (process_information_length != sizeof(SECTION_IMAGE_INFORMATION)) + if (process_information_length != sizeof(SECTION_IMAGE_INFORMATION>)) { return STATUS_BUFFER_OVERFLOW; } - const emulator_object info{c.emu, process_information}; - info.access([&](SECTION_IMAGE_INFORMATION& i) + const emulator_object>> info{c.emu, process_information}; + info.access([&](SECTION_IMAGE_INFORMATION>& i) { const auto& mod = *c.proc.executable; - const emulator_object dos_header_obj{c.emu, mod.image_base}; + const emulator_object dos_header_obj{c.emu, mod.image_base}; const auto dos_header = dos_header_obj.read(); - const emulator_object nt_headers_obj{c.emu, mod.image_base + dos_header.e_lfanew}; + const emulator_object> nt_headers_obj{ + c.emu, mod.image_base + dos_header.e_lfanew + }; const auto nt_headers = nt_headers_obj.read(); const auto& file_header = nt_headers.FileHeader; const auto& optional_header = nt_headers.OptionalHeader; - i.TransferAddress = nullptr; + i.TransferAddress = 0; i.MaximumStackSize = optional_header.SizeOfStackReserve; i.CommittedStackSize = optional_header.SizeOfStackCommit; i.SubSystemType = optional_header.Subsystem; @@ -1227,15 +1254,15 @@ namespace { if (return_length) { - return_length.write(sizeof(DWORD_PTR)); + return_length.write(sizeof(EmulatorTraits::PVOID)); } - if (process_information_length != sizeof(DWORD_PTR)) + if (process_information_length != sizeof(EmulatorTraits::PVOID)) { return STATUS_BUFFER_OVERFLOW; } - const emulator_object info{c.emu, process_information}; + const emulator_object::PVOID> info{c.emu, process_information}; info.write(0); return STATUS_SUCCESS; @@ -1287,19 +1314,19 @@ namespace { if (return_length) { - return_length.write(sizeof(PROCESS_BASIC_INFORMATION)); + return_length.write(sizeof(PROCESS_BASIC_INFORMATION64)); } - if (process_information_length != sizeof(PROCESS_BASIC_INFORMATION)) + if (process_information_length != sizeof(PROCESS_BASIC_INFORMATION64)) { return STATUS_BUFFER_OVERFLOW; } - const emulator_object info{c.emu, process_information}; - info.access([&](PROCESS_BASIC_INFORMATION& basic_info) + const emulator_object info{c.emu, process_information}; + info.access([&](PROCESS_BASIC_INFORMATION64& basic_info) { basic_info.PebBaseAddress = c.proc.peb.ptr(); - basic_info.UniqueProcessId = reinterpret_cast(1); + basic_info.UniqueProcessId = 1; }); return STATUS_SUCCESS; @@ -1308,9 +1335,9 @@ namespace if (info_class == ProcessImageFileNameWin32) { const auto peb = c.proc.peb.read(); - emulator_object proc_params{c.emu, peb.ProcessParameters}; + emulator_object proc_params{c.emu, peb.ProcessParameters}; const auto params = proc_params.read(); - const auto length = params.ImagePathName.Length + sizeof(UNICODE_STRING) + 2; + const auto length = params.ImagePathName.Length + sizeof(UNICODE_STRING>) + 2; if (return_length) { @@ -1322,15 +1349,16 @@ namespace return STATUS_BUFFER_OVERFLOW; } - const emulator_object info{c.emu, process_information}; - info.access([&](UNICODE_STRING& str) + const emulator_object>> info{c.emu, process_information}; + info.access([&](UNICODE_STRING>& str) { - const auto buffer_start = static_cast(process_information) + sizeof(UNICODE_STRING); + const auto buffer_start = static_cast(process_information) + sizeof(UNICODE_STRING< + EmulatorTraits>); const auto string = read_unicode_string(c.emu, params.ImagePathName); c.emu.write_memory(buffer_start, string.c_str(), (string.size() + 1) * 2); str.Length = params.ImagePathName.Length; str.MaximumLength = str.Length; - str.Buffer = reinterpret_cast(buffer_start); + str.Buffer = buffer_start; }); return STATUS_SUCCESS; @@ -1360,16 +1388,16 @@ namespace { if (return_length) { - return_length.write(sizeof(THREAD_BASIC_INFORMATION)); + return_length.write(sizeof(THREAD_BASIC_INFORMATION64)); } - if (thread_information_length != sizeof(THREAD_BASIC_INFORMATION)) + if (thread_information_length != sizeof(THREAD_BASIC_INFORMATION64)) { return STATUS_BUFFER_OVERFLOW; } - const emulator_object info{c.emu, thread_information}; - info.access([&](THREAD_BASIC_INFORMATION& i) + const emulator_object info{c.emu, thread_information}; + info.access([&](THREAD_BASIC_INFORMATION64& i) { i.TebBaseAddress = thread->teb->ptr(); i.ClientId = thread->teb->read().ClientId; @@ -1400,15 +1428,15 @@ namespace { if (return_length) { - return_length.write(sizeof(ULONG_PTR)); + return_length.write(sizeof(EmulatorTraits::PVOID)); } - if (thread_information_length != sizeof(ULONG_PTR)) + if (thread_information_length != sizeof(EmulatorTraits::PVOID)) { return STATUS_BUFFER_OVERFLOW; } - const emulator_object info{c.emu, thread_information}; + const emulator_object::PVOID> info{c.emu, thread_information}; info.write(thread->start_address); return STATUS_SUCCESS; @@ -1421,7 +1449,7 @@ namespace } NTSTATUS handle_NtSetInformationFile(const syscall_context& c, const handle file_handle, - const emulator_object io_status_block, + const emulator_object>> io_status_block, const uint64_t file_information, const ULONG length, const FILE_INFORMATION_CLASS info_class) { @@ -1440,7 +1468,7 @@ namespace if (io_status_block) { - IO_STATUS_BLOCK block{}; + IO_STATUS_BLOCK> block{}; block.Information = sizeof(FILE_POSITION_INFORMATION); io_status_block.write(block); } @@ -1476,14 +1504,15 @@ namespace for (const auto& file : std::filesystem::directory_iterator(dir)) { - files.emplace_back(file.path().filename()); + files.emplace_back(file_entry{.file_path = file.path().filename(),}); } return files; } template - NTSTATUS handle_file_enumeration(const syscall_context& c, const emulator_object io_status_block, + NTSTATUS handle_file_enumeration(const syscall_context& c, + const emulator_object>> io_status_block, const uint64_t file_information, const uint32_t length, const ULONG query_flags, file* f) { @@ -1517,7 +1546,7 @@ namespace { if (current_offset == 0) { - IO_STATUS_BLOCK block{}; + IO_STATUS_BLOCK> block{}; block.Information = end_offset; io_status_block.write(block); @@ -1559,7 +1588,7 @@ namespace enum_state.current_index = current_index; } - IO_STATUS_BLOCK block{}; + IO_STATUS_BLOCK> block{}; block.Information = current_offset; io_status_block.write(block); @@ -1570,10 +1599,11 @@ namespace const handle /*event_handle*/, const emulator_pointer /*PIO_APC_ROUTINE*/ /*apc_routine*/, const emulator_pointer /*apc_context*/, - const emulator_object io_status_block, + const emulator_object>> + io_status_block, const uint64_t file_information, const uint32_t length, const uint32_t info_class, const ULONG query_flags, - const emulator_object /*file_name*/) + const emulator_object>> /*file_name*/) { auto* f = c.proc.files.get(file_handle); if (!f || !f->is_directory()) @@ -1606,7 +1636,8 @@ namespace } NTSTATUS handle_NtQueryInformationFile(const syscall_context& c, const handle file_handle, - const emulator_object io_status_block, + const emulator_object>> + io_status_block, const uint64_t file_information, const uint32_t length, const uint32_t info_class) { @@ -1622,7 +1653,7 @@ namespace if (io_status_block) { - IO_STATUS_BLOCK block{}; + IO_STATUS_BLOCK> block{}; block.Information = sizeof(FILE_NAME_INFORMATION) + required_length; io_status_block.write(block); } @@ -1634,6 +1665,7 @@ namespace c.emu.write_memory(file_information, FILE_NAME_INFORMATION{ .FileNameLength = static_cast(f->name.size() * 2), + .FileName = {}, }); c.emu.write_memory(file_information + offsetof(FILE_NAME_INFORMATION, FileName), f->name.c_str(), @@ -1646,7 +1678,7 @@ namespace { if (io_status_block) { - IO_STATUS_BLOCK block{}; + IO_STATUS_BLOCK> block{}; block.Information = sizeof(FILE_STANDARD_INFORMATION); io_status_block.write(block); } @@ -1679,7 +1711,7 @@ namespace if (io_status_block) { - IO_STATUS_BLOCK block{}; + IO_STATUS_BLOCK> block{}; block.Information = sizeof(FILE_POSITION_INFORMATION); io_status_block.write(block); } @@ -1705,38 +1737,6 @@ namespace return STATUS_NOT_SUPPORTED; } - struct THREAD_TLS_INFO - { - ULONG Flags; - - union - { - PVOID* TlsVector; - PVOID TlsModulePointer; - }; - - ULONG_PTR ThreadId; - }; - - static_assert(sizeof(THREAD_TLS_INFO) == 0x18); - - struct PROCESS_TLS_INFO - { - ULONG Unknown; - PROCESS_TLS_INFORMATION_TYPE TlsRequest; - ULONG ThreadDataCount; - - union - { - ULONG TlsIndex; - ULONG TlsVectorLength; - }; - - THREAD_TLS_INFO ThreadData[1]; - }; - - static_assert(sizeof(PROCESS_TLS_INFO) - sizeof(THREAD_TLS_INFO) == 0x10); - NTSTATUS handle_NtSetInformationProcess(const syscall_context& c, const handle process_handle, const uint32_t info_class, const uint64_t process_information, const uint32_t process_information_length) @@ -1788,18 +1788,18 @@ namespace entry.Flags = 2; - thread_iterator->second.teb->access([&](TEB& teb) + thread_iterator->second.teb->access([&](TEB64& teb) { - entry.ThreadId = reinterpret_cast(teb.ClientId.UniqueThread); + entry.ThreadId = teb.ClientId.UniqueThread; - const auto tls_vector = static_cast(teb.ThreadLocalStoragePointer); + const auto tls_vector = teb.ThreadLocalStoragePointer; if (tls_info.TlsRequest == ProcessTlsReplaceIndex) { const auto tls_entry_ptr = tls_vector + tls_info.TlsIndex; - const auto old_entry = c.emu.read_memory(tls_entry_ptr); - c.emu.write_memory(tls_entry_ptr, entry.TlsModulePointer); + const auto old_entry = c.emu.read_memory::PVOID>(tls_entry_ptr); + c.emu.write_memory::PVOID>(tls_entry_ptr, entry.TlsModulePointer); entry.TlsModulePointer = old_entry; } @@ -1860,8 +1860,9 @@ namespace const auto requested_protection = map_nt_to_emulator_protection(protection); - c.win_emu.log.print(color::dark_gray, "--> Changing protection at 0x%llX-0x%llX to %s\n", aligned_start, - aligned_start + aligned_length, get_permission_string(requested_protection).c_str()); + c.win_emu.log.print(color::dark_gray, "--> Changing protection at 0x%" PRIx64 "-0x%" PRIx64 " to %s\n", + aligned_start, + aligned_start + aligned_length, get_permission_string(requested_protection).c_str()); memory_permission old_protection_value{}; @@ -1883,18 +1884,20 @@ namespace NTSTATUS handle_NtOpenDirectoryObject(const syscall_context& c, const emulator_object directory_handle, const ACCESS_MASK /*desired_access*/, - const emulator_object object_attributes) + const emulator_object>> + object_attributes) { const auto attributes = object_attributes.read(); - const auto object_name = read_unicode_string(c.emu, attributes.ObjectName); + const auto object_name = read_unicode_string( + c.emu, reinterpret_cast>*>(attributes.ObjectName)); - if (object_name == L"\\KnownDlls") + if (object_name == u"\\KnownDlls") { directory_handle.write(KNOWN_DLLS_DIRECTORY); return STATUS_SUCCESS; } - if (object_name == L"\\Sessions\\1\\BaseNamedObjects") + if (object_name == u"\\Sessions\\1\\BaseNamedObjects") { directory_handle.write(BASE_NAMED_OBJECTS_DIRECTORY); return STATUS_SUCCESS; @@ -1905,12 +1908,14 @@ namespace NTSTATUS handle_NtOpenSymbolicLinkObject(const syscall_context& c, const emulator_object link_handle, ACCESS_MASK /*desired_access*/, - const emulator_object object_attributes) + const emulator_object>> + object_attributes) { const auto attributes = object_attributes.read(); - const auto object_name = read_unicode_string(c.emu, attributes.ObjectName); + const auto object_name = read_unicode_string( + c.emu, reinterpret_cast>*>(attributes.ObjectName)); - if (object_name == L"KnownDllPath") + if (object_name == u"KnownDllPath") { link_handle.write(KNOWN_DLLS_SYMLINK); return STATUS_SUCCESS; @@ -1919,20 +1924,21 @@ namespace return STATUS_NOT_SUPPORTED; } - NTSTATUS WINAPI handle_NtQuerySymbolicLinkObject(const syscall_context& c, const handle link_handle, - const emulator_object link_target, - const emulator_object returned_length) + NTSTATUS handle_NtQuerySymbolicLinkObject(const syscall_context& c, const handle link_handle, + const emulator_object>> + link_target, + const emulator_object returned_length) { if (link_handle == KNOWN_DLLS_SYMLINK) { - constexpr std::wstring_view system32 = L"C:\\WINDOWS\\System32"; + constexpr std::u16string_view system32 = u"C:\\WINDOWS\\System32"; constexpr auto str_length = system32.size() * 2; constexpr auto max_length = str_length + 2; returned_length.write(max_length); bool too_small = false; - link_target.access([&](UNICODE_STRING& str) + link_target.access([&](UNICODE_STRING>& str) { if (str.MaximumLength < max_length) { @@ -1941,7 +1947,7 @@ namespace } str.Length = str_length; - c.emu.write_memory(reinterpret_cast(str.Buffer), system32.data(), max_length); + c.emu.write_memory(str.Buffer, system32.data(), max_length); }); return too_small @@ -2040,7 +2046,7 @@ namespace NTSTATUS handle_NtCreateSection(const syscall_context& c, const emulator_object section_handle, const ACCESS_MASK /*desired_access*/, - const emulator_object object_attributes, + const emulator_object>> object_attributes, const emulator_object maximum_size, const ULONG section_page_protection, const ULONG allocation_attributes, const handle file_handle) @@ -2052,7 +2058,7 @@ namespace const auto* file = c.proc.files.get(file_handle); if (file) { - c.win_emu.log.print(color::dark_gray, "--> Section for file %S\n", file->name.c_str()); + c.win_emu.log.print(color::dark_gray, "--> Section for file %s\n", u16_to_u8(file->name).c_str()); s.file_name = file->name; } @@ -2061,8 +2067,9 @@ namespace const auto attributes = object_attributes.read(); if (attributes.ObjectName) { - const auto name = read_unicode_string(c.emu, attributes.ObjectName); - c.win_emu.log.print(color::dark_gray, "--> Section with name %S\n", name.c_str()); + const auto name = read_unicode_string( + c.emu, reinterpret_cast>*>(attributes.ObjectName)); + c.win_emu.log.print(color::dark_gray, "--> Section with name %s\n", u16_to_u8(name).c_str()); s.name = std::move(name); } } @@ -2087,16 +2094,16 @@ namespace } NTSTATUS handle_NtConnectPort(const syscall_context& c, const emulator_object client_port_handle, - const emulator_object server_port_name, + const emulator_object>> server_port_name, const emulator_object /*security_qos*/, - const emulator_object client_shared_memory, - const emulator_object /*server_shared_memory*/, + const emulator_object client_shared_memory, + const emulator_object /*server_shared_memory*/, const emulator_object /*maximum_message_length*/, const emulator_pointer connection_info, const emulator_object connection_info_length) { auto port_name = read_unicode_string(c.emu, server_port_name); - c.win_emu.log.print(color::dark_gray, "NtConnectPort: %S\n", port_name.c_str()); + c.win_emu.log.print(color::dark_gray, "NtConnectPort: %s\n", u16_to_u8(port_name).c_str()); port p{}; p.name = std::move(port_name); @@ -2108,10 +2115,10 @@ namespace c.emu.write_memory(connection_info, zero_mem.data(), zero_mem.size()); } - client_shared_memory.access([&](PORT_VIEW& view) + client_shared_memory.access([&](PORT_VIEW64& view) { p.view_base = c.emu.allocate_memory(view.ViewSize, memory_permission::read_write); - view.ViewBase = reinterpret_cast(p.view_base); + view.ViewBase = p.view_base; view.ViewRemoteBase = view.ViewBase; }); @@ -2150,7 +2157,7 @@ namespace const handle event, const emulator_pointer /*PIO_APC_ROUTINE*/ apc_routine, const emulator_pointer apc_context, - const emulator_object io_status_block, + const emulator_object>> io_status_block, const ULONG io_control_code, const emulator_pointer input_buffer, const ULONG input_buffer_length, const emulator_pointer output_buffer, @@ -2263,7 +2270,8 @@ namespace NTSTATUS handle_NtDuplicateToken(const syscall_context&, const handle existing_token_handle, ACCESS_MASK /*desired_access*/, - const emulator_object /*object_attributes*/, + const emulator_object>> + /*object_attributes*/, const BOOLEAN /*effective_only*/, const TOKEN_TYPE type, const emulator_object new_token_handle) { @@ -2325,11 +2333,11 @@ namespace return STATUS_BUFFER_TOO_SMALL; } - TOKEN_USER user{}; + TOKEN_USER64 user{}; user.User.Attributes = 0; - user.User.Sid = reinterpret_cast(token_information + 0x10); + user.User.Sid = token_information + 0x10; - emulator_object{c.emu, token_information}.write(user); + emulator_object{c.emu, token_information}.write(user); c.emu.write_memory(token_information + 0x10, sid, sizeof(sid)); return STATUS_SUCCESS; } @@ -2447,7 +2455,9 @@ namespace c.emu.write_memory(token_information, TOKEN_SECURITY_ATTRIBUTES_INFORMATION{ .Version = 0, + .Reserved = {}, .AttributeCount = 0, + .Attribute = {}, }); return STATUS_SUCCESS; @@ -2455,7 +2465,7 @@ namespace if (token_information_class == TokenIntegrityLevel) { - constexpr auto required_size = sizeof(sid) + sizeof(TOKEN_MANDATORY_LABEL); + constexpr auto required_size = sizeof(sid) + sizeof(TOKEN_MANDATORY_LABEL64); return_length.write(required_size); if (required_size > token_information_length) @@ -2463,18 +2473,18 @@ namespace return STATUS_BUFFER_TOO_SMALL; } - TOKEN_MANDATORY_LABEL label{}; + TOKEN_MANDATORY_LABEL64 label{}; label.Label.Attributes = 0; - label.Label.Sid = reinterpret_cast(token_information + sizeof(TOKEN_MANDATORY_LABEL)); + label.Label.Sid = token_information + sizeof(TOKEN_MANDATORY_LABEL64); - emulator_object{c.emu, token_information}.write(label); - c.emu.write_memory(token_information + sizeof(TOKEN_MANDATORY_LABEL), sid, sizeof(sid)); + emulator_object{c.emu, token_information}.write(label); + c.emu.write_memory(token_information + sizeof(TOKEN_MANDATORY_LABEL64), sid, sizeof(sid)); return STATUS_SUCCESS; } if (token_information_class == TokenBnoIsolation) { - constexpr auto required_size = sizeof(TOKEN_BNO_ISOLATION_INFORMATION); + constexpr auto required_size = sizeof(TOKEN_BNO_ISOLATION_INFORMATION64); return_length.write(required_size); if (required_size > token_information_length) @@ -2482,15 +2492,15 @@ namespace return STATUS_BUFFER_TOO_SMALL; } - c.emu.write_memory(token_information, TOKEN_BNO_ISOLATION_INFORMATION{ - .IsolationPrefix = nullptr, + c.emu.write_memory(token_information, TOKEN_BNO_ISOLATION_INFORMATION64{ + .IsolationPrefix = 0, .IsolationEnabled = 0, }); return STATUS_SUCCESS; } - printf("Unsupported token info class: %lX\n", token_information_class); + printf("Unsupported token info class: %X\n", token_information_class); c.emu.stop(); return STATUS_NOT_SUPPORTED; } @@ -2514,11 +2524,12 @@ namespace NTSTATUS handle_NtGdiInit(const syscall_context& c) { - c.proc.peb.access([&](PEB& peb) + c.proc.peb.access([&](PEB64& peb) { if (!peb.GdiSharedHandleTable) { - peb.GdiSharedHandleTable = c.proc.base_allocator.reserve().ptr(); + peb.GdiSharedHandleTable = reinterpret_cast::PVOID*>(c.proc.base_allocator.reserve + ().ptr()); } }); @@ -2563,12 +2574,12 @@ namespace NTSTATUS handle_NtAlpcSendWaitReceivePort(const syscall_context& c, const handle port_handle, const ULONG /*flags*/, - const emulator_object /*send_message*/, + const emulator_object /*send_message*/, const emulator_object /*send_message_attributes*/ , - const emulator_object receive_message, - const emulator_object /*buffer_length*/, + const emulator_object receive_message, + const emulator_object::SIZE_T> /*buffer_length*/, const emulator_object /*receive_message_attributes*/, const emulator_object /*timeout*/) @@ -2579,7 +2590,7 @@ namespace return STATUS_INVALID_HANDLE; } - if (port->name != L"\\Windows\\ApiPort") + if (port->name != u"\\Windows\\ApiPort") { puts("!!! BAD PORT"); return STATUS_NOT_SUPPORTED; @@ -2587,9 +2598,9 @@ namespace // TODO: Fix this. This is broken and wrong. - const emulator_object data{c.emu, receive_message.value() + 0x48}; + const emulator_object>> data{c.emu, receive_message.value() + 0x48}; const auto dest = data.read(); - const auto base = reinterpret_cast(dest.Base); + const auto base = dest.Base; const auto value = base + 0x10; c.emu.write_memory(base + 8, &value, sizeof(value)); @@ -2617,7 +2628,7 @@ namespace return STATUS_SUCCESS; } - NTSTATUS handle_NtContinue(const syscall_context& c, const emulator_object thread_context, + NTSTATUS handle_NtContinue(const syscall_context& c, const emulator_object thread_context, const BOOLEAN /*raise_alert*/) { c.write_status = false; @@ -2657,7 +2668,7 @@ namespace NTSTATUS handle_NtReadFile(const syscall_context& c, const handle file_handle, const uint64_t /*event*/, const uint64_t /*apc_routine*/, const uint64_t /*apc_context*/, - const emulator_object io_status_block, + const emulator_object>> io_status_block, uint64_t buffer, const ULONG length, const emulator_object /*byte_offset*/, const emulator_object /*key*/) @@ -2675,7 +2686,7 @@ namespace if (io_status_block) { - IO_STATUS_BLOCK block{}; + IO_STATUS_BLOCK> block{}; block.Information = bytes_read; io_status_block.write(block); } @@ -2687,7 +2698,7 @@ namespace NTSTATUS handle_NtWriteFile(const syscall_context& c, const handle file_handle, const uint64_t /*event*/, const uint64_t /*apc_routine*/, const uint64_t /*apc_context*/, - const emulator_object io_status_block, + const emulator_object>> io_status_block, uint64_t buffer, const ULONG length, const emulator_object /*byte_offset*/, const emulator_object /*key*/) @@ -2701,7 +2712,7 @@ namespace { if (io_status_block) { - IO_STATUS_BLOCK block{}; + IO_STATUS_BLOCK> block{}; block.Information = length; io_status_block.write(block); } @@ -2727,7 +2738,7 @@ namespace if (io_status_block) { - IO_STATUS_BLOCK block{}; + IO_STATUS_BLOCK> block{}; block.Information = bytes_written; io_status_block.write(block); } @@ -2735,9 +2746,9 @@ namespace return STATUS_SUCCESS; } - const wchar_t* map_mode(const ACCESS_MASK desired_access, const ULONG create_disposition) + constexpr std::u16string map_mode(const ACCESS_MASK desired_access, const ULONG create_disposition) { - const auto* mode = L""; + std::u16string mode = u""; switch (create_disposition) { @@ -2745,7 +2756,7 @@ namespace case FILE_SUPERSEDE: if (desired_access & GENERIC_WRITE) { - mode = L"wb"; + mode = u"wb"; } break; @@ -2753,11 +2764,11 @@ namespace case FILE_OPEN_IF: if (desired_access & GENERIC_WRITE) { - mode = L"r+b"; + mode = u"r+b"; } else if (desired_access & GENERIC_READ || desired_access & SYNCHRONIZE) { - mode = L"rb"; + mode = u"rb"; } break; @@ -2765,18 +2776,18 @@ namespace case FILE_OVERWRITE_IF: if (desired_access & GENERIC_WRITE) { - mode = L"w+b"; + mode = u"w+b"; } break; default: - mode = L""; + mode = u""; break; } if (desired_access & FILE_APPEND_DATA) { - mode = L"a+b"; + mode = u"a+b"; } return mode; @@ -2784,22 +2795,23 @@ namespace NTSTATUS handle_NtCreateFile(const syscall_context& c, const emulator_object file_handle, ACCESS_MASK desired_access, - const emulator_object object_attributes, - const emulator_object /*io_status_block*/, + const emulator_object>> object_attributes, + const emulator_object>> /*io_status_block*/, const emulator_object /*allocation_size*/, ULONG /*file_attributes*/, ULONG /*share_access*/, ULONG create_disposition, ULONG create_options, uint64_t ea_buffer, ULONG ea_length) { const auto attributes = object_attributes.read(); - auto filename = read_unicode_string(c.emu, attributes.ObjectName); + auto filename = read_unicode_string( + c.emu, reinterpret_cast>*>(attributes.ObjectName)); auto printer = utils::finally([&] { - c.win_emu.log.print(color::dark_gray, "--> Opening file: %S\n", filename.c_str()); + c.win_emu.log.print(color::dark_gray, "--> Opening file: %s\n", u16_to_u8(filename).c_str()); }); - constexpr std::wstring_view device_prefix = L"\\Device\\"; + constexpr std::u16string_view device_prefix = u"\\Device\\"; if (filename.starts_with(device_prefix)) { const io_device_creation_data data{ @@ -2817,8 +2829,8 @@ namespace } handle root_handle{}; - root_handle.bits = reinterpret_cast(attributes.RootDirectory); - if (root_handle.value.is_pseudo && (filename == L"\\Reference" || filename == L"\\Connect")) + root_handle.bits = attributes.RootDirectory; + if (root_handle.value.is_pseudo && (filename == u"\\Reference" || filename == u"\\Connect")) { file_handle.write(root_handle); return STATUS_SUCCESS; @@ -2829,7 +2841,7 @@ namespace if (attributes.RootDirectory) { - const auto* root = c.proc.files.get(reinterpret_cast(attributes.RootDirectory)); + const auto* root = c.proc.files.get(attributes.RootDirectory); if (!root) { return STATUS_INVALID_HANDLE; @@ -2840,9 +2852,9 @@ namespace printer.cancel(); - if (f.name.ends_with(L"\\") || create_options & FILE_DIRECTORY_FILE) + if (f.name.ends_with(u"\\") || create_options & FILE_DIRECTORY_FILE) { - c.win_emu.log.print(color::dark_gray, "--> Opening folder: %S\n", f.name.c_str()); + c.win_emu.log.print(color::dark_gray, "--> Opening folder: %s\n", u16_to_u8(f.name).c_str()); if (create_disposition & FILE_CREATE) { @@ -2865,17 +2877,18 @@ namespace return STATUS_SUCCESS; } - c.win_emu.log.print(color::dark_gray, "--> Opening file: %S\n", f.name.c_str()); + c.win_emu.log.print(color::dark_gray, "--> Opening file: %s\n", u16_to_u8(f.name).c_str()); - const auto* mode = map_mode(desired_access, create_disposition); + std::u16string mode = map_mode(desired_access, create_disposition); - if (!mode || wcslen(mode) == 0) + if (mode.empty()) { return STATUS_NOT_SUPPORTED; } FILE* file{}; - const auto error = _wfopen_s(&file, f.name.c_str(), mode); + + const auto error = open_unicode(&file, f.name, mode); if (!file) { @@ -2901,7 +2914,8 @@ namespace } NTSTATUS handle_NtQueryAttributesFile(const syscall_context& c, - const emulator_object object_attributes, + const emulator_object>> + object_attributes, const emulator_object file_information) { if (!object_attributes) @@ -2915,10 +2929,12 @@ namespace return STATUS_INVALID_PARAMETER; } - const auto filename = read_unicode_string(c.emu, attributes.ObjectName); + const auto filename = read_unicode_string( + c.emu, emulator_object>>{c.emu, attributes.ObjectName}); + const auto u8_filename = u16_to_u8(filename); struct _stat64 file_stat{}; - if (_wstat64(filename.c_str(), &file_stat) != 0) + if (_stat64(u8_filename.c_str(), &file_stat) != 0) { return STATUS_OBJECT_NAME_NOT_FOUND; } @@ -2938,8 +2954,8 @@ namespace NTSTATUS handle_NtOpenFile(const syscall_context& c, const emulator_object file_handle, const ACCESS_MASK desired_access, - const emulator_object object_attributes, - const emulator_object io_status_block, + const emulator_object>> object_attributes, + const emulator_object>> io_status_block, const ULONG share_access, const ULONG open_options) { @@ -2978,7 +2994,8 @@ namespace NTSTATUS handle_NtRaiseHardError(const syscall_context& c, const NTSTATUS error_status, const ULONG /*number_of_parameters*/, - const emulator_object /*unicode_string_parameter_mask*/, + const emulator_object>> + /*unicode_string_parameter_mask*/, const emulator_object /*parameters*/, const HARDERROR_RESPONSE_OPTION /*valid_response_option*/, const emulator_object response) @@ -2996,8 +3013,9 @@ namespace } NTSTATUS handle_NtRaiseException(const syscall_context& c, - const emulator_object /*exception_record*/, - const emulator_object thread_context, BOOLEAN handle_exception) + const emulator_object>> + /*exception_record*/, + const emulator_object thread_context, BOOLEAN handle_exception) { if (handle_exception) { @@ -3014,7 +3032,7 @@ namespace NTSTATUS handle_NtOpenSemaphore(const syscall_context& c, const emulator_object semaphore_handle, const ACCESS_MASK /*desired_access*/, - const emulator_object object_attributes) + const emulator_object>> object_attributes) { if (!object_attributes) { @@ -3027,7 +3045,8 @@ namespace return STATUS_INVALID_PARAMETER; } - const auto name = read_unicode_string(c.emu, attributes.ObjectName); + const auto name = read_unicode_string( + c.emu, emulator_object>>{c.emu, attributes.ObjectName}); if (name.empty()) { return STATUS_INVALID_PARAMETER; @@ -3047,7 +3066,7 @@ namespace NTSTATUS handle_NtCreateSemaphore(const syscall_context& c, const emulator_object semaphore_handle, const ACCESS_MASK /*desired_access*/, - const emulator_object object_attributes, + const emulator_object>> object_attributes, const ULONG initial_count, const ULONG maximum_count) { semaphore s{}; @@ -3059,7 +3078,8 @@ namespace const auto attributes = object_attributes.read(); if (attributes.ObjectName) { - s.name = read_unicode_string(c.emu, attributes.ObjectName); + s.name = read_unicode_string( + c.emu, reinterpret_cast>*>(attributes.ObjectName)); } } @@ -3164,11 +3184,14 @@ namespace NTSTATUS handle_NtCreateThreadEx(const syscall_context& c, const emulator_object thread_handle, const ACCESS_MASK /*desired_access*/, - const emulator_object /*object_attributes*/, + const emulator_object>> + /*object_attributes*/, const handle process_handle, const uint64_t start_routine, - const uint64_t argument, const ULONG /*create_flags*/, const SIZE_T /*zero_bits*/, - const SIZE_T stack_size, const SIZE_T /*maximum_stack_size*/, - const emulator_object attribute_list) + const uint64_t argument, const ULONG /*create_flags*/, + const EmulatorTraits::SIZE_T /*zero_bits*/, + const EmulatorTraits::SIZE_T stack_size, + const EmulatorTraits::SIZE_T /*maximum_stack_size*/, + const emulator_object>> attribute_list) { if (process_handle != CURRENT_PROCESS) { @@ -3185,19 +3208,19 @@ namespace const auto* thread = c.proc.threads.get(h); - const emulator_object attributes{ - c.emu, attribute_list.value() + offsetof(PS_ATTRIBUTE_LIST, Attributes) + const emulator_object>> attributes{ + c.emu, attribute_list.value() + offsetof(PS_ATTRIBUTE_LIST>, Attributes) }; const auto total_length = attribute_list.read().TotalLength; - constexpr auto entry_size = sizeof(PS_ATTRIBUTE); - constexpr auto header_size = sizeof(PS_ATTRIBUTE_LIST) - entry_size; + constexpr auto entry_size = sizeof(PS_ATTRIBUTE>); + constexpr auto header_size = sizeof(PS_ATTRIBUTE_LIST>) - entry_size; const auto attribute_count = (total_length - header_size) / entry_size; for (size_t i = 0; i < attribute_count; ++i) { - attributes.access([&](const PS_ATTRIBUTE& attribute) + attributes.access([&](const PS_ATTRIBUTE>& attribute) { const auto type = attribute.Attribute & ~PS_ATTRIBUTE_THREAD; @@ -3212,7 +3235,7 @@ namespace } else { - printf("Unsupported thread attribute type: %llX\n", type); + printf("Unsupported thread attribute type: %" PRIx64 "\n", type); } }, i); } @@ -3259,7 +3282,7 @@ namespace if (!is_awaitable_object_type(h)) { c.win_emu.log.print(color::gray, "Unsupported handle type for NtWaitForMultipleObjects: %d!\n", - h.value.type); + h.value.type); return STATUS_NOT_SUPPORTED; } } @@ -3285,7 +3308,7 @@ namespace if (!is_awaitable_object_type(h)) { c.win_emu.log.print(color::gray, - "Unsupported handle type for NtWaitForSingleObject: %d!\n", h.value.type); + "Unsupported handle type for NtWaitForSingleObject: %d!\n", h.value.type); return STATUS_NOT_SUPPORTED; } @@ -3356,7 +3379,7 @@ namespace } NTSTATUS handle_NtAlertThreadByThreadIdEx(const syscall_context& c, const uint64_t thread_id, - const emulator_object lock) + const emulator_object>> lock) { if (lock.value()) { @@ -3393,7 +3416,7 @@ namespace } NTSTATUS handle_NtGetContextThread(const syscall_context& c, handle thread_handle, - const emulator_object thread_context) + const emulator_object thread_context) { const auto* thread = thread_handle == CURRENT_THREAD ? c.proc.active_thread @@ -3412,9 +3435,9 @@ namespace thread->restore(c.emu); - thread_context.access([&](CONTEXT& context) + thread_context.access([&](CONTEXT64& context) { - if (context.ContextFlags & CONTEXT_DEBUG_REGISTERS) + if (context.ContextFlags & CONTEXT_DEBUG_REGISTERS_64) { c.win_emu.log.print(color::pink, "--> Reading debug registers!\n"); } @@ -3434,7 +3457,7 @@ void syscall_dispatcher::add_handlers(std::map& ha handler_mapping[#syscall] = make_syscall_handler(); \ } while(0) - add_handler(NtSetInformationThread) ; + add_handler(NtSetInformationThread); add_handler(NtSetEvent); add_handler(NtClose); add_handler(NtOpenKey); diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index befd6e60..042b4aa5 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -14,8 +14,8 @@ namespace emulator_object allocate_object_on_stack(x64_emulator& emu) { const auto old_sp = emu.reg(x64_register::rsp); - const auto new_sp = align_down(old_sp - sizeof(CONTEXT), - std::max(alignof(CONTEXT), alignof(x64_emulator::pointer_type))); + const auto new_sp = align_down(old_sp - sizeof(CONTEXT64), + std::max(alignof(CONTEXT64), alignof(x64_emulator::pointer_type))); emu.reg(x64_register::rsp, new_sp); return {emu, new_sp}; @@ -143,8 +143,13 @@ namespace emulator_object build_api_set_map(x64_emulator& emu, emulator_allocator& allocator) { - const auto& orig_api_set_map = *NtCurrentTeb()->ProcessEnvironmentBlock->ApiSetMap; + // TODO: fix +#ifdef OS_WINDOWS + const auto& orig_api_set_map = *NtCurrentTeb64()->ProcessEnvironmentBlock->ApiSetMap; return clone_api_set_map(emu, allocator, orig_api_set_map); +#else + return clone_api_set_map(emu, allocator, {}); +#endif } emulator_allocator create_allocator(emulator& emu, const size_t size) @@ -187,7 +192,7 @@ namespace context.base_allocator = create_allocator(emu, PEB_SEGMENT_SIZE); auto& allocator = context.base_allocator; - context.peb = allocator.reserve(); + context.peb = allocator.reserve(); /* Values of the following fields must be * allocated relative to the process_params themselves @@ -204,9 +209,9 @@ namespace * RedirectionDllName */ - context.process_params = allocator.reserve(); + context.process_params = allocator.reserve(); - context.process_params.access([&](RTL_USER_PROCESS_PARAMETERS& proc_params) + context.process_params.access([&](RTL_USER_PROCESS_PARAMETERS64& proc_params) { proc_params.Flags = 0x6001; //| 0x80000000; // Prevent CsrClientConnectToServer @@ -215,41 +220,43 @@ namespace proc_params.StandardInput = STDIN_HANDLE.h; proc_params.StandardError = proc_params.StandardOutput; - proc_params.Environment = allocator.copy_string(L"=::=::\\"); - allocator.copy_string(L"EMULATOR=1"); - allocator.copy_string(L"COMPUTERNAME=momo"); - allocator.copy_string(L"SystemRoot=C:\\WINDOWS"); - allocator.copy_string(L""); + proc_params.Environment = reinterpret_cast(allocator.copy_string(u"=::=::\\")); + allocator.copy_string(u"EMULATOR=1"); + allocator.copy_string(u"COMPUTERNAME=momo"); + allocator.copy_string(u"SystemRoot=C:\\WINDOWS"); + allocator.copy_string(u""); - std::wstring command_line = L"\"" + settings.application.wstring() + L"\""; + std::u16string command_line = u"\"" + settings.application.u16string() + u"\""; for (const auto& arg : settings.arguments) { - command_line.push_back(L' '); + command_line.push_back(u' '); command_line.append(arg); } - std::wstring current_folder{}; + std::u16string current_folder{}; if (!settings.working_directory.empty()) { - current_folder = canonicalize_path(settings.working_directory).wstring() + L"\\"; + current_folder = canonicalize_path(settings.working_directory).u16string() + u"\\"; } else { - current_folder = canonicalize_path(settings.application).parent_path().wstring() + L"\\"; + current_folder = canonicalize_path(settings.application).parent_path().u16string() + u"\\"; } allocator.make_unicode_string(proc_params.CommandLine, command_line); allocator.make_unicode_string(proc_params.CurrentDirectory.DosPath, current_folder); - allocator.make_unicode_string(proc_params.ImagePathName, canonicalize_path(settings.application).wstring()); + allocator.make_unicode_string(proc_params.ImagePathName, + canonicalize_path(settings.application).u16string()); const auto total_length = allocator.get_next_address() - context.process_params.value(); - proc_params.Length = static_cast(std::max(sizeof(proc_params), total_length)); + proc_params.Length = static_cast(std::max(static_cast(sizeof(proc_params)), + total_length)); proc_params.MaximumLength = proc_params.Length; }); - context.peb.access([&](PEB& peb) + context.peb.access([&](PEB64& peb) { peb.ImageBaseAddress = nullptr; peb.ProcessParameters = context.process_params.ptr(); @@ -270,21 +277,24 @@ namespace }); } - using exception_record_map = std::unordered_map>; + using exception_record_map = std::unordered_map< + const EMU_EXCEPTION_RECORD>*, emulator_object>>>; - emulator_object save_exception_record(emulator_allocator& allocator, - const EXCEPTION_RECORD& record, - exception_record_map& record_mapping) + emulator_object>> save_exception_record(emulator_allocator& allocator, + const EMU_EXCEPTION_RECORD>& record, + exception_record_map& record_mapping) { - const auto record_obj = allocator.reserve(); + const auto record_obj = allocator.reserve>>(); record_obj.write(record); if (record.ExceptionRecord) { record_mapping.emplace(&record, record_obj); - emulator_object nested_record_obj{allocator.get_emulator()}; - const auto nested_record = record_mapping.find(record.ExceptionRecord); + emulator_object>> nested_record_obj{allocator.get_emulator()}; + const auto nested_record = record_mapping.find( + reinterpret_cast>*>(record.ExceptionRecord)); if (nested_record != record_mapping.end()) { @@ -292,21 +302,22 @@ namespace } else { - nested_record_obj = save_exception_record(allocator, *record.ExceptionRecord, - record_mapping); + nested_record_obj = save_exception_record( + allocator, *reinterpret_cast>*>(record.ExceptionRecord), + record_mapping); } - record_obj.access([&](EXCEPTION_RECORD& r) + record_obj.access([&](EMU_EXCEPTION_RECORD>& r) { - r.ExceptionRecord = nested_record_obj.ptr(); + r.ExceptionRecord = reinterpret_cast::PVOID>(nested_record_obj.ptr()); }); } return record_obj; } - emulator_object save_exception_record(emulator_allocator& allocator, - const EXCEPTION_RECORD& record) + emulator_object>> save_exception_record(emulator_allocator& allocator, + const EMU_EXCEPTION_RECORD>& record) { exception_record_map record_mapping{}; return save_exception_record(allocator, record, record_mapping); @@ -325,12 +336,12 @@ namespace } } - size_t calculate_exception_record_size(const EXCEPTION_RECORD& record) + size_t calculate_exception_record_size(const EMU_EXCEPTION_RECORD>& record) { - std::unordered_set records{}; + std::unordered_set>*> records{}; size_t total_size = 0; - const EXCEPTION_RECORD* current_record = &record; + const EMU_EXCEPTION_RECORD>* current_record = &record; while (current_record) { if (!records.insert(current_record).second) @@ -339,7 +350,7 @@ namespace } total_size += sizeof(*current_record); - current_record = record.ExceptionRecord; + current_record = reinterpret_cast>*>(record.ExceptionRecord); } return total_size; @@ -354,11 +365,13 @@ namespace uint64_t ss; }; - void dispatch_exception_pointers(x64_emulator& emu, const uint64_t dispatcher, const EXCEPTION_POINTERS pointers) + void dispatch_exception_pointers(x64_emulator& emu, const uint64_t dispatcher, + const EMU_EXCEPTION_POINTERS> pointers) { constexpr auto mach_frame_size = 0x40; constexpr auto context_record_size = 0x4F0; - const auto exception_record_size = calculate_exception_record_size(*pointers.ExceptionRecord); + const auto exception_record_size = calculate_exception_record_size( + *reinterpret_cast>*>(pointers.ExceptionRecord)); const auto combined_size = align_up(exception_record_size + context_record_size, 0x10); assert(combined_size == 0x590); @@ -379,11 +392,12 @@ namespace emu.reg(x64_register::rsp, new_sp); emu.reg(x64_register::rip, dispatcher); - const emulator_object context_record_obj{emu, new_sp}; - context_record_obj.write(*pointers.ContextRecord); + const emulator_object context_record_obj{emu, new_sp}; + context_record_obj.write(*reinterpret_cast(pointers.ContextRecord)); emulator_allocator allocator{emu, new_sp + context_record_size, exception_record_size}; - const auto exception_record_obj = save_exception_record(allocator, *pointers.ExceptionRecord); + const auto exception_record_obj = save_exception_record( + allocator, *reinterpret_cast>*>(pointers.ExceptionRecord)); if (exception_record_obj.value() != allocator.get_base()) { @@ -393,55 +407,56 @@ namespace const emulator_object machine_frame_obj{emu, new_sp + combined_size}; machine_frame_obj.access([&](machine_frame& frame) { - frame.rip = pointers.ContextRecord->Rip; - frame.rsp = pointers.ContextRecord->Rsp; - frame.ss = pointers.ContextRecord->SegSs; - frame.cs = pointers.ContextRecord->SegCs; - frame.eflags = pointers.ContextRecord->EFlags; + const auto& record = *reinterpret_cast(pointers.ContextRecord); + frame.rip = record.Rip; + frame.rsp = record.Rsp; + frame.ss = record.SegSs; + frame.cs = record.SegCs; + frame.eflags = record.EFlags; }); } void dispatch_access_violation(x64_emulator& emu, const uint64_t dispatcher, const uint64_t address, const memory_operation operation) { - CONTEXT ctx{}; - ctx.ContextFlags = CONTEXT_ALL; + CONTEXT64 ctx{}; + ctx.ContextFlags = CONTEXT64_ALL; context_frame::save(emu, ctx); - EXCEPTION_RECORD record{}; + EMU_EXCEPTION_RECORD> record{}; memset(&record, 0, sizeof(record)); record.ExceptionCode = static_cast(STATUS_ACCESS_VIOLATION); record.ExceptionFlags = 0; - record.ExceptionRecord = nullptr; - record.ExceptionAddress = reinterpret_cast(emu.read_instruction_pointer()); + record.ExceptionRecord = 0; + record.ExceptionAddress = static_cast::PVOID>(emu.read_instruction_pointer()); record.NumberParameters = 2; record.ExceptionInformation[0] = map_violation_operation_to_parameter(operation); record.ExceptionInformation[1] = address; - EXCEPTION_POINTERS pointers{}; - pointers.ContextRecord = &ctx; - pointers.ExceptionRecord = &record; + EMU_EXCEPTION_POINTERS> pointers{}; + pointers.ContextRecord = reinterpret_cast::PVOID>(&ctx); + pointers.ExceptionRecord = reinterpret_cast::PVOID>(&record); dispatch_exception_pointers(emu, dispatcher, pointers); } void dispatch_illegal_instruction_violation(x64_emulator& emu, const uint64_t dispatcher) { - CONTEXT ctx{}; - ctx.ContextFlags = CONTEXT_ALL; + CONTEXT64 ctx{}; + ctx.ContextFlags = CONTEXT64_ALL; context_frame::save(emu, ctx); - EXCEPTION_RECORD record{}; + EMU_EXCEPTION_RECORD> record{}; memset(&record, 0, sizeof(record)); record.ExceptionCode = static_cast(STATUS_ILLEGAL_INSTRUCTION); record.ExceptionFlags = 0; - record.ExceptionRecord = nullptr; - record.ExceptionAddress = reinterpret_cast(emu.read_instruction_pointer()); + record.ExceptionRecord = 0; + record.ExceptionAddress = static_cast::PVOID>(emu.read_instruction_pointer()); record.NumberParameters = 0; - EXCEPTION_POINTERS pointers{}; - pointers.ContextRecord = &ctx; - pointers.ExceptionRecord = &record; + EMU_EXCEPTION_POINTERS> pointers{}; + pointers.ContextRecord = reinterpret_cast::PVOID>(&ctx); + pointers.ExceptionRecord = reinterpret_cast::PVOID>(&record); dispatch_exception_pointers(emu, dispatcher, pointers); } @@ -596,7 +611,7 @@ emulator_thread::emulator_thread(x64_emulator& emu, const process_context& conte const uint64_t argument, const uint64_t stack_size, const uint32_t id) : emu_ptr(&emu) - , stack_size(page_align_up(std::max(stack_size, STACK_SIZE))) + , stack_size(page_align_up(std::max(stack_size, static_cast(STACK_SIZE)))) , start_address(start_address) , argument(argument) , id(id) @@ -610,14 +625,14 @@ emulator_thread::emulator_thread(x64_emulator& emu, const process_context& conte GS_SEGMENT_SIZE, }; - this->teb = this->gs_segment->reserve(); + this->teb = this->gs_segment->reserve(); - this->teb->access([&](TEB& teb_obj) + this->teb->access([&](TEB64& teb_obj) { - teb_obj.ClientId.UniqueProcess = reinterpret_cast(1); - teb_obj.ClientId.UniqueThread = reinterpret_cast(static_cast(this->id)); - teb_obj.NtTib.StackLimit = reinterpret_cast(this->stack_base); - teb_obj.NtTib.StackBase = reinterpret_cast(this->stack_base + this->stack_size); + teb_obj.ClientId.UniqueProcess = 1ul; + teb_obj.ClientId.UniqueThread = static_cast(this->id); + teb_obj.NtTib.StackLimit = reinterpret_cast(this->stack_base); + teb_obj.NtTib.StackBase = reinterpret_cast(this->stack_base + this->stack_size); teb_obj.NtTib.Self = &this->teb->ptr()->NtTib; teb_obj.ProcessEnvironmentBlock = context.peb.ptr(); }); @@ -712,8 +727,8 @@ void emulator_thread::setup_registers(x64_emulator& emu, const process_context& setup_stack(emu, this->stack_base, this->stack_size); setup_gs_segment(emu, *this->gs_segment); - CONTEXT ctx{}; - ctx.ContextFlags = CONTEXT_ALL; + CONTEXT64 ctx{}; + ctx.ContextFlags = CONTEXT64_ALL; unalign_stack(emu); context_frame::save(emu, ctx); @@ -722,7 +737,7 @@ void emulator_thread::setup_registers(x64_emulator& emu, const process_context& ctx.Rcx = this->start_address; ctx.Rdx = this->argument; - const auto ctx_obj = allocate_object_on_stack(emu); + const auto ctx_obj = allocate_object_on_stack(emu); ctx_obj.write(ctx); unalign_stack(emu); @@ -766,9 +781,9 @@ void windows_emulator::setup_process(const emulator_settings& settings) context.executable = context.mod_manager.map_module(settings.application, this->log); - context.peb.access([&](PEB& peb) + context.peb.access([&](PEB64& peb) { - peb.ImageBaseAddress = reinterpret_cast(context.executable->image_base); + peb.ImageBaseAddress = reinterpret_cast(context.executable->image_base); }); context.ntdll = context.mod_manager.map_module(R"(C:\Windows\System32\ntdll.dll)", this->log); @@ -843,16 +858,16 @@ void windows_emulator::on_instruction_execution(uint64_t address) if (export_entry != binary->address_names.end()) { log.print(is_interesting_call ? color::yellow : color::dark_gray, - "Executing function: %s - %s (0x%llX)\n", - binary->name.c_str(), - export_entry->second.c_str(), address); + "Executing function: %s - %s (0x%" PRIx64 ")\n", + binary->name.c_str(), + export_entry->second.c_str(), address); } else if (address == binary->entry_point) { log.print(is_interesting_call ? color::yellow : color::gray, - "Executing entry point: %s (0x%llX)\n", - binary->name.c_str(), - address); + "Executing entry point: %s (0x%" PRIx64 ")\n", + binary->name.c_str(), + address); } } @@ -864,7 +879,8 @@ void windows_emulator::on_instruction_execution(uint64_t address) auto& emu = this->emu(); printf( - "Inst: %16llX - RAX: %16llX - RBX: %16llX - RCX: %16llX - RDX: %16llX - R8: %16llX - R9: %16llX - RDI: %16llX - RSI: %16llX - %s\n", + "Inst: %16" PRIx64 " - RAX: %16" PRIx64 " - RBX: %16" PRIx64 " - RCX: %16" PRIx64 " - RDX: %16" PRIx64 + " - R8: %16" PRIx64 " - R9: %16" PRIx64 " - RDI: %16" PRIx64 " - RSI: %16" PRIx64 " - %s\n", address, emu.reg(x64_register::rax), emu.reg(x64_register::rbx), emu.reg(x64_register::rcx), @@ -901,7 +917,8 @@ void windows_emulator::setup_hooks() this->emu().hook_instruction(x64_hookable_instructions::invalid, [&] { const auto ip = this->emu().read_instruction_pointer(); - printf("Invalid instruction at: 0x%llX\n", ip); + + this->log.print(color::gray, "Invalid instruction at: 0x%" PRIx64 "\n", ip); return instruction_hook_continuation::skip_instruction; }); @@ -915,7 +932,7 @@ void windows_emulator::setup_hooks() } const auto rip = this->emu().read_instruction_pointer(); - printf("Interrupt: %i 0x%llX\n", interrupt, rip); + this->log.print(color::gray, "Interrupt: %i 0x%" PRIx64 "\n", interrupt, rip); if (this->fuzzing || true) // TODO: Fix { @@ -933,15 +950,17 @@ void windows_emulator::setup_hooks() if (type == memory_violation_type::protection) { - this->log.print(color::gray, "Protection violation: 0x%llX (%zX) - %s at 0x%llX (%s)\n", address, size, - permission.c_str(), ip, - name); + this->log.print(color::gray, "Protection violation: 0x%" PRIx64 " (%zX) - %s at 0x%" PRIx64 " (%s)\n", + address, size, + permission.c_str(), ip, + name); } else if (type == memory_violation_type::unmapped) { - this->log.print(color::gray, "Mapping violation: 0x%llX (%zX) - %s at 0x%llX (%s)\n", address, size, - permission.c_str(), ip, - name); + this->log.print(color::gray, "Mapping violation: 0x%" PRIx64 " (%zX) - %s at 0x%" PRIx64 " (%s)\n", address, + size, + permission.c_str(), ip, + name); } if (this->fuzzing) diff --git a/src/windows-emulator/windows_emulator.hpp b/src/windows-emulator/windows_emulator.hpp index 04db221f..6c46f5ec 100644 --- a/src/windows-emulator/windows_emulator.hpp +++ b/src/windows-emulator/windows_emulator.hpp @@ -15,7 +15,7 @@ struct emulator_settings std::filesystem::path application{}; std::filesystem::path working_directory{}; std::filesystem::path registry_directory{"./registry"}; - std::vector arguments{}; + std::vector arguments{}; std::function stdout_callback{}; bool disable_logging{false}; bool silent_until_main{false};