Beispiel #1
0
        public Dumper(IRemoteMemoryReader process)
        {
            Contract.Requires(process != null);
            Contract.Ensures(this.process != null);

            this.process = process;
        }
Beispiel #2
0
        public static string ReadRemoteString(this IRemoteMemoryReader reader, IntPtr address, Encoding encoding, int length)
        {
            Contract.Requires(encoding != null);
            Contract.Requires(length >= 0);
            Contract.Ensures(Contract.Result <string>() != null);

            var data = reader.ReadRemoteMemory(address, length * encoding.GuessByteCountPerChar());

            try
            {
                var sb = new StringBuilder(encoding.GetString(data));
                for (var i = 0; i < sb.Length; ++i)
                {
                    if (sb[i] == '\0')
                    {
                        sb.Length = i;
                        break;
                    }
                    if (!sb[i].IsPrintable())
                    {
                        sb[i] = '.';
                    }
                }
                return(sb.ToString());
            }
            catch
            {
                return(string.Empty);
            }
        }
Beispiel #3
0
        public static string ReadRemoteStringUntilFirstNullCharacter(this IRemoteMemoryReader reader, IntPtr address, Encoding encoding, int length)
        {
            Contract.Requires(encoding != null);
            Contract.Requires(length >= 0);
            Contract.Ensures(Contract.Result <string>() != null);

            var data = reader.ReadRemoteMemory(address, length * encoding.GuessByteCountPerChar());

            // TODO We should cache the pattern per encoding.
            var index = PatternScanner.FindPattern(BytePattern.From(new byte[encoding.GuessByteCountPerChar()]), data);

            if (index == -1)
            {
                index = data.Length;
            }

            try
            {
                return(encoding.GetString(data, 0, Math.Min(index, data.Length)));
            }
            catch
            {
                return(string.Empty);
            }
        }
Beispiel #4
0
        /// <summary>Disassembles the code in the given range (<paramref name="address"/>, <paramref name="length"/>) in the remote process.</summary>
        /// <param name="process">The process to read from.</param>
        /// <param name="address">The address of the code.</param>
        /// <param name="length">The length of the code in bytes.</param>
        /// <returns>A list of <see cref="DisassembledInstruction"/>.</returns>
        public IReadOnlyList <DisassembledInstruction> RemoteDisassembleCode(IRemoteMemoryReader process, IntPtr address, int length)
        {
            Contract.Requires(process != null);
            Contract.Ensures(Contract.Result <IList <DisassembledInstruction> >() != null);

            return(RemoteDisassembleCode(process, address, length, -1));
        }
Beispiel #5
0
        private static string ReadPtrInfo(IntPtr value, IRemoteMemoryReader process)
        {
            var getTypeFnPtr = process.ReadRemoteIntPtr(value);

            if (getTypeFnPtr.MayBeValid())
            {
#if RECLASSNET64
                var offset      = process.ReadRemoteInt32(getTypeFnPtr + 3);
                var typeInfoPtr = getTypeFnPtr + offset + 7;
#else
                var typeInfoPtr = process.ReadRemoteIntPtr(getTypeFnPtr + 1);
#endif
                if (typeInfoPtr.MayBeValid())
                {
                    var typeInfoDataPtr = process.ReadRemoteIntPtr(typeInfoPtr);
                    if (typeInfoDataPtr.MayBeValid())
                    {
                        var namePtr = process.ReadRemoteIntPtr(typeInfoDataPtr);
                        if (namePtr.MayBeValid())
                        {
                            var info = process.ReadRemoteStringUntilFirstNullCharacter(namePtr, Encoding.UTF8, 64);
                            if (info.Length > 0 && info[0].IsPrintable())
                            {
                                return(info);
                            }
                        }
                    }
                }
            }

            return(null);
        }
        /// <summary>Dumps a section to the given stream.</summary>
        /// <param name="reader">The memory reader to use.</param>
        /// <param name="section">The section to dump.</param>
        /// <param name="stream">The stream to dump to.</param>
        public static void DumpSection(IRemoteMemoryReader reader, Section section, Stream stream)
        {
            Contract.Requires(section != null);
            Contract.Requires(stream != null);

            DumpRaw(reader, section.Start, section.Size.ToInt32(), stream);
        }
