/// <summary> /// Currently we scan hard for only kernel regions (2MB pages + ExEC) /// If there are kernel modules named the OnlyModule it may cause us to ignore the real one in that case /// you can still scan for * by passing null or empty string /// </summary> /// <param name="OnlyModule">Stop when the first module named this is found</param> public VirtualScanner ScanAndLoadModules(string OnlyModule = "ntkrnlmp.pdb", bool OnlyLarge = true, bool IncludeKernelSpace = true, bool OnlyValid = true, bool IncludeData = false, bool DoExtraHeaderScan = true) { const int LARGE_PAGE_SIZE = 1024 * 1024 * 2; var curr = 0; PageTable.AddProcess(this, new Mem(MemAccess)); //var cnt = PT.FillPageQueue(OnlyLarge, IncludeKernelSpace); var KVS = new VirtualScanner(this, new Mem(MemAccess), DoExtraHeaderScan); // single threaded worked best so far //Parallel.For(0, cnt, (i, loopState) => x foreach (var range in PT.FillPageQueue(OnlyLarge, IncludeKernelSpace, OnlyValid, IncludeData)) //for (int i = 0; i < cnt; i++) { curr++; bool stop = false; if (Vtero.VerboseLevel > 1) { //var curr = cnt - PT.PageQueue.Count; //var done = Convert.ToDouble(curr) / Convert.ToDouble(cnt) * 100.0; Console.CursorLeft = 0; Console.Write($"{curr} scanned"); } if (range.PTE.Valid && !range.PTE.NoExecute) { foreach (var artifact in KVS.Run(range.VA.Address, range.VA.Address + (range.PTE.LargePage ? LARGE_PAGE_SIZE : MagicNumbers.PAGE_SIZE), range)) { var ms = new MemSection() { IsExec = true, Module = artifact, VA = new VIRTUAL_ADDRESS(artifact.VA), Source = range }; var extracted = ExtractCVDebug(ms); if (extracted == null) { if (Vtero.VerboseLevel > 1) { WriteColor(ConsoleColor.Yellow, $"failed debug info for PE @address {range.VA.Address:X}, extracted headers: {artifact}"); } continue; } if (!string.IsNullOrWhiteSpace(OnlyModule) && OnlyModule != ms.Name) { continue; } if (!Sections.ContainsKey(artifact.VA)) { Sections.TryAdd(artifact.VA, ms); } // we can clobber this guy all the time I guess since everything is stateless in Sym and managed // entirely by the handle ID really which is local to our GUID so.... sym = Vtero.TryLoadSymbols(ID.GetHashCode(), ms.DebugDetails, ms.VA.Address); if (Vtero.VerboseOutput) { WriteColor((sym != null) ? ConsoleColor.Green : ConsoleColor.Yellow, $" symbol loaded = [{sym != null}] PDB [{ms.DebugDetails.PDBFullPath}] @ {range.VA.Address:X}, {ms.Name}"); if (Vtero.VerboseLevel > 1) { WriteColor((sym != null) ? ConsoleColor.Green : ConsoleColor.Yellow, $"headers: { artifact} "); } } if (!string.IsNullOrWhiteSpace(OnlyModule)) { if (!string.IsNullOrWhiteSpace(ms.Name) && ms.Name == OnlyModule) { stop = true; //loopState.Stop(); break; } } //if (loopState.IsStopped) //return; if (stop) { break; } } } //if (loopState.IsStopped) // return;e //}); if (stop) { break; } } return(KVS); }
/// <summary> /// Currently we scan hard for only kernel regions (2MB pages + ExEC) /// If there are kernel modules named the OnlyModule it may cause us to ignore the real one in that case /// you can still scan for * by passing null or empty string /// </summary> /// <param name="OnlyModule">Stop when the first module named this is found</param> public VirtualScanner ScanAndLoadModules(string OnlyModule = "ntkrnlmp") { PageTable.AddProcess(this, new Mem(MemAccess)); var cnt = PT.FillPageQueue(true); var KVS = new VirtualScanner(this, new Mem(MemAccess)); KVS.ScanMode = VAScanType.PE_FAST; Parallel.For(0, cnt, (i, loopState) => { PFN range; var curr = cnt - PT.PageQueue.Count; var done = (int)(Convert.ToDouble(curr) / Convert.ToDouble(cnt) * 100.0) + 0.5; if (PT.PageQueue.TryDequeue(out range) && range.PTE.Valid) { var found = KVS.Run(range.VA.Address, range.VA.Address + (range.PTE.LargePage ? (1024 * 1024 * 2) : 0x1000), loopState); // Attempt load foreach (var artifact in found) { var ms = new MemSection() { IsExec = true, Module = artifact.Value, VA = new VIRTUAL_ADDRESS(artifact.Key) }; var extracted = ExtractCVDebug(ms); if (extracted == null) { continue; } if (!string.IsNullOrWhiteSpace(OnlyModule) && OnlyModule != ms.Name) { continue; } if (!Sections.ContainsKey(artifact.Key)) { Sections.TryAdd(artifact.Key, ms); } // we can clobber this guy all the time I guess since everything is stateless in Sym and managed // entirely by the handle ID really which is local to our GUID so.... sym = Vtero.TryLoadSymbols(ID.GetHashCode(), ms.DebugDetails, ms.VA.Address); if (Vtero.VerboseOutput) { WriteColor(ConsoleColor.Green, $"symbol loaded [{sym != null}] from file [{ms.DebugDetails.PDBFullPath}]"); } if (!string.IsNullOrWhiteSpace(OnlyModule)) { if (!string.IsNullOrWhiteSpace(ms.Name) && ms.Name == OnlyModule) { loopState.Stop(); return; } } if (loopState.IsStopped) { return; } } } if (loopState.IsStopped) { return; } }); return(KVS); }