Comprehensive WOW64 subsystem implementation

This commit is contained in:
brian
2025-10-13 19:53:14 +08:00
parent 9453123db0
commit 65eecf1cfd
51 changed files with 3772 additions and 283 deletions

View File

@@ -73,8 +73,18 @@
#define SL_NO_CURSOR_UPDATE 0x10
#ifndef SEC_IMAGE
#define SEC_IMAGE 0x01000000
#define SEC_RESERVE 0x04000000
#define SEC_HUGE_PAGES 0x00020000
#define SEC_PARTITION_OWNER_HANDLE 0x00040000
#define SEC_64K_PAGES 0x00080000
#define SEC_FILE 0x00800000
#define SEC_IMAGE 0x01000000
#define SEC_PROTECTED_IMAGE 0x02000000
#define SEC_RESERVE 0x04000000
#define SEC_COMMIT 0x08000000
#define SEC_NOCACHE 0x10000000
#define SEC_WRITECOMBINE 0x40000000
#define SEC_LARGE_PAGES 0x80000000
#define SEC_IMAGE_NO_EXECUTE (SEC_IMAGE | SEC_NOCACHE)
#endif
#define CTL_CODE(DeviceType, Function, Method, Access) (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))

View File

@@ -4,7 +4,12 @@
// NOLINTBEGIN(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif
#define PROCESSOR_FEATURE_MAX 64
#define GDI_HANDLE_BUFFER_SIZE32 34
#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
@@ -115,12 +120,21 @@ typedef struct _EMU_NT_TIB64
std::uint64_t StackBase;
std::uint64_t StackLimit;
std::uint64_t SubSystemTib;
std::uint64_t FibreData;
std::uint64_t FiberData;
std::uint64_t ArbitraryUserPointer;
EMULATOR_CAST(std::uint64_t, struct _EMU_NT_TIB64*) Self;
} EMU_NT_TIB64;
} EMU_NT_TIB64, *PEMU_NT_TIB64;
typedef EMU_NT_TIB64* PEMU_NT_TIB64;
typedef struct _EMU_NT_TIB32
{
EMULATOR_CAST(std::uint32_t, struct _EXCEPTION_REGISTRATION_RECORD*) ExceptionList;
std::uint32_t StackBase;
std::uint32_t StackLimit;
std::uint32_t SubSystemTib;
std::uint32_t FiberData;
std::uint32_t ArbitraryUserPointer;
EMULATOR_CAST(std::uint32_t, struct _EMU_NT_TIB32*) Self;
} EMU_NT_TIB32, *PEMU_NT_TIB32;
union PEB_BITFIELD_UNION
{
@@ -147,6 +161,105 @@ typedef struct _LIST_ENTRY64
ULONGLONG Blink;
} LIST_ENTRY64, *PLIST_ENTRY64, *RESTRICTED_POINTER PRLIST_ENTRY64;
typedef struct _LIST_ENTRY32
{
ULONG Flink;
ULONG Blink;
} LIST_ENTRY32, *PLIST_ENTRY32, *RESTRICTED_POINTER PRLIST_ENTRY32;
typedef enum _PROCESS_MITIGATION_POLICY
{
ProcessDEPPolicy,
ProcessASLRPolicy,
ProcessDynamicCodePolicy,
ProcessStrictHandleCheckPolicy,
ProcessSystemCallDisablePolicy,
ProcessMitigationOptionsMask,
ProcessExtensionPointDisablePolicy,
ProcessControlFlowGuardPolicy,
ProcessSignaturePolicy,
ProcessFontDisablePolicy,
ProcessImageLoadPolicy,
ProcessSystemCallFilterPolicy,
ProcessPayloadRestrictionPolicy,
ProcessChildProcessPolicy,
ProcessSideChannelIsolationPolicy,
ProcessUserShadowStackPolicy,
ProcessRedirectionTrustPolicy,
ProcessUserPointerAuthPolicy,
ProcessSEHOPPolicy,
ProcessActivationContextTrustPolicy,
MaxProcessMitigationPolicy
} PROCESS_MITIGATION_POLICY, *PPROCESS_MITIGATION_POLICY;
#define WOW64_SIZE_OF_80387_REGISTERS 80
#define WOW64_MAXIMUM_SUPPORTED_EXTENSION 512
typedef struct _WOW64_FLOATING_SAVE_AREA
{
DWORD ControlWord;
DWORD StatusWord;
DWORD TagWord;
DWORD ErrorOffset;
DWORD ErrorSelector;
DWORD DataOffset;
DWORD DataSelector;
BYTE RegisterArea[WOW64_SIZE_OF_80387_REGISTERS];
DWORD Cr0NpxState;
} WOW64_FLOATING_SAVE_AREA;
typedef struct _WOW64_CONTEXT
{
DWORD ContextFlags;
DWORD Dr0;
DWORD Dr1;
DWORD Dr2;
DWORD Dr3;
DWORD Dr6;
DWORD Dr7;
WOW64_FLOATING_SAVE_AREA FloatSave;
DWORD SegGs;
DWORD SegFs;
DWORD SegEs;
DWORD SegDs;
DWORD Edi;
DWORD Esi;
DWORD Ebx;
DWORD Edx;
DWORD Ecx;
DWORD Eax;
DWORD Ebp;
DWORD Eip;
DWORD SegCs;
DWORD EFlags;
DWORD Esp;
DWORD SegSs;
BYTE ExtendedRegisters[WOW64_MAXIMUM_SUPPORTED_EXTENSION];
} WOW64_CONTEXT;
#define MEM_EXTENDED_PARAMETER_GRAPHICS 0x00000001
#define MEM_EXTENDED_PARAMETER_NONPAGED 0x00000002
#define MEM_EXTENDED_PARAMETER_ZERO_PAGES_OPTIONAL 0x00000004
#define MEM_EXTENDED_PARAMETER_NONPAGED_LARGE 0x00000008
#define MEM_EXTENDED_PARAMETER_NONPAGED_HUGE 0x00000010
#define MEM_EXTENDED_PARAMETER_SOFT_FAULT_PAGES 0x00000020
#define MEM_EXTENDED_PARAMETER_EC_CODE 0x00000040
#define MEM_EXTENDED_PARAMETER_IMAGE_NO_HPAT 0x00000080
typedef enum MEM_EXTENDED_PARAMETER_TYPE
{
MemExtendedParameterInvalidType = 0,
MemExtendedParameterAddressRequirements,
MemExtendedParameterNumaNode,
MemExtendedParameterPartitionHandle,
MemExtendedParameterUserPhysicalHandle,
MemExtendedParameterAttributeFlags,
MemExtendedParameterImageMachine,
MemExtendedParameterMax
} MEM_EXTENDED_PARAMETER_TYPE, *PMEM_EXTENDED_PARAMETER_TYPE;
#endif
typedef struct _PEB_LDR_DATA64
@@ -162,6 +275,21 @@ typedef struct _PEB_LDR_DATA64
EmulatorTraits<Emu64>::HANDLE ShutdownThreadId;
} PEB_LDR_DATA64, *PPEB_LDR_DATA64;
typedef struct _PEB_LDR_DATA32
{
ULONG Length;
BOOLEAN Initialized;
EmulatorTraits<Emu32>::HANDLE SsHandle;
LIST_ENTRY32 InLoadOrderModuleList;
LIST_ENTRY32 InMemoryOrderModuleList;
LIST_ENTRY32 InInitializationOrderModuleList;
std::uint32_t EntryInProgress;
BOOLEAN ShutdownInProgress;
EmulatorTraits<Emu32>::HANDLE ShutdownThreadId;
} PEB_LDR_DATA32, *PPEB_LDR_DATA32;
static_assert(sizeof(PEB_LDR_DATA32) == 48);
using STRING64 = UNICODE_STRING<EmulatorTraits<Emu64>>;
using ANSI_STRING64 = STRING64;
using OEM_STRING64 = STRING64;
@@ -189,6 +317,19 @@ typedef struct _CURDIR64
EmulatorTraits<Emu64>::HANDLE Handle;
} CURDIR64, *PCURDIR64;
#define RTL_USER_PROCESS_PARAMETERS_NORMALIZED 0x01
#define RTL_USER_PROCESS_PARAMETERS_PROFILE_USER 0x02
#define RTL_USER_PROCESS_PARAMETERS_PROFILE_KERNEL 0x04
#define RTL_USER_PROCESS_PARAMETERS_PROFILE_SERVER 0x08
#define RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB 0x20
#define RTL_USER_PROCESS_PARAMETERS_RESERVE_16MB 0x40
#define RTL_USER_PROCESS_PARAMETERS_CASE_SENSITIVE 0x80
#define RTL_USER_PROCESS_PARAMETERS_DISABLE_HEAP_DECOMMIT 0x100
#define RTL_USER_PROCESS_PARAMETERS_DLL_REDIRECTION_LOCAL 0x1000
#define RTL_USER_PROCESS_PARAMETERS_APP_MANIFEST_PRESENT 0x2000
#define RTL_USER_PROCESS_PARAMETERS_IMAGE_KEY_MISSING 0x4000
#define RTL_USER_PROCESS_PARAMETERS_NX_OPTIN 0x20000
typedef struct _RTL_USER_PROCESS_PARAMETERS64
{
ULONG MaximumLength;
@@ -334,6 +475,77 @@ typedef struct _NLSTABLEINFO
EMULATOR_CAST(uint64_t, USHORT*) LowerCaseTable;
} NLSTABLEINFO, *PNLSTABLEINFO;
typedef struct _CURDIR32
{
UNICODE_STRING<EmulatorTraits<Emu32>> DosPath;
EmulatorTraits<Emu32>::HANDLE Handle;
} CURDIR32, *PCURDIR32;
static_assert(sizeof(CURDIR32) == 12);
typedef struct _RTL_DRIVE_LETTER_CURDIR32
{
USHORT Flags;
USHORT Length;
ULONG TimeStamp;
UNICODE_STRING<EmulatorTraits<Emu32>> DosPath;
} RTL_DRIVE_LETTER_CURDIR32, *PRTL_DRIVE_LETTER_CURDIR32;
static_assert(sizeof(RTL_DRIVE_LETTER_CURDIR32) == 16);
typedef struct _RTL_USER_PROCESS_PARAMETERS32
{
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
EmulatorTraits<Emu32>::HANDLE ConsoleHandle;
ULONG ConsoleFlags;
EmulatorTraits<Emu32>::HANDLE StandardInput;
EmulatorTraits<Emu32>::HANDLE StandardOutput;
EmulatorTraits<Emu32>::HANDLE StandardError;
CURDIR32 CurrentDirectory;
UNICODE_STRING<EmulatorTraits<Emu32>> DllPath;
UNICODE_STRING<EmulatorTraits<Emu32>> ImagePathName;
UNICODE_STRING<EmulatorTraits<Emu32>> CommandLine;
std::uint32_t Environment;
ULONG StartingX;
ULONG StartingY;
ULONG CountX;
ULONG CountY;
ULONG CountCharsX;
ULONG CountCharsY;
ULONG FillAttribute;
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING<EmulatorTraits<Emu32>> WindowTitle;
UNICODE_STRING<EmulatorTraits<Emu32>> DesktopInfo;
UNICODE_STRING<EmulatorTraits<Emu32>> ShellInfo;
UNICODE_STRING<EmulatorTraits<Emu32>> RuntimeData;
RTL_DRIVE_LETTER_CURDIR32 CurrentDirectories[RTL_MAX_DRIVE_LETTERS];
std::uint32_t EnvironmentSize;
std::uint32_t EnvironmentVersion;
std::uint32_t PackageDependencyData;
ULONG ProcessGroupId;
ULONG LoaderThreads;
UNICODE_STRING<EmulatorTraits<Emu32>> RedirectionDllName; // REDSTONE4
UNICODE_STRING<EmulatorTraits<Emu32>> HeapPartitionName; // 19H1
std::uint32_t DefaultThreadpoolCpuSetMasks;
ULONG DefaultThreadpoolCpuSetMaskCount;
ULONG DefaultThreadpoolThreadMaximum;
ULONG HeapMemoryTypeMask; // WIN11
} RTL_USER_PROCESS_PARAMETERS32, *PRTL_USER_PROCESS_PARAMETERS32;
static_assert(sizeof(RTL_USER_PROCESS_PARAMETERS32) == 708);
typedef struct _PEB64
{
BOOLEAN InheritedAddressSpace;
@@ -457,6 +669,184 @@ typedef struct _PEB64
static_assert(sizeof(PEB64) == 0x7D0);
typedef struct _PEB32
{
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
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;
};
};
EmulatorTraits<Emu32>::HANDLE Mutant;
std::uint32_t ImageBaseAddress;
EMULATOR_CAST(std::uint32_t, PPEB_LDR_DATA32) Ldr;
EMULATOR_CAST(std::uint32_t, struct _RTL_USER_PROCESS_PARAMETERS32*) ProcessParameters;
EMULATOR_CAST(std::uint32_t, PVOID32) SubSystemData;
EMULATOR_CAST(std::uint32_t, PVOID32) ProcessHeap;
EMULATOR_CAST(std::uint32_t, struct _RTL_CRITICAL_SECTION32*) FastPebLock;
EMULATOR_CAST(std::uint32_t, union _SLIST_HEADER*) AtlThunkSListPtr;
EMULATOR_CAST(std::uint32_t, PVOID32) IFEOKey;
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
{
EMULATOR_CAST(std::uint32_t, PVOID32) KernelCallbackTable;
EMULATOR_CAST(std::uint32_t, PVOID32) UserSharedInfoPtr;
};
ULONG SystemReserved;
ULONG AtlThunkSListPtr32;
EMULATOR_CAST(std::uint32_t, struct _API_SET_NAMESPACE*) ApiSetMap;
ULONG TlsExpansionCounter;
EMULATOR_CAST(std::uint32_t, struct _RTL_BITMAP*) TlsBitmap;
ARRAY_CONTAINER<ULONG, 2> TlsBitmapBits;
EMULATOR_CAST(std::uint32_t, PVOID32) ReadOnlySharedMemoryBase;
EMULATOR_CAST(std::uint32_t, struct _SILO_USER_SHARED_DATA*) SharedData; // HotpatchInformation
EMULATOR_CAST(std::uint32_t, PVOID32*) ReadOnlyStaticServerData;
EMULATOR_CAST(std::uint32_t, PVOID32) AnsiCodePageData; // PCPTABLEINFO
EMULATOR_CAST(std::uint32_t, PVOID32) OemCodePageData; // PCPTABLEINFO
EMULATOR_CAST(std::uint32_t, PVOID32) UnicodeCaseTableData; // PNLSTABLEINFO
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
ULARGE_INTEGER CriticalSectionTimeout;
EMULATOR_CAST(std::uint32_t, SIZE_T32) HeapSegmentReserve;
EMULATOR_CAST(std::uint32_t, SIZE_T32) HeapSegmentCommit;
EMULATOR_CAST(std::uint32_t, SIZE_T32) HeapDeCommitTotalFreeThreshold;
EMULATOR_CAST(std::uint32_t, SIZE_T32) HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
EMULATOR_CAST(std::uint32_t, PVOID32*) ProcessHeaps; // PHEAP
EMULATOR_CAST(std::uint32_t, PVOID32) GdiSharedHandleTable; // PGDI_SHARED_MEMORY
EMULATOR_CAST(std::uint32_t, PVOID32) ProcessStarterHelper;
ULONG GdiDCAttributeList;
EMULATOR_CAST(std::uint32_t, struct _RTL_CRITICAL_SECTION32*) LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
USHORT OSBuildNumber;
USHORT OSCSDVersion;
ULONG OSPlatformId;
ULONG ImageSubsystem;
ULONG ImageSubsystemMajorVersion;
ULONG ImageSubsystemMinorVersion;
EMULATOR_CAST(std::uint32_t, KAFFINITY32) ActiveProcessAffinityMask;
ARRAY_CONTAINER<ULONG, GDI_HANDLE_BUFFER_SIZE32> GdiHandleBuffer;
EMULATOR_CAST(std::uint32_t, PVOID32) PostProcessInitRoutine;
EMULATOR_CAST(std::uint32_t, PVOID32) TlsExpansionBitmap;
ARRAY_CONTAINER<ULONG, 32> TlsExpansionBitmapBits;
ULONG SessionId;
ULARGE_INTEGER AppCompatFlags;
ULARGE_INTEGER AppCompatFlagsUser;
EMULATOR_CAST(std::uint32_t, PVOID32) pShimData;
EMULATOR_CAST(std::uint32_t, PVOID32) AppCompatInfo; // APPCOMPAT_EXE_DATA
UNICODE_STRING<EmulatorTraits<Emu32>> CSDVersion;
EMULATOR_CAST(std::uint32_t, struct _ACTIVATION_CONTEXT_DATA*) ActivationContextData;
EMULATOR_CAST(std::uint32_t, struct _ASSEMBLY_STORAGE_MAP32*) ProcessAssemblyStorageMap;
EMULATOR_CAST(std::uint32_t, struct _ACTIVATION_CONTEXT_DATA*) SystemDefaultActivationContextData;
EMULATOR_CAST(std::uint32_t, struct _ASSEMBLY_STORAGE_MAP32*) SystemAssemblyStorageMap;
EMULATOR_CAST(std::uint32_t, SIZE_T32) MinimumStackCommit;
ARRAY_CONTAINER<ULONG, 2> SparePointers; // 19H1 (previously FlsCallback to FlsHighIndex)
EMULATOR_CAST(std::uint32_t, PVOID32) PatchLoaderData;
EMULATOR_CAST(std::uint32_t, PVOID32) ChpeV2ProcessInfo; // _CHPEV2_PROCESS_INFO
ULONG AppModelFeatureState;
ULONG SpareUlongs[2];
USHORT ActiveCodePage;
USHORT OemCodePage;
USHORT UseCaseMapping;
USHORT UnusedNlsField;
EMULATOR_CAST(std::uint32_t, PVOID32) WerRegistrationData;
EMULATOR_CAST(std::uint32_t, PVOID32) WerShipAssertPtr;
union
{
EMULATOR_CAST(std::uint32_t, PVOID32) pContextData; // WIN7
EMULATOR_CAST(std::uint32_t, PVOID32) pUnused; // WIN10
EMULATOR_CAST(std::uint32_t, PVOID32) EcCodeBitMap; // WIN11
};
EMULATOR_CAST(std::uint32_t, PVOID32) pImageHeaderHash;
union
{
ULONG TracingFlags;
struct
{
ULONG HeapTracingEnabled : 1;
ULONG CritSecTracingEnabled : 1;
ULONG LibLoaderTracingEnabled : 1;
ULONG SpareTracingBits : 29;
};
};
ULONGLONG CsrServerReadOnlySharedMemoryBase;
EMULATOR_CAST(std::uint32_t, struct _RTL_CRITICAL_SECTION32*) TppWorkerpListLock;
LIST_ENTRY32 TppWorkerpList;
ARRAY_CONTAINER<ULONG, 128> WaitOnAddressHashTable;
EMULATOR_CAST(std::uint32_t, struct _PTELEMETRY_COVERAGE_HEADER*) TelemetryCoverageHeader; // REDSTONE3
ULONG CloudFileFlags;
ULONG CloudFileDiagFlags; // REDSTONE4
CHAR PlaceholderCompatibilityMode;
ARRAY_CONTAINER<CHAR, 7> PlaceholderCompatibilityModeReserved;
EMULATOR_CAST(std::uint32_t, struct _LEAP_SECOND_DATA*) LeapSecondData; // REDSTONE5
union
{
ULONG LeapSecondFlags;
struct
{
ULONG SixtySecondEnabled : 1;
ULONG Reserved : 31;
};
};
ULONG NtGlobalFlag2;
ULONGLONG ExtendedFeatureDisableMask; // since WIN11
} PEB32, *PPEB32;
static_assert(sizeof(PEB32) == 0x488, "sizeof(PEB32) is incorrect"); // WIN11
typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME64
{
struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME* Previous;
@@ -464,6 +854,59 @@ typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME64
ULONG Flags; // RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_*
} RTL_ACTIVATION_CONTEXT_STACK_FRAME64, *PRTL_ACTIVATION_CONTEXT_STACK_FRAME64;
typedef struct _ASSEMBLY_STORAGE_MAP_ENTRY32
{
ULONG Flags;
UNICODE_STRING<EmulatorTraits<Emu32>> DosPath;
EMULATOR_CAST(std::uint32_t, HANDLE32) Handle;
} ASSEMBLY_STORAGE_MAP_ENTRY32, *PASSEMBLY_STORAGE_MAP_ENTRY32;
static_assert(sizeof(ASSEMBLY_STORAGE_MAP_ENTRY32) == 16);
typedef struct _ASSEMBLY_STORAGE_MAP32
{
ULONG Flags;
ULONG AssemblyCount;
EMULATOR_CAST(std::uint32_t, PASSEMBLY_STORAGE_MAP_ENTRY32*) AssemblyArray;
} ASSEMBLY_STORAGE_MAP32, *PASSEMBLY_STORAGE_MAP32;
static_assert(sizeof(ASSEMBLY_STORAGE_MAP32) == 12);
typedef struct _ACTIVATION_CONTEXT32
{
LONG RefCount;
ULONG Flags;
EMULATOR_CAST(std::uint32_t, struct _ACTIVATION_CONTEXT_DATA*) ActivationContextData;
std::uint32_t /*PACTIVATION_CONTEXT_NOTIFY_ROUTINE*/ NotificationRoutine;
std::uint32_t NotificationContext;
ULONG SentNotifications[8];
ULONG DisabledNotifications[8];
ASSEMBLY_STORAGE_MAP32 StorageMap;
EMULATOR_CAST(std::uint32_t, PASSEMBLY_STORAGE_MAP_ENTRY32) InlineStorageMapEntries[32];
} ACTIVATION_CONTEXT32, *PACTIVATION_CONTEXT32;
static_assert(sizeof(ACTIVATION_CONTEXT32) == 224);
typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME32
{
EMULATOR_CAST(std::uint32_t, struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME32*) Previous;
EMULATOR_CAST(std::uint32_t, PACTIVATION_CONTEXT32) ActivationContext;
ULONG Flags; // RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_*
} RTL_ACTIVATION_CONTEXT_STACK_FRAME32, *PRTL_ACTIVATION_CONTEXT_STACK_FRAME32;
static_assert(sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME32) == 12);
typedef struct _ACTIVATION_CONTEXT_STACK32
{
EMULATOR_CAST(std::uint32_t, PRTL_ACTIVATION_CONTEXT_STACK_FRAME32) ActiveFrame;
LIST_ENTRY32 FrameListCache;
ULONG Flags; // ACTIVATION_CONTEXT_STACK_FLAG_*
ULONG NextCookieSequenceNumber;
ULONG StackId;
} ACTIVATION_CONTEXT_STACK32, *PACTIVATION_CONTEXT_STACK32;
static_assert(sizeof(ACTIVATION_CONTEXT_STACK32) == 24);
typedef struct _ACTIVATION_CONTEXT_STACK64
{
EMULATOR_CAST(std::uint64_t, PRTL_ACTIVATION_CONTEXT_STACK_FRAME64) ActiveFrame;
@@ -480,6 +923,15 @@ typedef struct _GDI_TEB_BATCH64
ULONG Buffer[GDI_BATCH_BUFFER_SIZE];
} GDI_TEB_BATCH64, *PGDI_TEB_BATCH64;
typedef struct _GDI_TEB_BATCH32
{
ULONG Offset;
EMULATOR_CAST(std::uint32_t, ULONG_PTR32) HDC;
ULONG Buffer[GDI_BATCH_BUFFER_SIZE];
} GDI_TEB_BATCH32, *PGDI_TEB_BATCH32;
static_assert(sizeof(GDI_TEB_BATCH32) == 1248, "sizeof(GDI_TEB_BATCH32) is incorrect");
#ifndef OS_WINDOWS
typedef struct _GUID
{
@@ -686,6 +1138,164 @@ inline TEB64* NtCurrentTeb64()
}
#endif
typedef struct _TEB32
{
EMU_NT_TIB32 NtTib;
std::uint32_t EnvironmentPointer;
CLIENT_ID32 ClientId;
std::uint32_t ActiveRpcHandle;
std::uint32_t ThreadLocalStoragePointer;
EMULATOR_CAST(std::uint32_t, PPEB32) ProcessEnvironmentBlock;
ULONG LastErrorValue;
ULONG CountOfOwnedCriticalSections;
std::uint32_t CsrClientThread;
std::uint32_t Win32ThreadInfo;
ULONG User32Reserved[26];
ULONG UserReserved[5];
std::uint32_t WOW32Reserved;
LCID CurrentLocale;
ULONG FpSoftwareStatusRegister;
std::uint32_t ReservedForDebuggerInstrumentation[16];
std::uint32_t SystemReserved1[26];
CHAR PlaceholderCompatibilityMode;
BOOLEAN PlaceholderHydrationAlwaysExplicit;
CHAR PlaceholderReserved[10];
ULONG ProxiedProcessId;
ACTIVATION_CONTEXT_STACK32 ActivationStack;
UCHAR WorkingOnBehalfTicket[8];
NTSTATUS ExceptionCode;
EMULATOR_CAST(std::uint32_t, PACTIVATION_CONTEXT_STACK32) ActivationContextStackPointer;
EMULATOR_CAST(std::uint32_t, ULONG_PTR32) InstrumentationCallbackSp;
EMULATOR_CAST(std::uint32_t, ULONG_PTR32) InstrumentationCallbackPreviousPc;
EMULATOR_CAST(std::uint32_t, ULONG_PTR32) InstrumentationCallbackPreviousSp;
BOOLEAN InstrumentationCallbackDisabled;
UCHAR SpareBytes[23];
ULONG TxFsContext;
GDI_TEB_BATCH32 GdiTebBatch;
CLIENT_ID32 RealClientId;
EmulatorTraits<Emu32>::HANDLE GdiCachedProcessHandle;
ULONG GdiClientPID;
ULONG GdiClientTID;
std::uint32_t GdiThreadLocalInfo;
EMULATOR_CAST(std::uint32_t, ULONG_PTR32) Win32ClientInfo[WIN32_CLIENT_INFO_LENGTH];
std::uint32_t glDispatchTable[233];
EMULATOR_CAST(std::uint32_t, ULONG_PTR32) glReserved1[29];
std::uint32_t glReserved2;
std::uint32_t glSectionInfo;
std::uint32_t glSection;
std::uint32_t glTable;
std::uint32_t glCurrentRC;
std::uint32_t glContext;
NTSTATUS LastStatusValue;
UNICODE_STRING<EmulatorTraits<Emu32>> StaticUnicodeString;
WCHAR StaticUnicodeBuffer[STATIC_UNICODE_BUFFER_LENGTH];
std::uint32_t DeallocationStack;
ARRAY_CONTAINER<std::uint32_t, TLS_MINIMUM_AVAILABLE> TlsSlots;
LIST_ENTRY32 TlsLinks;
std::uint32_t Vdm;
std::uint32_t ReservedForNtRpc;
std::uint32_t DbgSsReserved[2];
ULONG HardErrorMode;
std::uint32_t Instrumentation[9];
GUID ActivityId;
std::uint32_t SubProcessTag;
std::uint32_t PerflibData;
std::uint32_t EtwTraceData;
std::uint32_t WinSockData;
ULONG GdiBatchCount;
union
{
EMULATOR_CAST(std::uint32_t, PROCESSOR_NUMBER) CurrentIdealProcessor;
ULONG IdealProcessorValue;
struct
{
UCHAR ReservedPad0;
UCHAR ReservedPad1;
UCHAR ReservedPad2;
UCHAR IdealProcessor;
};
};
ULONG GuaranteedStackBytes;
EMULATOR_CAST(std::uint32_t, PVOID32) ReservedForPerf;
EMULATOR_CAST(std::uint32_t, PVOID32) ReservedForOle; // tagSOleTlsData32
ULONG WaitingOnLoaderLock;
EMULATOR_CAST(std::uint32_t, PVOID32) SavedPriorityState;
EMULATOR_CAST(std::uint32_t, ULONG_PTR32) ReservedForCodeCoverage;
std::uint32_t ThreadPoolData;
EMULATOR_CAST(std::uint32_t, PVOID32*) TlsExpansionSlots;
ULONG MuiGeneration;
ULONG IsImpersonating;
std::uint32_t NlsCache;
std::uint32_t pShimData;
ULONG HeapData;
EMULATOR_CAST(std::uint32_t, HANDLE32) CurrentTransactionHandle;
EMULATOR_CAST(std::uint32_t, PTEB_ACTIVE_FRAME32) ActiveFrame;
std::uint32_t FlsData;
std::uint32_t PreferredLanguages;
std::uint32_t UserPrefLanguages;
std::uint32_t MergedPrefLanguages;
ULONG MuiImpersonation;
union
{
USHORT CrossTebFlags;
USHORT SpareCrossTebBits : 16;
};
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;
};
};
std::uint32_t TxnScopeEnterCallback;
std::uint32_t TxnScopeExitCallback;
std::uint32_t TxnScopeContext;
ULONG LockCount;
LONG WowTebOffset;
std::uint32_t ResourceRetValue;
std::uint32_t ReservedForWdf;
ULONGLONG ReservedForCrt;
GUID EffectiveContainerId;
ULONGLONG LastSleepCounter; // Win11
ULONG SpinCallCount;
ULONGLONG ExtendedFeatureDisableMask;
} TEB32, *PTEB32;
static_assert(sizeof(TEB32) == 4120, "sizeof(TEB32) is incorrect");
#pragma pack(push, 4)
typedef struct _KSYSTEM_TIME
{
@@ -993,6 +1603,33 @@ typedef struct _SYSTEM_DYNAMIC_TIMEZONE_INFORMATION
BOOLEAN DynamicDaylightTimeDisabled;
} SYSTEM_DYNAMIC_TIMEZONE_INFORMATION, *PSYSTEM_DYNAMIC_TIMEZONE_INFORMATION;
// Memory address requirements structure
typedef struct _MEM_ADDRESS_REQUIREMENTS64
{
EMULATOR_CAST(std::uint64_t, PVOID) LowestStartingAddress;
EMULATOR_CAST(std::uint64_t, PVOID) HighestEndingAddress;
EMULATOR_CAST(std::uint64_t, SIZE_T) Alignment;
} MEM_ADDRESS_REQUIREMENTS64, *PMEM_ADDRESS_REQUIREMENTS64;
// Extended memory parameter structure
typedef struct _MEM_EXTENDED_PARAMETER64
{
struct
{
ULONG64 Type : 8; // MEM_EXTENDED_PARAMETER_TYPE
ULONG64 Reserved : 56;
};
union
{
ULONG64 ULong64;
EMULATOR_CAST(std::uint64_t, PVOID) Pointer;
EMULATOR_CAST(std::uint64_t, SIZE_T) Size;
EMULATOR_CAST(std::uint64_t, HANDLE) Handle;
ULONG ULong;
};
} MEM_EXTENDED_PARAMETER64, *PMEM_EXTENDED_PARAMETER64;
typedef struct _PROCESS_BASIC_INFORMATION64
{
NTSTATUS ExitStatus;
@@ -1091,4 +1728,242 @@ struct OBJECT_TYPE_INFORMATION
ULONG DefaultNonPagedPoolCharge;
};
// WIN8 to REDSTONE
typedef struct _PS_MITIGATION_OPTIONS_MAP_V1
{
ULONG64 Map[1];
} PS_MITIGATION_OPTIONS_MAP_V1, *PPS_MITIGATION_OPTIONS_MAP_V1;
// private // REDSTONE2 to 19H2
typedef struct _PS_MITIGATION_OPTIONS_MAP_V2
{
ULONG64 Map[2];
} PS_MITIGATION_OPTIONS_MAP_V2, *PPS_MITIGATION_OPTIONS_MAP_V2;
// private // since 20H1
typedef struct _PS_MITIGATION_OPTIONS_MAP_V3
{
ULONG64 Map[3];
} PS_MITIGATION_OPTIONS_MAP_V3, *PPS_MITIGATION_OPTIONS_MAP_V3;
typedef PS_MITIGATION_OPTIONS_MAP_V3 PS_MITIGATION_OPTIONS_MAP, *PPS_MITIGATION_OPTIONS_MAP;
// private // REDSTONE3 to 19H2
typedef struct _PS_MITIGATION_AUDIT_OPTIONS_MAP_V2
{
ULONG64 Map[2];
} PS_MITIGATION_AUDIT_OPTIONS_MAP_V2, *PPS_MITIGATION_AUDIT_OPTIONS_MAP_V2;
// private // since 20H1
typedef struct _PS_MITIGATION_AUDIT_OPTIONS_MAP_V3
{
ULONG64 Map[3];
} PS_MITIGATION_AUDIT_OPTIONS_MAP_V3, *PPS_MITIGATION_AUDIT_OPTIONS_MAP_V3, PS_MITIGATION_AUDIT_OPTIONS_MAP,
*PPS_MITIGATION_AUDIT_OPTIONS_MAP;
// private // VISTA to WIN7 SP1
typedef enum class _WOW64_SHARED_INFORMATION_V1
{
SharedNtdll32LdrInitializeThunk = 0,
SharedNtdll32KiUserExceptionDispatcher = 1,
SharedNtdll32KiUserApcDispatcher = 2,
SharedNtdll32KiUserCallbackDispatcher = 3,
SharedNtdll32LdrHotPatchRoutine = 4,
SharedNtdll32ExpInterlockedPopEntrySListFault = 5,
SharedNtdll32ExpInterlockedPopEntrySListResume = 6,
SharedNtdll32ExpInterlockedPopEntrySListEnd = 7,
SharedNtdll32RtlUserThreadStart = 8,
SharedNtdll32pQueryProcessDebugInformationRemote = 9,
SharedNtdll32EtwpNotificationThread = 10,
SharedNtdll32BaseAddress = 11,
Wow64SharedPageEntriesCount = 12
} WOW64_SHARED_INFORMATION_V1;
// private // WIN8
typedef enum class _WOW64_SHARED_INFORMATION_V2
{
SharedNtdll32LdrInitializeThunk = 0,
SharedNtdll32KiUserExceptionDispatcher = 1,
SharedNtdll32KiUserApcDispatcher = 2,
SharedNtdll32KiUserCallbackDispatcher = 3,
SharedNtdll32LdrHotPatchRoutine = 4,
SharedNtdll32ExpInterlockedPopEntrySListFault = 5,
SharedNtdll32ExpInterlockedPopEntrySListResume = 6,
SharedNtdll32ExpInterlockedPopEntrySListEnd = 7,
SharedNtdll32RtlUserThreadStart = 8,
SharedNtdll32pQueryProcessDebugInformationRemote = 9,
SharedNtdll32EtwpNotificationThread = 10,
SharedNtdll32BaseAddress = 11,
SharedNtdll32RtlpWnfNotificationThread = 12,
SharedNtdll32LdrSystemDllInitBlock = 13,
Wow64SharedPageEntriesCount = 14
} WOW64_SHARED_INFORMATION_V2;
// private // WIN8.1 to THRESHOLD 1
typedef enum class _WOW64_SHARED_INFORMATION_V3
{
SharedNtdll32LdrInitializeThunk = 0,
SharedNtdll32KiUserExceptionDispatcher = 1,
SharedNtdll32KiUserApcDispatcher = 2,
SharedNtdll32KiUserCallbackDispatcher = 3,
SharedNtdll32ExpInterlockedPopEntrySListFault = 4,
SharedNtdll32ExpInterlockedPopEntrySListResume = 5,
SharedNtdll32ExpInterlockedPopEntrySListEnd = 6,
SharedNtdll32RtlUserThreadStart = 7,
SharedNtdll32pQueryProcessDebugInformationRemote = 8,
SharedNtdll32BaseAddress = 9,
SharedNtdll32LdrSystemDllInitBlock = 10,
Wow64SharedPageEntriesCount = 11
} WOW64_SHARED_INFORMATION_V3;
// private // THRESHOLD 2 to REDSTONE 2
typedef enum class _WOW64_SHARED_INFORMATION_V4
{
SharedNtdll32LdrInitializeThunk = 0,
SharedNtdll32KiUserExceptionDispatcher = 1,
SharedNtdll32KiUserApcDispatcher = 2,
SharedNtdll32KiUserCallbackDispatcher = 3,
SharedNtdll32RtlUserThreadStart = 4,
SharedNtdll32pQueryProcessDebugInformationRemote = 5,
SharedNtdll32BaseAddress = 6,
SharedNtdll32LdrSystemDllInitBlock = 7,
Wow64SharedPageEntriesCount = 8
} WOW64_SHARED_INFORMATION_V4;
// private // REDSTONE 3 to 24H2
typedef enum class _WOW64_SHARED_INFORMATION_V5
{
SharedNtdll32LdrInitializeThunk = 0,
SharedNtdll32KiUserExceptionDispatcher = 1,
SharedNtdll32KiUserApcDispatcher = 2,
SharedNtdll32KiUserCallbackDispatcher = 3,
SharedNtdll32RtlUserThreadStart = 4,
SharedNtdll32pQueryProcessDebugInformationRemote = 5,
SharedNtdll32BaseAddress = 6,
SharedNtdll32LdrSystemDllInitBlock = 7,
SharedNtdll32RtlpFreezeTimeBias = 8,
Wow64SharedPageEntriesCount = 9
} WOW64_SHARED_INFORMATION_V5;
// private // WIN8 to REDSTONE
typedef struct _PS_SYSTEM_DLL_INIT_BLOCK_V1
{
ULONG Size;
ULONG SystemDllWowRelocation;
ULONG64 SystemDllNativeRelocation;
ULONG Wow64SharedInformation[16]; // use WOW64_SHARED_INFORMATION as index
ULONG RngData;
union
{
ULONG Flags;
struct
{
ULONG CfgOverride : 1; // since REDSTONE
ULONG Reserved : 31;
};
};
ULONG64 MitigationOptions;
ULONG64 CfgBitMap; // since WINBLUE
ULONG64 CfgBitMapSize;
ULONG64 Wow64CfgBitMap; // since THRESHOLD
ULONG64 Wow64CfgBitMapSize;
} PS_SYSTEM_DLL_INIT_BLOCK_V1, *PPS_SYSTEM_DLL_INIT_BLOCK_V1;
// RS2 - 19H2
typedef struct _PS_SYSTEM_DLL_INIT_BLOCK_V2
{
ULONG Size;
ULONG64 SystemDllWowRelocation;
ULONG64 SystemDllNativeRelocation;
ULONG64 Wow64SharedInformation[16]; // use WOW64_SHARED_INFORMATION as index
ULONG RngData;
union
{
ULONG Flags;
struct
{
ULONG CfgOverride : 1;
ULONG Reserved : 31;
};
};
PS_MITIGATION_OPTIONS_MAP_V2 MitigationOptionsMap;
ULONG64 CfgBitMap;
ULONG64 CfgBitMapSize;
ULONG64 Wow64CfgBitMap;
ULONG64 Wow64CfgBitMapSize;
PS_MITIGATION_AUDIT_OPTIONS_MAP_V2 MitigationAuditOptionsMap; // since REDSTONE3
} PS_SYSTEM_DLL_INIT_BLOCK_V2, *PPS_SYSTEM_DLL_INIT_BLOCK_V2;
// private // since 20H1
typedef struct _PS_SYSTEM_DLL_INIT_BLOCK_V3
{
ULONG Size;
ULONG64 SystemDllWowRelocation; // effectively since WIN8
ULONG64 SystemDllNativeRelocation;
ULONG64 Wow64SharedInformation[16]; // use WOW64_SHARED_INFORMATION_V5 as index
ULONG RngData;
union
{
ULONG Flags;
struct
{
ULONG CfgOverride : 1; // effectively since REDSTONE
ULONG Reserved : 31;
};
};
PS_MITIGATION_OPTIONS_MAP_V3 MitigationOptionsMap;
ULONG64 CfgBitMap; // effectively since WINBLUE
ULONG64 CfgBitMapSize;
ULONG64 Wow64CfgBitMap; // effectively since THRESHOLD
ULONG64 Wow64CfgBitMapSize;
PS_MITIGATION_AUDIT_OPTIONS_MAP_V3 MitigationAuditOptionsMap; // effectively since REDSTONE3
ULONG64 ScpCfgCheckFunction; // since 24H2
ULONG64 ScpCfgCheckESFunction;
ULONG64 ScpCfgDispatchFunction;
ULONG64 ScpCfgDispatchESFunction;
ULONG64 ScpArm64EcCallCheck;
ULONG64 ScpArm64EcCfgCheckFunction;
ULONG64 ScpArm64EcCfgCheckESFunction;
} PS_SYSTEM_DLL_INIT_BLOCK_V3, *PPS_SYSTEM_DLL_INIT_BLOCK_V3, PS_SYSTEM_DLL_INIT_BLOCK, *PPS_SYSTEM_DLL_INIT_BLOCK;
static_assert(sizeof(PS_SYSTEM_DLL_INIT_BLOCK_V3) == 0x128);
//
// Process mitigation policy information
// NtSetInformationProcess using ProcessMitigationPolicy
//
typedef struct _PROCESS_MITIGATION_POLICY_RAW_DATA
{
PROCESS_MITIGATION_POLICY Policy;
ULONG Value;
} PROCESS_MITIGATION_POLICY_RAW_DATA, *PPROCESS_MITIGATION_POLICY_RAW_DATA;
static_assert(sizeof(PROCESS_MITIGATION_POLICY_RAW_DATA) == 0x8);
typedef struct _WOW64_CPURESERVED
{
USHORT Flags; // Initialised to 0x02 by ntdll.dll and periodically bitwise OR'd with WOW64_CPURESERVED_FLAG_RESET_STATE
USHORT MachineType; // IMAGE_FILE_MACHINE_I386 (0x014C) for x86 architecture
// Under IMAGE_FILE_MACHINE_I386 machine type, this is the WOW64_CONTEXT structure containing x86 architecture context
WOW64_CONTEXT Context;
// Padding to align WOW64 stack
BYTE AlignmentPad[0x10];
} WOW64_CPURESERVED, *PWOW64_CPURESERVED;
static_assert(sizeof(WOW64_CPURESERVED) == 0x2E0);
#define WOW64_CPURESERVED_FLAG_RESET_STATE 1
typedef enum class _SECTION_INFORMATION_CLASS
{
SectionBasicInformation = 0,
SectionImageInformation = 1,
SectionRelocationInformation = 2,
SectionOriginalBaseInformation = 3,
SectionInternalImageInformation = 4
} SECTION_INFORMATION_CLASS, *PSECTION_INFORMATION_CLASS;
// NOLINTEND(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)

