private static bool GuessPointerNode(IntPtr address, IProcessReader process, out BaseNode node) { Contract.Requires(process != null); node = null; if (address.IsNull()) { return(false); } var section = process.GetSectionToPointer(address); if (section == null) { return(false); } if (section.Category == SectionCategory.CODE) // If the section contains code, it should be a function pointer. { node = new FunctionPtrNode(); return(true); } if (section.Category == SectionCategory.DATA || section.Category == SectionCategory.HEAP) // If the section contains data, it is at least a pointer to a class or something. { // Check if it is a vtable. Check if the first 3 values are pointers to a code section. var possibleVmt = process.ReadRemoteObject <ThreePointersData>(address); if (process.GetSectionToPointer(possibleVmt.Pointer1)?.Category == SectionCategory.CODE && process.GetSectionToPointer(possibleVmt.Pointer2)?.Category == SectionCategory.CODE && process.GetSectionToPointer(possibleVmt.Pointer3)?.Category == SectionCategory.CODE) { node = new VirtualMethodTableNode(); return(true); } // Check if it is a string. var data = process.ReadRemoteMemory(address, IntPtr.Size * 2); if (data.Take(IntPtr.Size).InterpretAsSingleByteCharacter().IsLikelyPrintableData()) { node = new Utf8TextPtrNode(); return(true); } if (data.InterpretAsDoubleByteCharacter().IsLikelyPrintableData()) { node = new Utf16TextPtrNode(); return(true); } // Now it could be a pointer to something else but we can't tell. :( node = new PointerNode(); return(true); } return(false); }
public void Load(string filePath, ILogger logger) { using (var connection = new SQLiteConnection($"Data Source={filePath}")) { connection.Open(); var classes = new Dictionary <int, ClassNode>(); var vtables = new Dictionary <int, VirtualMethodTableNode>(); foreach (var row in Query(connection, "SELECT tbl_name FROM sqlite_master WHERE tbl_name LIKE 'class%'")) { var id = Convert.ToInt32(row["tbl_name"].ToString().Substring(5)); var classRow = Query(connection, $"SELECT variable, comment FROM class{id} WHERE type = 2 LIMIT 1").FirstOrDefault(); if (classRow == null) { continue; } // Skip the vtable classes. if (classRow["variable"].ToString() == "VTABLE") { var vtableNode = new VirtualMethodTableNode(); Query(connection, $"SELECT variable, comment FROM class{id} WHERE type = 16") .Select(e => new VirtualMethodNode { Name = Convert.ToString(e["variable"]), Comment = Convert.ToString(e["comment"]) }) .ForEach(vtableNode.AddNode); foreach (var method in vtableNode.Nodes.Where(m => m.Name == "void function()")) { method.Name = string.Empty; } vtables.Add(id, vtableNode); continue; } var node = new ClassNode(false) { Name = classRow["variable"].ToString(), Comment = classRow["comment"].ToString() }; project.AddClass(node); classes.Add(id, node); } foreach (var kv in classes) { ReadNodeRows( Query(connection, $"SELECT variable, comment, type, length, ref FROM class{kv.Key} WHERE type != 2"), kv.Value, classes, vtables, logger ).ForEach(kv.Value.AddNode); } } }