protected ExportedModuleTestBase(string modulePath)
        {
            mbbsEmuMemoryCore   = new MemoryCore();
            mbbsEmuCpuRegisters = new CpuRegisters();
            mbbsEmuCpuCore      = new CpuCore();
            mbbsModule          = new MbbsModule(FileUtility.CreateForTest(), _serviceResolver.GetService <ILogger>(), null, modulePath, mbbsEmuMemoryCore);

            testSessions = new PointerDictionary <SessionBase>();
            testSessions.Allocate(new TestSession(null));
            testSessions.Allocate(new TestSession(null));

            majorbbs = new HostProcess.ExportedModules.Majorbbs(
                _serviceResolver.GetService <ILogger>(),
                _serviceResolver.GetService <AppSettings>(),
                _serviceResolver.GetService <IFileUtility>(),
                _serviceResolver.GetService <IGlobalCache>(),
                mbbsModule,
                testSessions,
                _serviceResolver.GetService <IAccountKeyRepository>(),
                _serviceResolver.GetService <IAccountRepository>());

            galgsbl = new HostProcess.ExportedModules.Galgsbl(
                _serviceResolver.GetService <ILogger>(),
                _serviceResolver.GetService <AppSettings>(),
                _serviceResolver.GetService <IFileUtility>(),
                _serviceResolver.GetService <IGlobalCache>(),
                mbbsModule,
                testSessions);

            mbbsEmuCpuCore.Reset(mbbsEmuMemoryCore, mbbsEmuCpuRegisters, ExportedFunctionDelegate);
        }
        /// <summary>
        ///     Reads the four by four matrix.
        /// </summary>
        /// <param name="handle">The handle to the process where the matrix is located in memory.</param>
        /// <param name="lpBaseAddress">The <see cref="IntPtr" /> address of where the four by four matrix is located in memory.</param>
        /// <returns></returns>
        public static Matrix4X4 ReadFourByFourMatrix(SafeMemoryHandle handle, IntPtr lpBaseAddress)
        {
            var tmp = new Matrix4X4();

            var buffer = MemoryCore.ReadBytes(handle, lpBaseAddress, 64);

            tmp.M11 = BitConverter.ToSingle(buffer, 0 * 4);
            tmp.M12 = BitConverter.ToSingle(buffer, 1 * 4);
            tmp.M13 = BitConverter.ToSingle(buffer, 2 * 4);
            tmp.M14 = BitConverter.ToSingle(buffer, 3 * 4);

            tmp.M21 = BitConverter.ToSingle(buffer, 4 * 4);
            tmp.M22 = BitConverter.ToSingle(buffer, 5 * 4);
            tmp.M23 = BitConverter.ToSingle(buffer, 6 * 4);
            tmp.M24 = BitConverter.ToSingle(buffer, 7 * 4);

            tmp.M31 = BitConverter.ToSingle(buffer, 8 * 4);
            tmp.M32 = BitConverter.ToSingle(buffer, 9 * 4);
            tmp.M33 = BitConverter.ToSingle(buffer, 10 * 4);
            tmp.M34 = BitConverter.ToSingle(buffer, 11 * 4);

            tmp.M41 = BitConverter.ToSingle(buffer, 12 * 4);
            tmp.M42 = BitConverter.ToSingle(buffer, 13 * 4);
            tmp.M43 = BitConverter.ToSingle(buffer, 14 * 4);
            tmp.M44 = BitConverter.ToSingle(buffer, 15 * 4);
            return(tmp);
        }
Beispiel #3
0
 protected MajorbbsTestBase()
 {
     mbbsEmuMemoryCore   = new MemoryCore();
     mbbsEmuCpuRegisters = new CpuRegisters();
     mbbsEmuCpuCore      = new CpuCore();
     majorbbs            = new HostProcess.ExportedModules.Majorbbs(new MbbsModule(null, string.Empty, mbbsEmuMemoryCore), new PointerDictionary <Session.SessionBase>());
     mbbsEmuCpuCore.Reset(mbbsEmuMemoryCore, mbbsEmuCpuRegisters, MajorbbsFunctionDelegate);
 }