View File

@@ -20,6 +20,7 @@
using LONG = std::int32_t;
using ULONG = DWORD;
using DWORD64 = std::uint64_t;
using ULONG64 = std::uint64_t;
using ULONGLONG = DWORD64;
using LONGLONG = std::int64_t;
using UINT = std::uint32_t;
@@ -52,6 +53,7 @@ using BYTE = std::uint8_t;
#endif
using WORD = std::uint16_t;
#define WCHAR WORD
#define UCHAR uint8_t
#define BOOLEAN UCHAR

View File

@@ -6,24 +6,29 @@
#define CREATE_SUSPENDED 0x00000004
#endif
#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 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_EXTENDED_REGISTERS_32 (CONTEXT_X86_MAIN | 0x20L)
#define CONTEXT_XSTATE_32 (CONTEXT_X86_MAIN | 0x40L)
#define CONTEXT_XSTATE_64 (CONTEXT_AMD64_MAIN | 0x40L)
#define CONTEXT64_ALL \
(CONTEXT_CONTROL_64 | CONTEXT_INTEGER_64 | CONTEXT_SEGMENTS_64 | CONTEXT_FLOATING_POINT_64 | CONTEXT_DEBUG_REGISTERS_64)
#define CONTEXT32_ALL \
(CONTEXT_CONTROL_32 | CONTEXT_INTEGER_32 | CONTEXT_SEGMENTS_32 | CONTEXT_FLOATING_POINT_32 | CONTEXT_DEBUG_REGISTERS_32 | \
CONTEXT_EXTENDED_REGISTERS_32)
using SYSTEM_INFORMATION_CLASS = enum _SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation, // q: SYSTEM_BASIC_INFORMATION
@@ -977,6 +982,12 @@ struct GDI_SHARED_MEMORY64
static_assert(offsetof(GDI_SHARED_MEMORY64, Objects) == 0x1800B0);
struct CLIENT_ID32
{
ULONG UniqueProcess;
ULONG UniqueThread;
};
struct CLIENT_ID64
{
DWORD64 UniqueProcess;

View File

@@ -39,11 +39,14 @@ using NTSTATUS = std::uint32_t;
#define STATUS_INVALID_PAGE_PROTECTION ((NTSTATUS)0xC0000045L)
#define STATUS_MUTANT_NOT_OWNED ((NTSTATUS)0xC0000046L)
#define STATUS_SEMAPHORE_LIMIT_EXCEEDED ((NTSTATUS)0xC0000047L)
#define STATUS_SECTION_NOT_IMAGE ((NTSTATUS)0xC0000049L)
#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_INTERNAL_ERROR ((NTSTATUS)0xC00000E5L)
#define STATUS_PROCEDURE_NOT_FOUND ((NTSTATUS)0xC000007AL)
#define STATUS_INVALID_ADDRESS ((NTSTATUS)0xC0000141L)
#define STATUS_CONNECTION_RESET ((NTSTATUS)0xC000020DL)
#define STATUS_NOT_FOUND ((NTSTATUS)0xC0000225L)

View File

@@ -8,7 +8,6 @@ struct UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
uint32_t _Padding;
EMULATOR_CAST(typename Traits::PVOID, char16_t*) Buffer;
};

