Esempio n. 1
0
        /// <summary>
        /// A simple method example which demonstrates the <see cref="IMemory"/> interface.
        /// </summary>
        /// <param name="memory">This object is used to perform memory read/write/free/allocate operations.</param>
        /// <param name="memoryLocation">Arbitrary location in memory where this tutorial will be held.</param>
        private static void MemorySourceExample(IMemory memory, IntPtr memoryLocation)
        {
            // Earlier in the program; we have been writing generics to the program's memory using the 'Memory' class
            // implementing the IMemory interface. Well... that isn't the only stock class that implements this interface.

            // The implementation of `Memory` is just one of them; one that lets you read/write inside the current process.
            // Others you can find within Reloaded.Memory.Sources.

            // Well; let's look at another IMemory implementation, one that lets you read/write a DIFFERENT process.

            IMemory anotherProcessMemory = new ExternalMemory(Process.GetCurrentProcess());

            // ExternalMemory is yet another implementation of IMemory; allowing you to read from another process.
            // In this case we have pointed it at the current process - now let's show this working.

            // Write "1337" to memory address in external process.
            int leet = 1337;

            anotherProcessMemory.Write(memoryLocation, leet);

            // Read "1337" written by "another process" using our IMemory implementation (Memory) that reads from current process.
            memory.Read(memoryLocation, out int anotherLeet);

            // Implementing the IMemory interface is quite easy; especially with the many tools in the <Struct> class.

            // Extra note: Overloads for IMemory are implemented as Extension Methods
            // Make sure to add `using Reloaded.Memory.Sources;` in your own projects.
        }
Esempio n. 2
0
        /// <summary>
        /// Provides the implementation of a primitive DLL injector, supporting injection into
        /// suspended process.
        /// </summary>
        public BasicDllInjector(Process process)
        {
            // Set the Location and Handle to the Process to be Injected.
            _process = process;
            _memory  = new ExternalMemory(process);

            _loadLibraryAddress = _process.Is64Bit() ? x64LoadLibraryAddress : x86LoadLibraryAddress;
        }
