Support emulation on 32 bit Windows (#203)

Emulation of 32 bit Windows applications is still unsupported.
This commit is contained in:
Maurice Heumann
2025-04-14 15:57:30 +02:00
committed by GitHub
40 changed files with 307 additions and 274 deletions

View File

@@ -151,6 +151,7 @@ jobs:
fail-fast: false
matrix:
platform:
- Windows x86
- Windows x86_64
- Linux x86_64 GCC
- Linux x86_64 GCC Sanitizer
@@ -168,8 +169,12 @@ jobs:
preset: debug
- configuration: Release
preset: release
- platform: Windows x86
runner: windows-latest
devcmd_arch: x86
- platform: Windows x86_64
runner: windows-latest
devcmd_arch: x64
- platform: Linux x86_64 GCC Sanitizer
runner: ubuntu-24.04
cmake-options: "-DMOMO_ENABLE_SANITIZER=On"
@@ -224,6 +229,8 @@ jobs:
- name: Enable Developer Command Prompt
uses: ilammy/msvc-dev-cmd@v1.13.0
if: ${{ startsWith(matrix.platform, 'Windows') }}
with:
arch: ${{ matrix.devcmd_arch }}
- uses: nttld/setup-ndk@v1
id: setup-ndk
@@ -262,6 +269,7 @@ jobs:
fail-fast: false
matrix:
platform:
- Windows x86
- Windows x86_64
- Linux x86_64 GCC
- Linux x86_64 GCC Sanitizer
@@ -283,6 +291,8 @@ jobs:
preset: debug
- configuration: Release
preset: release
- platform: Windows x86
runner: windows-latest
- platform: Windows x86_64
runner: windows-latest
- platform: Linux x86_64 GCC
@@ -336,6 +346,7 @@ jobs:
run: cp build/${{matrix.preset}}/artifacts/test-sample.exe build/${{matrix.preset}}/artifacts/root/filesys/c/
- name: CMake Test
if: ${{ matrix.emulator != 'Icicle' || matrix.platform != 'Windows x86' }}
run: cd build/${{matrix.preset}} && ctest --verbose -j
env:
EMULATOR_ROOT: ${{github.workspace}}/build/${{matrix.preset}}/artifacts/root

View File

@@ -12,7 +12,7 @@ if (NOT MOMO_BUILD_AS_LIBRARY)
add_subdirectory(fuzzing-engine)
add_subdirectory(fuzzer)
add_subdirectory(windows-emulator-test)
if(WIN32)
if(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 8)
momo_add_subdirectory_and_get_targets("tools" TOOL_TARGETS)
momo_targets_set_folder("tools" ${TOOL_TARGETS})

View File

@@ -10,7 +10,7 @@ emulator_hook* watch_object(windows_emulator& emu, const std::set<std::string, s
const reflect_type_info<T> info{};
return emu.emu().hook_memory_read(
object.value(), object.size(),
object.value(), static_cast<size_t>(object.size()),
[i = std::move(info), object, &emu, cache_logging, modules](const uint64_t address, const void*, size_t) {
const auto rip = emu.emu().read_instruction_pointer();
const auto* mod = emu.mod_manager.find_by_address(rip);
@@ -33,6 +33,7 @@ emulator_hook* watch_object(windows_emulator& emu, const std::set<std::string, s
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() : "<N/A>");
i.get_member_name(static_cast<size_t>(offset)).c_str(), rip,
mod ? mod->name.c_str() : "<N/A>");
});
}

View File

@@ -11,9 +11,18 @@
#pragma clang diagnostic ignored "-Wunused-private-field"
#endif
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4308)
#endif
#include "reflect_extension.hpp"
#include <reflect>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#if defined(__clang__)
#pragma clang diagnostic pop
#endif

View File

