authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-30 17:18:34+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-30 21:08:31+02:00
log5d387742fd0f9e5c2072a2a527ccbf22044d4513
treefda426408a81c580afbb1cd79e269d8124eb08e9
parent423b9f11144cc7f7f027db9a091174e9c752c511

coff: reimplement VirtualProtectEx using our own ntdll wrapper


2 files changed, 26 insertions(+), 20 deletions(-)

lib/std/os/windows/ntdll.zig+1-1
...@@ -367,7 +367,7 @@ pub extern "ntdll" fn RtlQueryRegistryValues(...@@ -367,7 +367,7 @@ pub extern "ntdll" fn RtlQueryRegistryValues(
367pub extern "ntdll" fn NtProtectVirtualMemory(367pub extern "ntdll" fn NtProtectVirtualMemory(
368 ProcessHandle: HANDLE,368 ProcessHandle: HANDLE,
369 BaseAddress: *PVOID,369 BaseAddress: *PVOID,
370 NumberOfBytesToProtect: *ULONG,370 NumberOfBytesToProtect: *SIZE_T,
371 NewAccessProtection: ULONG,371 NewAccessProtection: ULONG,
372 OldAccessProtection: *ULONG,372 OldAccessProtection: *ULONG,
373) callconv(WINAPI) NTSTATUS;373) callconv(WINAPI) NTSTATUS;
src/link/Coff.zig+25-19
...@@ -820,6 +820,14 @@ extern "ntdll" fn NtWriteVirtualMemory(...@@ -820,6 +820,14 @@ extern "ntdll" fn NtWriteVirtualMemory(
820 NumberOfBytesWritten: ?*std.os.windows.SIZE_T,820 NumberOfBytesWritten: ?*std.os.windows.SIZE_T,
821) std.os.windows.NTSTATUS;821) std.os.windows.NTSTATUS;
822822
823extern "ntdll" fn NtProtectVirtualMemory(
824 ProcessHandle: std.os.windows.HANDLE,
825 BaseAddress: *std.os.windows.PVOID,
826 NumberOfBytesToProtect: *std.os.windows.SIZE_T,
827 NewAccessProtection: std.os.windows.ULONG,
828 OldAccessProtection: *std.os.windows.ULONG,
829) std.os.windows.NTSTATUS;
830
823fn ReadProcessMemory(handle: std.os.windows.HANDLE, base_addr: usize, buffer: []u8) ![]u8 {831fn ReadProcessMemory(handle: std.os.windows.HANDLE, base_addr: usize, buffer: []u8) ![]u8 {
824 var nread: usize = 0;832 var nread: usize = 0;
825 switch (NtReadVirtualMemory(833 switch (NtReadVirtualMemory(
...@@ -848,13 +856,21 @@ fn WriteProcessMemory(handle: std.os.windows.HANDLE, base_addr: usize, buffer: [...@@ -848,13 +856,21 @@ fn WriteProcessMemory(handle: std.os.windows.HANDLE, base_addr: usize, buffer: [
848 }856 }
849}857}
850858
851extern "kernel32" fn VirtualProtectEx(859fn VirtualProtectEx(handle: std.os.windows.HANDLE, base_addr: usize, size: usize, new_prot: u32) !u32 {
852 hProcess: std.os.windows.HANDLE,860 var out_paddr = @intToPtr(*anyopaque, base_addr);
853 lpAddress: std.os.windows.LPVOID,861 var out_size = size;
854 dwSize: std.os.windows.SIZE_T,862 var old_prot: u32 = undefined;
855 flNewProtect: std.os.windows.DWORD,863 switch (NtProtectVirtualMemory(
856 lpflOldProtect: *std.os.windows.DWORD,864 handle,
857) std.os.windows.BOOL;865 &out_paddr,
866 &out_size,
867 new_prot,
868 &old_prot,
869 )) {
870 .SUCCESS => return old_prot,
871 else => |rc| return std.os.windows.unexpectedStatus(rc),
872 }
873}
858874
859const PROCESS_BASIC_INFORMATION = extern struct {875const PROCESS_BASIC_INFORMATION = extern struct {
860 ExitStatus: std.os.windows.NTSTATUS,876 ExitStatus: std.os.windows.NTSTATUS,
...@@ -895,22 +911,12 @@ fn debugMem(allocator: Allocator, handle: std.ChildProcess.Id, vaddr: u64, code:...@@ -895,22 +911,12 @@ fn debugMem(allocator: Allocator, handle: std.ChildProcess.Id, vaddr: u64, code:
895}911}
896912
897fn writeMemProtected(handle: std.ChildProcess.Id, vaddr: u64, code: []const u8) !void {913fn writeMemProtected(handle: std.ChildProcess.Id, vaddr: u64, code: []const u8) !void {
898 const pvaddr = @intToPtr(*anyopaque, vaddr);914 const old_prot = try VirtualProtectEx(handle, vaddr, code.len, std.os.windows.PAGE_EXECUTE_WRITECOPY);
899 var new_prot: std.os.windows.DWORD = std.os.windows.PAGE_EXECUTE_WRITECOPY;
900 var old_prot: std.os.windows.DWORD = undefined;
901 if (VirtualProtectEx(handle, pvaddr, code.len, new_prot, &old_prot) == 0) {
902 const err = std.os.windows.kernel32.GetLastError();
903 log.warn("making page(s) writeable failed with error: {s}({x})", .{ @tagName(err), @enumToInt(err) });
904 return;
905 }
906 const amt = try WriteProcessMemory(handle, vaddr, code);915 const amt = try WriteProcessMemory(handle, vaddr, code);
907 if (amt != code.len) return error.InputOutput;916 if (amt != code.len) return error.InputOutput;
908 // TODO: We can probably just set the pages writeable and leave it at that without having to restore the attributes.917 // TODO: We can probably just set the pages writeable and leave it at that without having to restore the attributes.
909 // For that though, we want to track which page has already been modified.918 // For that though, we want to track which page has already been modified.
910 if (VirtualProtectEx(handle, pvaddr, code.len, old_prot, &new_prot) == 0) {919 _ = try VirtualProtectEx(handle, vaddr, code.len, old_prot);
911 const err = std.os.windows.kernel32.GetLastError();
912 log.warn("restoring page(s) attributes failed with error: {s}({x})", .{ @tagName(err), @enumToInt(err) });
913 }
914}920}
915921
916fn writePtrWidthAtom(self: *Coff, atom_index: Atom.Index) !void {922fn writePtrWidthAtom(self: *Coff, atom_index: Atom.Index) !void {