Beispiel #7
0
        public static IntPtr ReadRemoteIntPtr(this IRemoteMemoryReader reader, IntPtr address)
        {
#if RECLASSNET64
            return((IntPtr)reader.ReadRemoteInt64(address));
#else
            return((IntPtr)reader.ReadRemoteInt32(address));
#endif
        }
        public string ReadNodeInfo(BaseHexCommentNode node, IRemoteMemoryReader reader, MemoryBuffer memory, IntPtr nodeAddress, IntPtr nodeValue)
        {
            Contract.Requires(node != null);
            Contract.Requires(reader != null);
            Contract.Requires(memory != null);

            throw new NotImplementedException();
        }
Beispiel #9
0
        /// <summary>Tries to find and disassembles the instruction prior to the given address.</summary>
        /// <param name="process">The process to read from.</param>
        /// <param name="address">The address of the code.</param>
        /// <returns>The prior instruction.</returns>
        public DisassembledInstruction RemoteGetPreviousInstruction(IRemoteMemoryReader process, IntPtr address)
        {
            const int TotalBufferSize = 7 * MaximumInstructionLength;
            const int BufferShiftSize = 6 * MaximumInstructionLength;

            var buffer = process.ReadRemoteMemory(address - BufferShiftSize, TotalBufferSize);

            var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);

            try
            {
                var bufferAddress       = handle.AddrOfPinnedObject();
                var targetBufferAddress = bufferAddress + BufferShiftSize;

                var instruction = default(InstructionData);

                foreach (var offset in new[]
                {
                    6 * MaximumInstructionLength,
                    4 * MaximumInstructionLength,
                    2 * MaximumInstructionLength,
                    1 * MaximumInstructionLength,
                    14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
                })
                {
                    var currentAddress = targetBufferAddress - offset;

                    coreFunctions.DisassembleCode(currentAddress, offset + 1, address - offset, false, (ref InstructionData data) =>
                    {
                        var nextAddress = currentAddress + data.Length;
                        if (nextAddress.CompareTo(targetBufferAddress) > 0)
                        {
                            return(false);
                        }

                        instruction = data;

                        currentAddress = nextAddress;

                        return(true);
                    });

                    if (currentAddress == targetBufferAddress)
                    {
                        return(new DisassembledInstruction(ref instruction));
                    }
                }

                return(null);
            }
            finally
            {
                if (handle.IsAllocated)
                {
                    handle.Free();
                }
            }
        }
        /// <summary>Dumps a chunk of memory to the given stream.</summary>
        /// <param name="reader">The memory reader to use.</param>
        /// <param name="address">The begin of the chunk.</param>
        /// <param name="size">The size of the chunk.</param>
        /// <param name="stream">The stream to dump to.</param>
        public static void DumpRaw(IRemoteMemoryReader reader, IntPtr address, int size, Stream stream)
        {
            Contract.Requires(size >= 0);
            Contract.Requires(stream != null);

            var data = reader.ReadRemoteMemory(address, size);

            stream.Write(data, 0, data.Length);
        }
Beispiel #11
0
        /// <summary>Disassembles the code in the given range (<paramref name="address"/>, <paramref name="maxLength"/>) in the remote process until the first 0xCC instruction.</summary>
        /// <param name="process">The process to read from.</param>
        /// <param name="address">The address of the code.</param>
        /// <param name="maxLength">The maximum maxLength of the code.</param>
        /// <returns>A list of <see cref="DisassembledInstruction"/> which belong to the function.</returns>
        public IReadOnlyList <DisassembledInstruction> RemoteDisassembleFunction(IRemoteMemoryReader process, IntPtr address, int maxLength)
        {
            Contract.Requires(process != null);
            Contract.Ensures(Contract.Result <IEnumerable <DisassembledInstruction> >() != null);

            var buffer = process.ReadRemoteMemory(address, maxLength);

            return(DisassembleFunction(buffer, address));
        }
