Example #1
0
        /// <summary>
        /// Validate if mapped image is legitimate
        /// </summary>
        /// <param name="targetProcess">Target process</param>
        /// <param name="data">VirtualQuery data</param>
        /// <returns></returns>
        private static PE_SECTION_INFO ValidateImage(Process targetProcess, NT.MEMORY_BASIC_INFORMATION data)
        {
            if (!g_linkedModules.Exists(module => module.ModuleHandle == data.AllocationBase))
            {
                return(PE_SECTION_INFO.UnlinkedModule);
            }

            byte[] sectionData = targetProcess.ReadMemory(data.AllocationBase, data.RegionSize);

            if (!ValidateHeaders(sectionData))
            {
                return(PE_SECTION_INFO.InvalidHeader);
            }

            // I TESTED THIS ON EVERY RUNNING PROCESS ON MY SYSTEM AND
            // NOT A SINGLE PROCESS HAD AN IMAGE LOADED THAT WERE HAD DIFFERENT
            // ALLOCATION FLAGS, MIGHT CAUSE FALSE POSITIVES SO BE AWARE
            bool validAllocationFlags = data.AllocationProtect == NT.MemoryProtection.ExecuteWriteCopy || data.AllocationProtect == NT.MemoryProtection.ReadOnly;

            if (data.Type != NT.PAGE_TYPE.MEM_IMAGE || !validAllocationFlags)
            {
                return(PE_SECTION_INFO.InvalidSectionType);
            }

            return(PE_SECTION_INFO.Valid);
        }
Example #2
0
        public static void ScanForAnomalies(Process targetProcess, SCAN_MODE mode)
        {
            Log.LogGeneral($"Scanning {targetProcess.ProcessName}/{targetProcess.Id}");

            var scanList = new List <NT.MEMORY_BASIC_INFORMATION>();

            foreach (ProcessThread thread in targetProcess.Threads)
            {
                var startAddress = thread.GetRealStartAddress();
                var query        = targetProcess.VirtualQuery(startAddress);

                if (query.AllocationBase > 0 && !scanList.Exists(x => x.AllocationBase == query.AllocationBase))
                {
                    scanList.Add(query);
                }

                // GET THREAD INSTRUCTION POINTERS
                // TO PREVENT BYPASSING BY UNMAPPING
                // ALLOCATION BASE AFTER JUMPING TO
                // SOMEWHERE ELSE
                var instructionPointer = thread.GetInstructionPointer(targetProcess.IsWow64());
                var threadQuery        = targetProcess.VirtualQuery(instructionPointer);

                if (threadQuery.AllocationBase > 0 && !scanList.Exists(x => x.AllocationBase == threadQuery.AllocationBase))
                {
                    scanList.Add(threadQuery);
                }
            }

            // GET ALL MODULES VIA EnumProcessModulesEx
            g_linkedModules = targetProcess.GetModules();

            Log.LogInfo($"Finished iterating threads - Scanning {scanList.Count} address(es)", 1);
            scanList.ForEach(scanData =>
            {
                var result = ValidateImage(targetProcess, scanData);

                if (result != PE_SECTION_INFO.Valid)
                {
                    Log.LogWarning($"{scanData.AllocationBase.ToString("x2")} -> {result}", true, 2);
                }
            });

            // DO A DEEPER SCAN BY WALKING THE VIRTUAL ADDRESSES, LOOKING FOR
            // INDEPENDENT EXECUTABLE VIRTUAL PAGES

            Log.LogInfo($"Iterating virtual pages", 1);
            if (mode == SCAN_MODE.DEEP)
            {
                var query = new NT.MEMORY_BASIC_INFORMATION();

                do
                {
                    query = targetProcess.VirtualQuery(query.BaseAddress + query.RegionSize);

                    if (query.State == NT.PAGE_STATE.MEM_FREE)
                    {
                        continue;
                    }

                    if (query.Protect != NT.MemoryProtection.ExecuteReadWrite &&
                        query.Protect != NT.MemoryProtection.ExecuteWriteCopy)
                    {
                        continue;
                    }

                    // TEST IF ADDRESS IS WITHIN ANY LINKED MODULE
                    if (!g_linkedModules.Any(module => IsAddressInsideModule(module, query.BaseAddress)))
                    {
                        Log.LogWarning($"{query.BaseAddress.ToString("x2")} - {query.RegionSize / 1000}kb", query.Type == NT.PAGE_TYPE.MEM_IMAGE, 2);

                        if (query.RegionSize > 400000) // 40kb
                        {
                            var buffer  = targetProcess.ReadMemory(query.BaseAddress, query.RegionSize);
                            var pattern = FindPattern(buffer, "73 6E 78 68 6B 36 34 2E 64 6C 6C");
                        }

                        //if (query.Type == NT.PAGE_TYPE.MEM_IMAGE)
                        //{
                        //    var buffer = targetProcess.ReadMemory(query.BaseAddress, query.RegionSize);
                        //    File.WriteAllBytes(query.BaseAddress.ToString("x2"), buffer);
                        //}
                    }
                } while (query.RegionSize > 0);
            }

            bool IsAddressInsideModule(NT.ModuleInfo module, ulong address) =>
            module.ModuleHandle <= address && (module.ModuleHandle + module.ModuleSize) > address;
        }