/// <summary> /// Get a defined type from the symbol API (e.g. _EPROCESS) /// After the first call this is all cached staticlly /// /// WARNING!!! This means you need to reload every memory dump you're looking at /// TODO: Make this instance specific per-vtero /// </summary> /// <param name="TypeName"></param> /// <param name="cv"></param> /// <returns></returns> public static dynamic GetType(string TypeName, CODEVIEW_HEADER cv = null) { if (_dyn_cache.TryGetValue(TypeName, out Tuple <String, ExpandoObject> cachedVersion)) { return(cachedVersion.Item2.DeepCopy()); } var json = TypeDef(TypeName, cv); var dyn = JsonConvert.DeserializeObject <List <ExpandoObject> >(json.Result, converter).First(); _dyn_cache.TryAdd(TypeName, Tuple.Create(json.Result, dyn)); return(dyn.DeepCopy()); }
public static CODEVIEW_HEADER Init( string name = null, string pdb = null, string symname = null, string symaddr = null, string typename = null, string baseva = null, string vsize = null, string symrange = null, string age = null, string sig = null, string timestamp = null, string guid = null ) { bool parsed = false; var cv = new CODEVIEW_HEADER(); if (name.Contains("..")) { return(null); } if (pdb.Contains("..")) { return(null); } if (!string.IsNullOrWhiteSpace(pdb) && pdb.Any((x) => char.IsSurrogate(x) || char.IsSymbol(x) || char.IsControl(x) || x == Path.DirectorySeparatorChar || x == Path.AltDirectorySeparatorChar || x == Path.VolumeSeparatorChar || x == Path.PathSeparator)) { return(null); } if (!string.IsNullOrWhiteSpace(name) && name.Any((x) => char.IsSurrogate(x) || char.IsSymbol(x) || char.IsControl(x) || x == Path.DirectorySeparatorChar || x == Path.AltDirectorySeparatorChar || x == Path.VolumeSeparatorChar || x == Path.PathSeparator)) { return(null); } cv.Name = name; cv.PdbName = pdb; cv.Type = typename; cv.SymName = symname; cv.BaseVA = ParseUlong(baseva, ref parsed); cv.SymAddr = ParseUlong(symaddr, ref parsed); cv.VSize = ParseUint(vsize, ref parsed); cv.SymRange = ParseUint(symrange, ref parsed); cv.Age = ParseUint(age, ref parsed); cv.Sig = ParseUint(sig, ref parsed); cv.TimeDateStamp = ParseUint(timestamp, ref parsed); Guid.TryParse(guid, out cv.aGuid); return(cv); }
public static CODEVIEW_HEADER Init( string name = null, string pdb = null, string symaddr = null, string typename = null, string baseva = null, string vsize = null, string age = null, string sig = null, string timestamp = null, string guid = null ) { bool parsed = false; var cv = new CODEVIEW_HEADER(); cv.Name = name; cv.PdbName = pdb; cv.Type = typename; if (!string.IsNullOrWhiteSpace(baseva)) { cv.BaseVA = ParseUlong(baseva, ref parsed); } if (!string.IsNullOrWhiteSpace(symaddr)) { cv.SymAddr = ParseUlong(symaddr, ref parsed); } if (!string.IsNullOrWhiteSpace(vsize)) { cv.VSize = ParseUint(vsize, ref parsed); } if (!string.IsNullOrWhiteSpace(age)) { cv.Age = ParseUint(age, ref parsed); } if (!string.IsNullOrWhiteSpace(sig)) { cv.Sig = ParseUint(sig, ref parsed); } if (!string.IsNullOrWhiteSpace(timestamp)) { cv.TimeDateStamp = ParseUint(timestamp, ref parsed); } if (!string.IsNullOrWhiteSpace(guid)) { cv.aGuid = Guid.Parse(guid); } return(cv); }
public static SYMBOL_INFO SymFromName(string name, CODEVIEW_HEADER cvh) { SYMBOL_INFO rv = new SYMBOL_INFO(); var json = SymAPI.FromName(name, cvh); var names = JsonConvert.DeserializeObject <NameList>(json.Result); if (names == null) { return(rv); } var first = names.Names.First(); rv.Address = first.Address; rv.Size = (uint)first.Length; rv.Name = first.Name; return(rv); }
public async static Task <string> FromAddress(string address, CODEVIEW_HEADER cvh) => await GET($"SymFromName/x?symaddr={address}&guid={cvh.aGuid:N}&age={cvh.Age:X1}&PDB={cvh.PdbName}&baseva={cvh.BaseVA}");
public async static Task <string> TypeDef(string name, CODEVIEW_HEADER cvh) => await GET($"typedef/x?type={name}&guid={cvh.aGuid:N}&age={cvh.Age:X1}&PDB={cvh.PdbName}&baseva={cvh.BaseVA}");
/// <summary> /// Origionally this tended to be a lot faster than dynamically parsing this out of expando's /// </summary> /// <param name="TypeName">_EPROCESS or something that is contained by the passed in CV or is cached</param> /// <param name="cv">required for first time for a given type</param> /// <returns>Dictionary that represents length and offset_of for all defined struct fields (except bitfields)</returns> public static Dictionary <string, Tuple <int, int> > GetTypeOffsets(string TypeName, CODEVIEW_HEADER cv = null) { Dictionary <string, Tuple <int, int> > rv = new Dictionary <string, Tuple <int, int> >(); var str = GetTypeString(TypeName, cv); JsonTextReader reader = new JsonTextReader(new StringReader(str)); String Name = string.Empty; int Length = 0, Pos = 0; // the first entry is a bit different format while (reader.Read()) { if (reader.TokenType == JsonToken.PropertyName) { if (reader.Value.Equals("TypeName")) { Name = reader.ReadAsString(); } reader.Read(); Length = reader.ReadAsInt32() ?? 0; rv.Add(Name, Tuple.Create(0, Length)); break; } } // after the first entry we have a fairly consistant format of entries (tag is skipped between name & pos) while (reader.Read()) { if (reader.TokenType == JsonToken.PropertyName) { if (reader.Value.Equals("MemberName")) { Name = reader.ReadAsString(); do { reader.Read(); } while (reader.TokenType != JsonToken.PropertyName); do { reader.Read(); } while (reader.TokenType != JsonToken.PropertyName); Pos = reader.ReadAsInt32() ?? 0; do { reader.Read(); } while (reader.TokenType != JsonToken.PropertyName); Length = reader.ReadAsInt32() ?? 0; rv.Add(Name, Tuple.Create(Pos, Length)); } } } return(rv); }
// where the bindings all get originated public Dia3(CODEVIEW_HEADER cvh) { CV = cvh; }
public DiaSymbol(CODEVIEW_HEADER cv) : this() { CV = cv; }
public DiaSource(CODEVIEW_HEADER cv) : this() { CV = cv; }
public DiaSession(CODEVIEW_HEADER cv) { CV = cv; }
/// <summary> /// Perform full symbol walk scanning for a struct/member position and length /// /// TODO: make safe for type collisions in other pdb's /// </summary> /// <param name="PDBFile">d:\dev\symbols\ntkrnlmp.pdb\DD08DD42692B43F199A079D60E79D2171\ntkrnlmp.pdb</param> /// <param name="Struct">_EPROCESS</param> /// <param name="Member">Pcb.DirectoryTableBase</param> /// <returns>Tuple of Position & Length </returns> public static Tuple <int, int> StructMemberInfo(CODEVIEW_HEADER cv, string Struct, string Member) { #if !NETSTANDARD2_0 IDiaSession Session; IDiaSymbol Master = null; IDiaEnumSymbols EnumSymbols = null; uint compileFetched = 0; var result = from symx in StructInfo where symx.Key.EndsWith(Member) select symx; if (result.Count() > 0) { return(result.First().Value); } #endif #if NETSTANDARD2_0 IDictionary <string, dynamic> dInfo = null; dynamic memberInfo = null; var cnt = Member.Split('.').Length; var typeInfo = SymAPI.GetType(Struct, cv); dInfo = typeInfo as IDictionary <string, dynamic>; if (cnt == 1) { memberInfo = dInfo[Member]; } else { for (int i = 0; i < cnt; i++) { var path = Member.Split('.')[i]; dInfo = typeInfo as IDictionary <string, dynamic>; memberInfo = dInfo[path]; if (i < cnt) { typeInfo = memberInfo; } } } dInfo = memberInfo as IDictionary <string, dynamic>; return(Tuple.Create((int)dInfo["OffsetPos"], (int)dInfo["Length"])); /* bah, screw this just return the object :\ * var foo = new DiaSource(cv); * foo.loadDataFromPdb(cv.PDBFullPath); * foo.openSession(out Session); */ #else var foo = new DiaSource(); foo.loadDataFromPdb(cv.PDBFullPath); foo.openSession(out Session); if (Session == null) { return(null); } Session.findChildren(Session.globalScope, (uint)DebugHelp.SymTagEnum.Null, Struct, 0, out EnumSymbols); do { EnumSymbols.Next(1, out Master, out compileFetched); if (Master == null) { continue; } #if DEBUGX Console.ForegroundColor = ConsoleColor.White; WriteLine($"Dumping Type [{Master.name}] Len [{Master.length}]"); #endif if (!StructInfo.ContainsKey(Master.name)) { StructInfo.Add(Master.name, Tuple.Create <int, int>(0, (int)Master.length)); } DumpStructs(Master, Master.name, Struct, 0); } while (compileFetched == 1); var resultx = (from symx in StructInfo where symx.Key.EndsWith(Member) select symx).FirstOrDefault(); return(resultx.Value); #endif }
/// <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 }