예제 #1
0
        public static void Free(byte *p)
        {
            var remaining         = (int)((long)p % 4096);
            var firstWritablePage = p - remaining;

            for (int i = 0; i < remaining; i++)
            {
                if (firstWritablePage[i] != 0xED)
                {
                    throw new InvalidOperationException("Invalid memory usage, you killed Ed!");
                }
            }
            Win32MemoryProtectMethods.MemoryProtection protect;
            var address = firstWritablePage - 4096;

            // this will access the memory, which will error if this was already freed
            if (Win32MemoryProtectMethods.VirtualProtect(address, (UIntPtr)4096, Win32MemoryProtectMethods.MemoryProtection.READWRITE, out protect) ==
                false)
            {
                throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to VirtualProtect (ElectricFence) at address=" + new IntPtr(address));
            }
            var dwSize = *(int *)address;

            // decommit, not release, they are not available for reuse again, any
            // future access will throw
            if (Win32MemoryProtectMethods.VirtualFree(address, (UIntPtr)dwSize, Win32MemoryProtectMethods.FreeType.MEM_DECOMMIT) == false)
            {
                throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to VirtualFree (ElectricFence) at address=" + new IntPtr(address));
            }
        }
예제 #2
0
        private static string GetEncodedFilename(IntPtr processHandle, ref Win32MemoryProtectMethods.MEMORY_BASIC_INFORMATION memoryBasicInformation)
        {
            var memData   = BuffersPool.Allocate(2048);
            var pFilename = memData.Address;

            try
            {
                int stringLength;
                stringLength = Win32MemoryProtectMethods.GetMappedFileName(processHandle, memoryBasicInformation.BaseAddress.ToPointer(), pFilename, 2048);

                if (stringLength == 0)
                {
                    return(null);
                }

                var foundRelevantFilename = false;
                foreach (var item in RelevantFilesPostFixes)
                {
                    fixed(byte *pItem = item)
                    {
                        if (stringLength < item.Length ||
                            Memory.Compare(pItem, pFilename + stringLength - item.Length, item.Length) != 0)
                        {
                            continue;
                        }
                        foundRelevantFilename = true;
                        break;
                    }
                }
                if (foundRelevantFilename == false)
                {
                    return(null);
                }
                return(Encodings.Utf8.GetString(pFilename, stringLength));
            }
            finally
            {
                BuffersPool.Return(memData);
            }
        }
예제 #3
0
        public static byte *Allocate(int size)
        {
            var remaining   = size % 4096;
            var sizeInPages = (size / 4096) + (remaining == 0 ? 0 : 1);

            var allocatedSize = ((sizeInPages + 2) * 4096);
            var virtualAlloc  = Win32MemoryProtectMethods.VirtualAlloc(null, (UIntPtr)allocatedSize, Win32MemoryProtectMethods.AllocationType.COMMIT,
                                                                       Win32MemoryProtectMethods.MemoryProtection.READWRITE);

            if (virtualAlloc == null)
            {
                throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to VirtualAlloc (ElectricFence) size=" + size);
            }

            *(int *)virtualAlloc = allocatedSize;

            Win32MemoryProtectMethods.MemoryProtection protect;
            if (Win32MemoryProtectMethods.VirtualProtect(virtualAlloc, (UIntPtr)(4096), Win32MemoryProtectMethods.MemoryProtection.NOACCESS,
                                                         out protect) == false)
            {
                throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to VirtualProtect (ElectricFence) at address=" + new IntPtr(virtualAlloc));
            }

            if (Win32MemoryProtectMethods.VirtualProtect(virtualAlloc + (sizeInPages + 1) * 4096, (UIntPtr)(4096), Win32MemoryProtectMethods.MemoryProtection.NOACCESS,
                                                         out protect) == false)
            {
                throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to VirtualProtect (ElectricFence) at address=" + new IntPtr(virtualAlloc + (sizeInPages + 1) * 4096));
            }

            var firstWritablePage = virtualAlloc + 4096;

            Memory.Set(firstWritablePage, 0xED, 4096 * sizeInPages); // don't assume zero'ed mem
            if (remaining == 0)
            {
                return(firstWritablePage);
            }
            // give the memory out so its end would be at the 2nd guard page
            return(firstWritablePage + (4096 - remaining));
        }
