'Finding the value of an Memory Address which has an Offset. C#

I am new to C# and I am experiencing an issue when trying to display the value of a memory address.

This is the pointer and offset I am trying to get working: Link to Cheat Engine Image

When I read the address "0x005040E8" with no offset I receive the correct value in the console:

Console result below:

Last Error: 0 
Memory address 0x5040E8 
Memory value 13828056

When I add an offset I receive a 16 length address which naturally has no value.

Console result below:

Last Error: 0
Memory address 0xCA0FE800D41E70
Memory value 0

Here is my code attempting to find the value of 0x005040E8 with an offset of 0x00011E98:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;


namespace ConsoleApp3
{
    using memoryTest;
    class Program
    {
        static unsafe void Main(string[] args)
        {
            Process proc = Process.GetProcessesByName("testApp")[0];
            var hProc = memapi.OpenProcess(memapi.ProcessAccessFlags.All, false, proc.Id);
            var modBase = memapi.GetModuleBaseAddress(proc, "testApp");
            //var modBase2 = memapi.GetModuleBaseAddress(proc.Id, "testApp");

            var memoryAddr = memapi.FindDMAAddy(hProc, (IntPtr)(0x005040E8), new int[] { 0x00011E98 });
            System.Console.WriteLine("Last Error: " + Marshal.GetLastWin32Error());

            Console.WriteLine("Memory address " + "0x" + memoryAddr.ToString("X"));

            var buffer = new byte[IntPtr.Size];
            memapi.ReadProcessMemory(hProc, memoryAddr, buffer, buffer.Length, out var read);

            Console.WriteLine("Memory value " + BitConverter.ToInt32(buffer, 0));
            Console.ReadKey();
        }
    }
}

Here are the relevant functions:

public static extern bool ReadProcessMemory(
    IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesRead);
public static IntPtr GetModuleBaseAddress(int procId, string modName)
        {
            IntPtr modBaseAddr = IntPtr.Zero;

            IntPtr hSnap = CreateToolhelp32Snapshot(SnapshotFlags.Module | SnapshotFlags.Module32, procId);
            if (hSnap.ToInt64() != INVALID_HANDLE_VALUE)
            {
                MODULEENTRY32 modEntry = new MODULEENTRY32();
                modEntry.dwSize = (uint)Marshal.SizeOf(typeof(MODULEENTRY32));

                if (Module32First(hSnap, ref modEntry))
                {
                    do
                    {
                        if (modEntry.szModule.Equals(modName))
                        {
                            modBaseAddr = modEntry.modBaseAddr;
                            break;
                        }
                    } while (Module32Next(hSnap, ref modEntry));
                }
            }

            CloseHandle(hSnap);
            return modBaseAddr;
        }

        public static IntPtr FindDMAAddy(IntPtr hProc, IntPtr ptr, int[] offsets)
        {
            var buffer = new byte[IntPtr.Size];

            foreach (int i in offsets)
            {
                ReadProcessMemory(hProc, ptr, buffer, buffer.Length, out
                var read);
                ptr = (IntPtr.Size == 4) ? IntPtr.Add(new IntPtr(BitConverter.ToInt32(buffer, 0)), i) : ptr = IntPtr.Add(new IntPtr(BitConverter.ToInt64(buffer, 0)), i);
            }
            return ptr;
        }

I do not believe using a base address is needed, I have tried FindDMAAddy(hProc, (IntPtr)(modebase + 0x005040E8), new int[] { 0x00011E98 }); but it still failed. Any help would be greatly appreciated.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source