// 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); }
// 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; }