| ... | ... | @@ -820,6 +820,14 @@ extern "ntdll" fn NtWriteVirtualMemory( |
| 820 | 820 | NumberOfBytesWritten: ?*std.os.windows.SIZE_T, |
| 821 | 821 | ) std.os.windows.NTSTATUS; |
| 822 | 822 | |
| 823 | extern "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 | |
| 823 | 831 | fn ReadProcessMemory(handle: std.os.windows.HANDLE, base_addr: usize, buffer: []u8) ![]u8 { |
| 824 | 832 | var nread: usize = 0; |
| 825 | 833 | switch (NtReadVirtualMemory( |
| ... | ... | @@ -848,13 +856,21 @@ fn WriteProcessMemory(handle: std.os.windows.HANDLE, base_addr: usize, buffer: [ |
| 848 | 856 | } |
| 849 | 857 | } |
| 850 | 858 | |
| 851 | | extern "kernel32" fn VirtualProtectEx( |
| 852 | | hProcess: std.os.windows.HANDLE, |
| 853 | | lpAddress: std.os.windows.LPVOID, |
| 854 | | dwSize: std.os.windows.SIZE_T, |
| 855 | | flNewProtect: std.os.windows.DWORD, |
| 856 | | lpflOldProtect: *std.os.windows.DWORD, |
| 857 | | ) std.os.windows.BOOL; |
| 859 | fn VirtualProtectEx(handle: std.os.windows.HANDLE, base_addr: usize, size: usize, new_prot: u32) !u32 { |
| 860 | var out_paddr = @intToPtr(*anyopaque, base_addr); |
| 861 | var out_size = size; |
| 862 | var old_prot: u32 = undefined; |
| 863 | switch (NtProtectVirtualMemory( |
| 864 | handle, |
| 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 | } |
| 858 | 874 | |
| 859 | 875 | const PROCESS_BASIC_INFORMATION = extern struct { |
| 860 | 876 | ExitStatus: std.os.windows.NTSTATUS, |
| ... | ... | @@ -895,22 +911,12 @@ fn debugMem(allocator: Allocator, handle: std.ChildProcess.Id, vaddr: u64, code: |
| 895 | 911 | } |
| 896 | 912 | |
| 897 | 913 | fn writeMemProtected(handle: std.ChildProcess.Id, vaddr: u64, code: []const u8) !void { |
| 898 | | const pvaddr = @intToPtr(*anyopaque, vaddr); |
| 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 | | } |
| 914 | const old_prot = try VirtualProtectEx(handle, vaddr, code.len, std.os.windows.PAGE_EXECUTE_WRITECOPY); |
| 906 | 915 | const amt = try WriteProcessMemory(handle, vaddr, code); |
| 907 | 916 | if (amt != code.len) return error.InputOutput; |
| 908 | 917 | // TODO: We can probably just set the pages writeable and leave it at that without having to restore the attributes. |
| 909 | 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) { |
| 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 | | } |
| 919 | _ = try VirtualProtectEx(handle, vaddr, code.len, old_prot); |
| 914 | 920 | } |
| 915 | 921 | |
| 916 | 922 | fn writePtrWidthAtom(self: *Coff, atom_index: Atom.Index) !void { |