Example #1
0
        private Dictionary<int, string> GetManagedThreadNames(ClrHeap heap)
        {
            var result = new Dictionary<int, string>();
            if (!heap.CanWalkHeap)
                return result;

            var threadObjects = from obj in heap.EnumerateObjectAddresses()
                                let type = heap.GetObjectType(obj)
                                where type != null && type.Name == "System.Threading.Thread"
                                select obj;
            var threadType = heap.GetTypeByName("System.Threading.Thread");
            var nameField = threadType.GetFieldByName("m_Name");
            var managedIdField = threadType.GetFieldByName("m_ManagedThreadId");

            foreach (var threadObject in threadObjects)
            {
                string name = (string)nameField.GetValue(threadObject);
                int id = (int)managedIdField.GetValue(threadObject);
                result.Add(id, name);
            }

            return result;
        }
Example #2
0
        private static void DumpRetention(DataTarget dataTarget, ClrInfo clrVersion, ClrRuntime runtime, ClrAppDomain appDomain, ClrHeap heap, string targetType)
        {
            var graph = new Graph();

            Console.WriteLine("## What's the retention path of the {0} object?", targetType);
            Console.WriteLine("");
            foreach (var ptr in heap.EnumerateObjectAddresses())
            {
                var type = heap.GetObjectType(ptr);
                if (type == null || type.Name != targetType)
                {
                    continue;
                }

                // Enumerate roots and try to find the current object
                var stack = new Stack <ulong>();
                foreach (var root in heap.EnumerateRoots())
                {
                    stack.Clear();
                    stack.Push(root.Object);
                    if (GetPathToObject(heap, ptr, stack, new HashSet <ulong>()))
                    {
                        // Print retention path
                        var depth           = 0;
                        var previousAddress = (ulong)0;
                        foreach (var address in stack)
                        {
                            var t = heap.GetObjectType(address);
                            if (t == null)
                            {
                                continue;
                            }

                            Console.WriteLine("{0} {1} - {2} - {3} bytes", new string('+', depth++), address, t.Name, t.GetSize(address));

                            graph.AddNode(address.ToString()).LabelText = $"{t.Name} ({address})";
                            if (previousAddress > 0 && !graph.Edges.Any(e => e.Source == previousAddress.ToString() && e.Target == address.ToString()))
                            {
                                graph.AddEdge(previousAddress.ToString(), address.ToString());
                            }
                            previousAddress = address;
                        }

                        Console.WriteLine();
                    }
                }
            }

            Console.ReadLine();

            // Render graph
            var width    = 1600;
            var renderer = new GraphRenderer(graph);

            renderer.CalculateLayout();
            var bitmap = new Bitmap(width, (int)(graph.Height * (width / graph.Width)), PixelFormat.Format32bppRgb);

            renderer.Render(bitmap);
            bitmap.Save("test.png");
            Process.Start("test.png");
        }