Beispiel #4
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="RemoteModule" /> class.
 /// </summary>
 /// <param name="memorySharp">The reference of the <see cref="MemorySharp" /> object.</param>
 /// <param name="module">The native <see cref="ProcessModule" /> object corresponding to this module.</param>
 internal RemoteModule(MemoryBase memorySharp, ProcessModule module) : base(memorySharp, module.BaseAddress)
 {
     // Save the parameter
     Native   = module;
     LazyData =
         new Lazy <byte[]>(
             () => MemoryCore.ReadBytes(memorySharp.Handle, module.BaseAddress, module.ModuleMemorySize));
 }
Beispiel #5
0
 /// <summary>
 /// Write an array of bytes in the remote process.
 /// </summary>
 /// <param name="address">The address where the array is written.</param>
 /// <param name="byteArray">The array of bytes to write.</param>
 /// <param name="isRelative">[Optional] State if the address is relative to the main module.</param>
 protected void WriteBytes(IntPtr address, byte[] byteArray, bool isRelative = true)
 {
     // Change the protection of the memory to allow writable
     using (new MemoryProtection(this, isRelative ? MakeAbsolute(address) : address, MarshalType <byte> .Size * byteArray.Length))
     {
         // Write the byte array
         MemoryCore.WriteBytes(Handle, isRelative ? MakeAbsolute(address) : address, byteArray);
     }
 }
Beispiel #6
0
 /// <summary>
 ///     Writes a set of bytes to memory.
 /// </summary>
 /// <param name="address">The address.</param>
 /// <param name="bytes">The bytes.</param>
 /// <param name="isRelative">if set to <c>true</c> [is relative].</param>
 /// <returns>
 ///     Number of bytes written.
 /// </returns>
 public override int WriteBytes(IntPtr address, byte[] bytes, bool isRelative = false)
 {
     // Change the protection of the memory to allow writable
     using (
         new MemoryProtection(this, isRelative ? GetAbsolute(address) : address,
                              MarshalType <byte> .Size * bytes.Length))
     {
         // Write the byte array
         MemoryCore.WriteBytes(Handle, isRelative ? GetAbsolute(address) : address, bytes);
     }
     return(bytes.Length);
 }
        public void CreateRemoteThread()
        {
            // Arrange
            var handle = MemoryCore.OpenProcess(ProcessAccessFlags.AllAccess, Resources.ProcessTest.Id);

            // Act
            var thread   = ThreadCore.CreateRemoteThread(handle, new IntPtr(1), IntPtr.Zero, ThreadCreationFlags.Suspended);
            var threadId = HandleManipulator.HandleToThreadId(thread);

            // Assert
            Assert.IsFalse(thread.IsInvalid);
            Assert.IsTrue(Resources.ProcessTest.Threads.Cast <ProcessThread>().Any(t => t.Id == threadId));
        }
        public void VirtualQueryEx_AnyProcess_ListAllMemoryPages()
        {
            // Arrange
            var handle   = Resources.MemorySharp.Handle;
            var starting = new IntPtr(0);
            var ending   = new IntPtr(0x07fffffff);

            // Act
            var regions = MemoryCore.Query(handle, starting, ending);

            // Assert
            Assert.AreNotEqual(0, regions.Count(), "Memory pages cannot be gathered.");
        }
Beispiel #9
0
 protected MajorbbsTestBase()
 {
     mbbsEmuMemoryCore   = new MemoryCore();
     mbbsEmuCpuRegisters = new CpuRegisters();
     mbbsEmuCpuCore      = new CpuCore();
     mbbsModule          = new MbbsModule(FileUtility.CreateForTest(), _serviceResolver.GetService <ILogger>(), null, string.Empty, mbbsEmuMemoryCore);
     majorbbs            = new HostProcess.ExportedModules.Majorbbs(
         _serviceResolver.GetService <ILogger>(),
         _serviceResolver.GetService <IConfiguration>(),
         _serviceResolver.GetService <IFileUtility>(),
         _serviceResolver.GetService <IGlobalCache>(),
         mbbsModule,
         new PointerDictionary <Session.SessionBase>());
     mbbsEmuCpuCore.Reset(mbbsEmuMemoryCore, mbbsEmuCpuRegisters, MajorbbsFunctionDelegate);
 }
Beispiel #10
0
        public void AllocateFree()
        {
            // Arrange
            var handle = MemoryCore.OpenProcess(ProcessAccessFlags.AllAccess, Resources.ProcessTest.Id);

            // Act
            try
            {
                var address = MemoryCore.Allocate(handle, 1);
                MemoryCore.Free(handle, address);
            }
            catch (Win32Exception ex)
            {
                Assert.Fail(ex.Message);
            }
        }
