internal PageInfo(MEMORY_BASIC_INFORMATION mbi) { _address = mbi.BaseAddress; _size = mbi.RegionSize; _protectionFlags = (MemoryProtectionFlags)mbi.Protect; _typeFlags = (MemoryTypeFlags)mbi.Type; }
public void VirtualProtectEx() { IntPtr handle = ProcessMemory.OpenProcess(ProcessAccessFlags.All, _processId); Assert.IsFalse(handle == IntPtr.Zero); IntPtr address = ProcessMemory.VirtualAllocEx(handle, IntPtr.Zero, (IntPtr)1024, AllocationType.Reserve | AllocationType.Commit, MemoryProtectionFlags.ExecuteReadWrite); MemoryProtectionFlags oldProtection = default; Assert.IsTrue(ProcessMemory.VirtualProtectEx(handle, address, (IntPtr)1024, MemoryProtectionFlags.NoAccess, ref oldProtection)); Assert.IsTrue(oldProtection == MemoryProtectionFlags.ExecuteReadWrite); try { Marshal.WriteInt32(address, 1337); throw new Exception(); } catch { } Assert.IsTrue(ProcessMemory.VirtualFreeEx(handle, address, IntPtr.Zero, FreeType.Release)); ProcessMemory.CloseHandle(handle); }
/// <summary> /// Initializes a new instance of the <see cref="RemoteAllocation" /> class. /// </summary> /// <param name="memorySharp">The reference of the <see cref="MemorySharp" /> object.</param> /// <param name="size">The size of the allocated memory.</param> /// <param name="protection">The protection of the allocated memory.</param> /// <param name="mustBeDisposed">The allocated memory will be released when the finalizer collects the object.</param> internal RemoteAllocation(MemorySharp memorySharp, int size, MemoryProtectionFlags protection = MemoryProtectionFlags.ExecuteReadWrite, bool mustBeDisposed = true) : base(memorySharp, MemoryCore.Allocate(memorySharp.Handle, size, protection)) { // Set local vars MustBeDisposed = mustBeDisposed; IsDisposed = false; }
/// <summary> /// Changes the protection on a region of committed pages in the virtual address space of a specified process. /// </summary> /// <param name="processHandle">A handle to the process whose memory protection is to be changed.</param> /// <param name="address"> /// A pointer to the base address of the region of pages whose access protection attributes are to be /// changed. /// </param> /// <param name="size">The size of the region whose access protection attributes are changed, in bytes.</param> /// <param name="protection">The memory protection option.</param> /// <returns>The old protection of the region in a structure.</returns> public MemoryProtectionFlags ChangeMemoryProtection(MemoryProtectionFlags protection) { // Create the variable storing the old protection of the memory page MemoryProtectionFlags oldProtection; bool result; // Change the protection in the target process if (Internal) { result = NativeMethods.VirtualProtect(BaseAddress, Size, protection, out oldProtection); } else { result = NativeMethods.VirtualProtectEx(Handle, BaseAddress, Size, protection, out oldProtection); } if (result) { // Return the old protection return(oldProtection); } // Else the protection couldn't be changed, throws an exception throw new Win32Exception( string.Format("Couldn't change the protection of the memory at 0x{0} of {1} byte(s) to {2}.", BaseAddress.ToString("X"), Size, protection)); }
public RemoteAllocation Allocate(int size, MemoryProtectionFlags protection, bool mustBeDisposed = true) { var memory = new RemoteAllocation(m_Process, size, protection, mustBeDisposed); m_RemoteAllocations.Add(memory); return(memory); }
/// <summary> /// Reserves a region of memory within the virtual address space of a specified process. /// </summary> /// <param name="processHandle">The handle to a process.</param> /// <param name="allocAddress">The rough address of where the allocation should take place.</param> /// <param name="size">The size of the region of memory to allocate, in bytes.</param> /// <param name="protectionFlags">The memory protection for the region of pages to be allocated.</param> /// <param name="allocationFlags">The type of memory allocation.</param> /// <returns>The base address of the allocated region</returns> public static IntPtr Allocate( IntPtr processHandle, IntPtr allocAddress, Int32 size, MemoryProtectionFlags protectionFlags = MemoryProtectionFlags.ExecuteReadWrite, MemoryAllocationFlags allocationFlags = MemoryAllocationFlags.Commit | MemoryAllocationFlags.Reserve) { if (allocAddress != IntPtr.Zero) { /* A specific address has been given. We will modify it to support the following constraints: * - Aligned by 0x10000 / 65536 * - Pointing to an unallocated region of memory * - Within +/- 2GB (using 1GB for safety) of address space of the originally specified address, such as to always be in range of a far jump instruction * Note: A retry count has been put in place because VirtualAllocEx with an allocAddress specified may be invalid by the time we request the allocation. */ IntPtr result = IntPtr.Zero; Int32 retryCount = 0; // Request all chunks of unallocated memory. These will be very large in a 64-bit process. IEnumerable <MemoryBasicInformation64> freeMemory = Memory.QueryUnallocatedMemory( processHandle, allocAddress.Subtract(Int32.MaxValue >> 1, wrapAround: false), allocAddress.Add(Int32.MaxValue >> 1, wrapAround: false)); // Convert to normalized regions IEnumerable <NormalizedRegion> regions = freeMemory.Select(x => new NormalizedRegion(x.BaseAddress, x.RegionSize.ToInt32())); // Chunk the large regions into smaller regions based on the allocation size (minimum size is the alloc alignment to prevent creating too many chunks) List <NormalizedRegion> subRegions = new List <NormalizedRegion>(); foreach (NormalizedRegion region in regions) { region.BaseAddress = region.BaseAddress.Subtract(region.BaseAddress.Mod(Memory.AllocAlignment), wrapAround: false); IEnumerable <NormalizedRegion> chunkedRegions = region.ChunkNormalizedRegion(Math.Max(size, Memory.AllocAlignment)).Take(128).Where(x => x.RegionSize >= size); subRegions.AddRange(chunkedRegions); } do { // Sample a random chunk and attempt to allocate the memory result = subRegions.ElementAt(StaticRandom.Next(0, subRegions.Count())).BaseAddress; result = NativeMethods.VirtualAllocEx(processHandle, result, size, allocationFlags, protectionFlags); if (result != IntPtr.Zero || retryCount >= Memory.AllocateRetryCount) { break; } retryCount++; }while (result == IntPtr.Zero); return(result); } else { // Allocate a memory page return(NativeMethods.VirtualAllocEx(processHandle, allocAddress, size, allocationFlags, protectionFlags)); } }
/// <summary> /// Initializes a new instance of the <see cref="RemoteAllocation"/> class. /// </summary> /// <param name="memorySharp">The reference of the <see cref="MemorySharp"/> object.</param> /// <param name="size">The size of the allocated memory.</param> /// <param name="protection">The protection of the allocated memory.</param> /// <param name="mustBeDisposed">The allocated memory will be released when the finalizer collects the object.</param> internal RemoteAllocation(MemorySharp memorySharp, int size, MemoryProtectionFlags protection = MemoryProtectionFlags.ExecuteReadWrite, bool mustBeDisposed = true) : base(memorySharp, MemoryCore.Allocate(memorySharp.Handle, size, protection)) { // Set local vars MustBeDisposed = mustBeDisposed; IsDisposed = false; }
public AAlloc() { Name = ""; Address = UIntPtr.Zero; Size = 0; Preferred = UIntPtr.Zero; Protection = MemoryProtectionFlags.ExecuteReadWrite; }
public AAlloc(String name, UIntPtr address, UInt32 size, UIntPtr preferred, MemoryProtectionFlags protection) { Name = name; Address = address; Size = size; Preferred = preferred; Protection = protection; }
/// <summary> /// Allocates a region of memory within the virtual address space of the remote process. /// </summary> /// <param name="size">The size of the memory to allocate.</param> /// <param name="protection">The protection of the memory to allocate.</param> /// <param name="mustBeDisposed">The allocated memory will be released when the finalizer collects the object.</param> /// <returns>A new instance of the <see cref="RemoteAllocation"/> class.</returns> public RemoteAllocation Allocate(int size, MemoryProtectionFlags protection = MemoryProtectionFlags.ExecuteReadWrite, bool mustBeDisposed = true) { // Allocate a memory space var memory = new RemoteAllocation(MemorySharp, size, protection, mustBeDisposed); // Add the memory in the list InternalRemoteAllocations.Add(memory); return memory; }
public MemoryProtection(SafeMemoryHandle handle, IntPtr address, int size, bool @internal = true, MemoryProtectionFlags protection = MemoryProtectionFlags.ExecuteReadWrite) { BaseAddress = address; NewProtection = protection; Size = size; Internal = @internal; Handle = handle; OldProtection = ChangeMemoryProtection(protection); }
public MemoryProtection(SafeMemoryHandle handle, IntPtr address, int size,bool @internal = true, MemoryProtectionFlags protection = MemoryProtectionFlags.ExecuteReadWrite) { BaseAddress = address; NewProtection = protection; Size = size; Internal = @internal; Handle = handle; OldProtection = ChangeMemoryProtection(protection); }
/// <summary> /// Allocates a region of memory within the virtual address space of the remote process. /// </summary> /// <param name="name"></param> /// <param name="size">The size of the memory to allocate.</param> /// <param name="protection">The protection of the memory to allocate.</param> /// <param name="mustBeDisposed">The allocated memory will be released when the finalizer collects the object.</param> public IAAllocatedMemory Allocate(string name, int size, MemoryProtectionFlags protection = MemoryProtectionFlags.ExecuteReadWrite, bool mustBeDisposed = true) { // Allocate a memory space var memory = new AAllocatedMemory(Process, name, size, protection, mustBeDisposed); // Add the memory in the list InternalRemoteAllocations.Add(memory); return(memory); }
/// <summary>Changes the protection of the n next bytes in remote process.</summary> /// <param name="handle"></param> /// <param name="size">The size of the memory to change.</param> /// <param name="protection">The new protection to apply.</param> /// <param name="mustBeDisposed"> /// The resource will be automatically disposed when the finalizer /// collects the object. /// </param> /// <returns>A new instance of the <see cref="MemoryProtection" /> class.</returns> public MemoryProtection ChangeProtection(SafeMemoryHandle handle, int size, MemoryProtectionFlags protection = MemoryProtectionFlags.ExecuteReadWrite, bool mustBeDisposed = true) { return(new MemoryProtection(handle, BaseAddress, size, protection, mustBeDisposed)); }
public static IntPtr Allocate(SafeMemoryHandle handle, int size, MemoryProtectionFlags protectionFlags = MemoryProtectionFlags.ExecuteReadWrite, MemoryAllocationFlags allocationFlags = MemoryAllocationFlags.Commit) { var address = IntPtr.Zero; var regionSize = new IntPtr(size); if (NativeMethods.NtAllocateVirtualMemory(handle, ref address, 0x7FFF_FFFF, ref regionSize, allocationFlags, protectionFlags) == 0) { return(address); } return(NativeMethods.VirtualAllocEx(handle, IntPtr.Zero, size, allocationFlags, protectionFlags)); }
/// <summary> /// Initializes a new instance of the <see cref="AAllocatedMemory" /> class. /// </summary> /// <param name="processPlus">The reference of the <see cref="AProcessSharp" /> object.</param> /// <param name="name"></param> /// <param name="size">The size of the allocated memory.</param> /// <param name="protection">The protection of the allocated memory.</param> /// <param name="mustBeDisposed">The allocated memory will be released when the finalizer collects the object.</param> public AAllocatedMemory(AProcessSharp processPlus, string name, int size, MemoryProtectionFlags protection = MemoryProtectionFlags.ExecuteReadWrite, bool mustBeDisposed = true) : base(processPlus, AMemoryHelper.Allocate(processPlus.Handle, size, protection)) { // Set local vars Identifier = name; MustBeDisposed = mustBeDisposed; IsDisposed = false; Size = size; }
public void CacheMemoryRegions() { memoryRegions.Clear(); InitMemoryRegions(); MemoryProtectionFlags MemFlagsExecutable = MemoryProtectionFlags.PAGE_EXECUTE | MemoryProtectionFlags.PAGE_EXECUTE_READ | MemoryProtectionFlags.PAGE_EXECUTE_READWRITE | MemoryProtectionFlags.PAGE_EXECUTE_WRITECOPY; MemoryProtectionFlags MemFlagsWriteable = MemoryProtectionFlags.PAGE_EXECUTE_READWRITE | MemoryProtectionFlags.PAGE_EXECUTE_WRITECOPY | MemoryProtectionFlags.PAGE_READWRITE | MemoryProtectionFlags.PAGE_WRITECOPY; int regionInfoSize = Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION)); for (long scanAddress = 0; scanAddress < Int64.MaxValue;) { MEMORY_BASIC_INFORMATION regionInfo; int result = VirtualQueryEx(cachedProcessHandle, (IntPtr)scanAddress, out regionInfo, (uint)regionInfoSize); if (result != regionInfoSize) { break; } bool bIsCommited = (regionInfo.State & MemoryStateFlags.MEM_COMMIT) != 0; bool bIsGuarded = (regionInfo.Protect & MemoryProtectionFlags.PAGE_GUARD) != 0; bool bIsWritebale = (regionInfo.Protect & MemFlagsWriteable) != 0; bool bIsExecutable = (regionInfo.Protect & MemFlagsExecutable) != 0; bool bShouldCacheRegion = bIsCommited && !bIsGuarded && (bIsWritebale || bIsExecutable); Logger.WriteLine("scan:0x{0}, size:0x{1}, state:[{2}], protect:[{3}], type:0x{4} => {5}", scanAddress.ToString("x"), regionInfo.RegionSize.ToString("x"), regionInfo.State, regionInfo.Protect, regionInfo.Type.ToString("x"), bShouldCacheRegion ? "CACHE" : "meh"); if (bShouldCacheRegion) { MemoryRegionFlags storeType = (bIsWritebale ? MemoryRegionFlags.Writeable : 0) | (bIsExecutable ? MemoryRegionFlags.Executable : 0); MemoryRegionInfo storeInfo = new MemoryRegionInfo { BaseAddress = regionInfo.BaseAddress, Size = regionInfo.RegionSize, Type = storeType, }; memoryRegions.Add(storeInfo); } scanAddress = (long)regionInfo.BaseAddress + (long)regionInfo.RegionSize; } }
/// <summary> /// Initializes a new instance of the <see cref="MemoryProtection" /> class. /// </summary> /// <param name="memorySharp">The reference of the <see cref="MemorySharp" /> object.</param> /// <param name="baseAddress">The base address of the memory to change the protection.</param> /// <param name="size">The size of the memory to change.</param> /// <param name="protection">The new protection to apply.</param> /// <param name="mustBeDisposed">The resource will be automatically disposed when the finalizer collects the object.</param> public MemoryProtection(MemorySharp memorySharp, IntPtr baseAddress, int size, MemoryProtectionFlags protection = MemoryProtectionFlags.ExecuteReadWrite, bool mustBeDisposed = true) { // Save the parameters _memorySharp = memorySharp; BaseAddress = baseAddress; NewProtection = protection; Size = size; MustBeDisposed = mustBeDisposed; // Change the memory protection OldProtection = MemoryCore.ChangeProtection(_memorySharp.Handle, baseAddress, size, protection); }
/// <summary> /// Gets regions of memory allocated in the remote process based on provided parameters /// </summary> /// <param name="requiredProtection">Protection flags required to be present</param> /// <param name="excludedProtection">Protection flags that must not be present</param> /// <param name="allowedTypes">Memory types that can be present</param> /// <param name="startAddress">The start address of the query range</param> /// <param name="endAddress">The end address of the query range</param> /// <returns>A collection of pointers to virtual pages in the target process</returns> public IEnumerable <NormalizedRegion> GetVirtualPages( MemoryProtectionEnum requiredProtection, MemoryProtectionEnum excludedProtection, MemoryTypeEnum allowedTypes, IntPtr startAddress, IntPtr endAddress) { MemoryProtectionFlags requiredFlags = 0; MemoryProtectionFlags excludedFlags = 0; if ((requiredProtection & MemoryProtectionEnum.Write) != 0) { requiredFlags |= MemoryProtectionFlags.ExecuteReadWrite; requiredFlags |= MemoryProtectionFlags.ReadWrite; } if ((requiredProtection & MemoryProtectionEnum.Execute) != 0) { requiredFlags |= MemoryProtectionFlags.Execute; requiredFlags |= MemoryProtectionFlags.ExecuteRead; requiredFlags |= MemoryProtectionFlags.ExecuteReadWrite; requiredFlags |= MemoryProtectionFlags.ExecuteWriteCopy; } if ((requiredProtection & MemoryProtectionEnum.CopyOnWrite) != 0) { requiredFlags |= MemoryProtectionFlags.WriteCopy; requiredFlags |= MemoryProtectionFlags.ExecuteWriteCopy; } if ((excludedProtection & MemoryProtectionEnum.Write) != 0) { excludedFlags |= MemoryProtectionFlags.ExecuteReadWrite; excludedFlags |= MemoryProtectionFlags.ReadWrite; } if ((excludedProtection & MemoryProtectionEnum.Execute) != 0) { excludedFlags |= MemoryProtectionFlags.Execute; excludedFlags |= MemoryProtectionFlags.ExecuteRead; excludedFlags |= MemoryProtectionFlags.ExecuteReadWrite; excludedFlags |= MemoryProtectionFlags.ExecuteWriteCopy; } if ((excludedProtection & MemoryProtectionEnum.CopyOnWrite) != 0) { excludedFlags |= MemoryProtectionFlags.WriteCopy; excludedFlags |= MemoryProtectionFlags.ExecuteWriteCopy; } return(Memory.VirtualPages(this.SystemProcess == null ? IntPtr.Zero : this.SystemProcess.Handle, startAddress, endAddress, requiredFlags, excludedFlags, allowedTypes) .Select(x => new NormalizedRegion(x.BaseAddress, x.RegionSize.ToUInt64()))); }
internal MemoryProtection(RemoteProcess process, IntPtr baseAddress, long size, MemoryProtectionFlags newProtect = MemoryProtectionFlags.ExecuteReadWrite, bool mustBeDisposed = true) { m_Process = process; MustBeDisposed = mustBeDisposed; BaseAddress = baseAddress; Size = size; NewProtection = newProtect; if (!NativeMethods.VirtualProtectEx(m_Process.Handle, baseAddress, size, newProtect, out var oldProtect)) { throw new Win32Exception(); } OldProtection = oldProtect; }
/// <summary> /// Initializes a new instance of the <see cref="MemoryProtection"/> class. /// </summary> /// <param name="memorySharp">The reference of the <see cref="MemorySharp"/> object.</param> /// <param name="baseAddress">The base address of the memory to change the protection.</param> /// <param name="size">The size of the memory to change.</param> /// <param name="protection">The new protection to apply.</param> /// <param name="mustBeDisposed">The resource will be automatically disposed when the finalizer collects the object.</param> public MemoryProtection(MemorySharp memorySharp, IntPtr baseAddress, int size, MemoryProtectionFlags protection = MemoryProtectionFlags.ExecuteReadWrite, bool mustBeDisposed = true) { // Save the parameters _memorySharp = memorySharp; BaseAddress = baseAddress; NewProtection = protection; Size = size; MustBeDisposed = mustBeDisposed; // Change the memory protection OldProtection = MemoryCore.ChangeProtection(_memorySharp.Handle, baseAddress, size, protection); }
public static uint NtAllocateVirtualMemory( IntPtr handle, IntPtr size, AllocationType allocationType, MemoryProtectionFlags memoryProtection, out IntPtr address) { IL.DeclareLocals( new LocalVar("result", typeof(uint)), new LocalVar("localAddress", typeof(IntPtr))); address = default; Ldloca("localAddress"); Initobj(typeof(IntPtr)); Ldarg(nameof(handle)); Ldloca("localAddress"); Conv_U(); Ldc_I4_0(); Conv_I(); Ldarga(nameof(size)); Conv_U(); Ldarg(nameof(allocationType)); Ldarg(nameof(memoryProtection)); Ldsfld(new FieldRef(typeof(NtDll), nameof(_ntAllocateVirtualMemory))); Calli(new StandAloneMethodSig( CallingConvention.StdCall, typeof(uint), typeof(IntPtr), typeof(IntPtr).MakePointerType(), typeof(IntPtr), typeof(IntPtr).MakePointerType(), typeof(AllocationType), typeof(MemoryProtectionFlags))); Stloc("result"); Ldarg(nameof(address)); Ldloc("localAddress"); Stind_I(); Ldloc("result"); return(IL.Return <uint>()); }
/// <summary> /// Initializes a new instance of the <see cref="MemoryProtection" /> class. /// </summary> /// <param name="handle">The reference of the <see cref="SafeMemoryHandle" /> object.</param> /// <param name="baseAddress">The base address of the memory to change the protection.</param> /// <param name="size">The size of the memory to change.</param> /// <param name="protection">The new protection to apply.</param> /// <param name="mustBeDisposed">The resource will be automatically disposed when the finalizer collects the object.</param> public MemoryProtection(SafeMemoryHandle handle, IntPtr baseAddress, int size, MemoryProtectionFlags protection = MemoryProtectionFlags.ExecuteReadWrite, bool mustBeDisposed = true) { // Save the parameters Handle = handle; BaseAddress = baseAddress; NewProtection = protection; Size = size; MustBeDisposed = mustBeDisposed; // Change the memory protection OldProtection = MemoryHelper.ChangeProtection(Handle, baseAddress, size, protection); }
/// <summary> /// Reserves a region of memory within the virtual address space of a specified process. /// </summary> /// <param name="processHandle">The handle to a process.</param> /// <param name="size">The size of the region of memory to allocate, in bytes.</param> /// <param name="protectionFlags">The memory protection for the region of pages to be allocated.</param> /// <param name="allocationFlags">The type of memory allocation.</param> /// <returns>The base address of the allocated region.</returns> public static IntPtr Allocate(SafeMemoryHandle processHandle, int size, MemoryProtectionFlags protectionFlags = MemoryProtectionFlags.ExecuteReadWrite, MemoryAllocationFlags allocationFlags = MemoryAllocationFlags.Commit) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(processHandle, "processHandle"); // Allocate a memory page var ret = NativeMethods.VirtualAllocEx(processHandle, IntPtr.Zero, size, allocationFlags, protectionFlags); // Check whether the memory page is valid if (ret != IntPtr.Zero) return ret; // If the pointer isn't valid, throws an exception throw new Win32Exception(string.Format("Couldn't allocate memory of {0} byte(s).", size)); }
/// <summary> /// Reserves a region of memory within the virtual address space of a specified process. /// </summary> /// <param name="processHandle">The handle to a process.</param> /// <param name="size">The size of the region of memory to allocate, in bytes.</param> /// <param name="protectionFlags">The memory protection for the region of pages to be allocated.</param> /// <param name="allocationFlags">The type of memory allocation.</param> /// <returns>The base address of the allocated region.</returns> public static IntPtr Allocate(SafeMemoryHandle processHandle, int size, MemoryProtectionFlags protectionFlags = MemoryProtectionFlags.ExecuteReadWrite, MemoryAllocationFlags allocationFlags = MemoryAllocationFlags.Commit) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(processHandle, "processHandle"); // Allocate a memory page var ret = NativeMethods.VirtualAllocEx(processHandle, IntPtr.Zero, size, allocationFlags, protectionFlags); // Check whether the memory page is valid if (ret != IntPtr.Zero) { return(ret); } // If the pointer isn't valid, throws an exception throw new Win32Exception(string.Format("Couldn't allocate memory of {0} byte(s).", size)); }
/// <summary> /// Changes the protection on a region of committed pages in the virtual address space of a specified process. /// </summary> /// <param name="processHandle">A handle to the process whose memory protection is to be changed.</param> /// <param name="address"> /// A pointer to the base address of the region of pages whose access protection attributes are to be /// changed. /// </param> /// <param name="size">The size of the region whose access protection attributes are changed, in bytes.</param> /// <param name="protection">The memory protection option.</param> /// <returns>The old protection of the region in a <see cref="Native.MemoryBasicInformation" /> structure.</returns> public static MemoryProtectionFlags ChangeProtection(SafeMemoryHandle processHandle, IntPtr address, int size, MemoryProtectionFlags protection) { // Check if the handles are valid HandleManipulator.ValidateAsArgument(processHandle, "processHandle"); HandleManipulator.ValidateAsArgument(address, "address"); // Create the variable storing the old protection of the memory page MemoryProtectionFlags oldProtection; // Change the protection in the target process if (NativeMethods.VirtualProtectEx(processHandle, address, size, protection, out oldProtection)) { // Return the old protection return oldProtection; } // Else the protection couldn't be changed, throws an exception throw new Win32Exception(string.Format("Couldn't change the protection of the memory at 0x{0} of {1} byte(s) to {2}.", address.ToString("X"), size, protection)); }
/// <summary> /// Changes the protection on a region of committed pages in the virtual address space of a specified process. /// </summary> /// <param name="processHandle">A handle to the process whose memory protection is to be changed.</param> /// <param name="address"> /// A pointer to the base address of the region of pages whose access protection attributes are to be /// changed. /// </param> /// <param name="size">The size of the region whose access protection attributes are changed, in bytes.</param> /// <param name="protection">The memory protection option.</param> /// <returns>The old protection of the region in a <see cref="MemoryBasicInformation" /> structure.</returns> public static MemoryProtectionFlags ChangeProtection(SafeMemoryHandle processHandle, IntPtr address, int size, MemoryProtectionFlags protection) { // Check if the handles are valid HandleManipulator.ValidateAsArgument(processHandle, "processHandle"); HandleManipulator.ValidateAsArgument(address, "address"); // Create the variable storing the old protection of the memory page MemoryProtectionFlags oldProtection; // Change the protection in the target process if (Kernel32.VirtualProtectEx(processHandle, address, size, protection, out oldProtection)) { // Return the old protection return(oldProtection); } // Else the protection couldn't be changed, throws an exception throw new Win32Exception( $"Couldn't change the protection of the memory at 0x{address.ToString("X")} of {size} byte(s) to {protection}."); }
/// <summary> /// </summary> /// <param name="processHandle"> /// </param> /// <param name="address"> /// </param> /// <param name="size"> /// </param> /// <param name="protection"> /// </param> /// <returns> /// </returns> /// <exception cref="Win32Exception"> /// </exception> public static MemoryProtectionFlags ChangeProtection( SafeMemoryHandle processHandle, IntPtr address, int size, MemoryProtectionFlags protection) { // Create the variable storing the old protection of the memory page MemoryProtectionFlags oldProtection; // Change the protection in the target process if (VirtualProtectEx(processHandle, address, size, protection, out oldProtection)) { // Return the old protection return(oldProtection); } // Else the protection couldn't be changed, throws an exception throw new Win32Exception( string.Format( "Couldn't change the protection of the memory at 0x{0} of {1} byte(s) to {2}.", address.ToString("X"), size, protection)); }
/// <summary> /// Allocates a region of memory within the virtual address space of the remote process. /// </summary> /// <param name="size">The size of the memory to allocate.</param> /// <param name="protection">The protection of the memory to allocate.</param> /// <param name="mustBeDisposed">The allocated memory will be released when the finalizer collects the object.</param> /// <returns>A new instance of the <see cref="RemoteAllocation" /> class.</returns> public RemoteAllocation Allocate(int size, MemoryProtectionFlags protection = MemoryProtectionFlags.ExecuteReadWrite, bool mustBeDisposed = true) { // Allocate a memory space var memory = new RemoteAllocation(MemorySharp, size, protection, mustBeDisposed); // Add the memory in the list InternalRemoteAllocations.Add(memory); return memory; }
public static extern IntPtr VirtualAllocEx(SafeMemoryHandle hProcess, IntPtr lpAddress, int dwSize, MemoryAllocationFlags flAllocationType, MemoryProtectionFlags flProtect);
public static extern bool VirtualProtect(IntPtr lpAddress, int dwSize, MemoryProtectionFlags flNewProtect, out MemoryProtectionFlags lpflOldProtect);
/// <summary> /// Changes the protection on a region of committed pages in the virtual address space of a specified process. /// </summary> /// <param name="processHandle">A handle to the process whose memory protection is to be changed.</param> /// <param name="address"> /// A pointer to the base address of the region of pages whose access protection attributes are to be /// changed. /// </param> /// <param name="size">The size of the region whose access protection attributes are changed, in bytes.</param> /// <param name="protection">The memory protection option.</param> /// <returns>The old protection of the region in a structure.</returns> public MemoryProtectionFlags ChangeMemoryProtection(MemoryProtectionFlags protection) { // Create the variable storing the old protection of the memory page MemoryProtectionFlags oldProtection; bool result; // Change the protection in the target process if (Internal) result = NativeMethods.VirtualProtect(BaseAddress, Size, protection, out oldProtection); else result = NativeMethods.VirtualProtectEx(Handle, BaseAddress, Size, protection, out oldProtection); if (result) { // Return the old protection return oldProtection; } // Else the protection couldn't be changed, throws an exception throw new Win32Exception( string.Format("Couldn't change the protection of the memory at 0x{0} of {1} byte(s) to {2}.", BaseAddress.ToString("X"), Size, protection)); }
/// <summary> /// Changes the protection of the n next bytes in remote process. /// </summary> /// <param name="protection">The new protection to apply.</param> /// <param name="mustBeDisposed">The resource will be automatically disposed when the finalizer collects the object.</param> /// <returns>A new instance of the <see cref="MemoryProtection"/> class.</returns> public MemoryProtection ChangeProtection(MemoryProtectionFlags protection = MemoryProtectionFlags.ExecuteReadWrite, bool mustBeDisposed = true) { return(new MemoryProtection(MemorySharp, BaseAddress, Information.RegionSize, protection, mustBeDisposed)); }
/// <summary> /// Retrieves information about a range of pages within the virtual address space of a specified process. /// </summary> /// <param name="processHandle">A handle to the process whose memory information is queried.</param> /// <param name="startAddress">A pointer to the starting address of the region of pages to be queried.</param> /// <param name="endAddress">A pointer to the ending address of the region of pages to be queried.</param> /// <param name="requiredProtection">Protection flags required to be present.</param> /// <param name="excludedProtection">Protection flags that must not be present.</param> /// <param name="allowedTypes">Memory types that can be present.</param> /// <returns> /// A collection of <see cref="MemoryBasicInformation64"/> structures containing info about all virtual pages in the target process. /// </returns> public static IEnumerable <MemoryBasicInformation64> VirtualPages( IntPtr processHandle, IntPtr startAddress, IntPtr endAddress, MemoryProtectionFlags requiredProtection, MemoryProtectionFlags excludedProtection, MemoryTypeEnum allowedTypes) { if (startAddress.ToUInt64() >= endAddress.ToUInt64()) { yield return(new MemoryBasicInformation64()); } Boolean wrappedAround = false; Int32 queryResult; // Enumerate the memory pages do { // Allocate the structure to store information of memory MemoryBasicInformation64 memoryInfo = new MemoryBasicInformation64(); if (!Environment.Is64BitProcess) { // 32 Bit struct is not the same MemoryBasicInformation32 memoryInfo32 = new MemoryBasicInformation32(); // Query the memory region (32 bit native method) queryResult = NativeMethods.VirtualQueryEx(processHandle, startAddress, out memoryInfo32, Marshal.SizeOf(memoryInfo32)); // Copy from the 32 bit struct to the 64 bit struct memoryInfo.AllocationBase = memoryInfo32.AllocationBase; memoryInfo.AllocationProtect = memoryInfo32.AllocationProtect; memoryInfo.BaseAddress = memoryInfo32.BaseAddress; memoryInfo.Protect = memoryInfo32.Protect; memoryInfo.RegionSize = memoryInfo32.RegionSize; memoryInfo.State = memoryInfo32.State; memoryInfo.Type = memoryInfo32.Type; } else { // Query the memory region (64 bit native method) queryResult = NativeMethods.VirtualQueryEx(processHandle, startAddress, out memoryInfo, Marshal.SizeOf(memoryInfo)); } // Increment the starting address with the size of the page IntPtr previousFrom = startAddress; startAddress = startAddress.Add(memoryInfo.RegionSize); if (previousFrom.ToUInt64() > startAddress.ToUInt64()) { wrappedAround = true; } // Ignore free memory. These are unallocated memory regions. if ((memoryInfo.State & MemoryStateFlags.Free) != 0) { continue; } // At least one readable memory flag is required if ((memoryInfo.Protect & MemoryProtectionFlags.ReadOnly) == 0 && (memoryInfo.Protect & MemoryProtectionFlags.ExecuteRead) == 0 && (memoryInfo.Protect & MemoryProtectionFlags.ExecuteReadWrite) == 0 && (memoryInfo.Protect & MemoryProtectionFlags.ReadWrite) == 0) { continue; } // Do not bother with this shit, this memory is not worth scanning if ((memoryInfo.Protect & MemoryProtectionFlags.ZeroAccess) != 0 || (memoryInfo.Protect & MemoryProtectionFlags.NoAccess) != 0 || (memoryInfo.Protect & MemoryProtectionFlags.Guard) != 0) { continue; } // Enforce allowed types switch (memoryInfo.Type) { case MemoryTypeFlags.None: if ((allowedTypes & MemoryTypeEnum.None) == 0) { continue; } break; case MemoryTypeFlags.Private: if ((allowedTypes & MemoryTypeEnum.Private) == 0) { continue; } break; case MemoryTypeFlags.Image: if ((allowedTypes & MemoryTypeEnum.Image) == 0) { continue; } break; case MemoryTypeFlags.Mapped: if ((allowedTypes & MemoryTypeEnum.Mapped) == 0) { continue; } break; } // Ensure at least one required protection flag is set if (requiredProtection != 0 && (memoryInfo.Protect & requiredProtection) == 0) { continue; } // Ensure no ignored protection flags are set if (excludedProtection != 0 && (memoryInfo.Protect & excludedProtection) != 0) { continue; } // Return the memory page yield return(memoryInfo); }while (startAddress.ToUInt64() < endAddress.ToUInt64() && queryResult != 0 && !wrappedAround); }
public static extern bool VirtualProtectEx(SafeMemoryHandle hProcess, IntPtr lpAddress, int dwSize, MemoryProtectionFlags flNewProtect, out MemoryProtectionFlags lpflOldProtect);
/// <summary> /// Gets regions of memory allocated in the remote process based on provided parameters. /// </summary> /// <param name="requiredProtection">Protection flags required to be present.</param> /// <param name="excludedProtection">Protection flags that must not be present.</param> /// <param name="allowedTypes">Memory types that can be present.</param> /// <param name="startAddress">The start address of the query range.</param> /// <param name="endAddress">The end address of the query range.</param> /// <returns>A collection of pointers to virtual pages in the target process.</returns> public IEnumerable <NormalizedRegion> GetVirtualPages( Process process, MemoryProtectionEnum requiredProtection, MemoryProtectionEnum excludedProtection, MemoryTypeEnum allowedTypes, UInt64 startAddress, UInt64 endAddress) { MemoryProtectionFlags requiredFlags = 0; MemoryProtectionFlags excludedFlags = 0; if ((requiredProtection & MemoryProtectionEnum.Write) != 0) { requiredFlags |= MemoryProtectionFlags.ExecuteReadWrite; requiredFlags |= MemoryProtectionFlags.ReadWrite; } if ((requiredProtection & MemoryProtectionEnum.Execute) != 0) { requiredFlags |= MemoryProtectionFlags.Execute; requiredFlags |= MemoryProtectionFlags.ExecuteRead; requiredFlags |= MemoryProtectionFlags.ExecuteReadWrite; requiredFlags |= MemoryProtectionFlags.ExecuteWriteCopy; } if ((requiredProtection & MemoryProtectionEnum.CopyOnWrite) != 0) { requiredFlags |= MemoryProtectionFlags.WriteCopy; requiredFlags |= MemoryProtectionFlags.ExecuteWriteCopy; } if ((excludedProtection & MemoryProtectionEnum.Write) != 0) { excludedFlags |= MemoryProtectionFlags.ExecuteReadWrite; excludedFlags |= MemoryProtectionFlags.ReadWrite; } if ((excludedProtection & MemoryProtectionEnum.Execute) != 0) { excludedFlags |= MemoryProtectionFlags.Execute; excludedFlags |= MemoryProtectionFlags.ExecuteRead; excludedFlags |= MemoryProtectionFlags.ExecuteReadWrite; excludedFlags |= MemoryProtectionFlags.ExecuteWriteCopy; } if ((excludedProtection & MemoryProtectionEnum.CopyOnWrite) != 0) { excludedFlags |= MemoryProtectionFlags.WriteCopy; excludedFlags |= MemoryProtectionFlags.ExecuteWriteCopy; } IEnumerable <MemoryBasicInformation64> memoryInfo = WindowsMemoryQuery.VirtualPages(process == null ? IntPtr.Zero : process.Handle, startAddress, endAddress, requiredFlags, excludedFlags, allowedTypes); IList <NormalizedRegion> regions = new List <NormalizedRegion>(); foreach (MemoryBasicInformation64 next in memoryInfo) { if (next.RegionSize < ChunkSize) { regions.Add(new NormalizedRegion(next.BaseAddress.ToUInt64(), next.RegionSize.ToInt32())); } else { // This region requires chunking Int64 remaining = next.RegionSize; UInt64 currentBaseAddress = next.BaseAddress.ToUInt64(); while (remaining >= ChunkSize) { regions.Add(new NormalizedRegion(currentBaseAddress, ChunkSize)); remaining -= ChunkSize; currentBaseAddress = currentBaseAddress.Add(ChunkSize, wrapAround: false); } if (remaining > 0) { regions.Add(new NormalizedRegion(currentBaseAddress, remaining.ToInt32())); } } } return(regions); }
/// <summary> /// Changes the protection on a region of committed pages in the virtual address space of a specified process. /// </summary> /// <param name="processHandle">A handle to the process whose memory protection is to be changed.</param> /// <param name="address">A pointer to the base address of the region of pages whose access protection attributes are to be changed.</param> /// <param name="size">The size of the region whose access protection attributes are changed, in bytes.</param> /// <param name="protection">The memory protection option.</param> /// <returns>The old protection of the region in a <see cref="MemoryBasicInformation32"/> structure.</returns> public static MemoryProtectionFlags ChangeProtection(IntPtr processHandle, IntPtr address, Int32 size, MemoryProtectionFlags protection) { // Create the variable storing the old protection of the memory page MemoryProtectionFlags oldProtection; // Change the protection in the target process NativeMethods.VirtualProtectEx(processHandle, address, size, protection, out oldProtection); return(oldProtection); }
internal RemoteAllocation(RemoteProcess process, int size, MemoryProtectionFlags protect, bool mustBeDisposed) : base(process, MemoryManager.Allocate(process.Handle, size, protect)) { MustBeDisposed = mustBeDisposed; }