Example #3
0
        private static KeyValuePair <bool, string> Enumerate()
        {
            //Attach to target process
            DataTarget dt = null;

            try
            {
                dt = DataTarget.AttachToProcess(targetPID, 10000, AttachFlag.NonInvasive);
            }
            catch (Exception e)
            {
                return(new KeyValuePair <bool, string>(false, e.ToString()));
            }

            //If no ClrVersions, return
            if (dt.ClrVersions.Count == 0)
            {
                return(new KeyValuePair <bool, string>(false, "[!] No Clr Versions detected"));
            }

#if DEBUG
            foreach (var ver in dt.ClrVersions)
            {
                Console.WriteLine("Clr Runtime Version Found: " + ver.Version.ToString());
            }
#endif

            ClrInfo Version = dt.ClrVersions[0];


            try
            {
                cRun = Version.CreateRuntime();
#if DEBUG
                Console.WriteLine("[+] Created Runtime");
#endif
            }
            catch (Exception e)
            {
#if DEBUG
                Console.WriteLine("[!] Failed to create runtime");
#endif
                return(new KeyValuePair <bool, string>(false, e.ToString()));
            }


            ClrHeap Heap = cRun.GetHeap();

            //if we can't walk the heap, return
            if (!Heap.CanWalkHeap)
            {
                return(new KeyValuePair <bool, string>(false, "[!] Unable to walk the heap"));
            }

            Console.WriteLine("[+] Walking the heap....");
            string m  = WildCardToRegWithQM("System.*");
            string m1 = WildCardToRegWithQM("_*");
            string m2 = WildCardToRegWithQM("Microsoft.*");
            foreach (ulong obj in Heap.EnumerateObjectAddresses())
            {
                //Grab each object, check if it has a simple value, if so, display it
                ClrType type = Heap.GetObjectType(obj);

                if (TypeName != null)
                {
                    if (type == null && type.Name == TypeName || Regex.IsMatch(type.Name, m) || Regex.IsMatch(type.Name, m1) || Regex.IsMatch(type.Name, m2) || type.Name == "Free")
                    {
                        continue;
                    }
                }
                else
                {
                    if (type == null || Regex.IsMatch(type.Name, m) || Regex.IsMatch(type.Name, m1) || Regex.IsMatch(type.Name, m2) || type.Name == "Free")
                    {
                        continue;
                    }
                }

                if (!type.IsPrimitive)
                {
#if DEBUG
                    Console.WriteLine("[+] Enumerating type: " + type.Name);
#endif
                    //if the type has a simple value, add the type and its value to the results
                    resultOutput.Append("\r\nType: " + type.Name + "\r\n\r\n");
                    //Enumerate all of the instance fields for the given type
                    if (showFields)
                    {
                        if (type.Fields != null)
                        {
                            GetInstanceFields(type.Fields, obj);
                        }
                    }


                    if (showstaticFields)
                    {
                        if (type.StaticFields != null)
                        {
                            GetStaticFields(type.StaticFields, cRun.AppDomains[0]);
                        }
                    }

                    if (showMethods)
                    {
                        if (type.Methods != null)
                        {
                            GetMethods(type.Methods);
                        }
                    }

                    if (referenceObjects)
                    {
                        resultOutput.Append("\r\nReferencedTypes\r\n\r\n");
                        List <ulong> referencedObjects = ClrMDHelper.GetReferencedObjects(Heap, obj);
                        foreach (ulong refObj in referencedObjects)
                        {
                            ClrType refObjType = Heap.GetObjectType(refObj);
                            if (refObjType == null || Regex.IsMatch(refObjType.Name, m) || Regex.IsMatch(refObjType.Name, m1) || Regex.IsMatch(refObjType.Name, m2) || refObjType.Name == "Free")
                            {
                                continue;
                            }

                            if (showFields)
                            {
                                if (refObjType.Fields != null)
                                {
                                    GetInstanceFields(refObjType.Fields, obj, fieldName);
                                }
                            }

                            if (showstaticFields)
                            {
                                if (refObjType.StaticFields != null)
                                {
                                    GetStaticFields(refObjType.StaticFields, cRun.AppDomains[0], fieldName);
                                }
                            }

                            if (showMethods)
                            {
                                if (refObjType.Methods != null)
                                {
                                    GetMethods(refObjType.Methods);
                                }
                            }
                        }
                    }
                }
            }

            return(new KeyValuePair <bool, string>(true, "[+] Successfully walked the heap."));
        }
Example #4
0
        public void OptimizedClassHistogram()
        {
            using (DataTarget dt = TestTargets.Types.LoadFullDump())
            {
                ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime();
                ClrHeap    heap    = runtime.Heap;

                // ensure that the optimized version is faster than the default one
                Stopwatch timing = new Stopwatch();
                var       notOptimizedStatistics  = new Dictionary <ClrType, TypeEntry>(32768);
                int       notOptimizedObjectCount = 0;

                // with an optimized version
                timing.Start();

                foreach (var objDetails in heap.EnumerateObjectDetails())
                {
                    ClrType type = objDetails.Item3;
                    ulong   size = objDetails.Item4;

                    TypeEntry entry;
                    if (!notOptimizedStatistics.TryGetValue(type, out entry))
                    {
                        entry = new TypeEntry()
                        {
                            TypeName = type.Name,
                            Size     = 0
                        };
                        notOptimizedStatistics[type] = entry;
                    }
                    entry.Count++;
                    entry.Size += size;
                    notOptimizedObjectCount++;
                }

                timing.Stop();
                var notOptimizedTime = TimeSpan.FromMilliseconds(timing.ElapsedMilliseconds);


                // with an non-optimized version
                var statistics  = new Dictionary <ClrType, TypeEntry>(32768);
                int objectCount = 0;
                timing.Restart();

                foreach (ulong objAddress in heap.EnumerateObjectAddresses())
                {
                    ClrType type = heap.GetObjectType(objAddress);
                    ulong   size = type.GetSize(objAddress);

                    TypeEntry entry;
                    if (!statistics.TryGetValue(type, out entry))
                    {
                        entry = new TypeEntry()
                        {
                            TypeName = type.Name,
                            Size     = 0
                        };
                        statistics[type] = entry;
                    }
                    entry.Count++;
                    entry.Size += size;
                    objectCount++;
                }

                timing.Stop();

                // check object count
                Assert.AreEqual(notOptimizedObjectCount, objectCount);

                // check heap content
                var types = notOptimizedStatistics.Keys;
                foreach (var type in types)
                {
                    var notOptimizedDetails = notOptimizedStatistics[type];
                    var details             = statistics[type];

                    Assert.AreEqual(notOptimizedDetails.TypeName, details.TypeName);
                    Assert.AreEqual(notOptimizedDetails.Count, details.Count);
                    Assert.AreEqual(notOptimizedDetails.Size, details.Size);
                }
                Assert.AreEqual(types.Count, statistics.Count);

                // checking that optimized is faster could be flaky
                // Assert.IsTrue(notOptimizedTime > TimeSpan.FromMilliseconds(timing.ElapsedMilliseconds));
            }
        }