Beispiel #11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MemorySharp"/> class.
 /// </summary>
 /// <param name="process">Process to open.</param>
 public MemorySharp(Process process)
 {
     // Save the reference of the process
     Native = process;
     // Open the process with all rights
     Handle = MemoryCore.OpenProcess(ProcessAccessFlags.AllAccess, process.Id);
     // Initialize the PEB
     Peb = new ManagedPeb(this, ManagedPeb.FindPeb(Handle));
     // Create instances of the factories
     Factories = new List <IFactory>();
     Factories.AddRange(
         new IFactory[] {
         Assembly = new AssemblyFactory(this),
         Memory   = new MemoryFactory(this),
         Modules  = new ModuleFactory(this),
         Threads  = new ThreadFactory(this),
         Windows  = new WindowFactory(this)
     });
 }
Beispiel #12
0
        public void VirtualProtectExWriteReadBytes()
        {
            // Arrange
            var handle   = MemoryCore.OpenProcess(ProcessAccessFlags.AllAccess, Resources.ProcessTest.Id);
            var expected = new byte[] { 0x90, 0x90, 0x90, 0x90, 0x90 };
            var memory   = new IntPtr(0x00400000);

            // Act
            try
            {
                MemoryCore.ChangeProtection(handle, memory, 5, MemoryProtectionFlags.ExecuteReadWrite);
                MemoryCore.WriteBytes(handle, memory, expected);
                var actual = MemoryCore.ReadBytes(handle, memory, 5);

                // Assert
                CollectionAssert.AreEqual(expected, actual, "The collections are not equal.");
            }
            catch (Win32Exception ex)
            {
                Assert.Fail(ex.Message);
            }
        }
 /// <summary>
 ///     Performs a pattern scan.
 /// </summary>
 /// <param name="processHandle">The process the <see cref="ProcessModule" /> containing the data resides in.</param>
 /// <param name="processModule">The <see cref="ProcessModule" /> that contains the pattern data resides in.</param>
 /// <param name="data">The array of bytes containing the data to search for matches in.</param>
 /// <param name="mask">
 ///     The mask that defines the byte pattern we are searching for.
 ///     <example>
 ///         <code>
 /// var bytes = new byte[]{55,45,00,00,55} ;
 /// var mask = "xx??x";
 /// </code>
 ///     </example>
 /// </param>
 /// <param name="offsetToAdd">The offset to add to the offset result found from the pattern.</param>
 /// <param name="reBase">If the address should be rebased to this  Instance's base address.</param>
 /// <param name="wildCardChar">
 ///     [Optinal] The 'wild card' defines the <see cref="char" /> value that the mask uses to differentiate
 ///     between pattern data that is relevant, and pattern data that should be ignored. The default value is 'x'.
 /// </param>
 /// <param name="pattern">The byte array that contains the pattern of bytes we're looking for.</param>
 /// <returns>A new <see cref="PatternScanResult" /> instance.</returns>
 public static PatternScanResult Find(SafeMemoryHandle processHandle, ProcessModule processModule, byte[] data,
                                      byte[] pattern,
                                      string mask, int offsetToAdd, bool reBase, char wildCardChar = 'x')
 {
     for (var offset = 0; offset < data.Length; offset++)
     {
         if (mask.Where((m, b) => m == 'x' && pattern[b] != data[b + offset]).Any())
         {
             continue;
         }
         var found = MemoryCore.Read <IntPtr>(processHandle,
                                              processModule.BaseAddress + offset + offsetToAdd);
         var result = new PatternScanResult
         {
             OriginalAddress = found,
             Address         = reBase ? found : found.Subtract(processModule.BaseAddress),
             Offset          = (IntPtr)offset
         };
         return(result);
     }
     // If this is reached, the pattern was not found.
     throw new Exception("The pattern scan for the pattern mask: " + "[" + mask + "]" + " was not found.");
 }
        protected ExportedModuleTestBase(string modulePath)
        {
            _serviceResolver = new ServiceResolver(fakeClock, SessionBuilder.ForTest($"MBBSDb_{RANDOM.Next()}"));
            var textVariableService = _serviceResolver.GetService <ITextVariableService>();

            mbbsEmuMemoryCore   = new MemoryCore();
            mbbsEmuCpuRegisters = new CpuRegisters();
            mbbsEmuCpuCore      = new CpuCore();
            mbbsModule          = new MbbsModule(FileUtility.CreateForTest(), fakeClock, _serviceResolver.GetService <ILogger>(), null, modulePath, mbbsEmuMemoryCore);

            testSessions = new PointerDictionary <SessionBase>();
            testSessions.Allocate(new TestSession(null, textVariableService));
            testSessions.Allocate(new TestSession(null, textVariableService));

            majorbbs = new HostProcess.ExportedModules.Majorbbs(
                _serviceResolver.GetService <IClock>(),
                _serviceResolver.GetService <ILogger>(),
                _serviceResolver.GetService <AppSettings>(),
                _serviceResolver.GetService <IFileUtility>(),
                _serviceResolver.GetService <IGlobalCache>(),
                mbbsModule,
                testSessions,
                _serviceResolver.GetService <IAccountKeyRepository>(),
                _serviceResolver.GetService <IAccountRepository>());

            galgsbl = new HostProcess.ExportedModules.Galgsbl(
                _serviceResolver.GetService <IClock>(),
                _serviceResolver.GetService <ILogger>(),
                _serviceResolver.GetService <AppSettings>(),
                _serviceResolver.GetService <IFileUtility>(),
                _serviceResolver.GetService <IGlobalCache>(),
                mbbsModule,
                testSessions);

            mbbsEmuCpuCore.Reset(mbbsEmuMemoryCore, mbbsEmuCpuRegisters, ExportedFunctionDelegate, null);
        }