Beispiel #12
0
        /// <summary>Disassembles the code in the given range (<paramref name="address"/>, <paramref name="length"/>) in the remote process.</summary>
        /// <param name="process">The process to read from.</param>
        /// <param name="address">The address of the code.</param>
        /// <param name="length">The length of the code in bytes.</param>
        /// <param name="maxInstructions">The maximum number of instructions to disassemble. If <paramref name="maxInstructions"/> is -1, all available instructions get returned.</param>
        /// <returns>A list of <see cref="DisassembledInstruction"/>.</returns>
        public IReadOnlyList <DisassembledInstruction> RemoteDisassembleCode(IRemoteMemoryReader process, IntPtr address, int length, int maxInstructions)
        {
            Contract.Requires(process != null);
            Contract.Ensures(Contract.Result <IList <DisassembledInstruction> >() != null);

            var buffer = process.ReadRemoteMemory(address, length);

            return(DisassembleCode(buffer, address, maxInstructions));
        }
        /// <summary>Dumps a module to the given stream. The section headers of the pe header get fixed to build a valid pe file.</summary>
        /// <param name="reader">The memory reader to use.</param>
        /// <param name="module">The module to dump.</param>
        /// <param name="stream">The stream to dump to.</param>
        public static void DumpModule(IRemoteMemoryReader reader, Module module, Stream stream)
        {
            Contract.Requires(module != null);
            Contract.Requires(stream != null);

            var data = reader.ReadRemoteMemory(module.Start, module.Size.ToInt32());

            SimplePeHeader.FixSectionHeaders(data);

            stream.Write(data, 0, data.Length);
        }
Beispiel #14
0
        /// <summary>Tries to find the start address of the function <paramref name="address"/> points into.</summary>
        /// <param name="process">The process to read from.</param>
        /// <param name="address">The address inside the function.</param>
        /// <returns>The start address of the function (maybe) or <see cref="IntPtr.Zero"/> if no start address could be found.</returns>
        public IntPtr RemoteGetFunctionStartAddress(IRemoteMemoryReader process, IntPtr address)
        {
            const int BufferLength = 512;

            var buffer = new byte[2 + BufferLength + 2 + 1];

            for (var i = 1; i <= 10; ++i)
            {
                if (!process.ReadRemoteMemoryIntoBuffer(address - i * BufferLength - 2, ref buffer))
                {
                    return(IntPtr.Zero);
                }

                for (var o = BufferLength + 4; o > 0; --o)
                {
                    // Search for two CC in a row.
                    if (buffer[o] == 0xCC && buffer[o - 1] == 0xCC)
                    {
                        var start = address - i * BufferLength + o - 1;

                        // Check if the two previous instructions are really a CC.
                        var prevInstruction = RemoteGetPreviousInstruction(process, start);
                        if (prevInstruction.Length == 1 && prevInstruction.Data[0] == 0xCC)
                        {
                            prevInstruction = RemoteGetPreviousInstruction(process, start - 1);
                            if (prevInstruction.Length == 1 && prevInstruction.Data[0] == 0xCC)
                            {
                                // Disassemble the code from the start and check if the instructions sum up to address.
                                var totalInstructionLength = RemoteDisassembleCode(process, start, address.Sub(start).ToInt32())
                                                             .Sum(ins => ins.Length);
                                if (start + totalInstructionLength == address)
                                {
                                    return(start);
                                }
                            }
                            else
                            {
                                o -= prevInstruction.Length;
                            }
                        }
                        else
                        {
                            o -= prevInstruction.Length;
                        }
                    }
                }
            }

            return(IntPtr.Zero);
        }
Beispiel #15
0
        public string ReadNodeInfo(BaseHexCommentNode node, IRemoteMemoryReader reader, MemoryBuffer memory, IntPtr nodeAddress, IntPtr nodeValue)
        {
            // 1. try the direct value
            var info = ReadPtrInfo(nodeValue, reader);

            if (!string.IsNullOrEmpty(info))
            {
                return(info);
            }

            // 2. try indirect pointer
            var indirectPtr = reader.ReadRemoteIntPtr(nodeValue);

            if (indirectPtr.MayBeValid())
            {
                info = ReadPtrInfo(indirectPtr, reader);
                if (!string.IsNullOrEmpty(info))
                {
                    return($"Ptr -> {info}");
                }

                // 3. try weak pointer
                var weakTempPtr = indirectPtr - IntPtr.Size;
                if (weakTempPtr.MayBeValid())
                {
                    var weakPtr = reader.ReadRemoteIntPtr(weakTempPtr);
                    if (weakPtr.MayBeValid())
                    {
                        info = ReadPtrInfo(weakPtr, reader);
                        if (!string.IsNullOrEmpty(info))
                        {
                            return($"WeakPtr -> {info}");
                        }
                    }
                }
            }

            return(null);
        }
