Пример #1
0
        /// <summary>
        /// Resolves the address of an address, pointer, or managed object.
        /// </summary>
        /// <returns>The base address of this object.</returns>
        protected override UInt64 ResolveAddress()
        {
            UInt64  pointer        = Query.Default.ResolveModule(this.ModuleName);
            Boolean successReading = true;

            pointer = pointer.Add(this.ModuleOffset);

            if (this.PointerOffsets == null || this.PointerOffsets.Count() == 0)
            {
                return(pointer);
            }

            foreach (Int32 offset in this.PointerOffsets)
            {
                if (Processes.Default.IsOpenedProcess32Bit())
                {
                    pointer = Reader.Default.Read <Int32>(pointer, out successReading).ToUInt64();
                }
                else
                {
                    pointer = Reader.Default.Read <UInt64>(pointer, out successReading);
                }

                if (pointer == 0 || !successReading)
                {
                    pointer = 0;
                    break;
                }

                pointer = pointer.Add(offset);
            }

            return(pointer);
        }
Пример #2
0
        public UInt64 EvaluatePointer(UInt64 address, IEnumerable <int> offsets)
        {
            UInt64 finalAddress = address;

            if (!offsets.IsNullOrEmpty())
            {
                // Add and trace offsets
                foreach (Int32 offset in offsets.Take(offsets.Count() - 1))
                {
                    if (Processes.Default.IsOpenedProcess32Bit())
                    {
                        finalAddress = this.Read <UInt32>(finalAddress.Add(offset), out _);
                    }
                    else
                    {
                        finalAddress = this.Read <UInt64>(finalAddress, out _).Add(offset);
                    }
                }

                // The last offset is added, but not traced
                finalAddress = finalAddress.Add(offsets.Last());
            }

            return(finalAddress);
        }
Пример #3
0
        /// <summary>
        /// Resolves the address of an address, pointer, or managed object.
        /// </summary>
        /// <returns>The base address of this object.</returns>
        protected override UInt64 ResolveAddress()
        {
            UInt64 pointer = MemoryQueryer.Instance.ResolveModule(processSession?.OpenedProcess, this.ModuleName);

            pointer = pointer.Add(this.ModuleOffset);

            if (this.PointerOffsets == null || this.PointerOffsets.Count() == 0)
            {
                return(pointer);
            }

            foreach (Int32 offset in this.PointerOffsets)
            {
                bool successReading = false;

                if (processSession?.OpenedProcess?.Is32Bit() ?? false)
                {
                    pointer = MemoryReader.Instance.Read <Int32>(processSession?.OpenedProcess, pointer, out successReading).ToUInt64();
                }
                else
                {
                    pointer = MemoryReader.Instance.Read <UInt64>(processSession?.OpenedProcess, pointer, out successReading);
                }

                if (pointer == 0 || !successReading)
                {
                    return(0);
                }

                pointer = pointer.Add(offset);
            }

            return(pointer);
        }
Пример #4
0
        /// <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 UInt64 Allocate(
            IntPtr processHandle,
            UInt64 allocAddress,
            Int32 size,
            MemoryProtectionFlags protectionFlags = MemoryProtectionFlags.ExecuteReadWrite,
            MemoryAllocationFlags allocationFlags = MemoryAllocationFlags.Commit | MemoryAllocationFlags.Reserve)
        {
            if (allocAddress != 0)
            {
                /* 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.
                 */

                UInt64 result     = 0;
                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.ToUInt64(), 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.ToIntPtr(), size, allocationFlags, protectionFlags).ToUInt64();

                    if (result != 0 || retryCount >= Memory.AllocateRetryCount)
                    {
                        break;
                    }

                    retryCount++;
                }while (result == 0);

                return(result);
            }
            else
            {
                // Allocate a memory page
                return(NativeMethods.VirtualAllocEx(processHandle, allocAddress.ToIntPtr(), size, allocationFlags, protectionFlags).ToUInt64());
            }
        }
Пример #5
0
        /// <summary>
        /// Determines the address that a code cave would need to return to, if one were to be created at the specified address.
        /// </summary>
        /// <param name="address">The address of the code cave.</param>
        /// <returns>The address to which the code cave will return upon completion.</returns>
        public UInt64 GetCaveExitAddress(UInt64 address)
        {
            this.PrintDebugTag();

            Byte[] originalBytes = this.CollectOriginalBytes(address, MemoryCore.JumpSize);
            Int32  originalByteSize;

            if (originalBytes != null && originalBytes.Length < MemoryCore.JumpSize)
            {
                // Determine the size of the minimum number of instructions we will be overwriting
                originalByteSize = originalBytes.Length;
            }
            else
            {
                // Fall back if something goes wrong
                originalByteSize = MemoryCore.JumpSize;
            }

            address = address.Add(originalByteSize);

            return(address);
        }
Пример #6
0
        /// <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);
        }
Пример #7
0
        /// <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>
        private static IEnumerable <MemoryBasicInformation64> VirtualPages(
            IntPtr processHandle,
            UInt64 startAddress,
            UInt64 endAddress,
            MemoryProtectionFlags requiredProtection,
            MemoryProtectionFlags excludedProtection,
            MemoryTypeEnum allowedTypes)
        {
            if (startAddress >= endAddress)
            {
                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.ToIntPtr(), 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.ToIntPtr(), out memoryInfo, Marshal.SizeOf(memoryInfo));
                }

                // Increment the starting address with the size of the page
                UInt64 previousFrom = startAddress;
                startAddress = startAddress.Add(memoryInfo.RegionSize);

                if (previousFrom > startAddress)
                {
                    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 < endAddress && queryResult != 0 && !wrappedAround);
        }
Пример #8
0
        /// <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>
        /// <returns>
        /// A collection of <see cref="MemoryBasicInformation64"/> structures containing info about all virtual pages in the target process.
        /// </returns>
        public static IEnumerable <MemoryBasicInformation64> QueryUnallocatedMemory(
            IntPtr processHandle,
            UInt64 startAddress,
            UInt64 endAddress)
        {
            if (startAddress >= endAddress)
            {
                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.ToIntPtr(), 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.ToIntPtr(), out memoryInfo, Marshal.SizeOf(memoryInfo));
                }

                // Increment the starting address with the size of the page
                UInt64 previousFrom = startAddress;
                startAddress = startAddress.Add(memoryInfo.RegionSize);

                if (previousFrom > startAddress)
                {
                    wrappedAround = true;
                }

                if ((memoryInfo.State & MemoryStateFlags.Free) != 0)
                {
                    // Return the unallocated memory page
                    yield return(memoryInfo);
                }
                else
                {
                    // Ignore actual memory
                    continue;
                }
            }while (startAddress < endAddress && queryResult != 0 && !wrappedAround);
        }