diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-31 00:38:30 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-31 00:38:30 +0200 |
| commit | 5b82b40043e3a930e6693867c83de00ab3d20ef7 (patch) | |
| tree | acc4e2cec84c50612cf0dc5428ec648d32ae76dd /lib/std | |
| parent | c964e10821c417ceb7d0efcf1625d67484e734f7 (diff) | |
| parent | 908ccce064a898d5db1d43dbdc4a3590fd84d4ba (diff) | |
| download | zig-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.zig | 199 | ||||
| -rw-r--r-- | lib/std/os/windows/ntdll.zig | 130 |
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; |
