private static KeyValuePair <ClrInstanceField, string> GetField(string fieldName, string typeName, ClrHeap Heap) { //helper function to get an instance field if (!Heap.CanWalkHeap) { return(new KeyValuePair <ClrInstanceField, string>(null, "[!] Unable to walk the heap")); } Console.WriteLine("[+] Walking the heap...."); foreach (ulong obj in Heap.EnumerateObjectAddresses()) { ClrType type = Heap.GetObjectType(obj); if (type == null || type.Name != typeName) { continue; } try { ClrInstanceField field = type.GetFieldByName(fieldName); #if DEBUG Console.WriteLine("[+] Found desired field: " + fieldName); #endif ulong a = field.GetAddress(obj); if (field.HasSimpleValue) { fieldValue = field.GetValue(obj); } fieldAddr = new IntPtr(long.Parse(a.ToString())); return(new KeyValuePair <ClrInstanceField, string>(field, "[+] Found field " + fieldName)); } catch (Exception e) { return(new KeyValuePair <ClrInstanceField, string>(null, e.ToString())); } } return(new KeyValuePair <ClrInstanceField, string>(null, "Unable to locate field: " + fieldName)); }
public void GetFieldFrom_WhenStructureHasReferenceField_ReturnsField([Frozen] ClrHeap heap, ClrObject target, [Frozen] ClrType structType, ClrValueClass rawStruct, ClrInstanceField structReferenceField, ulong fieldAddress) { // Arrange IAddressableTypedEntity entity = rawStruct; structReferenceField.IsObjectReference.Returns(true); structReferenceField.GetAddress(entity.Address, Arg.Any <bool>()).Returns(fieldAddress); heap.ReadPointer(fieldAddress, out var whatever) .Returns(call => { call[1] = target.Address; return(true); }); // Act var fieldByName = entity.GetFieldFrom(structReferenceField.Name); // Assert fieldByName.Address.Should().Be(target.Address); }
public void GetFieldFrom_WhenClrObjectHasReferenceField_ReturnsField([Frozen] ClrHeap heap, [Frozen] ClrType objectType, ClrObject rawClrObject, ClrInstanceField clrField, ulong fieldAddress, ClrObject target) { // Arrange IAddressableTypedEntity entity = rawClrObject; clrField.IsObjectReference.Returns(true); clrField.GetAddress(entity.Address).Returns(fieldAddress); heap.ReadPointer(fieldAddress, out var whatever) .Returns(call => { call[1] = target.Address; return(true); }); // Act var fieldFoundByName = entity.GetFieldFrom(clrField.Name); // Assert fieldFoundByName.Address.Should().Be(target.Address); }
public static KcpKeyFile GetKcpKeyFileInfo(ulong KcpKeyFileAddr, ClrType KcpKeyFileType, ClrHeap Heap, string databaseLocation) { KcpKeyFile KeyFileInfo = new KcpKeyFile(); // key file path ClrInstanceField KcpStringField = KcpKeyFileType.GetFieldByName("m_strPath"); ulong KcpStringFieldAddr = KcpStringField.GetAddress(KcpKeyFileAddr); object keyFilePath = KcpStringField.GetValue(KcpStringFieldAddr, true); // Get the embedded ProtectedBinary ClrInstanceField KcpProtectedBinaryField = KcpKeyFileType.GetFieldByName("m_pbKeyData"); ulong KcpProtectedBinaryAddr = KcpProtectedBinaryField.GetAddress(KcpKeyFileAddr); ulong KcpProtectedBinaryObjAddr = (ulong)KcpProtectedBinaryField.GetValue(KcpKeyFileAddr); ClrInstanceField EncDataField = KcpProtectedBinaryField.Type.GetFieldByName("m_pbData"); ulong EncDataAddr = EncDataField.GetAddress(KcpProtectedBinaryObjAddr); ulong EncDataArrayAddr = (ulong)EncDataField.GetValue(KcpProtectedBinaryObjAddr); ClrType EncDataArrayType = Heap.GetObjectType(EncDataArrayAddr); int len = EncDataField.Type.GetArrayLength(EncDataArrayAddr); if (len <= 0 || len % 16 != 0) // Small sanity check to make sure everything's ok { return(null); } byte[] EncData = new byte[len]; for (int i = 0; i < len; i++) { EncData[i] = (byte)EncDataArrayType.GetArrayElementValue(EncDataArrayAddr, i); } KeyFileInfo.databaseLocation = databaseLocation; KeyFileInfo.encryptedBlob = EncData; KeyFileInfo.encryptedBlobAddress = (IntPtr)KcpKeyFileType.GetArrayElementAddress(EncDataArrayAddr, 0); KeyFileInfo.encryptedBlobLen = len; KeyFileInfo.keyFilePath = keyFilePath.ToString(); return(KeyFileInfo); }
public static KcpPassword GetKcpPasswordInfo(ulong KcpPasswordAddr, ClrType KcpPasswordType, ClrHeap Heap, string databaseLocation) { KcpPassword PasswordInfo = new KcpPassword(); // Protected String ClrInstanceField KcpProtectedStringField = KcpPasswordType.GetFieldByName("m_psPassword"); ulong KcpProtectedStringAddr = KcpProtectedStringField.GetAddress(KcpPasswordAddr); ulong KcpProtectedStringObjAddr = (ulong)KcpProtectedStringField.GetValue(KcpPasswordAddr); // Get the embedded ProtectedBinary ClrInstanceField KcpProtectedBinaryField = KcpProtectedStringField.Type.GetFieldByName("m_pbUtf8"); ulong KcpProtectedBinaryAddr = KcpProtectedBinaryField.GetAddress(KcpProtectedStringObjAddr); ulong KcpProtectedBinaryObjAddr = (ulong)KcpProtectedBinaryField.GetValue(KcpProtectedStringObjAddr); ClrInstanceField EncDataField = KcpProtectedBinaryField.Type.GetFieldByName("m_pbData"); ulong EncDataAddr = EncDataField.GetAddress(KcpProtectedBinaryObjAddr); ulong EncDataArrayAddr = (ulong)EncDataField.GetValue(KcpProtectedBinaryObjAddr); ClrType EncDataArrayType = Heap.GetObjectType(EncDataArrayAddr); int len = EncDataField.Type.GetArrayLength(EncDataArrayAddr); if (len <= 0 || len % 16 != 0) // Small sanity check to make sure everything's ok { return(null); } byte[] EncData = new byte[len]; for (int i = 0; i < len; i++) { EncData[i] = (byte)EncDataArrayType.GetArrayElementValue(EncDataArrayAddr, i); } PasswordInfo.databaseLocation = databaseLocation; PasswordInfo.encryptedBlob = EncData; PasswordInfo.encryptedBlobAddress = (IntPtr)KcpPasswordType.GetArrayElementAddress(EncDataArrayAddr, 0); PasswordInfo.encryptedBlobLen = len; return(PasswordInfo); }
static string GetOutput(ulong obj, ClrInstanceField field) { // If we don't have a simple value, return the address of the field in hex. if (!field.HasSimpleValue) { return(field.GetAddress(obj).ToString("X")); } object value = field.GetValue(obj); if (value == null) { return("{error}"); // Memory corruption in the target process. } // Decide how to format the string based on the underlying type of the field. switch (field.ElementType) { case ClrElementType.String: // In this case, value is the actual string itself. return((string)value); case ClrElementType.Array: case ClrElementType.SZArray: case ClrElementType.Object: case ClrElementType.Class: case ClrElementType.FunctionPointer: case ClrElementType.NativeInt: case ClrElementType.NativeUInt: // These types are pointers. Print as hex. return(string.Format("{0:X}", value)); default: // Everything else will look fine by simply calling ToString. return(value.ToString()); } }
public ClrObject this[ClrInstanceField field] => GetInnerObject(field.GetAddress(Address, IsInterior), field.Type);
public override bool TryGetMember(GetMemberBinder binder, out object result) { if (IsNull()) { result = new ClrNullValue(m_heap); return(true); } ClrInstanceField field = null; if (binder.IgnoreCase) { foreach (var inst in m_type.Fields) { if (inst.Name.Equals(binder.Name, StringComparison.CurrentCultureIgnoreCase)) { field = inst; break; } } } else { field = m_type.GetFieldByName(binder.Name); } if (field == null) { if (ClrDynamicClass.GetStaticField(m_heap, m_type, binder, out result)) { return(true); } throw new InvalidOperationException(string.Format("Type '{0}' does not contain a '{1}' field.", m_type.Name, binder.Name)); } if (field.IsPrimitive) { object value = field.GetValue(m_addr, m_inner); if (value == null) { result = new ClrNullValue(m_heap); } else { result = new ClrPrimitiveValue(value, field.ElementType); } return(true); } else if (field.IsValueClass) { ulong addr = field.GetAddress(m_addr, m_inner); result = new ClrObject(m_heap, field.Type, addr, true); return(true); } else if (field.ElementType == ClrElementType.String) { ulong addr = field.GetAddress(m_addr, m_inner); if (!m_heap.Runtime.ReadPointer(addr, out addr)) { result = new ClrNullValue(m_heap); return(true); } result = new ClrObject(m_heap, field.Type, addr); return(true); } else { object value = field.GetValue(m_addr, m_inner); if (value == null) { result = new ClrNullValue(m_heap); } else { result = new ClrObject(m_heap, field.Type, (ulong)value); } return(true); } }
private static ulong GetFieldAddressValue(ClrRuntime runtime, ClrInstanceField field, ulong addr) { ulong fieldAddress = field.GetAddress(addr); return(ReadMemory(runtime, fieldAddress)); }
// 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); }
/// <summary> /// Returns the address of the value of this field. Equivalent to GetFieldAddress(objRef, false). /// </summary> /// <param name="objRef">The object to get the field address for.</param> /// <returns>The value of the field.</returns> /// <exception cref="NotImplementedException"></exception> /// <inheritdoc /> public ulong GetAddress(ulong objRef) => InstanceField.GetAddress(objRef);
public override bool TryGetMember(GetMemberBinder binder, out object result) { if (IsNull()) { result = new ClrNullValue(m_heap); return(true); } if (binder.Name == "__Size") { result = m_type.GetSize(m_addr); return(true); } if (binder.Name == "__Type") { result = m_type.Name; return(true); } if (binder.Name == "__Address") { result = String.Format("{0:x16}", m_addr); return(true); } if (binder.Name == "__Fields") { result = (from f in m_type.Fields where f.Type != null select new { Name = f.Name, Type = f.Type.Name }).ToArray(); return(true); } ClrInstanceField field = null; foreach (var instanceField in m_type.Fields) { // Auto-generated properties have this ugly <> thing around their fields that you can't put // in a C# expression. Clean them up to make them accessible by their property name. var cleanFieldName = instanceField.Name; if (cleanFieldName.StartsWith("<") && cleanFieldName.EndsWith(">k__BackingField")) { cleanFieldName = cleanFieldName.Substring( 1, cleanFieldName.Length - (1 + ">k__BackingField".Length)); } if (cleanFieldName == binder.Name) { field = instanceField; break; } } if (field == null) { if (ClrDynamicClass.GetStaticField(m_heap, m_type, binder, out result)) { return(true); } throw new InvalidOperationException(string.Format("Type '{0}' does not contain a '{1}' field.", m_type.Name, binder.Name)); } if (field.IsPrimitive()) { object value = field.GetValue(m_addr, m_inner); if (value == null) { result = new ClrNullValue(m_heap); } else { result = new ClrPrimitiveValue(value, field.ElementType); } return(true); } else if (field.IsValueClass()) { ulong addr = field.GetAddress(m_addr, m_inner); result = new ClrObject(m_heap, field.Type, addr, true); return(true); } else if (field.ElementType == ClrElementType.String) { ulong addr = field.GetAddress(m_addr, m_inner); if (!m_heap.GetRuntime().ReadPointer(addr, out addr)) { result = new ClrNullValue(m_heap); return(true); } result = new ClrObject(m_heap, field.Type, addr); return(true); } else { object value = field.GetValue(m_addr, m_inner); if (value == null) { result = new ClrNullValue(m_heap); } else { result = new ClrObject(m_heap, field.Type, (ulong)value); } return(true); } }