Example #5
0
        // Returns all the info about any Composite Keys stored in memory
        public static List <CompositeKeyInfo> GetCompositeKeyInfo(Process process)
        {
            List <CompositeKeyInfo> keyInfo = new List <CompositeKeyInfo>();
            DataTarget dt = null;
            string     databaseLocation = "";

            try
            {
                dt = DataTarget.AttachToProcess(process.Id, 50000);

                if (dt.ClrVersions.Count == 0)
                {
                    string err = "CLR is not loaded. Is it Keepass 1.x, perhaps?";
                    Logger.WriteLine(err);
                    throw new Exception(err);
                }

                if (dt.ClrVersions.Count > 1)
                {
                    Logger.WriteLine("*** Interesting... there are multiple .NET runtimes loaded in KeePass");
                }

                ClrInfo    Version = dt.ClrVersions[0];
                ClrRuntime Runtime = Version.CreateRuntime();
                ClrHeap    Heap    = Runtime.GetHeap();

                if (!Heap.CanWalkHeap)
                {
                    string err = "Error: Cannot walk the heap!";
                    Logger.WriteLine(err);
                    throw new Exception(err);
                }

                foreach (ulong obj in Heap.EnumerateObjectAddresses())
                {
                    ClrType type = Heap.GetObjectType(obj);

                    if (type == null || type.Name != "KeePassLib.PwDatabase")
                    {
                        continue;
                    }

                    Logger.WriteLine("************ Found a PwDatabase! **********");

                    List <ulong> referencedObjects = ClrMDHelper.GetReferencedObjects(Heap, obj);

                    // First walk the referenced objects to find the database path
                    foreach (ulong refObj in referencedObjects)
                    {
                        ClrType refObjType = Heap.GetObjectType(refObj);
                        if (refObjType.Name == "KeePassLib.Serialization.IOConnectionInfo")
                        {
                            ClrInstanceField UrlField     = refObjType.GetFieldByName("m_strUrl");
                            ulong            UrlFieldAddr = UrlField.GetAddress(refObj);
                            object           Url          = UrlField.GetValue(UrlFieldAddr, true);
                            databaseLocation = (string)Url;
                        }
                    }

                    if (databaseLocation != "")
                    {
                        Logger.WriteLine("*** PwDatabase location : " + databaseLocation);

                        referencedObjects = ClrMDHelper.GetReferencedObjects(Heap, obj);

                        // now walk the referenced objects looking for a master composite key
                        foreach (ulong refObj in referencedObjects)
                        {
                            ClrType refObjType = Heap.GetObjectType(refObj);
                            if (refObjType.Name == "KeePassLib.Keys.CompositeKey")
                            {
                                Logger.WriteLine("************ Found a CompositeKey! **********");
                                CompositeKeyInfo CompositeKey = new CompositeKeyInfo();

                                // Get all objects kept alive by the composite key.
                                // (A shortcut to get references to all Key types)
                                List <ulong> referencedObjects2 = ClrMDHelper.GetReferencedObjects(Heap, refObj);

                                foreach (ulong refObj2 in referencedObjects2)
                                {
                                    ClrType refObjType2 = Heap.GetObjectType(refObj2);

                                    if (refObjType2.Name == "KeePassLib.Keys.KcpPassword")
                                    {
                                        KcpPassword KcpPassword = GetKcpPasswordInfo(refObj2, refObjType2, Heap, databaseLocation);

                                        if (KcpPassword == null)
                                        {
                                            continue;
                                        }

                                        CompositeKey.AddUserKey(KcpPassword);
                                    }
                                    else if (refObjType2.Name == "KeePassLib.Keys.KcpKeyFile")
                                    {
                                        KcpKeyFile KcpKeyFile = GetKcpKeyFileInfo(refObj2, refObjType2, Heap, databaseLocation);

                                        if (KcpKeyFile == null)
                                        {
                                            continue;
                                        }

                                        CompositeKey.AddUserKey(KcpKeyFile);
                                    }
                                    else if (refObjType2.Name == "KeePassLib.Keys.KcpUserAccount")
                                    {
                                        KcpUserAccount KcpUserAccount = GetKcpUserAccountInfo(refObj2, refObjType2, Heap, databaseLocation);

                                        if (KcpUserAccount == null)
                                        {
                                            continue;
                                        }

                                        CompositeKey.AddUserKey(KcpUserAccount);
                                    }
                                }
                                if (CompositeKey.UserKeyCount > 0)
                                {
                                    keyInfo.Add(CompositeKey);
                                }
                            }
                        }
                    }
                }

                Logger.Write("\n");
            }
            catch (Exception e)
            {
                Logger.WriteLine(e.Message);
                throw;
            }
            finally
            {
                if (dt != null)
                {
                    dt.Dispose();
                }
            }

            return(keyInfo);
        }