Esempio n. 3
0
        /// <summary>
        /// The legacy implementation of Rip.
        /// </summary>
        private static void LegacyRip(LegacyRipOptions options)
        {
            // Read emulated memory.
            var process = new ExternalMemory(Process.GetProcessesByName(options.ProcessName)[0]);

            process.ReadRaw((IntPtr)options.MinRamAddress, out var ps2Memory, 0x2000000);

            // Parse known file list.
            var sizeToFileMap = JsonFile.FromFileAsSizeToFileMap(options.JsonPath);

            // Read PCSX2 Logs
            using var fileStream = new FileStream(options.LogPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            var logData = new byte[fileStream.Length];

            fileStream.Read(logData);

            var pcsx2CrashLog     = Encoding.UTF8.GetString(logData);
            var pcsx2CrashLogInfo = new ParsedCrashLog(pcsx2CrashLog.Replace("\r\n", "\n"));

            // Pattern scan for archive:
            // Build search string.
            var searchPatternBuilder = new StringBuilder($"{(options.GroupNum != -1 ? options.GroupNum.ToString("X8") : "??")} 00 00 00 "); // Note: Assuming less than 255 items!

            var groupItemCountBytes = pcsx2CrashLogInfo.Metadata.Select(x => x.NoOfItems).ToArray();
            var itemCountPattern    = Utilities.BytesToScanPattern(groupItemCountBytes);

            searchPatternBuilder.Append(itemCountPattern);

            // Scan for potential matches.
            var scanner       = new Scanner(ps2Memory);
            var patterns      = Utilities.FindAllPatterns(scanner, new CompiledScanPattern(searchPatternBuilder.ToString()));
            int archiveOffset = patterns[0].Offset;

            // Handle multiple matches.
            if (patterns.Count > 1)
            {
                // Note: Not tested.
                Console.WriteLine("More than 1 match for possible archive data. Trying to reconstruct header and searching for ID. (Note: This code is not yet implemented, exiting!)");
                return;
            }

            // Extract match from memory.
            if (sizeToFileMap.TryGetValue(pcsx2CrashLogInfo.FileSize, out var fileInfoList))
            {
                // Get user picked entry from list.
                var entry = RipUserSelectEntryFromList(fileInfoList);

                // Save file.
                var slice = ps2Memory.AsSpan().Slice(archiveOffset, entry.UncompressedSize);
                RipWriteFileToFolder(options.OutputPath, entry, slice);
            }
            else
            {
                Console.WriteLine($"No known file in JSON found. File Size from Crashlog: 0x{pcsx2CrashLogInfo.FileSize:X}");
            }
        }
        /// <summary>
        /// Creates a signature scanner given a process and a module (EXE/DLL)
        /// from which the signatures are to be found.
        /// </summary>
        /// <param name="process">The process from which</param>
        /// <param name="module">An individual module of the given process, which</param>
        public Scanner(Process process, ProcessModule module)
        {
            var externalProcess = new ExternalMemory(process);

            externalProcess.ReadRaw(module.BaseAddress, out var data, module.ModuleMemorySize);

            _data     = data;
            _gcHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
            _dataPtr  = (byte *)_gcHandle.AddrOfPinnedObject();
        }
Esempio n. 5
0
        private long _getProcAddressReturnValuePtr; /* Address of GetProcAddress' return value. */

        /// <summary>
        /// Builds the shellcode necessary to successfully call LoadLibraryW and GetProcAddress
        /// inside the address space of another executable.
        /// </summary>
        /// <param name="targetProcess">Process inside which to execute.</param>
        public Shellcode(Process targetProcess)
        {
            Safety.WaitForModuleInitialization(targetProcess);

            _privateBuffer  = new MemoryBufferHelper(targetProcess).CreatePrivateMemoryBuffer(4096);
            _assembler      = new Assembler.Assembler();
            _memory         = new ExternalMemory(targetProcess);
            _circularBuffer = new CircularBuffer(4096, _memory);
            _targetProcess  = targetProcess;

            // Get arch of target process.
            PeFile targetPeFile = new PeFile(targetProcess.Modules[0].FileName);

            _machineType = (MachineType)targetPeFile.ImageNtHeaders.FileHeader.Machine;

            // Get Kernel32 load address in target.
            Module kernel32Module = GetKernel32InRemoteProcess(targetProcess);

            Kernel32Handle = (long)kernel32Module.BaseAddress;

            // We need to change the module path if 32bit process; because the given path is not true,
            // it is being actively redirected by Windows on Windows 64 (WoW64)
            if (_machineType == MachineType.I386)
            {
                StringBuilder builder = new StringBuilder(256);
                GetSystemWow64Directory(builder, (uint)builder.Capacity);
                kernel32Module.ModulePath = builder.ToString() + "\\" + Path.GetFileName(kernel32Module.ModulePath);
            }

            // Parse Kernel32 loaded by target and get address of LoadLibrary & GetProcAddress.
            PeFile kernel32PeFile    = new PeFile(kernel32Module.ModulePath);
            var    exportedFunctions = kernel32PeFile.ExportedFunctions;

            _loadLibraryWOffset   = GetExportedFunctionOffset(exportedFunctions, "LoadLibraryW");
            _getProcAddressOffset = GetExportedFunctionOffset(exportedFunctions, "GetProcAddress");

            if (_loadLibraryWOffset == 0 || _getProcAddressOffset == 0)
            {
                throw new ShellCodeGeneratorException("Failed to find GetProcAddress or LoadLibraryW methods in target process' Kernel32.");
            }

            if (_machineType == MachineType.AMD64)
            {
                BuildLoadLibraryW64();
                BuildGetProcAddress64();
            }
            else
            {
                BuildLoadLibraryW86();
                BuildGetProcAddress86();
            }

            _assembler.Dispose();
            _assembler = null;
        }
        /// <summary>
        /// Tests the "Add" functionality of the <see cref="MemoryBuffer"/>; including
        /// the return of the correct pointer and CanItemFit.
        /// </summary>
        private unsafe void MemoryBufferAddGeneric(MemoryBuffer buffer, Process process)
        {
            // Setup test.
            ExternalMemory externalMemory = new ExternalMemory(process);

            // Disable item alignment.
            var bufferHeader = buffer.Properties;

            buffer.Properties = bufferHeader;

            // Get remaining space, items to place.
            int remainingBufferSpace = bufferHeader.Remaining;
            int structSize           = Struct.GetSize <RandomIntStruct>();
            int itemsToFit           = remainingBufferSpace / structSize;

            // Generate array of random int structs.
            RandomIntStruct[] randomIntStructs = new RandomIntStruct[itemsToFit];

            for (int x = 0; x < itemsToFit; x++)
            {
                randomIntStructs[x] = RandomIntStruct.BuildRandomStruct();
            }

            // Fill the buffer and verify each item as it's added.
            for (int x = 0; x < itemsToFit; x++)
            {
                IntPtr writeAddress = buffer.Add(ref randomIntStructs[x], false, 1);

                // Read back and compare.
                externalMemory.Read(writeAddress, out RandomIntStruct actual);
                Assert.Equal(randomIntStructs[x], actual);
            }

            // Compare again, running the entire array this time.
            IntPtr bufferStartPtr = bufferHeader.DataPointer;

            for (int x = 0; x < itemsToFit; x++)
            {
                IntPtr readAddress = bufferStartPtr + (x * structSize);

                // Read back and compare.
                externalMemory.Read(readAddress, out RandomIntStruct actual);
                Assert.Equal(randomIntStructs[x], actual);
            }

            // The array is full, calling CanItemFit should return false.
            Assert.False(buffer.CanItemFit(ref randomIntStructs[0]));

            // Likewise, calling Add should return IntPtr.Zero.
            var randIntStr = RandomIntStruct.BuildRandomStruct();

            Assert.Equal(IntPtr.Zero, buffer.Add(ref randIntStr, false, 1));
        }
Esempio n. 7
0
        /// <summary>
        /// A simple method example which demonstrates struct Array operations.
        /// </summary>
        /// <param name="memory">This object is used to perform memory read/write/free/allocate operations.</param>
        /// <param name="memoryLocation">Arbitrary location in memory where this tutorial will be held.</param>
        private static void StructArrayExample(IMemory memory, IntPtr memoryLocation)
        {
            // Let's load a binary file from the disk and write it to memory.
            const int itemCount = 40; // Number of items in struct array (known).

            byte[] physicsData = File.ReadAllBytes($"phys.bin");
            memory.WriteRaw(memoryLocation, physicsData);

            // Array Read & Write from/to Memory
            memory.Read(memoryLocation, out AdventurePhysics[] adventurePhysicsData, itemCount);
            memory.Write(memoryLocation, adventurePhysicsData);

            // Pointer to array in memory. Provides enhanced functionality over a standard pointer.
            var adventurePhysics = new ArrayPtr <AdventurePhysics>((ulong)memoryLocation);

            adventurePhysics.Get(out AdventurePhysics value, 0);                        // And of course read/writes work..
                                                                                        // Uh? Yeah, for performance the indexer is not overwritten.
            float speedCap = value.HorizontalSpeedCap;

            // Pointer to array in memory with known length. Provides even extra functionality. (Like foreach, LINQ)
            var   adventurePhysicsFixed  = new FixedArrayPtr <AdventurePhysics>((ulong)memoryLocation, itemCount);
            float averageAirAcceleration = adventurePhysicsFixed.Average(physics => physics.AirAcceleration); // LINQ

            // All of these classes support read/writes from arbitrary memory of course...
            // this is where `IMemory` comes in after all.
            IMemory anotherProcessMemory     = new ExternalMemory(Process.GetCurrentProcess());
            var     physicsFixedOtherProcess = new FixedArrayPtr <AdventurePhysics>((ulong)memoryLocation, itemCount, false, anotherProcessMemory);
            float   averageAirAcceleration2  = physicsFixedOtherProcess.Average(physics => physics.AirAcceleration);

            // What you just witnessed was LINQ over arbitrary structs inside memory of another process.

            // Foreach loop over structs in other processes? Of course.
            float greatestInitialJump = float.MinValue;
            float smallestInitialJump = float.MaxValue;

            foreach (var physics in physicsFixedOtherProcess)
            {
                if (physics.InitialJumpSpeed > greatestInitialJump)
                {
                    greatestInitialJump = physics.InitialJumpSpeed;
                }

                if (physics.InitialJumpSpeed < smallestInitialJump)
                {
                    smallestInitialJump = physics.InitialJumpSpeed;
                }
            }

            Console.WriteLine($"LINQ Over Arbitrary Memory: {averageAirAcceleration} (Average air Acceleration in Sonic Adventure-Heroes)");
            Console.WriteLine($"LINQ Over Memory in Another Process: {greatestInitialJump - smallestInitialJump} (Sonic Adventure-Heroes Physics delta between jump speeds)");
        }
Esempio n. 8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Injector"/> class.
        /// </summary>
        /// <param name="targetProcess">Process to inject.</param>
        public Injector(Process targetProcess)
        {
            this.targetProcess = targetProcess;

            this.extMemory      = new ExternalMemory(targetProcess);
            this.circularBuffer = new CircularBuffer(4096, this.extMemory);
            this.privateBuffer  = new MemoryBufferHelper(targetProcess).CreatePrivateMemoryBuffer(4096);

            using var kernel32Module = this.GetProcessModule("KERNEL32.DLL");
            var kernel32PeFile  = new PeFile(kernel32Module.FileName);
            var kernel32Exports = kernel32PeFile.ExportedFunctions;

            this.SetupLoadLibrary(kernel32Module, kernel32Exports);
            this.SetupGetProcAddress(kernel32Module, kernel32Exports);
        }
Esempio n. 9
0
        /// <summary>
        /// Creates a signature scanner given a process and a module (EXE/DLL)
        /// from which the signatures are to be found.
        /// </summary>
        /// <param name="process">The process from which to scan patterns in. (Not Null)</param>
        /// <param name="module">An individual module of the given process, which denotes the start and end of memory region scanned.</param>
        public Scanner(Process process, ProcessModule module)
        {
            // Optimization
            if (process.Id == _currentProcess.Id)
            {
                _dataPtr    = (byte *)module.BaseAddress;
                _dataLength = module.ModuleMemorySize;
            }
            else
            {
                var externalProcess = new ExternalMemory(process);
                externalProcess.ReadRaw(module.BaseAddress, out var data, module.ModuleMemorySize);

                _gcHandle   = GCHandle.Alloc(data, GCHandleType.Pinned);
                _dataPtr    = (byte *)_gcHandle.Value.AddrOfPinnedObject();
                _dataLength = data.Length;
            }
        }
        private void AllocateFree()
        {
            for (int x = 0; x < 20; x++)
            {
                // Commit
                var buf    = _bufferHelper.Allocate(4096);
                var extBuf = _externalBufferHelper.Allocate(4096);

                // Write something to start of buffers to test allocation.
                var bufMem    = new Sources.Memory();
                var extBufMem = new ExternalMemory(_externalBufferHelper.Process);

                bufMem.Write(buf.MemoryAddress, 5);
                extBufMem.Write(extBuf.MemoryAddress, 5);

                // Release
                _bufferHelper.Free(buf.MemoryAddress);
                _externalBufferHelper.Free(extBuf.MemoryAddress);
            }
        }
        /// <summary>
        /// Tests the "Add" functionality of the <see cref="MemoryBuffer"/>, with raw data;
        /// including the return of the correct pointer and CanItemFit.
        /// </summary>
        private unsafe void MemoryBufferAddByteArray(MemoryBuffer buffer, Process process)
        {
            // Setup test.
            ExternalMemory externalMemory = new ExternalMemory(process);

            // Disable item alignment.
            var bufferHeader = buffer.Properties;

            buffer.Properties = bufferHeader;

            // Get remaining space, items to place.
            int remainingBufferSpace = bufferHeader.Remaining;
            var randomByteArray      = RandomByteArray.GenerateRandomByteArray(remainingBufferSpace);

            byte[] rawArray = randomByteArray.Array;

            // Fill the buffer with the whole array.
            buffer.Add(rawArray, 1);

            // Compare against the array written.
            IntPtr bufferStartPtr = bufferHeader.DataPointer;

            for (int x = 0; x < remainingBufferSpace; x++)
            {
                IntPtr readAddress = bufferStartPtr + x;

                // Read back and compare.
                externalMemory.Read(readAddress, out byte actual);
                Assert.Equal(rawArray[x], actual);
            }

            // The array is full, calling CanItemFit should return false.
            Assert.False(buffer.CanItemFit(sizeof(byte)));

            // Likewise, calling Add should return IntPtr.Zero.
            byte testByte = 55;

            Assert.Equal(IntPtr.Zero, buffer.Add(ref testByte, false, 1));
        }
Esempio n. 12
0
        /// <summary>
        /// The new implementation of Rip.
        /// </summary>
        private static void NewRip(RipOptions options)
        {
            // Read emulated memory.
            var process = new ExternalMemory(Process.GetProcessesByName(options.ProcessName)[0]);

            // Parse known file list.
            var sizeToFileMap = JsonFile.FromFileAsSizeToFileMap(options.JsonPath);

            // Read PCSX2 Logs
            using var fileStream = new FileStream(options.LogPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            var logData = new byte[fileStream.Length];

            fileStream.Read(logData);

            // Get size, address from log.
            var pcsx2Log        = Encoding.UTF8.GetString(logData);
            var memoryDumpRegex = new Regex(@"^Addr: ([\d]*) , Size: ([\d]*), DumpFlagAddr: ([\d]*) [\n\r]+", RegexOptions.Multiline);
            var lastMatch       = memoryDumpRegex.Matches(pcsx2Log).Last();
            var archiveOffset   = Convert.ToInt32(lastMatch.Groups[1].Value);
            var fileSize        = Convert.ToInt32(lastMatch.Groups[2].Value);
            var dumpFlagAddr    = Convert.ToInt32(lastMatch.Groups[3].Value);

            // Extract match from memory.
            if (sizeToFileMap.TryGetValue(fileSize, out var fileInfoList))
            {
                var entry = RipUserSelectEntryFromList(fileInfoList);
                process.ReadRaw((IntPtr)(options.MinRamAddress + archiveOffset), out var file, entry.UncompressedSize);
                RipWriteFileToFolder(options.OutputPath, entry, file);
            }
            else
            {
                Console.WriteLine($"No known file in JSON found. Allowing game to advance.");
            }

            process.SafeWrite <int>((IntPtr)(options.MinRamAddress + dumpFlagAddr), 1);
        }
Esempio n. 13
0
 /// <summary>
 /// Provides the implementation of a primitive DLL injector, supporting injection into
 /// suspended process.
 /// </summary>
 public BasicDllInjector(Process process)
 {
     // Set the Location and Handle to the Process to be Injected.
     _process = process;
     _memory  = new ExternalMemory(process);
 }