Beispiel #15
0
 /// <summary>
 /// Finds the Process Environment Block address of a specified process.
 /// </summary>
 /// <param name="processHandle">A handle of the process.</param>
 /// <returns>A <see cref="IntPtr"/> pointer of the PEB.</returns>
 public static IntPtr FindPeb(SafeMemoryHandle processHandle)
 {
     return(MemoryCore.NtQueryInformationProcess(processHandle).PebBaseAddress);
 }
Beispiel #16
0
        /// <summary>
        ///     Constructor for MbbsModule
        ///
        ///     Pass in an empty/blank moduleIdentifier for a Unit Test/Fake Module
        /// </summary>
        /// <param name="logger"></param>
        /// <param name="moduleIdentifier">Will be null in a test</param>
        /// <param name="path"></param>
        /// <param name="memoryCore"></param>
        /// <param name="fileUtility"></param>
        public MbbsModule(IFileUtility fileUtility, IClock clock, ILogger logger, string moduleIdentifier, string path = "", MemoryCore memoryCore = null)
        {
            _fileUtility = fileUtility;
            _logger      = logger;
            _clock       = clock;

            ModuleIdentifier = moduleIdentifier;
            ModuleDlls       = new List <MbbsDll>();


            //Sanitize and setup Path
            if (string.IsNullOrEmpty(path))
            {
                path = Directory.GetCurrentDirectory();
            }

            if (!Path.EndsInDirectorySeparator(path))
            {
                path += Path.DirectorySeparatorChar;
            }

            ModulePath = path;

            // will be null in tests
            if (string.IsNullOrEmpty(ModuleIdentifier))
            {
                Mdf = MdfFile.createForTest();
                ModuleDlls.Add(new MbbsDll(fileUtility, logger)
                {
                    File = NEFile.createForTest()
                });
            }
            else
            {
                //Verify MDF File Exists
                var mdfFile         = fileUtility.FindFile(ModulePath, $"{ModuleIdentifier}.MDF");
                var fullMdfFilePath = Path.Combine(ModulePath, mdfFile);
                if (!System.IO.File.Exists(fullMdfFilePath))
                {
                    throw new FileNotFoundException($"Unable to locate Module: {fullMdfFilePath}");
                }

                Mdf = new MdfFile(fullMdfFilePath);
                var moduleDll = new MbbsDll(fileUtility, logger);
                moduleDll.Load(Mdf.DLLFiles[0].Trim(), ModulePath);
                ModuleDlls.Add(moduleDll);


                if (Mdf.Requires.Count > 0)
                {
                    foreach (var r in Mdf.Requires)
                    {
                        var requiredDll = new MbbsDll(fileUtility, logger);
                        if (requiredDll.Load(r.Trim(), ModulePath))
                        {
                            requiredDll.SegmentOffset = (ushort)(ModuleDlls.Sum(x => x.File.SegmentTable.Count) + 1);
                            ModuleDlls.Add(requiredDll);
                        }
                    }
                }

                if (Mdf.MSGFiles.Count > 0)
                {
                    Msgs = new List <MsgFile>(Mdf.MSGFiles.Count);
                    foreach (var m in Mdf.MSGFiles)
                    {
                        Msgs.Add(new MsgFile(ModulePath, m));
                    }
                }
            }

            //Set Initial Values
            RtkickRoutines           = new PointerDictionary <RealTimeRoutine>();
            RtihdlrRoutines          = new PointerDictionary <RealTimeRoutine>();
            TaskRoutines             = new PointerDictionary <RealTimeRoutine>();
            TextVariables            = new Dictionary <string, FarPtr>();
            GlobalCommandHandlers    = new List <FarPtr>();
            ExportedModuleDictionary = new Dictionary <ushort, IExportedModule>(6);
            ExecutionUnits           = new Queue <ExecutionUnit>(2);

            Memory = memoryCore ?? new MemoryCore();

            //Declare PSP Segment
            var psp = new PSPStruct {
                NextSegOffset = 0x9FFF, EnvSeg = 0xFFFF
            };

            Memory.AddSegment(0x4000);
            Memory.SetArray(0x4000, 0, psp.Data);

            Memory.AllocateVariable("Int21h-PSP", sizeof(ushort));
            Memory.SetWord("Int21h-PSP", 0x4000);

            //Find _INIT_ values if any
            foreach (var dll in ModuleDlls)
            {
                //If it's a Test, setup a fake _INIT_
                if (string.IsNullOrEmpty(ModuleIdentifier))
                {
                    dll.EntryPoints["_INIT_"] = null;
                    return;
                }

                //Setup _INIT_ Entrypoint
                FarPtr initEntryPointPointer;
                var    initResidentName = dll.File.ResidentNameTable.FirstOrDefault(x => x.Name.StartsWith("_INIT__"));
                if (initResidentName == null)
                {
                    //This only happens with MajorMUD -- I have no idea why it's a special little snowflake ¯\_(ツ)_/¯
                    _logger.Warn($"({moduleIdentifier}) Unable to locate _INIT_ in Resident Name Table, checking Non-Resident Name Table...");

                    var initNonResidentName = dll.File.NonResidentNameTable.FirstOrDefault(x => x.Name.StartsWith("_INIT__"));

                    if (initNonResidentName == null)
                    {
                        throw new Exception("Unable to locate _INIT__ entry in Resident Name Table");
                    }

                    var initEntryPoint = dll.File.EntryTable.First(x => x.Ordinal == initNonResidentName.IndexIntoEntryTable);

                    initEntryPointPointer = new FarPtr((ushort)(initEntryPoint.SegmentNumber + dll.SegmentOffset), initEntryPoint.Offset);
                }
                else
                {
                    var initEntryPoint = dll.File.EntryTable.First(x => x.Ordinal == initResidentName.IndexIntoEntryTable);
                    initEntryPointPointer = new FarPtr((ushort)(initEntryPoint.SegmentNumber + dll.SegmentOffset), initEntryPoint.Offset);
                }


                _logger.Debug($"({ModuleIdentifier}) Located _INIT__: {initEntryPointPointer}");
                dll.EntryPoints["_INIT_"] = initEntryPointPointer;
            }
        }