View File

@@ -1,6 +1,11 @@
#pragma once
#include <cstring>
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <system_error>
#include <variant>
// NOLINTBEGIN(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
@@ -54,10 +59,42 @@
#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040
#define IMAGE_FILE_DLL 0x2000
#define IMAGE_FILE_MACHINE_I386 0x014c
#define IMAGE_FILE_MACHINE_AMD64 0x8664
#ifndef OS_WINDOWS
#define IMAGE_FILE_MACHINE_UNKNOWN 0
#define IMAGE_FILE_MACHINE_TARGET_HOST 0x0001 // Useful for indicating we want to interact with the host and not a WoW guest.
#define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386.
#define IMAGE_FILE_MACHINE_R3000 0x0162 // MIPS little-endian, 0x160 big-endian
#define IMAGE_FILE_MACHINE_R4000 0x0166 // MIPS little-endian
#define IMAGE_FILE_MACHINE_R10000 0x0168 // MIPS little-endian
#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 // MIPS little-endian WCE v2
#define IMAGE_FILE_MACHINE_ALPHA 0x0184 // Alpha_AXP
#define IMAGE_FILE_MACHINE_SH3 0x01a2 // SH3 little-endian
#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3
#define IMAGE_FILE_MACHINE_SH3E 0x01a4 // SH3E little-endian
#define IMAGE_FILE_MACHINE_SH4 0x01a6 // SH4 little-endian
#define IMAGE_FILE_MACHINE_SH5 0x01a8 // SH5
#define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian
#define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian
#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian
#define IMAGE_FILE_MACHINE_AM33 0x01d3
#define IMAGE_FILE_MACHINE_POWERPC 0x01F0 // IBM PowerPC Little-Endian
#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1
#define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64
#define IMAGE_FILE_MACHINE_MIPS16 0x0266 // MIPS
#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64
#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 // MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 // MIPS
#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64
#define IMAGE_FILE_MACHINE_TRICORE 0x0520 // Infineon
#define IMAGE_FILE_MACHINE_CEF 0x0CEF
#define IMAGE_FILE_MACHINE_EBC 0x0EBC // EFI Byte Code
#define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8)
#define IMAGE_FILE_MACHINE_M32R 0x9041 // M32R little-endian
#define IMAGE_FILE_MACHINE_ARM64 0xAA64 // ARM64 Little-Endian
#define IMAGE_FILE_MACHINE_CEE 0xC0EE
#endif
#define PROCESSOR_ARCHITECTURE_AMD64 9
#define PROCESSOR_ARCHITECTURE_AMD64 9
enum class PEMachineType : std::uint16_t
{
@@ -311,7 +348,7 @@ typedef struct _IMAGE_IMPORT_DESCRIPTOR
DWORD ForwarderChain; // -1 if no forwarders
DWORD Name;
DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses)
} IMAGE_IMPORT_DESCRIPTOR;
} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR;
typedef struct _IMAGE_THUNK_DATA64
{
@@ -322,10 +359,65 @@ typedef struct _IMAGE_THUNK_DATA64
ULONGLONG Ordinal;
ULONGLONG AddressOfData; // PIMAGE_IMPORT_BY_NAME
} u1;
} IMAGE_THUNK_DATA64;
} IMAGE_THUNK_DATA64, *PIMAGE_THUNK_DATA64;
typedef struct _IMAGE_THUNK_DATA32
{
union
{
DWORD ForwarderString; // PBYTE
DWORD Function; // PDWORD
DWORD Ordinal;
DWORD AddressOfData; // PIMAGE_IMPORT_BY_NAME
} u1;
} IMAGE_THUNK_DATA32, *PIMAGE_THUNK_DATA32;
#endif
// Template type definitions for architecture-specific thunk data
template <typename T>
struct thunk_data_traits;
template <>
struct thunk_data_traits<std::uint32_t>
{
using type = IMAGE_THUNK_DATA32;
static constexpr DWORD ordinal_flag = IMAGE_ORDINAL_FLAG32;
static constexpr WORD ordinal_mask(DWORD ordinal)
{
return IMAGE_ORDINAL32(ordinal);
}
static constexpr bool snap_by_ordinal(DWORD ordinal)
{
return IMAGE_SNAP_BY_ORDINAL32(ordinal);
}
};
template <>
struct thunk_data_traits<std::uint64_t>
{
using type = IMAGE_THUNK_DATA64;
static constexpr ULONGLONG ordinal_flag = IMAGE_ORDINAL_FLAG64;
static constexpr WORD ordinal_mask(ULONGLONG ordinal)
{
return IMAGE_ORDINAL64(ordinal);
}
static constexpr bool snap_by_ordinal(ULONGLONG ordinal)
{
return IMAGE_SNAP_BY_ORDINAL64(ordinal);
}
};
template <typename Traits>
struct SECTION_BASIC_INFORMATION
{
typename Traits::PVOID BaseAddress;
ULONG Attributes;
LARGE_INTEGER Size;
};
template <typename Traits>
struct SECTION_IMAGE_INFORMATION
{
@@ -383,4 +475,121 @@ struct SECTION_IMAGE_INFORMATION
ULONG CheckSum;
};
namespace winpe
{
enum class pe_arch
{
pe32,
pe64
};
inline std::variant<pe_arch, std::error_code> get_pe_arch(const std::filesystem::path& file)
{
std::ifstream f(file, std::ios::binary);
if (!f)
{
return std::make_error_code(std::errc::no_such_file_or_directory);
}
PEDosHeader_t dos{};
f.read(reinterpret_cast<char*>(&dos), sizeof(dos));
if (!f || dos.e_magic != PEDosHeader_t::k_Magic)
{
return std::make_error_code(std::errc::executable_format_error);
}
f.seekg(dos.e_lfanew, std::ios::beg);
uint32_t nt_signature = 0;
f.read(reinterpret_cast<char*>(&nt_signature), sizeof(nt_signature));
if (!f || nt_signature != PENTHeaders_t<std::uint32_t>::k_Signature)
{
return std::make_error_code(std::errc::executable_format_error);
}
PEFileHeader_t file_header{};
f.read(reinterpret_cast<char*>(&file_header), sizeof(file_header));
if (!f)
{
return std::make_error_code(std::errc::executable_format_error);
}
uint16_t magic = 0;
f.read(reinterpret_cast<char*>(&magic), sizeof(magic));
if (!f)
{
return std::make_error_code(std::errc::executable_format_error);
}
if (magic == PEOptionalHeader_t<std::uint32_t>::k_Magic)
{
return pe_arch::pe32;
}
if (magic == PEOptionalHeader_t<std::uint64_t>::k_Magic)
{
return pe_arch::pe64;
}
return std::make_error_code(std::errc::executable_format_error);
}
inline std::variant<pe_arch, std::error_code> get_pe_arch(uint64_t base_address, uint64_t image_size)
{
const auto* base = reinterpret_cast<const std::byte*>(reinterpret_cast<const void*>(static_cast<uintptr_t>(base_address)));
const uint64_t size = image_size;
auto read = [&](uint64_t off, void* dst, size_t n) -> bool {
if (off > size)
{
return false;
}
if (n > size - off)
{
return false;
}
memcpy(dst, base + off, n);
return true;
};
PEDosHeader_t dos{};
if (!read(0, &dos, sizeof(dos)) || dos.e_magic != PEDosHeader_t::k_Magic)
{
return std::make_error_code(std::errc::executable_format_error);
}
const auto nt_off = static_cast<uint64_t>(dos.e_lfanew);
uint32_t nt_signature = 0;
if (!read(nt_off, &nt_signature, sizeof(nt_signature)) || nt_signature != PENTHeaders_t<std::uint32_t>::k_Signature)
{
return std::make_error_code(std::errc::executable_format_error);
}
PEFileHeader_t file_header{};
const uint64_t fh_off = nt_off + sizeof(nt_signature);
if (!read(fh_off, &file_header, sizeof(file_header)))
{
return std::make_error_code(std::errc::executable_format_error);
}
uint16_t magic = 0;
const uint64_t opt_magic_off = fh_off + sizeof(file_header);
if (!read(opt_magic_off, &magic, sizeof(magic)))
{
return std::make_error_code(std::errc::executable_format_error);
}
if (magic == PEOptionalHeader_t<std::uint32_t>::k_Magic)
{
return pe_arch::pe32;
}
if (magic == PEOptionalHeader_t<std::uint64_t>::k_Magic)
{
return pe_arch::pe64;
}
return std::make_error_code(std::errc::executable_format_error);
}
}
// NOLINTEND(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)