private bool GetArrayValue(ClrType type, ulong addr, int index, out object result) { var componentType = type.ArrayComponentType; // componentType being null is a dac bug which should only happen when we have an array of // value types, where we have never *actually* constructed one of the types. If there are // other dac bugs which cause this, we unfortunately cannot work around it. if (addr == 0 || componentType == null) { result = new ClrNullValue(m_heap); return(true); } if (index < 0 || index >= m_len) { throw new IndexOutOfRangeException(); } // Now construct the value based on the element type. if (componentType.ElementType == ClrElementType.Struct) { addr = type.GetArrayElementAddress(addr, index); result = new ClrObject(m_heap, componentType, addr, true); return(true); } else if (componentType.IsObjectReference) { addr = type.GetArrayElementAddress(addr, index); if (!m_heap.GetRuntime().ReadPointer(addr, out addr) || addr == 0) { result = new ClrNullValue(m_heap); return(true); } else { result = new ClrObject(m_heap, componentType, addr); return(true); } } else if (componentType.IsPrimitive) { result = new ClrPrimitiveValue(type.GetArrayElementValue(addr, index), componentType.ElementType); return(true); } result = null; return(false); }
public void ArrayOffsetsTest() { using (DataTarget dt = TestTargets.Types.LoadFullDump()) { ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); ClrHeap heap = runtime.Heap; ClrAppDomain domain = runtime.AppDomains.Single(); ClrModule typesModule = runtime.GetModule("types.exe"); ClrType type = heap.GetTypeByName("Types"); ulong s_array = (ulong)type.GetStaticFieldByName("s_array").GetValue(domain); ulong s_one = (ulong)type.GetStaticFieldByName("s_one").GetValue(domain); ulong s_two = (ulong)type.GetStaticFieldByName("s_two").GetValue(domain); ulong s_three = (ulong)type.GetStaticFieldByName("s_three").GetValue(domain); ulong[] expected = new ulong[] { s_one, s_two, s_three }; ClrType arrayType = heap.GetObjectType(s_array); for (int i = 0; i < expected.Length; i++) { Assert.Equal(expected[i], (ulong)arrayType.GetArrayElementValue(s_array, i)); ulong address = arrayType.GetArrayElementAddress(s_array, i); ulong value = dt.DataReader.ReadPointerUnsafe(address); Assert.NotEqual(0ul, address); Assert.Equal(expected[i], value); } } }
public static KcpUserAccount GetKcpUserAccountInfo(ulong KcpUserAccountAddr, ClrType KcpUserAccountType, ClrHeap Heap, string databaseLocation) { KcpUserAccount UserAccountInfo = new KcpUserAccount(); // Get the embedded ProtectedBinary ClrInstanceField KcpProtectedBinaryField = KcpUserAccountType.GetFieldByName("m_pbKeyData"); ulong KcpProtectedBinaryAddr = KcpProtectedBinaryField.GetAddress(KcpUserAccountAddr); ulong KcpProtectedBinaryObjAddr = (ulong)KcpProtectedBinaryField.GetValue(KcpUserAccountAddr); 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); } UserAccountInfo.databaseLocation = databaseLocation; UserAccountInfo.encryptedBlob = EncData; UserAccountInfo.encryptedBlobAddress = (IntPtr)KcpUserAccountType.GetArrayElementAddress(EncDataArrayAddr, 0); UserAccountInfo.encryptedBlobLen = len; return(UserAccountInfo); }
static void ReadComplexArray(ClrType type, ulong obj) { int len = type.GetArrayLength(obj); Console.WriteLine("Object: {0:X}", obj); Console.WriteLine("Type: {0}", type.Name); Console.WriteLine("Length: {0}", len); for (int i = 0; i < len; i++) { ulong addr = type.GetArrayElementAddress(obj, i); foreach (var field in type.ComponentType.Fields) { string output; if (field.HasSimpleValue) { var tmpOutput = field.GetValue(addr, true); if (tmpOutput == null) { continue; } output = tmpOutput.ToString(); // <- true here, as this is an embedded struct } else { output = field.GetAddress(addr, true).ToString("X"); // <- true here as well } Console.WriteLine("{0} +{1,2:X2} {2} {3} = {4}", i, field.Offset, field.Type.Name, field.Name, output); } } }
public static List <KVP> GetKVPs(ClrType type, ulong items) { int length = type.GetArrayLength(items); var ret = new List <KVP>(); for (int i = 0; i < length; i++) { ulong addr = type.GetArrayElementAddress(items, i); var keyField = type.ComponentType.GetFieldByName("key"); var key = (ulong)keyField.GetValue(addr - (ulong)IntPtr.Size); // no need to add these pre-allocated entries if (key == 0) { continue; } var valueField = type.ComponentType.GetFieldByName("value"); var value = (ulong)valueField.GetValue(addr - (ulong)IntPtr.Size); ret.Add(new KVP(key, value)); } return(ret); }
private ulong GetClrTypeArrayElementAddress(Tuple <int, ulong, int> input) { int clrTypeId = input.Item1; ulong address = input.Item2; int index = input.Item3; ClrType clrType = clrTypesCache[clrTypeId]; return(clrType.GetArrayElementAddress(address, index)); }
public void InternalSetIndex(int[] indexes, object value) { Type valueType = value.GetType(); ClrType iobjType = Type; nuint addr = iobjType.GetArrayElementAddress(BaseAddress, indexes); if (value is ClrObject obj) { Context.DataAccess.Write(addr, obj.Address); } else if (value is ClrValue val) { Context.DataAccess.WriteBytes(addr, Context.DataAccess.ReadBytes(val.Address, iobjType.ComponentSize)); } else if (valueType.IsValueType) { Context.DataAccess.Write(addr, value); } }
public List <T> Read <T>() where T : new() { ClrType type = Heap.GetObjectType(Value.Address); // Only consider types which are arrays that do not have simple values (I.E., are structs). if (!type.IsArray || type.ComponentType.HasSimpleValue) { return(null); } int len = type.GetArrayLength(Value.Address); List <T> list = new List <T>(); FieldInfo[] fields = typeof(T).GetFields(); for (int i = 0; i < len; i++) { ulong addr = type.GetArrayElementAddress(Value.Address, i); T item = new T(); foreach (var field in type.ComponentType.Fields) { if (!field.HasSimpleValue) { continue; } for (int j = 0; j < fields.Length; j++) { if (fields[j].Name == field.Name) { var val = field.GetValue(addr, true); typeof(T).GetField(field.Name).SetValueDirect(__makeref(item), val); } } } list.Add(item); } return(list); }
private List <ClrObjectModel> GetValues(ulong obj, ClrType type, string baseName, int offset, bool inner, List <ClrObjectModel> values) { if (type.Name == "System.String") { object value; try { value = type.GetValue(obj); } catch (Exception ex) { value = ex.Message; } values.Add(new ClrObjectModel { Address = obj, BaseName = baseName, TypeName = type.Name, Value = value }); values.AddRange(type.Fields.Select(field => new ClrObjectModel { Address = obj, BaseName = baseName, FieldName = field.Name, Offset = field.Offset + offset, TypeName = field.Type.Name, Value = field.GetValue(obj, inner).ToString() })); } else if (type.IsArray) { int len = type.GetArrayLength(obj); if (type.ComponentType == null) { try { for (int i = 0; i < len; i++) { values.Add(new ClrObjectModel { Address = obj, BaseName = baseName, TypeName = type.Name, Value = type.GetArrayElementValue(obj, i) }); } } catch { } } else if (type.ComponentType.HasSimpleValue) { for (int i = 0; i < len; i++) { values.Add(new ClrObjectModel { Address = obj, BaseName = baseName, TypeName = type.Name, Value = type.GetArrayElementValue(obj, i) }); } } else { for (int i = 0; i < len; i++) { ulong arrAddress = type.GetArrayElementAddress(obj, i); foreach (var field in type.ComponentType.Fields) { string value; if (field.HasSimpleValue) { value = field.GetValue(arrAddress, inner).ToString(); // an embedded struct } else { value = field.GetAddress(arrAddress, inner).ToString(); } values.Add(new ClrObjectModel { Address = obj, BaseName = baseName, FieldName = field.Name, Offset = field.Offset + offset, TypeName = field.Type.Name, Value = value }); if (field.ElementType == ClrElementType.Struct) { values.AddRange(GetValues(arrAddress, field.Type, baseName + field.Name, offset + field.Offset, true, new List <ClrObjectModel>())); } } } } } else { foreach (var field in type.Fields) { ulong addr = field.GetAddress(obj, inner); object value; if (field.HasSimpleValue) { try { value = field.GetValue(obj, inner); } catch (Exception) { value = "{Unknown}"; } } else { value = addr; } string sValue = value?.ToString() ?? "{Null}"; values.Add(new ClrObjectModel { Address = obj, BaseName = baseName, FieldName = field.Name, Offset = field.Offset + offset, TypeName = field.Type.Name, Value = sValue }); if (field.ElementType == ClrElementType.Struct) { values.AddRange(GetValues(addr, field.Type, baseName + field.Name, offset + field.Offset, true, new List <ClrObjectModel>())); } } } return(values); }
public static void PrintDict(ClrRuntime runtime, string args) { bool failed = false; ulong obj = 0; try { obj = Convert.ToUInt64(args, 16); failed = obj == 0; } catch (ArgumentException) { failed = true; } if (failed) { Console.WriteLine("Usage: !PrintDict <dictionary>"); return; } ClrHeap heap = runtime.GetHeap(); ClrType type = heap.GetObjectType(obj); if (type == null) { Console.WriteLine("Invalid object {0:X}", obj); return; } if (!type.Name.StartsWith("System.Collections.Generic.Dictionary")) { Console.WriteLine("Error: Expected object {0:X} to be a dictionary, instead it's of type '{1}'."); return; } // Get the entries field. ulong entries = type.GetFieldValue(obj, "entries"); if (entries == 0) { return; } ClrType entryArray = heap.GetObjectType(entries); ClrType arrayComponent = entryArray.ComponentType; ClrInstanceField hashCodeField = arrayComponent.GetFieldByName("hashCode"); ClrInstanceField keyField = arrayComponent.GetFieldByName("key"); ClrInstanceField valueField = arrayComponent.GetFieldByName("value"); Console.WriteLine("{0,8} {1,16} : {2}", "hash", "key", "value"); int len = entryArray.GetArrayLength(entries); for (int i = 0; i < len; ++i) { ulong arrayElementAddr = entryArray.GetArrayElementAddress(entries, i); int hashCode = (int)hashCodeField.GetValue(arrayElementAddr, true); object key = keyField.GetValue(arrayElementAddr, true); object value = valueField.GetValue(arrayElementAddr, true); key = Format(heap, key); value = Format(heap, value); bool skip = key is ulong && (ulong)key == 0 && value is ulong && (ulong)value == 0; if (!skip) { Console.WriteLine("{0,8:X} {1,16} : {2}", hashCode, key, value); } } }
private static Dictionary <string, HeapObjectCounter> GetObjectOwners(ClrRuntime runtime, HashSet <ulong> instances) { Dictionary <string, HeapObjectCounter> dict = new Dictionary <string, HeapObjectCounter>(); if (!runtime.Heap.CanWalkHeap) { Console.WriteLine("Cannot walk the heap!"); } else { foreach (ClrSegment seg in runtime.Heap.Segments) { for (ulong obj = seg.FirstObject; obj != 0; obj = seg.NextObject(obj)) { ClrType type = runtime.Heap.GetObjectType(obj); if (type == null || type.IsFree == true) { continue; } string typeName = type.ToString(); int gen = runtime.Heap.GetGeneration(obj); if (gen != 2) { continue; } if (type.IsArray == true) { int arrayLength = type.GetArrayLength(obj); for (int i = 0; i < arrayLength; i++) { ulong elemAddress = type.GetArrayElementAddress(obj, i); ClrType elemType = type.ComponentType; if (elemType.IsValueClass == false) { ulong elemRef = ReadMemory(runtime, elemAddress); if (instances.Contains(elemRef) == true) { if (dict.ContainsKey(typeName) == true) { dict[typeName].AddCount(obj); } else { dict.Add(typeName, new HeapObjectCounter(obj)); } } } else { AddItem(type, typeName, obj); } } } else { AddItem(type, typeName, obj); } } } } return(dict); void AddItem(ClrType type, string typeName, ulong objAddress) { foreach (ClrInstanceField field in type.Fields) { ulong fieldAddress = GetFieldAddressValue(runtime, field, objAddress); if (instances.Contains(fieldAddress) == true) { if (dict.ContainsKey(typeName) == true) { dict[typeName].AddCount(objAddress); } else { dict.Add(typeName, new HeapObjectCounter(objAddress)); } } } } }
public override IClrObjMappingModel ReadEntity(ClrObject obj, ModelMapperFactory factory) { var hashtableModel = new HashtableMappingModel { Obj = obj }; ClrObject entriesField = obj.GetRefFld(entriesFldName); if (entriesField == null || entriesField.Type == null) { // Object contains this field, but value is null. // Most likely dictionary is either in the middle of construction, or destruction. // Anyway we can assume it is empty. return(hashtableModel); } ClrType type = entriesField.Type; ClrHeap heap = type.Heap; var componentType = type.ComponentType; if (componentType == null) { // TODO :Try reload type. return(null); } ClrInstanceField valueField = componentType.GetFieldByName("value"); ClrInstanceField keyField = componentType.GetFieldByName("key"); int len = type.GetArrayLength(entriesField.Address); ulong entriesFieldAddress = entriesField.Address; for (int i = 0; i < len; i++) { ulong addr = type.GetArrayElementAddress(entriesFieldAddress, i); if (addr == 0) { continue; } try { var key = keyField.GetValue(addr, true); if (!(key is ulong)) { continue; } var keyPointer = (ulong)key; if (keyPointer == 0) { continue; } var val = valueField.GetValue(addr, true); ulong valuePointer; if (val is ulong) { valuePointer = (ulong)val; } else { valuePointer = 0; } var keyObj = new ClrObject(keyPointer, heap); var valObj = new ClrObject(valuePointer, heap); hashtableModel.Elements.Add(factory.BuildModel(keyObj), factory.BuildModel(valObj)); } catch (Exception) { Trace.TraceError("Count not read {0} object", obj.HexAddress); // Do nothing for now } } return(hashtableModel); }
/// <summary> /// Returns the absolute address to the given array element. You may then make a direct memory read out /// of the process to get the value if you want. /// </summary> /// <param name="objRef">The object reference.</param> /// <param name="index">The index.</param> /// <returns>System.UInt64.</returns> public ulong GetArrayElementAddress(ulong objRef, int index) => ClrType.GetArrayElementAddress(objRef, index);
public void GetArrayElementAddress(ulong objRef, int index, out ulong pAddr) { pAddr = m_type.GetArrayElementAddress(objRef, index); }