| ... | @@ -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; |
| 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 | fn ReadProcessMemory(handle: std.os.windows.HANDLE, base_addr: usize, buffer: []u8) ![]u8 { | 831 | fn 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 | } |
| 850 | | 858 | |
| 851 | extern "kernel32" fn VirtualProtectEx( | 859 | fn 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 | } |
| 858 | | 874 | |
| 859 | const PROCESS_BASIC_INFORMATION = extern struct { | 875 | const 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 | } |
| 896 | | 912 | |
| 897 | fn writeMemProtected(handle: std.ChildProcess.Id, vaddr: u64, code: []const u8) !void { | 913 | fn 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 | } |
| 915 | | 921 | |
| 916 | fn writePtrWidthAtom(self: *Coff, atom_index: Atom.Index) !void { | 922 | fn writePtrWidthAtom(self: *Coff, atom_index: Atom.Index) !void { |