예제 #4
0
        public static (long ProcessClean, DynamicJsonArray Json) GetMaps()
        {
            long processClean = 0;

            const uint uintMaxVal = uint.MaxValue;
            var        dja        = new DynamicJsonArray();

            GetSystemInfo(out var systemInfo);

            var procMinAddress = systemInfo.minimumApplicationAddress;
            var procMaxAddress = systemInfo.maximumApplicationAddress;
            var processHandle  = GetCurrentProcess();
            var results        = new Dictionary <string, (long Size, long Clean, long Dirty)>();

            while (procMinAddress.ToInt64() < procMaxAddress.ToInt64())
            {
                Win32MemoryProtectMethods.MEMORY_BASIC_INFORMATION memoryBasicInformation;
                Win32MemoryProtectMethods.VirtualQueryEx(processHandle, (byte *)procMinAddress.ToPointer(),
                                                         &memoryBasicInformation, new UIntPtr((uint)sizeof(Win32MemoryProtectMethods.MEMORY_BASIC_INFORMATION)));

                // if this memory chunk is accessible
                if (memoryBasicInformation.Protect == (uint)MemoryProtectionConstants.PAGE_READWRITE &&
                    memoryBasicInformation.State == (uint)MemoryStateConstants.MEM_COMMIT &&
                    memoryBasicInformation.Type == (uint)MemoryTypeConstants.MEM_MAPPED)
                {
                    var encodedString = GetEncodedFilename(processHandle, ref memoryBasicInformation);
                    if (encodedString != null)
                    {
                        var regionSize = memoryBasicInformation.RegionSize.ToInt64();
                        for (long size = uintMaxVal; size < regionSize + uintMaxVal; size += uintMaxVal)
                        {
                            var partLength = size > regionSize ? regionSize % uintMaxVal : uintMaxVal;

                            var totalDirty = AddressWillCauseHardPageFault((byte *)memoryBasicInformation.BaseAddress.ToPointer(), (uint)partLength,
                                                                           performCount: true);
                            var totalClean = partLength - totalDirty;

                            if (results.TryGetValue(encodedString, out var values))
                            {
                                var prevValClean = values.Item1 + totalClean;
                                var prevValDirty = values.Item2 + totalDirty;
                                var prevValSize  = values.Item3 + partLength;
                                results[encodedString] = (prevValSize, prevValClean, prevValDirty);
                            }
                            else
                            {
                                results[encodedString] = (partLength, totalClean, totalDirty);
                            }

                            processClean += totalClean;
                        }
                    }
                }

                // move to the next memory chunk
                procMinAddress = new IntPtr(procMinAddress.ToInt64() + memoryBasicInformation.RegionSize.ToInt64());
            }

            foreach (var result in results)
            {
                var djv = new DynamicJsonValue
                {
                    ["File"]              = result.Key,
                    ["Size"]              = result.Value.Size,
                    ["SizeHumanly"]       = Sizes.Humane(result.Value.Size),
                    ["Rss"]               = "N/A",
                    ["SharedClean"]       = "N/A",
                    ["SharedDirty"]       = "N/A",
                    ["PrivateClean"]      = "N/A",
                    ["PrivateDirty"]      = "N/A",
                    ["TotalClean"]        = result.Value.Clean,
                    ["TotalCleanHumanly"] = Sizes.Humane(result.Value.Clean),
                    ["TotalDirty"]        = result.Value.Dirty,
                    ["TotalDirtyHumanly"] = Sizes.Humane(result.Value.Dirty)
                };

                dja.Add(djv);
            }

            return(processClean, dja);
        }