aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2023-03-31 00:38:30 +0200
committerGitHub <noreply@github.com>2023-03-31 00:38:30 +0200
commit5b82b40043e3a930e6693867c83de00ab3d20ef7 (patch)
treeacc4e2cec84c50612cf0dc5428ec648d32ae76dd /lib/std
parentc964e10821c417ceb7d0efcf1625d67484e734f7 (diff)
parent908ccce064a898d5db1d43dbdc4a3590fd84d4ba (diff)
downloadzig-5b82b40043e3a930e6693867c83de00ab3d20ef7.tar.gz
zig-5b82b40043e3a930e6693867c83de00ab3d20ef7.zip
Merge pull request #15125 from ziglang/hcs-win-poc
coff: add hot-code swapping PoC
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/os/windows.zig199
-rw-r--r--lib/std/os/windows/ntdll.zig130
2 files changed, 221 insertions, 108 deletions
diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig
index fe0a68a13a..1e6f717bb2 100644
--- a/lib/std/os/windows.zig
+++ b/lib/std/os/windows.zig
@@ -1514,6 +1514,24 @@ pub fn VirtualProtect(lpAddress: ?LPVOID, dwSize: SIZE_T, flNewProtect: DWORD, l
}
}
+pub fn VirtualProtectEx(handle: HANDLE, addr: ?LPVOID, size: SIZE_T, new_prot: DWORD) VirtualProtectError!DWORD {
+ var old_prot: DWORD = undefined;
+ var out_addr = addr;
+ var out_size = size;
+ switch (ntdll.NtProtectVirtualMemory(
+ handle,
+ &out_addr,
+ &out_size,
+ new_prot,
+ &old_prot,
+ )) {
+ .SUCCESS => return old_prot,
+ .INVALID_ADDRESS => return error.InvalidAddress,
+ // TODO: map errors
+ else => |rc| return std.os.windows.unexpectedStatus(rc),
+ }
+}
+
pub const VirtualQueryError = error{Unexpected};
pub fn VirtualQuery(lpAddress: ?LPVOID, lpBuffer: PMEMORY_BASIC_INFORMATION, dwLength: SIZE_T) VirtualQueryError!SIZE_T {
@@ -4457,3 +4475,184 @@ pub const MODULEENTRY32 = extern struct {
szModule: [MAX_MODULE_NAME32 + 1]CHAR,
szExePath: [MAX_PATH]CHAR,
};
+
+pub const THREADINFOCLASS = enum(c_int) {
+ ThreadBasicInformation,
+ ThreadTimes,
+ ThreadPriority,
+ ThreadBasePriority,
+ ThreadAffinityMask,
+ ThreadImpersonationToken,
+ ThreadDescriptorTableEntry,
+ ThreadEnableAlignmentFaultFixup,
+ ThreadEventPair_Reusable,
+ ThreadQuerySetWin32StartAddress,
+ ThreadZeroTlsCell,
+ ThreadPerformanceCount,
+ ThreadAmILastThread,
+ ThreadIdealProcessor,
+ ThreadPriorityBoost,
+ ThreadSetTlsArrayAddress,
+ ThreadIsIoPending,
+ // Windows 2000+ from here
+ ThreadHideFromDebugger,
+ // Windows XP+ from here
+ ThreadBreakOnTermination,
+ ThreadSwitchLegacyState,
+ ThreadIsTerminated,
+ // Windows Vista+ from here
+ ThreadLastSystemCall,
+ ThreadIoPriority,
+ ThreadCycleTime,
+ ThreadPagePriority,
+ ThreadActualBasePriority,
+ ThreadTebInformation,
+ ThreadCSwitchMon,
+ // Windows 7+ from here
+ ThreadCSwitchPmu,
+ ThreadWow64Context,
+ ThreadGroupInformation,
+ ThreadUmsInformation,
+ ThreadCounterProfiling,
+ ThreadIdealProcessorEx,
+ // Windows 8+ from here
+ ThreadCpuAccountingInformation,
+ // Windows 8.1+ from here
+ ThreadSuspendCount,
+ // Windows 10+ from here
+ ThreadHeterogeneousCpuPolicy,
+ ThreadContainerId,
+ ThreadNameInformation,
+ ThreadSelectedCpuSets,
+ ThreadSystemThreadInformation,
+ ThreadActualGroupAffinity,
+};
+
+pub const PROCESSINFOCLASS = enum(c_int) {
+ ProcessBasicInformation,
+ ProcessQuotaLimits,
+ ProcessIoCounters,
+ ProcessVmCounters,
+ ProcessTimes,
+ ProcessBasePriority,
+ ProcessRaisePriority,
+ ProcessDebugPort,
+ ProcessExceptionPort,
+ ProcessAccessToken,
+ ProcessLdtInformation,
+ ProcessLdtSize,
+ ProcessDefaultHardErrorMode,
+ ProcessIoPortHandlers,
+ ProcessPooledUsageAndLimits,
+ ProcessWorkingSetWatch,
+ ProcessUserModeIOPL,
+ ProcessEnableAlignmentFaultFixup,
+ ProcessPriorityClass,
+ ProcessWx86Information,
+ ProcessHandleCount,
+ ProcessAffinityMask,
+ ProcessPriorityBoost,
+ ProcessDeviceMap,
+ ProcessSessionInformation,
+ ProcessForegroundInformation,
+ ProcessWow64Information,
+ ProcessImageFileName,
+ ProcessLUIDDeviceMapsEnabled,
+ ProcessBreakOnTermination,
+ ProcessDebugObjectHandle,
+ ProcessDebugFlags,
+ ProcessHandleTracing,
+ ProcessIoPriority,
+ ProcessExecuteFlags,
+ ProcessTlsInformation,
+ ProcessCookie,
+ ProcessImageInformation,
+ ProcessCycleTime,
+ ProcessPagePriority,
+ ProcessInstrumentationCallback,
+ ProcessThreadStackAllocation,
+ ProcessWorkingSetWatchEx,
+ ProcessImageFileNameWin32,
+ ProcessImageFileMapping,
+ ProcessAffinityUpdateMode,
+ ProcessMemoryAllocationMode,
+ ProcessGroupInformation,
+ ProcessTokenVirtualizationEnabled,
+ ProcessConsoleHostProcess,
+ ProcessWindowInformation,
+ MaxProcessInfoClass,
+};
+
+pub const PROCESS_BASIC_INFORMATION = extern struct {
+ ExitStatus: NTSTATUS,
+ PebBaseAddress: *PEB,
+ AffinityMask: ULONG_PTR,
+ BasePriority: KPRIORITY,
+ UniqueProcessId: ULONG_PTR,
+ InheritedFromUniqueProcessId: ULONG_PTR,
+};
+
+pub const ReadMemoryError = error{
+ Unexpected,
+};
+
+pub fn ReadProcessMemory(handle: HANDLE, addr: ?LPVOID, buffer: []u8) ReadMemoryError![]u8 {
+ var nread: usize = 0;
+ switch (ntdll.NtReadVirtualMemory(
+ handle,
+ addr,
+ buffer.ptr,
+ buffer.len,
+ &nread,
+ )) {
+ .SUCCESS => return buffer[0..nread],
+ // TODO: map errors
+ else => |rc| return unexpectedStatus(rc),
+ }
+}
+
+pub const WriteMemoryError = error{
+ Unexpected,
+};
+
+pub fn WriteProcessMemory(handle: HANDLE, addr: ?LPVOID, buffer: []const u8) WriteMemoryError!usize {
+ var nwritten: usize = 0;
+ switch (ntdll.NtWriteVirtualMemory(
+ handle,
+ addr,
+ @ptrCast(*const anyopaque, buffer.ptr),
+ buffer.len,
+ &nwritten,
+ )) {
+ .SUCCESS => return nwritten,
+ // TODO: map errors
+ else => |rc| return unexpectedStatus(rc),
+ }
+}
+
+pub const ProcessBaseAddressError = GetProcessMemoryInfoError || ReadMemoryError;
+
+/// Returns the base address of the process loaded into memory.
+pub fn ProcessBaseAddress(handle: HANDLE) ProcessBaseAddressError!HMODULE {
+ var info: PROCESS_BASIC_INFORMATION = undefined;
+ var nread: DWORD = 0;
+ const rc = ntdll.NtQueryInformationProcess(
+ handle,
+ .ProcessBasicInformation,
+ &info,
+ @sizeOf(PROCESS_BASIC_INFORMATION),
+ &nread,
+ );
+ switch (rc) {
+ .SUCCESS => {},
+ .ACCESS_DENIED => return error.AccessDenied,
+ .INVALID_HANDLE => return error.InvalidHandle,
+ .INVALID_PARAMETER => unreachable,
+ else => return unexpectedStatus(rc),
+ }
+
+ var peb_buf: [@sizeOf(PEB)]u8 align(@alignOf(PEB)) = undefined;
+ const peb_out = try ReadProcessMemory(handle, info.PebBaseAddress, &peb_buf);
+ const ppeb = @ptrCast(*const PEB, @alignCast(@alignOf(PEB), peb_out.ptr));
+ return ppeb.ImageBaseAddress;
+}
diff --git a/lib/std/os/windows/ntdll.zig b/lib/std/os/windows/ntdll.zig
index 429b36039e..a8af39aa4d 100644
--- a/lib/std/os/windows/ntdll.zig
+++ b/lib/std/os/windows/ntdll.zig
@@ -31,61 +31,10 @@ const UNWIND_HISTORY_TABLE = windows.UNWIND_HISTORY_TABLE;
const RUNTIME_FUNCTION = windows.RUNTIME_FUNCTION;
const KNONVOLATILE_CONTEXT_POINTERS = windows.KNONVOLATILE_CONTEXT_POINTERS;
const EXCEPTION_ROUTINE = windows.EXCEPTION_ROUTINE;
-
-pub const PROCESSINFOCLASS = enum(c_int) {
- ProcessBasicInformation,
- ProcessQuotaLimits,
- ProcessIoCounters,
- ProcessVmCounters,
- ProcessTimes,
- ProcessBasePriority,
- ProcessRaisePriority,
- ProcessDebugPort,
- ProcessExceptionPort,
- ProcessAccessToken,
- ProcessLdtInformation,
- ProcessLdtSize,
- ProcessDefaultHardErrorMode,
- ProcessIoPortHandlers,
- ProcessPooledUsageAndLimits,
- ProcessWorkingSetWatch,
- ProcessUserModeIOPL,
- ProcessEnableAlignmentFaultFixup,
- ProcessPriorityClass,
- ProcessWx86Information,
- ProcessHandleCount,
- ProcessAffinityMask,
- ProcessPriorityBoost,
- ProcessDeviceMap,
- ProcessSessionInformation,
- ProcessForegroundInformation,
- ProcessWow64Information,
- ProcessImageFileName,
- ProcessLUIDDeviceMapsEnabled,
- ProcessBreakOnTermination,
- ProcessDebugObjectHandle,
- ProcessDebugFlags,
- ProcessHandleTracing,
- ProcessIoPriority,
- ProcessExecuteFlags,
- ProcessTlsInformation,
- ProcessCookie,
- ProcessImageInformation,
- ProcessCycleTime,
- ProcessPagePriority,
- ProcessInstrumentationCallback,
- ProcessThreadStackAllocation,
- ProcessWorkingSetWatchEx,
- ProcessImageFileNameWin32,
- ProcessImageFileMapping,
- ProcessAffinityUpdateMode,
- ProcessMemoryAllocationMode,
- ProcessGroupInformation,
- ProcessTokenVirtualizationEnabled,
- ProcessConsoleHostProcess,
- ProcessWindowInformation,
- MaxProcessInfoClass,
-};
+const THREADINFOCLASS = windows.THREADINFOCLASS;
+const PROCESSINFOCLASS = windows.PROCESSINFOCLASS;
+const LPVOID = windows.LPVOID;
+const LPCVOID = windows.LPCVOID;
pub extern "ntdll" fn NtQueryInformationProcess(
ProcessHandle: HANDLE,
@@ -95,57 +44,6 @@ pub extern "ntdll" fn NtQueryInformationProcess(
ReturnLength: ?*ULONG,
) callconv(WINAPI) NTSTATUS;
-pub const THREADINFOCLASS = enum(c_int) {
- ThreadBasicInformation,
- ThreadTimes,
- ThreadPriority,
- ThreadBasePriority,
- ThreadAffinityMask,
- ThreadImpersonationToken,
- ThreadDescriptorTableEntry,
- ThreadEnableAlignmentFaultFixup,
- ThreadEventPair_Reusable,
- ThreadQuerySetWin32StartAddress,
- ThreadZeroTlsCell,
- ThreadPerformanceCount,
- ThreadAmILastThread,
- ThreadIdealProcessor,
- ThreadPriorityBoost,
- ThreadSetTlsArrayAddress,
- ThreadIsIoPending,
- // Windows 2000+ from here
- ThreadHideFromDebugger,
- // Windows XP+ from here
- ThreadBreakOnTermination,
- ThreadSwitchLegacyState,
- ThreadIsTerminated,
- // Windows Vista+ from here
- ThreadLastSystemCall,
- ThreadIoPriority,
- ThreadCycleTime,
- ThreadPagePriority,
- ThreadActualBasePriority,
- ThreadTebInformation,
- ThreadCSwitchMon,
- // Windows 7+ from here
- ThreadCSwitchPmu,
- ThreadWow64Context,
- ThreadGroupInformation,
- ThreadUmsInformation,
- ThreadCounterProfiling,
- ThreadIdealProcessorEx,
- // Windows 8+ from here
- ThreadCpuAccountingInformation,
- // Windows 8.1+ from here
- ThreadSuspendCount,
- // Windows 10+ from here
- ThreadHeterogeneousCpuPolicy,
- ThreadContainerId,
- ThreadNameInformation,
- ThreadSelectedCpuSets,
- ThreadSystemThreadInformation,
- ThreadActualGroupAffinity,
-};
pub extern "ntdll" fn NtQueryInformationThread(
ThreadHandle: HANDLE,
ThreadInformationClass: THREADINFOCLASS,
@@ -364,10 +262,26 @@ pub extern "ntdll" fn RtlQueryRegistryValues(
Environment: ?*anyopaque,
) callconv(WINAPI) NTSTATUS;
+pub extern "ntdll" fn NtReadVirtualMemory(
+ ProcessHandle: HANDLE,
+ BaseAddress: ?PVOID,
+ Buffer: LPVOID,
+ NumberOfBytesToRead: SIZE_T,
+ NumberOfBytesRead: ?*SIZE_T,
+) callconv(WINAPI) NTSTATUS;
+
+pub extern "ntdll" fn NtWriteVirtualMemory(
+ ProcessHandle: HANDLE,
+ BaseAddress: ?PVOID,
+ Buffer: LPCVOID,
+ NumberOfBytesToWrite: SIZE_T,
+ NumberOfBytesWritten: ?*SIZE_T,
+) callconv(WINAPI) NTSTATUS;
+
pub extern "ntdll" fn NtProtectVirtualMemory(
ProcessHandle: HANDLE,
- BaseAddress: *PVOID,
- NumberOfBytesToProtect: *ULONG,
+ BaseAddress: *?PVOID,
+ NumberOfBytesToProtect: *SIZE_T,
NewAccessProtection: ULONG,
OldAccessProtection: *ULONG,
) callconv(WINAPI) NTSTATUS;