Beispiel #17
0
        /// <summary>
        ///     Constructor for MbbsModule
        ///
        ///     Pass in an empty/blank moduleIdentifier for a Unit Test/Fake Module
        /// </summary>
        /// <param name="moduleIdentifier"></param>
        /// <param name="path"></param>
        /// <param name="memoryCore"></param>
        public MbbsModule(string moduleIdentifier, string path = "", MemoryCore memoryCore = null)
        {
            ModuleIdentifier = moduleIdentifier;

            //Sanitize and setup Path
            if (string.IsNullOrEmpty(path))
            {
                path = Directory.GetCurrentDirectory();
            }

            if (!path.EndsWith(Path.DirectorySeparatorChar))
            {
                path += Path.DirectorySeparatorChar;
            }

            ModulePath = path;

            //Verify MDF File Exists
            if (!string.IsNullOrEmpty(ModuleIdentifier) && !System.IO.File.Exists($"{ModulePath}{ModuleIdentifier}.MDF"))
            {
                throw new FileNotFoundException($"Unable to locate Module: {ModulePath}{ModuleIdentifier}.MDF");
            }

            Mdf  = !string.IsNullOrEmpty(ModuleIdentifier) ? new MdfFile($"{ModulePath}{ModuleIdentifier}.MDF") : MdfFile.createForTest();
            File = !string.IsNullOrEmpty(ModuleIdentifier) ? new NEFile($"{ModulePath}{Mdf.DLLFiles[0].Trim()}.DLL") : NEFile.createForTest();

            if (Mdf.MSGFiles.Count > 0)
            {
                Msgs = new List <MsgFile>(Mdf.MSGFiles.Count);
                foreach (var m in Mdf.MSGFiles)
                {
                    Msgs.Add(new MsgFile(ModulePath, m));
                }
            }

            //Set Initial Values
            EntryPoints              = new Dictionary <string, IntPtr16>();
            RtkickRoutines           = new PointerDictionary <RealTimeRoutine>();
            RtihdlrRoutines          = new PointerDictionary <RealTimeRoutine>();
            TaskRoutines             = new PointerDictionary <RealTimeRoutine>();
            TextVariables            = new Dictionary <string, IntPtr16>();
            ExecutionUnits           = new Queue <ExecutionUnit>(2);
            ExportedModuleDictionary = new Dictionary <ushort, IExportedModule>(4);
            GlobalCommandHandlers    = new List <IntPtr16>();
            Memory = memoryCore ?? new MemoryCore();

            //If it's a Test, setup a fake _INIT_
            if (string.IsNullOrEmpty(ModuleIdentifier))
            {
                EntryPoints["_INIT_"] = null;
                return;
            }

            //Setup _INIT_ Entrypoint
            IntPtr16 initEntryPointPointer;
            var      initResidentName = File.ResidentNameTable.FirstOrDefault(x => x.Name.StartsWith("_INIT__"));

            if (initResidentName == null)
            {
                //This only happens with MajorMUD -- I have no idea why it's a special little snowflake ¯\_(ツ)_/¯
                _logger.Warn("Unable to locate _INIT_ in Resident Name Table, checking Non-Resident Name Table...");

                var initNonResidentName = File.NonResidentNameTable.FirstOrDefault(x => x.Name.StartsWith("_INIT__"));

                if (initNonResidentName == null)
                {
                    throw new Exception("Unable to locate _INIT__ entry in Resident Name Table");
                }

                var initEntryPoint = File.EntryTable.First(x => x.Ordinal == initNonResidentName.IndexIntoEntryTable);
                initEntryPointPointer = new IntPtr16(initEntryPoint.SegmentNumber, initEntryPoint.Offset);
            }
            else
            {
                var initEntryPoint = File.EntryTable.First(x => x.Ordinal == initResidentName.IndexIntoEntryTable);
                initEntryPointPointer = new IntPtr16(initEntryPoint.SegmentNumber, initEntryPoint.Offset);
            }


            _logger.Info($"Located _INIT__: {initEntryPointPointer}");
            EntryPoints["_INIT_"] = initEntryPointPointer;
        }
Beispiel #18
0
 /// <summary>
 ///     Reads a specific number of bytes from memory.
 /// </summary>
 /// <param name="address">The address.</param>
 /// <param name="count">The count.</param>
 /// <param name="isRelative">if set to <c>true</c> [is relative].</param>
 /// <returns></returns>
 public override byte[] ReadBytes(IntPtr address, int count, bool isRelative = false)
 {
     return(MemoryCore.ReadBytes(Handle, isRelative ? GetAbsolute(address) : address, count));
 }
Beispiel #19
0
 /// <summary>
 /// Reads an array of bytes in the remote process.
 /// </summary>
 /// <param name="address">The address where the array is read.</param>
 /// <param name="count">The number of cells.</param>
 /// <param name="isRelative">[Optional] State if the address is relative to the main module.</param>
 /// <returns>The array of bytes.</returns>
 protected byte[] ReadBytes(IntPtr address, int count, bool isRelative = true)
 {
     return(MemoryCore.ReadBytes(Handle, isRelative ? MakeAbsolute(address) : address, count));
 }