0

I'm trying to get the static address of a game called assault cube so I can get a better understanding of how memory and such works in c#, however I am stuck at one part. As seen above I need to add "ac_client.exe" and 0x10F4F4. This I have done as "ac_client.exe" is 0x400000 so I just added the hex values together. This gave me 0x50F4F4; I then need to dereference that which is where I get stuck. I've tried loads of different ways and searched about it but there isn't too much info about it in c#. I did get some code working which I'm assuming dereferenced it but when I added the dereferenced part to the offset of 0x150 I don't get the same dynamic address. Therefore it doesn't work as it doesn't point anywhere.

int BaseAddress = 0x400000 + 0x10F4F4;
unsafe
{
    int* ptr = &BaseAddress;//this is what should defreference it
    var FinalAddress = ptr + 0x150;
    Console.WriteLine($"Final value is: {(long)FinalAddress:X}");
}

The code above works but doesn't give me the output I am looking for. I've searched many places and there are videos about how to get the static address and they just end on saying "now you can get the dynamic address each time" but don't actually show how to do it.

Chris hansen
  • 31
  • 1
  • 5
  • I can't pretend to have followed any of the explanation in your queston, but `int* ptr = &BaseAddress` gets the address of the `BaseAddress` variable itself (in other words, the *value* of `BaseAddress` is entirely irrelevant here: you're getting the memory location that the `BaseAddress` lives at, which will be on the stack). – canton7 Jul 09 '21 at 10:04
  • What output did you expect? – Sweeper Jul 09 '21 at 10:08
  • @canton7 I understand what you mean but in that case how am I mean to dereference it then? Following the same thing as what cheat engine does is add the module address and the local offset together and then dereference it. If the code gets the address of the variable itself then how am I meant to dereference the base address then? – Chris hansen Jul 09 '21 at 10:33
  • @Sweeper The output I expect is random, or should I say the output i expect is the dynamic address of the value of ammo in the game. The base address dereferenced and then that plus the offset should give me the dynamic address each time however it gives a different output but not the same one as cheat engine says (which is the correct one) – Chris hansen Jul 09 '21 at 10:34
  • 1
    @Chrishansen: It sounds like you're trying to read a value out of another process space (ac_client.exe). If that's true then dereferencing a pointer within your C# app wouldn't buy you anything. Instead google around for how to use [ReadProcessMemory](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-readprocessmemory) from C#. – 500 - Internal Server Error Jul 09 '21 at 10:43
  • @500-InternalServerError ahhh forgot about that lol, i tested something like that but it was only a slight thought. Pretty sure what i have to do now. Thanks :)))) – Chris hansen Jul 09 '21 at 11:56
  • What exactly are you trying to achieve? Why do you need `a better understanding of how memory and such works in c#`, these are internal CLR details which are very rarely relevant – Charlieface Jul 09 '21 at 12:43

1 Answers1

0

These are just imports which allows you to get static address

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(ProcessAccessFlags processAccess, bool bInheritHandle, int processID);

[StructLayout(LayoutKind.Sequential)]
public struct PROCESSENTRY32
{
    public uint dwSize;
    public uint cntUsage;
    public uint th32ProcessID;
    public IntPtr th32DefaultHeapID;
    public uint th32ModuleID;
    public uint cntThreads;
    public uint th32ParentProcessID;
    public int pcPriClassBase;
    public uint dwFlags;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szExeFile;
};

//inner enum used only internally
[Flags]
public enum SnapshotFlags : uint
{
    HeapList = 0x00000001,
    Process = 0x00000002,
    Thread = 0x00000004,
    Module = 0x00000008,
    Module32 = 0x00000010,
    Inherit = 0x80000000,
    All = 0x0000001F,
    NoHeaps = 0x40000000
}
//inner struct used only internally

[DllImport("kernel32.dll")]
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [MarshalAs(UnmanagedType.AsAny)] object lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten);


[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadProcessMemory(IntPtr hProcess,IntPtr lpBaseAddress,[Out, MarshalAs(UnmanagedType.AsAny)] object lpBuffer,int dwSize,out IntPtr lpNumberOfBytesRead);

[DllImport("kernel32.dll")]
public static extern bool Process32First(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);

[DllImport("kernel32.dll")]
public static extern bool Process32Next(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);

[DllImport("kernel32.dll")]
public static extern bool Module32First(IntPtr hSnapshot, ref MODULEENTRY32 lpme);

[DllImport("kernel32.dll")]
public static extern bool Module32Next(IntPtr hSnapshot, ref MODULEENTRY32 lpme);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr hHandle);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateToolhelp32Snapshot(SnapshotFlags dwFlags, int th32ProcessID);

public static IntPtr GetModuleBaseAddress(Process proc, string modName)
{
    IntPtr addr = IntPtr.Zero;

    foreach (ProcessModule m in proc.Modules)
    {
        if (m.ModuleName == modName)
        {
            addr = m.BaseAddress;
            break; ;
        }
    }
    return addr;
}

const int INVALID_HANDLE_VALUE = -1;
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[] offsetse)
{
    var buffer = new byte[IntPtr.Size];
    foreach (int i in offsetse)
    {
        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;
}

[Flags]
public enum ProcessAccessFlags : uint
{
    All = 0x001F0FFF,
    Terminate = 0x00000001,
    CreateThread = 0x00000002,
    VirtualMemoryOperation = 0x00000008,
    VirtualMemoryRead = 0x00000010,
    VirtualMemoryWrite = 0x00000020,
    DuplicateHandle = 0x00000040,
    CreateProcess = 0x000000080,
    SetQuota = 0x00000100,
    SetInformation = 0x00000200,
    QueryInformation = 0x00000400,
    QueryLimitedInformation = 0x00001000,
    Synchronize = 0x00100000
}


[StructLayout(LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
public struct MODULEENTRY32
{
    internal uint dwSize;
    internal uint th32ModuleID;
    internal uint th32ProcessID;
    internal uint GlblcntUsage;
    internal uint ProccntUsage;
    internal IntPtr modBaseAddr;
    internal uint modBaseSize;
    internal IntPtr hModule;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    internal string szModule;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
    internal string szExePath;
}

public static IntPtr GetModuleBaseAddress()
{
    Process process = Process.GetProcessesByName("ac_client")[0];

    var module = process.Modules.Cast<ProcessModule>().SingleOrDefault(m => string.Equals(m.ModuleName, "ac_client.exe", StringComparison.OrdinalIgnoreCase));

    // Attempt to get the base address of the module - Return IntPtr.Zero if the module doesn't exist in the process
    return module?.BaseAddress ?? IntPtr.Zero;
}


The code below is how you would use it

Process proc = Process.GetProcessesByName("ac_client")[0];

var hProc = MainFunctions.OpenProcess(MainFunctions.ProcessAccessFlags.All, false, proc.Id);

var modBase = MainFunctions.GetModuleBaseAddress(proc, "ac_client.exe");

var modBase2 = MainFunctions.GetModuleBaseAddress(proc.Id, "ac_client.exe");

var ammoAddr = MainFunctions.FindDMAAddy(hProc, (IntPtr)(modBase + 0xE56BC), new int[] { 0x0, 0x274 });
//put the offsets here and put the local offset next to modBase


Console.WriteLine("Last Error: " + Marshal.GetLastWin32Error());

Console.WriteLine("Ammo address " + "0x" + ammoAddr.ToString("X"));

Chris hansen
  • 31
  • 1
  • 5