public void LoadModulesInRange(long VA, long length, string OnlyModule = null) { var KVS = new VirtualScanner(this, new Mem(MemAccess)); foreach (var artifact in KVS.Run(VA, VA + length)) { var ms = new MemSection() { IsExec = true, Module = artifact, VA = new VIRTUAL_ADDRESS(artifact.VA) }; var extracted = ExtractCVDebug(ms); if (extracted == null) { 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(ConsoleColor.Green, $"symbol loaded [{sym != null}] from file [{ms.DebugDetails.PDBFullPath}]"); } } }
public dynamic xStructInfo(string Struct, long Address, int minLen = 4096, string Module = "ntkrnlmp") { MemSection pdb = null; if (Module == "ntkrnlmp" && KernelSection != null) { pdb = KernelSection; } else { var pdbPaths = from files in Sections.Values where files.DebugDetails != null && !string.IsNullOrWhiteSpace(files.DebugDetails.PDBFullPath) && files.DebugDetails.PDBFullPath.ToLower().Contains(Module.ToLower()) select files; pdb = pdbPaths.FirstOrDefault(); KernelSection = pdb; } long[] memRead = null; if (Address != 0) { memRead = GetVirtualLongLen(Address, minLen); } var rv = sym.xStructInfo(pdb.DebugDetails.PDBFullPath, Struct, memRead, GetVirtualByte, GetVirtualLong); rv.SelfAddr = Address; return(rv); }
public dynamic xStructInfo(string Struct, long[] memRead = null, string Module = "ntkrnlmp") { MemSection pdb = null; if (Module == "ntkrnlmp" && KernelSection != null) { pdb = KernelSection; } else { var pdbPaths = from files in Sections.Values where files.DebugDetails != null && !string.IsNullOrWhiteSpace(files.DebugDetails.PDBFullPath) && files.DebugDetails.PDBFullPath.ToLower().Contains(Module.ToLower()) select files; pdb = pdbPaths.FirstOrDefault(); KernelSection = pdb; } if (sym == null) { sym = Vtero.TryLoadSymbols(ID.GetHashCode(), pdb.DebugDetails, pdb.VA.Address); } return(sym.xStructInfo(pdb.DebugDetails.PDBFullPath, Struct, memRead, GetVirtualByte, GetVirtualLong)); }
/// <summary> /// This guy names the section and establishes the codeview data needed for symbol handling /// </summary> /// <param name="sec"></param> /// <returns></returns> public CODEVIEW_HEADER ExtractCVDebug(MemSection sec) { uint SizeData = 0, RawData = 0, PointerToRawData = 0; Extract Ext = sec.Module; long VA = sec.VA.Address; var _va = VA + Ext.DebugDirPos; var block = VGetBlock(_va); var TimeDate2 = BitConverter.ToUInt32(block, ((int)Ext.DebugDirPos & 0xfff) + 4); if (TimeDate2 != Ext.TimeStamp & Vtero.VerboseOutput) { WriteColor(ConsoleColor.Yellow, "Unable to lock on to CV data."); return(null); } var max_offset = (int)(_va & 0xfff) + 28; if (max_offset > 0x1000) { return(null); } SizeData = BitConverter.ToUInt32(block, (int)(_va & 0xfff) + 16); RawData = BitConverter.ToUInt32(block, (int)(_va & 0xfff) + 20); PointerToRawData = BitConverter.ToUInt32(block, (int)(_va & 0xfff) + 24); _va = VA + RawData; var bytes = new byte[16]; block = VGetBlock(_va); // first 4 bytes var sig = block[((int)_va & 0xfff)]; Array.ConstrainedCopy(block, (((int)_va & 0xfff) + 4), bytes, 0, 16); var gid = new Guid(bytes); // after GUID var age = block[((int)_va & 0xfff) + 20]; // char* at end var str = Encoding.Default.GetString(block, (((int)_va & 0xfff) + 24), 32).Trim(); var cv = new CODEVIEW_HEADER { VSize = (int)Ext.SizeOfImage, TimeDateStamp = TimeDate2, byteGuid = bytes, Age = age, aGuid = gid, Sig = sig, PdbName = str }; sec.Name = str.Substring(0, str.IndexOf('.')).ToLower(); sec.DebugDetails = cv; return(cv); }
/// <summary> /// This guy names the section and establishes the codeview data needed for symbol handling /// </summary> /// <param name="sec"></param> /// <returns></returns> public CODEVIEW_HEADER ExtractCVDebug(MemSection sec) { uint SizeData = 0, RawData = 0, PointerToRawData = 0; Extract Ext = sec.Module; long VA = sec.VA.Address; var _va = VA + Ext.DebugDirPos; var block = GetVirtualByte(_va); var TimeDate2 = BitConverter.ToUInt32(block, 4); if (TimeDate2 != Ext.TimeStamp & Vtero.VerboseOutput) { WriteColor(ConsoleColor.Yellow, "Unable to lock on to CV data."); return(null); } SizeData = BitConverter.ToUInt32(block, 16); RawData = BitConverter.ToUInt32(block, 20); PointerToRawData = BitConverter.ToUInt32(block, 24); // Advance to the debug section where we may find the code view info _va = VA + RawData; var b2 = GetVirtualByte(_va); var bytes2 = new byte[16]; var s2 = b2[0]; Array.ConstrainedCopy(b2, 4, bytes2, 0, 16); var gid2 = new Guid(bytes2); // after GUID var age2 = b2[20]; // char* at end var str2 = Encoding.Default.GetString(b2, 24, 32).Trim(); var cv2 = new CODEVIEW_HEADER { VSize = (int)Ext.SizeOfImage, TimeDateStamp = TimeDate2, byteGuid = bytes2, Age = age2, aGuid = gid2, Sig = s2, PdbName = str2 }; if (str2.Contains(".") && str2.Contains(".pdb")) { sec.Name = str2.Substring(0, str2.IndexOf(".pdb") + 4).ToLower(); } else { sec.Name = str2.ToLower(); } sec.DebugDetails = cv2; return(cv2); }
public void LoadSymbols(MemSection OnlyMS = null) { foreach (var ms in Sections) { if (OnlyMS == null || (OnlyMS != null && OnlyMS.VA.Address == ms.Key)) { sym = Vtero.TryLoadSymbols(ID.GetHashCode(), ms.Value.DebugDetails, ms.Value.VA.Address); if (Vtero.VerboseOutput) { WriteColor(ConsoleColor.Green, $"symbol loaded [{sym != null}] from file [{ms.Value.DebugDetails.PDBFullPath}]"); } } } }
/// <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); }
// TODO: MOVE below to DetectedProc class public CODEVIEW_HEADER ExtractCVDebug(DetectedProc dp, MemSection sec) { uint SizeData=0, RawData=0, PointerToRawData=0; Extract Ext = sec.Module; long VA = sec.VA.Address; if (dp.MemAccess == null) dp.MemAccess = new Mem(MemAccess); var _va = VA + Ext.DebugDirPos; var block = dp.VGetBlock(_va); var TimeDate2 = BitConverter.ToUInt32(block, ((int) Ext.DebugDirPos & 0xfff) + 4); if(TimeDate2 != Ext.TimeStamp & Vtero.VerboseOutput) { WriteColor(ConsoleColor.Yellow, "Unable to lock on to CV data."); return null; } if(Vtero.VerboseOutput) WriteColor(ConsoleColor.Green, $"Locked on to CV Debug info. Time2 = {TimeDate2:X} Time1 = {Ext.TimeStamp:X}"); var max_offset = (int)(_va & 0xfff) + 28; if (max_offset > 0x1000) { if (Vtero.VerboseOutput) WriteColor(ConsoleColor.Yellow, "CV block seems too straddle into next block (too large)"); return null; } SizeData = BitConverter.ToUInt32(block, (int)(_va & 0xfff) + 16); RawData = BitConverter.ToUInt32(block, (int)(_va & 0xfff) + 20); PointerToRawData = BitConverter.ToUInt32(block, (int)(_va & 0xfff) + 24); _va = VA + RawData; var bytes = new byte[16]; block = dp.VGetBlock(_va); // first 4 bytes var sig = block[((int)_va & 0xfff)]; Array.ConstrainedCopy(block, (((int) _va & 0xfff) + 4), bytes, 0, 16); var gid = new Guid(bytes); // after GUID var age = block[((int)_va & 0xfff) + 20]; // char* at end var str = Encoding.Default.GetString(block, (((int)_va & 0xfff) + 24), 32).Trim(); if (Vtero.VerboseOutput) { WriteLine($"Size = {SizeData} \t Raw = {RawData} \t Pointer {PointerToRawData}"); WriteLine($"Str {str} : GUID : {gid} : AGE {age}"); } var cv = new CODEVIEW_HEADER { VSize = (int) Ext.SizeOfImage, TimeDateStamp = TimeDate2, byteGuid = bytes, Age = age, aGuid = gid, Sig = sig, PdbName = str }; sec.DebugDetails = cv; return cv; }