public dynamic[] WalkProcList(DetectedProc dp) { bool GotData = false; // TODO: Build out symbol system / auto registration into DLR for DIA2 // expected kernel hardcoded var pdbFile = (from kern in dp.Sections where kern.DebugDetails != null && !string.IsNullOrWhiteSpace(kern.DebugDetails.PDBFullPath) && kern.DebugDetails.PDBFullPath.ToLower().Contains("ntkrnlmp") select kern.DebugDetails.PDBFullPath).FirstOrDefault(); if (string.IsNullOrWhiteSpace(pdbFile)) return null; // this is for DIA API SDK... // TODO: Perf analysis of switching over to xStruct... however it's expando objects // are a lot slower than using the dictionary SymForKernel = Sym.Initalize(pdbFile); long[] memRead = null; var PsHeadAddr = GetSymValueLong(dp, "PsActiveProcessHead"); // TODO: update this to be used instead of legacy .Dictionary kludge ;) //var rv = SymForKernel.xStructInfo(pdbFile, "_EPROCESS"); // figure out OFFSET_OF the process LIST_ENTRY // MemberInfo returned is Byte Position, Length var aplinks = SymForKernel.StructMemberInfo(pdbFile, "_EPROCESS", "ActiveProcessLinks.Flink"); var offset_of = aplinks.Item1; var sym_dtb = SymForKernel.StructMemberInfo(pdbFile, "_EPROCESS", "Pcb.DirectoryTableBase"); var sym_ImagePathPtr = SymForKernel.StructMemberInfo(pdbFile, "_EPROCESS", "SeAuditProcessCreationInfo.ImageFileName"); var sym_procID = SymForKernel.StructMemberInfo(pdbFile, "_EPROCESS", "UniqueProcessId"); var sym_vadRoot = SymForKernel.StructMemberInfo(pdbFile, "_EPROCESS", "VadRoot"); // adjust the first link through //var flink = dp.GetLongValue(PsHeadAddr); var typeDefs = from typeDef in SymForKernel.StructInfo where typeDef.Key.StartsWith("_EPROCESS") select typeDef; var flink = PsHeadAddr; do { // walk the offset back to the head of the _EPROCESS // this needs to adjsut since we get the entire block here based to the page not offset memRead = dp.GetVirtualLong((flink - offset_of), ref GotData); if (!GotData) break; // memRead is a long array so we have to divide the length by 8 var EprocCR3 = memRead[sym_dtb.Item1 / 8]; var ProcessID = memRead[sym_procID.Item1 / 8]; var VadRootPtr = memRead[sym_vadRoot.Item1 / 8]; // ImagePath here is a pointer to a struct, get ptr // +0x10 in this unicode string object var ImagePathPtr = memRead[sym_ImagePathPtr.Item1 / 8]; var ImagePathArr = dp.GetVirtualByte(ImagePathPtr+0x10); var ImagePath = Encoding.Unicode.GetString(ImagePathArr); var pathTrim = ImagePath.Split('\x0'); ImagePath = pathTrim[0]; dynamic lproc = new ExpandoObject(); var dproc = (IDictionary<string, object>)lproc; var staticDict = new Dictionary<string, object>(); lproc.Dictionary = staticDict; foreach (var def in typeDefs) { // custom types are not fitted this way // we just recuse into basic types if (def.Value.Item2 > 8) continue; // TODO: expand on this dynamic object stuff var defName = def.Key.Substring("_EPROCESS".Length + 1); //.Replace('.', '_'); switch (def.Value.Item2) { case 4: var ival = (int)(memRead[def.Value.Item1 / 8] & 0xffffffffff); dproc.Add(defName, ival); staticDict.Add(defName, ival); break; case 2: var sval = (short)(memRead[def.Value.Item1 / 8] & 0xffffff); dproc.Add(defName, sval); staticDict.Add(defName, sval); break; case 1: var bval = (byte)(memRead[def.Value.Item1 / 8] & 0xff); dproc.Add(defName, bval); staticDict.Add(defName, bval); break; default: var lval = memRead[def.Value.Item1 / 8]; dproc.Add(defName, lval); staticDict.Add(defName, lval); break; } } lproc.ImagePath = ImagePath; dp.LogicalProcessList.Add(lproc); // move flink to next list entry flink = memRead[offset_of / 8]; } while (PsHeadAddr != flink); return dp.LogicalProcessList.ToArray(); }
public AModInfo() { LoadedMods = new List <string>(); SymCtx = Sym.Initalize(); uniqD = new Dictionary <ulong, AStepEvent>(); }
/// <summary> /// We use sympath environment variable /// </summary> /// <param name="cv_data"></param> /// <param name="BaseVA"></param> /// <param name="SymPath"></param> /// <returns></returns> public static bool TryLoadSymbols(long Handle, CODEVIEW_HEADER cv_data, ulong BaseVA, bool Verbose = false) { #if NETSTANDARD2_0 cv_data.PDBFullPath = $"NET_BINDING-{cv_data}"; return(true); #else var symStatus = false; if (string.IsNullOrWhiteSpace(cv_data.PdbName)) { return(symStatus); } var sym = Sym.Initalize(Handle, null, DebugHelp.SymOptions.SYMOPT_UNDNAME); if (!sym && Verbose) { Sym.Errors.Enqueue($"Can not initialize symbols for ${Handle}, error: {new Win32Exception(Marshal.GetLastWin32Error()).Message }"); } StringBuilder sbx = new StringBuilder(1024); StringBuilder sbName = new StringBuilder(cv_data.PdbName.Substring(0, cv_data.PdbName.IndexOf(".pdb") + 4)); uint three = 0; var flags = DebugHelp.SSRVOPT_GUIDPTR; symStatus = DebugHelp.SymFindFileInPathW(Handle, null, sbName, ref cv_data.aGuid, cv_data.Age, three, flags, sbx, IntPtr.Zero, IntPtr.Zero); //// try twice, just in case if (!symStatus) { symStatus = DebugHelp.SymFindFileInPathW(Handle, null, sbName, ref cv_data.aGuid, cv_data.Age, three, flags, sbx, IntPtr.Zero, IntPtr.Zero); } if (!symStatus) { if (Verbose) { Sym.Errors.Enqueue($" Symbol locate returned {symStatus}: {new Win32Exception(Marshal.GetLastWin32Error()).Message }, attempting less precise request."); } flags = DebugHelp.SSRVOPT_DWORDPTR; var refBytes = BitConverter.GetBytes(cv_data.TimeDateStamp); GCHandle pinnedArray = GCHandle.Alloc(refBytes, GCHandleType.Pinned); IntPtr pointer = pinnedArray.AddrOfPinnedObject(); symStatus = DebugHelp.SymFindFileInPathW(Handle, null, sbName, pointer, cv_data.VSize, three, flags, sbx, IntPtr.Zero, IntPtr.Zero); pinnedArray.Free(); if (!symStatus && Verbose) { Sym.Errors.Enqueue($" Find Symbols returned value: {symStatus}:[{sbx.ToString()}]"); } } if (symStatus) { var symLoaded = DebugHelp.SymLoadModuleEx(Handle, IntPtr.Zero, sbx.ToString(), null, BaseVA, cv_data.VSize, IntPtr.Zero, 0); if (symLoaded == 0 && Verbose) { Sym.Errors.Enqueue($"Symbols file located @ {sbx.ToString()} yet load Failed: [{new Win32Exception(Marshal.GetLastWin32Error()).Message }]"); } cv_data.PDBFullPath = sbx.ToString(); } return(symStatus); #endif }