@@ -13,7 +13,9 @@ endif()
set(CARGO_TRIPLE)
set(CARGO_OPTIONS)
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
if(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 4)
set(CARGO_TRIPLE "i686-pc-windows-msvc")
elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS")
set(CARGO_TRIPLE "aarch64-apple-ios")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
if(CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a")

View File

@@ -207,8 +207,8 @@ namespace unicorn
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
uce(uc_ctl_set_tcg_buffer_size(this->uc_, 2 << 30 /* 2 gb */));
constexpr auto is_64_bit = sizeof(void*) >= 8;
uce(uc_ctl_set_tcg_buffer_size(this->uc_, (is_64_bit ? 2 : 1) << 30 /* 2 gb */));
#ifndef OS_WINDOWS
#pragma GCC diagnostic pop
@@ -264,8 +264,8 @@ namespace unicorn
struct msr_value
{
uint32_t id;
uint64_t value;
uint64_t id{};
uint64_t value{};
};
msr_value msr_val{

View File

@@ -2,6 +2,13 @@
#if defined(_WIN32) || defined(_WIN64)
#define OS_WINDOWS
#if defined(_WIN64)
#define OS_WINDOWS_64
#else
#define OS_WINDOWS_32
#endif
#elif defined(__APPLE__) || defined(__MACH__)
#define OS_MAC
#elif defined(__linux__)

View File

@@ -19,13 +19,13 @@
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;
EMULATOR_CAST(std::uint64_t, 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;
EMULATOR_CAST(std::uint64_t, struct _EMU_NT_TIB64*) Self;
} EMU_NT_TIB64;
typedef EMU_NT_TIB64* PEMU_NT_TIB64;
@@ -51,8 +51,8 @@ union PEB_BITFIELD_UNION
typedef struct _LIST_ENTRY64
{
struct _LIST_ENTRY* Flink;
struct _LIST_ENTRY* Blink;
ULONGLONG Flink;
ULONGLONG Blink;
} LIST_ENTRY64, *PLIST_ENTRY64, *RESTRICTED_POINTER PRLIST_ENTRY64;
#endif
@@ -65,17 +65,14 @@ typedef struct _PEB_LDR_DATA64
LIST_ENTRY64 InLoadOrderModuleList;
LIST_ENTRY64 InMemoryOrderModuleList;
LIST_ENTRY64 InInitializationOrderModuleList;
std::uint64_t* EntryInProgress;
std::uint64_t EntryInProgress;
BOOLEAN ShutdownInProgress;
EmulatorTraits<Emu64>::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;
using STRING64 = UNICODE_STRING<EmulatorTraits<Emu64>>;
using ANSI_STRING64 = STRING64;
using OEM_STRING64 = STRING64;
typedef struct _RTL_DRIVE_LETTER_CURDIR64
{
@@ -118,7 +115,7 @@ typedef struct _RTL_USER_PROCESS_PARAMETERS64
UNICODE_STRING<EmulatorTraits<Emu64>> DllPath;
UNICODE_STRING<EmulatorTraits<Emu64>> ImagePathName;
UNICODE_STRING<EmulatorTraits<Emu64>> CommandLine;
std::uint64_t* Environment;
std::uint64_t Environment;
ULONG StartingX;
ULONG StartingY;
@@ -136,21 +133,23 @@ typedef struct _RTL_USER_PROCESS_PARAMETERS64
UNICODE_STRING<EmulatorTraits<Emu64>> RuntimeData;
ARRAY_CONTAINER<RTL_DRIVE_LETTER_CURDIR64, RTL_MAX_DRIVE_LETTERS> CurrentDirectories;
std::uint64_t* EnvironmentSize;
std::uint64_t* EnvironmentVersion;
std::uint64_t EnvironmentSize;
std::uint64_t EnvironmentVersion;
std::uint64_t* PackageDependencyData;
std::uint64_t PackageDependencyData;
ULONG ProcessGroupId;
ULONG LoaderThreads;
UNICODE_STRING<EmulatorTraits<Emu64>> RedirectionDllName; // REDSTONE4
UNICODE_STRING<EmulatorTraits<Emu64>> HeapPartitionName; // 19H1
std::uint64_t* DefaultThreadpoolCpuSetMasks;
std::uint64_t DefaultThreadpoolCpuSetMasks;
ULONG DefaultThreadpoolCpuSetMaskCount;
ULONG DefaultThreadpoolThreadMaximum;
ULONG HeapMemoryTypeMask; // WIN11
} RTL_USER_PROCESS_PARAMETERS64, *PRTL_USER_PROCESS_PARAMETERS64;
static_assert(sizeof(RTL_USER_PROCESS_PARAMETERS64) == 0x448);
union PEB_CROSS_PROCESS_FLAGS_UNION
{
ULONG CrossProcessFlags;
@@ -171,8 +170,8 @@ union PEB_CROSS_PROCESS_FLAGS_UNION
union PEB_KERNEL_CALLBACK_TABLE_UNION64
{
void* KernelCallbackTable;
void* UserSharedInfoPtr;
std::uint64_t KernelCallbackTable;
std::uint64_t UserSharedInfoPtr;
};
typedef struct _API_SET_NAMESPACE
@@ -188,9 +187,9 @@ typedef struct _API_SET_NAMESPACE
union PEB_CONTEXT_DATA_UNION64
{
void* pContextData; // WIN7
void* pUnused; // WIN10
void* EcCodeBitMap; // WIN11
std::uint64_t pContextData; // WIN7
std::uint64_t pUnused; // WIN10
std::uint64_t EcCodeBitMap; // WIN11
};
union PEB_TRACING_FLAGS_UNION
@@ -229,18 +228,18 @@ typedef struct _CPTABLEINFO
USHORT TransUniDefaultChar;
USHORT DBCSCodePage;
UCHAR LeadByte[MAXIMUM_LEADBYTES];
USHORT* MultiByteTable;
void* WideCharTable;
USHORT* DBCSRanges;
USHORT* DBCSOffsets;
EMULATOR_CAST(uint64_t, USHORT*) MultiByteTable;
EMULATOR_CAST(uint64_t, void*) WideCharTable;
EMULATOR_CAST(uint64_t, USHORT*) DBCSRanges;
EMULATOR_CAST(uint64_t, USHORT*) DBCSOffsets;
} CPTABLEINFO, *PCPTABLEINFO;
typedef struct _NLSTABLEINFO
{
CPTABLEINFO OemTableInfo;
CPTABLEINFO AnsiTableInfo;
USHORT* UpperCaseTable;
USHORT* LowerCaseTable;
EMULATOR_CAST(uint64_t, USHORT*) UpperCaseTable;
EMULATOR_CAST(uint64_t, USHORT*) LowerCaseTable;
} NLSTABLEINFO, *PNLSTABLEINFO;
typedef struct _PEB64
@@ -253,26 +252,26 @@ typedef struct _PEB64
EmulatorTraits<Emu64>::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;
EMULATOR_CAST(std::uint64_t, PPEB_LDR_DATA64) Ldr;
EMULATOR_CAST(std::uint64_t, PRTL_USER_PROCESS_PARAMETERS64) ProcessParameters;
std::uint64_t SubSystemData;
std::uint64_t ProcessHeap;
EMULATOR_CAST(std::uint64_t, PRTL_CRITICAL_SECTION) FastPebLock;
EMULATOR_CAST(std::uint64_t, 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;
EMULATOR_CAST(std::uint64_t, PAPI_SET_NAMESPACE) ApiSetMap;
ULONG TlsExpansionCounter;
EMULATOR_CAST(void*, PRTL_BITMAP) TlsBitmap;
EMULATOR_CAST(std::uint64_t, PRTL_BITMAP) TlsBitmap;
ARRAY_CONTAINER<ULONG, 2> TlsBitmapBits; // TLS_MINIMUM_AVAILABLE
void* ReadOnlySharedMemoryBase;
EMULATOR_CAST(void*, PSILO_USER_SHARED_DATA) SharedData; // HotpatchInformation
std::uint64_t** ReadOnlyStaticServerData;
std::uint64_t ReadOnlySharedMemoryBase;
EMULATOR_CAST(std::uint64_t, PSILO_USER_SHARED_DATA) SharedData; // HotpatchInformation
std::uint64_t ReadOnlyStaticServerData;
EMULATOR_CAST(EmulatorTraits<Emu64>::PVOID, PCPTABLEINFO) AnsiCodePageData; // PCPTABLEINFO
EMULATOR_CAST(EmulatorTraits<Emu64>::PVOID, PCPTABLEINFO) OemCodePageData; // PCPTABLEINFO
@@ -289,13 +288,13 @@ typedef struct _PEB64
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
std::uint64_t** ProcessHeaps; // PHEAP
std::uint64_t ProcessHeaps; // PHEAP
std::uint64_t GdiSharedHandleTable; // PGDI_SHARED_MEMORY
std::uint64_t* ProcessStarterHelper;
std::uint64_t ProcessStarterHelper;
ULONG GdiDCAttributeList;
EMULATOR_CAST(void*, PRTL_CRITICAL_SECTION) LoaderLock;
EMULATOR_CAST(std::uint64_t, PRTL_CRITICAL_SECTION) LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
@@ -307,30 +306,30 @@ typedef struct _PEB64
ULONG ImageSubsystemMinorVersion;
EMULATOR_CAST(std::uint64_t, KAFFINITY) ActiveProcessAffinityMask;
ARRAY_CONTAINER<ULONG, GDI_HANDLE_BUFFER_SIZE64> GdiHandleBuffer;
std::uint64_t* PostProcessInitRoutine;
std::uint64_t PostProcessInitRoutine;
EMULATOR_CAST(void*, PRTL_BITMAP) TlsExpansionBitmap;
EMULATOR_CAST(std::uint64_t, PRTL_BITMAP) TlsExpansionBitmap;
ARRAY_CONTAINER<ULONG, 32> TlsExpansionBitmapBits; // TLS_EXPANSION_SLOTS
ULONG SessionId;
ULARGE_INTEGER AppCompatFlags; // KACF_*
ULARGE_INTEGER AppCompatFlagsUser;
std::uint64_t* pShimData;
std::uint64_t* AppCompatInfo; // APPCOMPAT_EXE_DATA
std::uint64_t pShimData;
std::uint64_t AppCompatInfo; // APPCOMPAT_EXE_DATA
UNICODE_STRING<EmulatorTraits<Emu64>> 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::uint64_t, PACTIVATION_CONTEXT_DATA) ActivationContextData;
EMULATOR_CAST(std::uint64_t, PASSEMBLY_STORAGE_MAP) ProcessAssemblyStorageMap;
EMULATOR_CAST(std::uint64_t, PACTIVATION_CONTEXT_DATA) SystemDefaultActivationContextData;
EMULATOR_CAST(std::uint64_t, PASSEMBLY_STORAGE_MAP) SystemAssemblyStorageMap;
EMULATOR_CAST(std::int64_t, SIZE_T) MinimumStackCommit;
EMULATOR_CAST(std::uint64_t, SIZE_T) MinimumStackCommit;
ARRAY_CONTAINER<std::uint64_t*, 2> SparePointers; // 19H1 (previously FlsCallback to FlsHighIndex)
std::uint64_t* PatchLoaderData;
std::uint64_t* ChpeV2ProcessInfo; // _CHPEV2_PROCESS_INFO
ARRAY_CONTAINER<std::uint64_t, 2> SparePointers; // 19H1 (previously FlsCallback to FlsHighIndex)
std::uint64_t PatchLoaderData;
std::uint64_t ChpeV2ProcessInfo; // _CHPEV2_PROCESS_INFO
ULONG AppModelFeatureState;
ARRAY_CONTAINER<ULONG, 2> SpareUlongs;
@@ -340,40 +339,42 @@ typedef struct _PEB64
USHORT UseCaseMapping;
USHORT UnusedNlsField;
std::uint64_t* WerRegistrationData;
std::uint64_t* WerShipAssertPtr;
std::uint64_t WerRegistrationData;
std::uint64_t WerShipAssertPtr;
PEB_CONTEXT_DATA_UNION64 ContextData;
std::uint64_t* pImageHeaderHash;
std::uint64_t pImageHeaderHash;
PEB_TRACING_FLAGS_UNION TracingFlags;
ULONGLONG CsrServerReadOnlySharedMemoryBase;
EMULATOR_CAST(void*, PRTL_CRITICAL_SECTION) TppWorkerpListLock;
EMULATOR_CAST(std::uint64_t, PRTL_CRITICAL_SECTION) TppWorkerpListLock;
LIST_ENTRY64 TppWorkerpList;
ARRAY_CONTAINER<std::uint64_t*, 128> WaitOnAddressHashTable;
EMULATOR_CAST(void*, PTELEMETRY_COVERAGE_HEADER) TelemetryCoverageHeader; // REDSTONE3
ARRAY_CONTAINER<std::uint64_t, 128> WaitOnAddressHashTable;
EMULATOR_CAST(std::uint64_t, PTELEMETRY_COVERAGE_HEADER) TelemetryCoverageHeader; // REDSTONE3
ULONG CloudFileFlags;
ULONG CloudFileDiagFlags; // REDSTONE4
CHAR PlaceholderCompatibilityMode;
ARRAY_CONTAINER<CHAR, 7> PlaceholderCompatibilityModeReserved;
EMULATOR_CAST(void*, PLEAP_SECOND_DATA) LeapSecondData; // REDSTONE5
EMULATOR_CAST(std::uint64_t, PLEAP_SECOND_DATA) LeapSecondData; // REDSTONE5
PEB_LEAP_SECONDS_FLAG_UNION LeapSecondFlags;
ULONG NtGlobalFlag2;
ULONGLONG ExtendedFeatureDisableMask; // since WIN11
} PEB64, *PPEB64;
static_assert(sizeof(PEB64) == 0x7D0);
typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME64
{
struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME* Previous;
EMULATOR_CAST(void*, ACTIVATION_CONTEXT) ActivationContext;
EMULATOR_CAST(std::uint64_t, 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;
EMULATOR_CAST(std::uint64_t, PRTL_ACTIVATION_CONTEXT_STACK_FRAME64) ActiveFrame;
LIST_ENTRY64 FrameListCache;
ULONG Flags; // ACTIVATION_CONTEXT_STACK_FLAG_*
ULONG NextCookieSequenceNumber;
@@ -383,7 +384,7 @@ typedef struct _ACTIVATION_CONTEXT_STACK64
typedef struct _GDI_TEB_BATCH64
{
ULONG Offset;
std::uint64_t* HDC;
std::uint64_t HDC;
ULONG Buffer[GDI_BATCH_BUFFER_SIZE];
} GDI_TEB_BATCH64, *PGDI_TEB_BATCH64;
@@ -458,25 +459,25 @@ typedef struct _TEB64
{
EMU_NT_TIB64 NtTib;
std::uint64_t* EnvironmentPointer;
std::uint64_t EnvironmentPointer;
CLIENT_ID64 ClientId;
std::uint64_t* ActiveRpcHandle;
std::uint64_t* ThreadLocalStoragePointer;
PPEB64 ProcessEnvironmentBlock;
std::uint64_t ActiveRpcHandle;
std::uint64_t ThreadLocalStoragePointer;
EMULATOR_CAST(std::uint64_t, PPEB64) ProcessEnvironmentBlock;
ULONG LastErrorValue;
ULONG CountOfOwnedCriticalSections;
std::uint64_t* CsrClientThread;
std::uint64_t* Win32ThreadInfo;
std::uint64_t CsrClientThread;
std::uint64_t Win32ThreadInfo;
ARRAY_CONTAINER<ULONG, 26> User32Reserved;
ARRAY_CONTAINER<ULONG, 5> UserReserved;
std::uint64_t* WOW32Reserved;
std::uint64_t WOW32Reserved;
LCID CurrentLocale;
ULONG FpSoftwareStatusRegister;
ARRAY_CONTAINER<void*, 16> ReservedForDebuggerInstrumentation;
ARRAY_CONTAINER<void*, 25> SystemReserved1;
std::uint64_t* HeapFlsData;
ARRAY_CONTAINER<std::uint64_t*, 4> RngState;
ARRAY_CONTAINER<std::uint64_t, 16> ReservedForDebuggerInstrumentation;
ARRAY_CONTAINER<std::uint64_t, 25> SystemReserved1;
std::uint64_t HeapFlsData;
ARRAY_CONTAINER<std::uint64_t, 4> RngState;
CHAR PlaceholderCompatibilityMode;
BOOLEAN PlaceholderHydrationAlwaysExplicit;
ARRAY_CONTAINER<CHAR, 10> PlaceholderReserved;
@@ -488,10 +489,10 @@ typedef struct _TEB64
NTSTATUS ExceptionCode;
PACTIVATION_CONTEXT_STACK64 ActivationContextStackPointer;
std::uint64_t* InstrumentationCallbackSp;
std::uint64_t* InstrumentationCallbackPreviousPc;
std::uint64_t* InstrumentationCallbackPreviousSp;
EMULATOR_CAST(std::uint64_t, PACTIVATION_CONTEXT_STACK64) ActivationContextStackPointer;
std::uint64_t InstrumentationCallbackSp;
std::uint64_t InstrumentationCallbackPreviousPc;
std::uint64_t InstrumentationCallbackPreviousSp;
ULONG TxFsContext;
BOOLEAN InstrumentationCallbackDisabled;
BOOLEAN UnalignedLoadStoreExceptions;
@@ -500,90 +501,92 @@ typedef struct _TEB64
EmulatorTraits<Emu64>::HANDLE GdiCachedProcessHandle;
ULONG GdiClientPID;
ULONG GdiClientTID;
std::uint64_t* GdiThreadLocalInfo;
ARRAY_CONTAINER<std::uint64_t*, WIN32_CLIENT_INFO_LENGTH> Win32ClientInfo;
std::uint64_t GdiThreadLocalInfo;
ARRAY_CONTAINER<std::uint64_t, WIN32_CLIENT_INFO_LENGTH> Win32ClientInfo;
ARRAY_CONTAINER<void*, 233> glDispatchTable;
ARRAY_CONTAINER<std::uint64_t*, 29> 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;
ARRAY_CONTAINER<std::uint64_t, 233> glDispatchTable;
ARRAY_CONTAINER<std::uint64_t, 29> 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<EmulatorTraits<Emu64>> StaticUnicodeString;
ARRAY_CONTAINER<char16_t, STATIC_UNICODE_BUFFER_LENGTH> StaticUnicodeBuffer;
std::uint64_t* DeallocationStack;
std::uint64_t DeallocationStack;
ARRAY_CONTAINER<std::uint64_t*, TLS_MINIMUM_AVAILABLE> TlsSlots;
ARRAY_CONTAINER<std::uint64_t, TLS_MINIMUM_AVAILABLE> TlsSlots;
LIST_ENTRY64 TlsLinks;
std::uint64_t* Vdm;
std::uint64_t* ReservedForNtRpc;
ARRAY_CONTAINER<void*, 2> DbgSsReserved;
std::uint64_t Vdm;
std::uint64_t ReservedForNtRpc;
ARRAY_CONTAINER<std::uint64_t, 2> DbgSsReserved;
ULONG HardErrorMode;
ARRAY_CONTAINER<void*, 11> Instrumentation;
ARRAY_CONTAINER<std::uint64_t, 11> Instrumentation;
GUID ActivityId;
std::uint64_t* SubProcessTag;
std::uint64_t* PerflibData;
std::uint64_t* EtwTraceData;
std::uint64_t* WinSockData;
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
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
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;
std::uint64_t NlsCache;
std::uint64_t pShimData;
ULONG HeapData;
EmulatorTraits<Emu64>::HANDLE CurrentTransactionHandle;
EMULATOR_CAST(void*, PTEB_ACTIVE_FRAME) ActiveFrame;
std::uint64_t* FlsData;
EMULATOR_CAST(std::uint64_t, PTEB_ACTIVE_FRAME) ActiveFrame;
std::uint64_t FlsData;
std::uint64_t* PreferredLanguages;
std::uint64_t* UserPrefLanguages;
std::uint64_t* MergedPrefLanguages;
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;
std::uint64_t TxnScopeEnterCallback;
std::uint64_t TxnScopeExitCallback;
std::uint64_t TxnScopeContext;
ULONG LockCount;
LONG WowTebOffset;
std::uint64_t* ResourceRetValue;
std::uint64_t* ReservedForWdf;
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;
std::uint64_t SchedulerSharedDataSlot; // 24H2
std::uint64_t HeapWalkContext;
EMU_GROUP_AFFINITY64 PrimaryGroupAffinity;
ARRAY_CONTAINER<ULONG, 2> Rcu;
} TEB64, *PTEB64;
#ifdef OS_WINDOWS
static_assert(sizeof(TEB64) == 0x1878);
#if defined(OS_WINDOWS) && defined(_WIN64)
inline TEB64* NtCurrentTeb64()
{
return reinterpret_cast<TEB64*>(__readgsqword(FIELD_OFFSET(EMU_NT_TIB64, Self)));
@@ -838,7 +841,7 @@ struct PS_ATTRIBUTE
typename Traits::PVOID ValuePtr;
};
typename Traits::SIZE_T* ReturnLength;
EMULATOR_CAST(uint64_t, typename Traits::SIZE_T*) ReturnLength;
};
template <typename Traits>
@@ -862,7 +865,7 @@ typedef struct _SYSTEM_TIMEOFDAY_INFORMATION64
typedef struct _PROCESS_BASIC_INFORMATION64
{
NTSTATUS ExitStatus;
PPEB64 PebBaseAddress;
EMULATOR_CAST(uint64_t, PPEB64) PebBaseAddress;
EMULATOR_CAST(std::uint64_t, KAFFINITY) AffinityMask;
EMULATOR_CAST(std::uint32_t, KPRIORITY) BasePriority;
EMULATOR_CAST(std::uint64_t, HANDLE) UniqueProcessId;
@@ -883,7 +886,7 @@ struct THREAD_TLS_INFO
union
{
EmulatorTraits<Emu64>::PVOID* TlsVector;
EmulatorTraits<Emu64>::PVOID TlsVector;
EmulatorTraits<Emu64>::PVOID TlsModulePointer;
};

View File

@@ -66,8 +66,8 @@ typedef enum _SECTION_INHERIT
typedef struct DECLSPEC_ALIGN(16) _EMU_MEMORY_BASIC_INFORMATION64
{
void* BaseAddress;
void* AllocationBase;
uint64_t BaseAddress;
uint64_t AllocationBase;
DWORD AllocationProtect;
WORD PartitionId;
std::int64_t RegionSize;
@@ -78,7 +78,7 @@ typedef struct DECLSPEC_ALIGN(16) _EMU_MEMORY_BASIC_INFORMATION64
typedef struct _MEMORY_IMAGE_INFORMATION64
{
void* ImageBase;
uint64_t ImageBase;
std::int64_t SizeOfImage;
union
@@ -98,7 +98,7 @@ typedef struct _MEMORY_IMAGE_INFORMATION64
typedef struct _MEMORY_REGION_INFORMATION
{
void* AllocationBase;
uint64_t AllocationBase;
ULONG AllocationProtect;
union

View File

@@ -553,13 +553,15 @@ struct SYSTEM_PROCESSOR_INFORMATION64
ULONG ProcessorFeatureBits;
};
#ifndef OS_WINDOWS
#if !defined(OS_WINDOWS) || !defined(_WIN64)
#if !defined(OS_WINDOWS)
typedef struct _M128A
{
ULONGLONG Low;
LONGLONG High;
} M128A, *PM128A;
#endif
typedef struct _XMM_SAVE_AREA32
{

View File

@@ -76,7 +76,7 @@ struct THREAD_NAME_INFORMATION
typedef struct _THREAD_BASIC_INFORMATION64
{
NTSTATUS ExitStatus;
PTEB64 TebBaseAddress;
EMULATOR_CAST(uint64_t, PTEB64) TebBaseAddress;
CLIENT_ID64 ClientId;
EMULATOR_CAST(std::uint64_t, KAFFINITY) AffinityMask;
EMULATOR_CAST(std::uint32_t, KPRIORITY) Priority;

View File

@@ -378,7 +378,7 @@ namespace utils
{
const auto size = this->read<uint64_t>();
result.clear();
result.reserve(size);
result.reserve(static_cast<size_t>(size));
for (uint64_t i = 0; i < size; ++i)
{
@@ -447,7 +447,7 @@ namespace utils
const auto size = this->read<uint64_t>();
result.clear();
result.reserve(size);
result.reserve(static_cast<size_t>(size));
for (uint64_t i = 0; i < size; ++i)
{

View File

@@ -5,6 +5,10 @@
#include "utils/finally.hpp"
#ifdef _MSC_VER
#pragma warning(disable : 4702)
#endif
bool use_gdb = false;
namespace
@@ -63,12 +67,6 @@ namespace
utils::buffer_deserializer deserializer{emulator_data};
emu.deserialize(deserializer);
emu.save_snapshot();
const auto ret = emu.emu().read_stack(0);
emu.emu().hook_memory_execution(ret, [&](uint64_t) {
emu.emu().stop(); //
});
}
void restore_emulator()
@@ -87,8 +85,9 @@ namespace
restore_emulator();
const auto memory = emu.memory.allocate_memory(page_align_up(std::max(data.size(), static_cast<size_t>(1))),
memory_permission::read_write);
const auto memory = emu.memory.allocate_memory(
static_cast<size_t>(page_align_up(std::max(data.size(), static_cast<size_t>(1)))),
memory_permission::read_write);
emu.emu().write_memory(memory, data.data(), data.size());
emu.emu().reg(x64_register::rcx, memory);

View File

@@ -22,7 +22,7 @@ int main()
printf("------------\n\n");
const auto peb = static_cast<PPEB64>(GetCurrentProcessPeb());
const auto api_set_map = peb->ApiSetMap;
const auto api_set_map = reinterpret_cast<API_SET_NAMESPACE*>(peb->ApiSetMap);
printf("APISET: 0x%p\n", api_set_map);
printf("Version: %d\n", api_set_map->Version);

View File

@@ -16,7 +16,7 @@ target_link_libraries(windows-emulator-test PRIVATE
windows-emulator
)
if(WIN32)
if(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 8)
add_dependencies(windows-emulator-test test-sample)
endif()

View File

@@ -34,7 +34,7 @@ namespace test
constexpr auto offset = 1;
const auto instructionsToExecute = executedInstructions - offset;
new_emu.start(instructionsToExecute);
new_emu.start(static_cast<size_t>(instructionsToExecute));
ASSERT_EQ(new_emu.get_executed_instructions(), instructionsToExecute);
ASSERT_NOT_TERMINATED(new_emu);

View File

@@ -155,7 +155,7 @@ namespace test
return s1.get_diff(s2).has_value();
};
if (!has_diff_after_count(limit))
if (!has_diff_after_count(static_cast<size_t>(limit)))
{
puts("Emulation has no diff");
}
@@ -170,7 +170,7 @@ namespace test
const auto diff = (upper_bound - lower_bound);
const auto pivot = lower_bound + (diff / 2);
const auto has_diff = has_diff_after_count(pivot);
const auto has_diff = has_diff_after_count(static_cast<size_t>(pivot));
auto* bound = has_diff ? &upper_bound : &lower_bound;
*bound = pivot;
@@ -178,7 +178,7 @@ namespace test
printf("Bounds: %" PRIx64 " - %" PRIx64 "\n", lower_bound, upper_bound);
}
(void)get_state_for_count(lower_bound);
(void)get_state_for_count(static_cast<size_t>(lower_bound));
const auto rip = emu.emu().read_instruction_pointer();

View File

@@ -57,12 +57,13 @@ namespace apiset
{
switch (location)
{
#ifdef OS_WINDOWS
#ifdef OS_WINDOWS_64
case location::host: {
const auto apiSetMap =
reinterpret_cast<const API_SET_NAMESPACE*>(NtCurrentTeb64()->ProcessEnvironmentBlock->ApiSetMap);
const auto* dataPtr = reinterpret_cast<const std::byte*>(apiSetMap);
return {dataPtr, dataPtr + apiSetMap->Size};
const auto* teb = NtCurrentTeb64();
const auto* peb = reinterpret_cast<PEB64*>(teb->ProcessEnvironmentBlock);
const auto* api_set_map = reinterpret_cast<const API_SET_NAMESPACE*>(peb->ApiSetMap);
const auto* data_ptr = reinterpret_cast<const std::byte*>(api_set_map);
return {data_ptr, data_ptr + api_set_map->Size};
}
#else
case location::host:

View File

@@ -93,7 +93,7 @@ emulator_thread::emulator_thread(memory_manager& memory, const process_context&
suspended(suspended),
last_registers(context.default_register_set)
{
this->stack_base = memory.allocate_memory(this->stack_size, memory_permission::read_write);
this->stack_base = memory.allocate_memory(static_cast<size_t>(this->stack_size), memory_permission::read_write);
this->gs_segment = emulator_allocator{
memory,
@@ -111,10 +111,10 @@ emulator_thread::emulator_thread(memory_manager& memory, const process_context&
teb_obj.ClientId.UniqueProcess = 1ul;
teb_obj.ClientId.UniqueThread = static_cast<uint64_t>(this->id);
teb_obj.NtTib.StackLimit = reinterpret_cast<std::uint64_t*>(this->stack_base);
teb_obj.NtTib.StackBase = reinterpret_cast<std::uint64_t*>(this->stack_base + this->stack_size);
teb_obj.NtTib.Self = &this->teb->ptr()->NtTib;
teb_obj.ProcessEnvironmentBlock = context.peb.ptr();
teb_obj.NtTib.StackLimit = this->stack_base;
teb_obj.NtTib.StackBase = this->stack_base + this->stack_size;
teb_obj.NtTib.Self = this->teb->value();
teb_obj.ProcessEnvironmentBlock = context.peb.value();
});
}
@@ -214,7 +214,7 @@ void emulator_thread::setup_registers(x64_emulator& emu, const process_context&
throw std::runtime_error("Missing GS segment");
}
setup_stack(emu, this->stack_base, this->stack_size);
setup_stack(emu, this->stack_base, static_cast<size_t>(this->stack_size));
emu.set_segment_base(x64_register::gs, this->gs_segment->get_base());
CONTEXT64 ctx{};

View File

@@ -227,7 +227,7 @@ class emulator_thread : public ref_counted_object
throw std::runtime_error("Emulator was never assigned!");
}
this->memory_ptr->release_memory(this->stack_base, this->stack_size);
this->memory_ptr->release_memory(this->stack_base, static_cast<size_t>(this->stack_size));
this->stack_base = 0;
}

View File

@@ -95,11 +95,6 @@ class emulator_object
return this->value() + this->size();
}
T* ptr() const
{
return reinterpret_cast<T*>(this->address_);
}
explicit operator bool() const
{
return this->address_ != 0;
@@ -221,11 +216,11 @@ class emulator_allocator
return emulator_object<T>(*this->memory_, potential_start);
}
char16_t* copy_string(const std::u16string_view str)
uint64_t copy_string(const std::u16string_view str)
{
UNICODE_STRING<EmulatorTraits<Emu64>> uc_str{};
this->make_unicode_string(uc_str, str);
return reinterpret_cast<char16_t*>(uc_str.Buffer);
return uc_str.Buffer;
}
void make_unicode_string(UNICODE_STRING<EmulatorTraits<Emu64>>& result, const std::u16string_view str,
@@ -300,7 +295,8 @@ class emulator_allocator
{
if (this->address_ && this->size_)
{
manager.release_memory(this->address_, this->size_);
// TODO: Make all sizes uint64_t
manager.release_memory(this->address_, static_cast<size_t>(this->size_));
this->address_ = 0;
this->size_ = 0;
}
@@ -356,7 +352,7 @@ inline std::u16string read_unicode_string(const emulator& emu,
return read_unicode_string(emu, ucs);
}
inline std::u16string read_unicode_string(emulator& emu, const UNICODE_STRING<EmulatorTraits<Emu64>>* uc_string)
inline std::u16string read_unicode_string(emulator& emu, const uint64_t uc_string)
{
return read_unicode_string(emu, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>>{emu, uc_string});
}

View File

@@ -33,7 +33,7 @@ namespace
}
record_obj.access([&](exception_record& r) {
r.ExceptionRecord = reinterpret_cast<EmulatorTraits<Emu64>::PVOID>(nested_record_obj.ptr());
r.ExceptionRecord = nested_record_obj.value(); //
});
}
@@ -109,7 +109,7 @@ namespace
assert(total_size >= allocation_size);
std::vector<uint8_t> zero_memory{};
zero_memory.resize(total_size, 0);
zero_memory.resize(static_cast<size_t>(total_size), 0);
emu.write_memory(new_sp, zero_memory.data(), zero_memory.size());

View File

@@ -144,7 +144,7 @@ void kusd_mmio::read(const uint64_t addr, void* data, const size_t size)
const auto real_size = valid_end - addr;
const auto* kusd_buffer = reinterpret_cast<uint8_t*>(&this->kusd_);
memcpy(data, kusd_buffer + addr, real_size);
memcpy(data, kusd_buffer + addr, static_cast<size_t>(real_size));
}
uint64_t kusd_mmio::address()

View File

@@ -22,9 +22,10 @@ namespace
const auto first_length = split_point - i->first;
const auto second_length = i->second.length - first_length;
i->second.length = first_length;
i->second.length = static_cast<size_t>(first_length);
regions[split_point] = memory_manager::committed_region{second_length, i->second.permissions};
regions[split_point] =
memory_manager::committed_region{static_cast<size_t>(second_length), i->second.permissions};
}
}
}
@@ -312,8 +313,8 @@ bool memory_manager::commit_memory(const uint64_t address, const size_t size, co
if (map_length > 0)
{
this->map_memory(map_start, map_length, permissions);
committed_regions[map_start] = committed_region{map_length, permissions};
this->map_memory(map_start, static_cast<size_t>(map_length), permissions);
committed_regions[map_start] = committed_region{static_cast<size_t>(map_length), permissions};
}
last_region_start = sub_region.first;
@@ -326,8 +327,8 @@ bool memory_manager::commit_memory(const uint64_t address, const size_t size, co
const auto map_start = last_region ? (last_region_start + last_region->length) : address;
const auto map_length = end - map_start;
this->map_memory(map_start, map_length, permissions);
committed_regions[map_start] = committed_region{map_length, permissions};
this->map_memory(map_start, static_cast<size_t>(map_length), permissions);
committed_regions[map_start] = committed_region{static_cast<size_t>(map_length), permissions};
}
merge_regions(committed_regions);
@@ -398,7 +399,7 @@ bool memory_manager::release_memory(const uint64_t address, size_t size)
size = entry->second.length;
}
size = page_align_up(size);
size = static_cast<size_t>(page_align_up(size));
if (size > entry->second.length)
{
@@ -498,7 +499,7 @@ region_info memory_manager::get_region_info(const uint64_t address)
{
region_info result{};
result.start = MIN_ALLOCATION_ADDRESS;
result.length = MAX_ALLOCATION_ADDRESS - result.start;
result.length = static_cast<size_t>(MAX_ALLOCATION_ADDRESS - result.start);
result.permissions = memory_permission::none;
result.initial_permissions = memory_permission::none;
result.allocation_base = {};
@@ -514,7 +515,7 @@ region_info memory_manager::get_region_info(const uint64_t address)
auto upper_bound = this->reserved_regions_.upper_bound(address);
if (upper_bound == this->reserved_regions_.begin())
{
result.length = upper_bound->first - result.start;
result.length = static_cast<size_t>(upper_bound->first - result.start);
return result;
}
@@ -523,7 +524,7 @@ region_info memory_manager::get_region_info(const uint64_t address)
if (lower_end <= address)
{
result.start = lower_end;
result.length = MAX_ALLOCATION_ADDRESS - result.start;
result.length = static_cast<size_t>(MAX_ALLOCATION_ADDRESS - result.start);
return result;
}
@@ -546,7 +547,7 @@ region_info memory_manager::get_region_info(const uint64_t address)
auto committed_bound = committed_regions.upper_bound(address);
if (committed_bound == committed_regions.begin())
{
result.length = committed_bound->first - result.start;
result.length = static_cast<size_t>(committed_bound->first - result.start);
return result;
}
@@ -555,7 +556,7 @@ region_info memory_manager::get_region_info(const uint64_t address)
if (committed_lower_end <= address)
{
result.start = committed_lower_end;
result.length = lower_end - result.start;
result.length = static_cast<size_t>(lower_end - result.start);
return result;
}

View File

@@ -107,7 +107,7 @@ mapped_module* module_manager::map_module(const windows_path& file, const logger
mapped_module* module_manager::map_local_module(const std::filesystem::path& file, const logger& logger,
const bool is_static)
{
auto local_file = canonical(absolute(file));
auto local_file = weakly_canonical(absolute(file));
for (auto& mod : this->modules_ | std::views::values)
{

View File

@@ -10,9 +10,9 @@ namespace
uint64_t get_first_section_offset(const PENTHeaders_t<std::uint64_t>& nt_headers, const uint64_t nt_headers_offset)
{
const auto* nt_headers_addr = reinterpret_cast<const uint8_t*>(&nt_headers);
size_t optional_header_offset =
const size_t optional_header_offset =
reinterpret_cast<uintptr_t>(&(nt_headers.OptionalHeader)) - reinterpret_cast<uintptr_t>(&nt_headers);
size_t optional_header_size = nt_headers.FileHeader.SizeOfOptionalHeader;
const size_t optional_header_size = nt_headers.FileHeader.SizeOfOptionalHeader;
const auto* first_section_addr = nt_headers_addr + optional_header_offset + optional_header_size;
const auto first_section_absolute = reinterpret_cast<uint64_t>(first_section_addr);
@@ -23,7 +23,7 @@ namespace
std::vector<std::byte> read_mapped_memory(const memory_manager& memory, const mapped_module& binary)
{
std::vector<std::byte> mem{};
mem.resize(binary.size_of_image);
mem.resize(static_cast<size_t>(binary.size_of_image));
memory.read_memory(binary.image_base, mem.data(), mem.size());
return mem;
@@ -73,7 +73,7 @@ namespace
void apply_relocation(const utils::safe_buffer_accessor<std::byte> buffer, const uint64_t offset,
const uint64_t delta)
{
const auto obj = buffer.as<T>(offset);
const auto obj = buffer.as<T>(static_cast<size_t>(offset));
const auto value = obj.get();
const auto new_value = value + static_cast<T>(delta);
obj.set(new_value);
@@ -146,7 +146,7 @@ namespace
const PENTHeaders_t<std::uint64_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<IMAGE_SECTION_HEADER>(first_section_offset);
const auto sections = buffer.as<IMAGE_SECTION_HEADER>(static_cast<size_t>(first_section_offset));
for (size_t i = 0; i < nt_headers.FileHeader.NumberOfSections; ++i)
{
@@ -179,11 +179,11 @@ namespace
const auto size_of_section = page_align_up(std::max(section.SizeOfRawData, section.Misc.VirtualSize));
memory.protect_memory(target_ptr, size_of_section, permissions, nullptr);
memory.protect_memory(target_ptr, static_cast<size_t>(size_of_section), permissions, nullptr);
mapped_section section_info{};
section_info.region.start = target_ptr;
section_info.region.length = size_of_section;
section_info.region.length = static_cast<size_t>(size_of_section);
section_info.region.permissions = permissions;
for (size_t j = 0; j < sizeof(section.Name) && section.Name[j]; ++j)
@@ -219,21 +219,22 @@ mapped_module map_module_from_data(memory_manager& memory, const std::span<const
binary.image_base = optional_header.ImageBase;
binary.size_of_image = page_align_up(optional_header.SizeOfImage); // TODO: Sanitize
if (!memory.allocate_memory(binary.image_base, binary.size_of_image, memory_permission::all))
if (!memory.allocate_memory(binary.image_base, static_cast<size_t>(binary.size_of_image), memory_permission::all))
{
binary.image_base = memory.find_free_allocation_base(binary.size_of_image);
binary.image_base = memory.find_free_allocation_base(static_cast<size_t>(binary.size_of_image));
const auto is_dll = nt_headers.FileHeader.Characteristics & IMAGE_FILE_DLL;
const auto has_dynamic_base = optional_header.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
const auto is_relocatable = is_dll || has_dynamic_base;
if (!is_relocatable || !memory.allocate_memory(binary.image_base, binary.size_of_image, memory_permission::all))
if (!is_relocatable || !memory.allocate_memory(binary.image_base, static_cast<size_t>(binary.size_of_image),
memory_permission::all))
{
throw std::runtime_error("Memory range not allocatable");
}
}
// TODO: Make sure to match kernel allocation patterns to attain correct initial permissions!
memory.protect_memory(binary.image_base, binary.size_of_image, memory_permission::read);
memory.protect_memory(binary.image_base, static_cast<size_t>(binary.size_of_image), memory_permission::read);
binary.entry_point = binary.image_base + optional_header.AddressOfEntryPoint;
@@ -266,5 +267,5 @@ mapped_module map_module_from_file(memory_manager& memory, std::filesystem::path
bool unmap_module(memory_manager& memory, const mapped_module& mod)
{
return memory.release_memory(mod.image_base, mod.size_of_image);
return memory.release_memory(mod.image_base, static_cast<size_t>(mod.size_of_image));
}

View File

@@ -65,7 +65,7 @@ void process_context::setup(x64_emulator& emu, memory_manager& memory, const app
proc_params.StandardInput = STDIN_HANDLE.h;
proc_params.StandardError = proc_params.StandardOutput;
proc_params.Environment = reinterpret_cast<std::uint64_t*>(allocator.copy_string(u"=::=::\\"));
proc_params.Environment = allocator.copy_string(u"=::=::\\");
allocator.copy_string(u"EMULATOR=1");
allocator.copy_string(u"COMPUTERNAME=momo");
allocator.copy_string(u"SystemRoot=C:\\WINDOWS");
@@ -95,11 +95,11 @@ void process_context::setup(x64_emulator& emu, memory_manager& memory, const app
this->peb.access([&](PEB64& p) {
p.BeingDebugged = 0;
p.ImageBaseAddress = executable.image_base;
p.ProcessParameters = this->process_params.ptr();
p.ApiSetMap = apiset::clone(emu, allocator, apiset_container).ptr();
p.ProcessParameters = this->process_params.value();
p.ApiSetMap = apiset::clone(emu, allocator, apiset_container).value();
p.ProcessHeap = nullptr;
p.ProcessHeaps = nullptr;
p.ProcessHeap = 0;
p.ProcessHeaps = 0;
p.HeapSegmentReserve = 0x0000000000100000; // TODO: Read from executable
p.HeapSegmentCommit = 0x0000000000002000;
p.HeapDeCommitTotalFreeThreshold = 0x0000000000010000;
@@ -235,4 +235,4 @@ handle process_context::create_thread(memory_manager& memory, const uint64_t sta
auto [h, thr] = this->threads.store_and_get(std::move(t));
this->callbacks_->on_create_thread(h, *thr);
return h;
}
}

View File

@@ -54,7 +54,8 @@ inline std::optional<uint32_t> extract_syscall_id(const exported_symbol& symbol,
const auto instruction_rva = symbol.rva + instruction_offset;
if (data.size() < (instruction_rva + instruction_size) || data[instruction_rva] != instruction_opcode)
if (data.size() < (instruction_rva + instruction_size) ||
data[static_cast<size_t>(instruction_rva)] != instruction_opcode)
{
return std::nullopt;
}

View File

@@ -62,8 +62,7 @@ namespace syscalls
const auto attributes = object_attributes.read();
if (attributes.ObjectName)
{
name = read_unicode_string(
c.emu, reinterpret_cast<UNICODE_STRING<EmulatorTraits<Emu64>>*>(attributes.ObjectName));
name = read_unicode_string(c.emu, attributes.ObjectName);
}
}
@@ -99,8 +98,7 @@ namespace syscalls
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes)
{
const auto attributes = object_attributes.read();
const auto name =
read_unicode_string(c.emu, reinterpret_cast<UNICODE_STRING<EmulatorTraits<Emu64>>*>(attributes.ObjectName));
const auto name = read_unicode_string(c.emu, attributes.ObjectName);
c.win_emu.log.print(color::dark_gray, "--> Event name: %s\n", u16_to_u8(name).c_str());
if (name == u"\\KernelObjects\\SystemErrorPortReady")
@@ -133,4 +131,4 @@ namespace syscalls
return STATUS_NOT_FOUND;
}
}
}

View File

@@ -130,7 +130,7 @@ namespace syscalls
auto& enum_state = *f->enumeration_state;
size_t current_offset{0};
uint64_t current_offset{0};
emulator_object<T> object{c.emu};
size_t current_index = enum_state.current_index;
@@ -400,7 +400,8 @@ namespace syscalls
std::cin.readsome(temp_buffer.data(), static_cast<std::streamsize>(temp_buffer.size()));
const auto count = std::max(read_count, static_cast<std::streamsize>(0));
commit_file_data(std::string_view(temp_buffer.data(), count), c.emu, io_status_block, buffer);
commit_file_data(std::string_view(temp_buffer.data(), static_cast<size_t>(count)), c.emu, io_status_block,
buffer);
return STATUS_SUCCESS;
}
@@ -551,8 +552,7 @@ namespace syscalls
uint64_t ea_buffer, ULONG ea_length)
{
const auto attributes = object_attributes.read();
auto filename =
read_unicode_string(c.emu, reinterpret_cast<UNICODE_STRING<EmulatorTraits<Emu64>>*>(attributes.ObjectName));
auto filename = read_unicode_string(c.emu, attributes.ObjectName);
auto printer = utils::finally([&] {
c.win_emu.log.print(color::dark_gray, "--> Opening file: %s\n", u16_to_u8(filename).c_str()); //
@@ -756,8 +756,7 @@ namespace syscalls
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes)
{
const auto attributes = object_attributes.read();
const auto object_name =
read_unicode_string(c.emu, reinterpret_cast<UNICODE_STRING<EmulatorTraits<Emu64>>*>(attributes.ObjectName));
const auto object_name = read_unicode_string(c.emu, attributes.ObjectName);
if (object_name == u"\\KnownDlls")
{
@@ -779,8 +778,7 @@ namespace syscalls
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes)
{
const auto attributes = object_attributes.read();
const auto object_name =
read_unicode_string(c.emu, reinterpret_cast<UNICODE_STRING<EmulatorTraits<Emu64>>*>(attributes.ObjectName));
const auto object_name = read_unicode_string(c.emu, attributes.ObjectName);
if (object_name == u"KnownDllPath")
{
@@ -848,4 +846,4 @@ namespace syscalls
return STATUS_NOT_SUPPORTED;
}
}
}

View File

@@ -17,7 +17,7 @@ namespace syscalls
return STATUS_FILE_INVALID;
}
const auto size = page_align_up(locale_file.size());
const auto size = static_cast<size_t>(page_align_up(locale_file.size()));
const auto base = c.win_emu.memory.allocate_memory(size, memory_permission::read);
c.emu.write_memory(base, locale_file.data(), locale_file.size());
@@ -58,4 +58,4 @@ namespace syscalls
{
return STATUS_NOT_SUPPORTED;
}
}
}

View File

@@ -41,8 +41,8 @@ namespace syscalls
assert(!region_info.is_committed || region_info.is_reserved);
const auto state = region_info.is_reserved ? MEM_RESERVE : MEM_FREE;
image_info.State = region_info.is_committed ? MEM_COMMIT : state;
image_info.BaseAddress = reinterpret_cast<void*>(region_info.start);
image_info.AllocationBase = reinterpret_cast<void*>(region_info.allocation_base);
image_info.BaseAddress = region_info.start;
image_info.AllocationBase = region_info.allocation_base;
image_info.PartitionId = 0;
image_info.RegionSize = static_cast<int64_t>(region_info.length);
@@ -76,7 +76,7 @@ namespace syscalls
const emulator_object<MEMORY_IMAGE_INFORMATION64> info{c.emu, memory_information};
info.access([&](MEMORY_IMAGE_INFORMATION64& image_info) {
image_info.ImageBase = reinterpret_cast<void*>(mod->image_base);
image_info.ImageBase = mod->image_base;
image_info.SizeOfImage = static_cast<int64_t>(mod->size_of_image);
image_info.ImageFlags = 0;
});
@@ -107,7 +107,7 @@ namespace syscalls
info.access([&](MEMORY_REGION_INFORMATION64& image_info) {
memset(&image_info, 0, sizeof(image_info));
image_info.AllocationBase = reinterpret_cast<void*>(region_info.allocation_base);
image_info.AllocationBase = region_info.allocation_base;
image_info.AllocationProtect = map_emulator_to_nt_protection(region_info.initial_permissions);
// image_info.PartitionId = 0;
image_info.RegionSize = static_cast<int64_t>(region_info.allocation_length);
@@ -151,7 +151,8 @@ namespace syscalls
try
{
c.win_emu.memory.protect_memory(aligned_start, aligned_length, requested_protection, &old_protection_value);
c.win_emu.memory.protect_memory(aligned_start, static_cast<size_t>(aligned_length), requested_protection,
&old_protection_value);
}
catch (...)
{
@@ -183,7 +184,7 @@ namespace syscalls
auto potential_base = base_address.read();
if (!potential_base)
{
potential_base = c.win_emu.memory.find_free_allocation_base(allocation_bytes);
potential_base = c.win_emu.memory.find_free_allocation_base(static_cast<size_t>(allocation_bytes));
}
if (!potential_base)
@@ -203,7 +204,8 @@ namespace syscalls
throw std::runtime_error("Unsupported allocation type!");
}
if (commit && !reserve && c.win_emu.memory.commit_memory(potential_base, allocation_bytes, protection))
if (commit && !reserve &&
c.win_emu.memory.commit_memory(potential_base, static_cast<size_t>(allocation_bytes), protection))
{
c.win_emu.log.print(color::dark_gray, "--> Committed 0x%" PRIx64 " - 0x%" PRIx64 "\n", potential_base,
potential_base + allocation_bytes);
@@ -214,7 +216,8 @@ namespace syscalls
c.win_emu.log.print(color::dark_gray, "--> Allocated 0x%" PRIx64 " - 0x%" PRIx64 "\n", potential_base,
potential_base + allocation_bytes);
return c.win_emu.memory.allocate_memory(potential_base, allocation_bytes, protection, !commit)
return c.win_emu.memory.allocate_memory(potential_base, static_cast<size_t>(allocation_bytes), protection,
!commit)
? STATUS_SUCCESS
: STATUS_MEMORY_NOT_ALLOCATED;
}
@@ -242,14 +245,16 @@ namespace syscalls
if (free_type & MEM_RELEASE)
{
return c.win_emu.memory.release_memory(allocation_base, allocation_size) ? STATUS_SUCCESS
: STATUS_MEMORY_NOT_ALLOCATED;
return c.win_emu.memory.release_memory(allocation_base, static_cast<size_t>(allocation_size))
? STATUS_SUCCESS
: STATUS_MEMORY_NOT_ALLOCATED;
}
if (free_type & MEM_DECOMMIT)
{
return c.win_emu.memory.decommit_memory(allocation_base, allocation_size) ? STATUS_SUCCESS
: STATUS_MEMORY_NOT_ALLOCATED;
return c.win_emu.memory.decommit_memory(allocation_base, static_cast<size_t>(allocation_size))
? STATUS_SUCCESS
: STATUS_MEMORY_NOT_ALLOCATED;
}
throw std::runtime_error("Bad free type");
@@ -284,4 +289,4 @@ namespace syscalls
{
return STATUS_NOT_SUPPORTED;
}
}
}

View File

@@ -27,7 +27,8 @@ namespace syscalls
}
client_shared_memory.access([&](PORT_VIEW64& view) {
p.view_base = c.win_emu.memory.allocate_memory(view.ViewSize, memory_permission::read_write);
p.view_base =
c.win_emu.memory.allocate_memory(static_cast<size_t>(view.ViewSize), memory_permission::read_write);
view.ViewBase = p.view_base;
view.ViewRemoteBase = view.ViewBase;
});
@@ -76,4 +77,4 @@ namespace syscalls
{
return STATUS_NOT_SUPPORTED;
}
}
}

View File

@@ -212,7 +212,7 @@ namespace syscalls
const emulator_object<PROCESS_BASIC_INFORMATION64> info{c.emu, process_information};
info.access([&](PROCESS_BASIC_INFORMATION64& basic_info) {
basic_info.PebBaseAddress = c.proc.peb.ptr();
basic_info.PebBaseAddress = c.proc.peb.value();
basic_info.UniqueProcessId = 1;
});
@@ -306,11 +306,12 @@ namespace syscalls
thread_iterator->second.teb->access([&](TEB64& teb) {
entry.ThreadId = teb.ClientId.UniqueThread;
auto* tls_vector = teb.ThreadLocalStoragePointer;
const auto tls_vector = teb.ThreadLocalStoragePointer;
constexpr auto ptr_size = sizeof(EmulatorTraits<Emu64>::PVOID);
if (tls_info.TlsRequest == ProcessTlsReplaceIndex)
{
auto* tls_entry_ptr = tls_vector + tls_info.TlsIndex;
const auto tls_entry_ptr = tls_vector + (tls_info.TlsIndex * ptr_size);
const auto old_entry = c.emu.read_memory<EmulatorTraits<Emu64>::PVOID>(tls_entry_ptr);
c.emu.write_memory<EmulatorTraits<Emu64>::PVOID>(tls_entry_ptr, entry.TlsModulePointer);
@@ -319,12 +320,12 @@ namespace syscalls
}
else if (tls_info.TlsRequest == ProcessTlsReplaceVector)
{
auto* new_tls_vector = entry.TlsVector;
const auto new_tls_vector = entry.TlsVector;
for (uint32_t index = 0; index < tls_info.TlsVectorLength; ++index)
{
auto* old_entry = c.emu.read_memory<void*>(tls_vector + index);
c.emu.write_memory<void*>(new_tls_vector + index, old_entry);
const auto old_entry = c.emu.read_memory<uint64_t>(tls_vector + index * ptr_size);
c.emu.write_memory(new_tls_vector + index * ptr_size, old_entry);
}
teb.ThreadLocalStoragePointer = new_tls_vector;
@@ -386,4 +387,4 @@ namespace syscalls
return STATUS_NOT_SUPPORTED;
}
}
}

View File

@@ -11,8 +11,7 @@ namespace syscalls
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes)
{
const auto attributes = object_attributes.read();
auto key =
read_unicode_string(c.emu, reinterpret_cast<UNICODE_STRING<EmulatorTraits<Emu64>>*>(attributes.ObjectName));
auto key = read_unicode_string(c.emu, attributes.ObjectName);
if (attributes.RootDirectory)
{
@@ -247,4 +246,4 @@ namespace syscalls
{
return STATUS_NOT_SUPPORTED;
}
}
}

View File

@@ -29,8 +29,7 @@ namespace syscalls
const auto attributes = object_attributes.read();
if (attributes.ObjectName)
{
auto name = read_unicode_string(
c.emu, reinterpret_cast<UNICODE_STRING<EmulatorTraits<Emu64>>*>(attributes.ObjectName));
auto name = read_unicode_string(c.emu, 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);
}
@@ -60,8 +59,7 @@ namespace syscalls
{
const auto attributes = object_attributes.read();
auto filename =
read_unicode_string(c.emu, reinterpret_cast<UNICODE_STRING<EmulatorTraits<Emu64>>*>(attributes.ObjectName));
auto filename = read_unicode_string(c.emu, attributes.ObjectName);
c.win_emu.log.print(color::dark_gray, "--> Opening section: %s\n", u16_to_u8(filename).c_str());
if (filename == u"\\Windows\\SharedSection")
@@ -227,7 +225,7 @@ namespace syscalls
const auto reserve_only = section_entry->allocation_attributes == SEC_RESERVE;
const auto protection = map_nt_to_emulator_protection(section_entry->section_page_protection);
const auto address = c.win_emu.memory.allocate_memory(size, protection, reserve_only);
const auto address = c.win_emu.memory.allocate_memory(static_cast<size_t>(size), protection, reserve_only);
if (!reserve_only && !file_data.empty())
{
@@ -289,4 +287,4 @@ namespace syscalls
{
return handle_NtUnmapViewOfSection(c, process_handle, base_address);
}
}
}

View File

@@ -78,8 +78,7 @@ namespace syscalls
const auto attributes = object_attributes.read();
if (attributes.ObjectName)
{
s.name = read_unicode_string(
c.emu, reinterpret_cast<UNICODE_STRING<EmulatorTraits<Emu64>>*>(attributes.ObjectName));
s.name = read_unicode_string(c.emu, attributes.ObjectName);
}
}
@@ -101,4 +100,4 @@ namespace syscalls
return STATUS_SUCCESS;
}
}
}

View File

@@ -73,7 +73,7 @@ namespace syscalls
t.teb->access([&](TEB64& teb) {
if (tls_cell < TLS_MINIMUM_AVAILABLE)
{
teb.TlsSlots.arr[tls_cell] = nullptr;
teb.TlsSlots.arr[tls_cell] = 0;
}
else if (teb.TlsExpansionSlots)
{
@@ -136,7 +136,7 @@ namespace syscalls
const emulator_object<THREAD_BASIC_INFORMATION64> info{c.emu, thread_information};
info.access([&](THREAD_BASIC_INFORMATION64& i) {
i.TebBaseAddress = thread->teb->ptr();
i.TebBaseAddress = thread->teb->value();
i.ClientId = thread->teb->read().ClientId;
});
@@ -542,7 +542,7 @@ namespace syscalls
}
else if (type == PsAttributeTebAddress)
{
write_attribute(c.emu, attribute, thread->teb->ptr());
write_attribute(c.emu, attribute, thread->teb->value());
}
else
{

View File

@@ -341,8 +341,8 @@ void windows_emulator::setup_process(const application_settings& app_settings)
this->process.setup(this->emu(), this->memory, app_settings, *executable, *ntdll, apiset_data);
const auto ntdll_data = emu.read_memory(ntdll->image_base, ntdll->size_of_image);
const auto win32u_data = emu.read_memory(win32u->image_base, win32u->size_of_image);
const auto ntdll_data = emu.read_memory(ntdll->image_base, static_cast<size_t>(ntdll->size_of_image));
const auto win32u_data = emu.read_memory(win32u->image_base, static_cast<size_t>(win32u->size_of_image));
this->dispatcher.setup(ntdll->exports, ntdll_data, win32u->exports, win32u_data);
@@ -601,7 +601,7 @@ void windows_emulator::start(size_t count)
break;
}
count = target_instructions - current_instructions;
count = static_cast<size_t>(target_instructions - current_instructions);
}
}
}

View File

@@ -10,7 +10,7 @@
struct breakpoint_key
{
size_t addr{};
uint64_t addr{};
size_t size{};
gdb_stub::breakpoint_type type{};
@@ -25,7 +25,7 @@ struct std::hash<breakpoint_key>
{
std::size_t operator()(const breakpoint_key& k) const noexcept
{
return ((std::hash<size_t>()(k.addr) ^ (std::hash<size_t>()(k.size) << 1)) >> 1) ^
return ((std::hash<uint64_t>()(k.addr) ^ (std::hash<size_t>()(k.size) << 1)) >> 1) ^
(std::hash<size_t>()(static_cast<size_t>(k.type)) << 1);
}
};