Beispiel #16
0
        /// <summary>
        /// Used to print custom informations about a node.
        /// </summary>
        /// <param name="node">The node.</param>
        /// <param name="reader">The current <see cref="T:ReClassNET.Memory.IRemoteMemoryReader" />.</param>
        /// <param name="memory">The current <see cref="T:ReClassNET.Memory.MemoryBuffer" />.</param>
        /// <param name="nodeAddress">The absolute address of the node.</param>
        /// <param name="nodeValue">The memory value of the node as <see cref="T:System.IntPtr" />.</param>
        public string ReadNodeInfo(BaseHexCommentNode node, IRemoteMemoryReader reader, MemoryBuffer memory, IntPtr nodeAddress, IntPtr nodeValue)
        {
            if (nodeValue.IsNull() || _base.NameDump.Count is 0)
            {
                return(null);
            }

            dynamic uobject = null;

            switch (_base.Game)
            {
            case UE3PluginExt.GameType.KillingFloor2:
            {
                uobject = reader.ReadRemoteObject <KillingFloor2.UObject>(nodeValue);
                break;
            }

            case UE3PluginExt.GameType.RocketLeague:
            {
                uobject = reader.ReadRemoteObject <RocketLeague.UObject>(nodeValue);
                break;
            }
            }

            if (uobject.Name.Index < 0 || uobject.Name.Index >= _base.NameDump.Count)
            {
                return(null);
            }

            if (_base.NameDump.TryGetValue(uobject.Name.Index, out string name))
            {
                return(name);
            }

            return(null);
        }
 /// <summary>This method lets ReClass.NET print the name and the value of the node.</summary>
 public string ReadNodeInfo(BaseHexCommentNode node, IRemoteMemoryReader reader, MemoryBuffer memory, IntPtr nodeAddress, IntPtr nodeValue)
 {
     return($"{node.Name}@{nodeAddress.ToString("X")} => {nodeValue.ToString("X")}");
 }
Beispiel #18
0
        public static byte ReadRemoteUInt8(this IRemoteMemoryReader reader, IntPtr address)
        {
            var data = reader.ReadRemoteMemory(address, sizeof(byte));

            return(data[0]);
        }
Beispiel #19
0
        public static ushort ReadRemoteUInt16(this IRemoteMemoryReader reader, IntPtr address)
        {
            var data = reader.ReadRemoteMemory(address, sizeof(ushort));

            return(reader.BitConverter.ToUInt16(data, 0));
        }
Beispiel #20
0
        public static int ReadRemoteInt32(this IRemoteMemoryReader reader, IntPtr address)
        {
            var data = reader.ReadRemoteMemory(address, sizeof(int));

            return(reader.BitConverter.ToInt32(data, 0));
        }
Beispiel #21
0
        public static double ReadRemoteDouble(this IRemoteMemoryReader reader, IntPtr address)
        {
            var data = reader.ReadRemoteMemory(address, sizeof(double));

            return(reader.BitConverter.ToDouble(data, 0));
        }
Beispiel #22
0
        public static float ReadRemoteFloat(this IRemoteMemoryReader reader, IntPtr address)
        {
            var data = reader.ReadRemoteMemory(address, sizeof(float));

            return(reader.BitConverter.ToSingle(data, 0));
        }
Beispiel #23
0
        public static ulong ReadRemoteUInt64(this IRemoteMemoryReader reader, IntPtr address)
        {
            var data = reader.ReadRemoteMemory(address, sizeof(ulong));

            return(reader.BitConverter.ToUInt64(data, 0));
        }