C# / CE Memory Pointer Reading + Offset

06/03/2013 20:12 N(fx)#1
Hi,
ich hab folgendes Problem:
Ich hab mit CE (6.2) einen statischen Pointer ermittelt mit dem ich dann zur gewünschten speicher Adresse komme.

Leider bekomme ich beim dem hinzufügen der Offsets immer nur eine null als wert raus.

[Only registered and activated users can see links. Click Here To Register...]
(toll img tag geht nicht)
[Only registered and activated users can see links. Click Here To Register...]


Die endgültige Adresse müsste doch wie folgt sein:

[[[[[[[BaseAddress+0x0003CDD0]+0x38]+0x8]+0x18]+0x18]+0x8]+0x98] = Value 96


Im Code hab ich es wie folgt versucht:

Memory Class:
Code:
class NFXMemory
    {
        [Flags]
        public enum ProcessAccessType
        {
            PROCESS_TERMINATE = (0x0001),
            PROCESS_CREATE_THREAD = (0x0002),
            PROCESS_SET_SESSIONID = (0x0004),
            PROCESS_VM_OPERATION = (0x0008),
            PROCESS_VM_READ = (0x0010),
            PROCESS_VM_WRITE = (0x0020),
            PROCESS_DUP_HANDLE = (0x0040),
            PROCESS_CREATE_PROCESS = (0x0080),
            PROCESS_SET_QUOTA = (0x0100),
            PROCESS_SET_INFORMATION = (0x0200),
            PROCESS_QUERY_INFORMATION = (0x0400)
        }
        [DllImport("kernel32.dll")]
        public static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId);

        [DllImport("kernel32.dll")]
        public static extern Int32 CloseHandle(IntPtr hObject);

        [DllImport("kernel32.dll")]
        public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size,IntPtr lpNumberOfBytesRead);

        [DllImport("kernel32.dll")]
        public static extern Int32 WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size,IntPtr lpNumberOfBytesWritten);

        private Process _process = null;
        private IntPtr _handleProcess = IntPtr.Zero;
        public IntPtr _baseAdress = IntPtr.Zero;
        private string _application;
        private int _processID;
        private ProcessAccessType _accessFlags = ProcessAccessType.PROCESS_VM_READ | ProcessAccessType.PROCESS_VM_WRITE | ProcessAccessType.PROCESS_VM_OPERATION;

        public NFXMemory(string Application)
        {
            _application = Application;
            OpenProcess();
        }

        public void OpenProcess()
        {
            if (Process.GetProcessesByName(_application).Length > 0)
            {
                _process = Process.GetProcessesByName(_application)[0];
                _baseAdress = _process.MainModule.BaseAddress;
                _processID = _process.Id;
                _handleProcess = OpenProcess((uint)_accessFlags, 1, (uint)_processID);
                
            }
        }

        public IntPtr GetPointer(int[] Offsets)
        {
            byte[] buffer = new byte[4];
            IntPtr _address = _baseAdress;
            ReadProcessMemory(_handleProcess, _address, buffer, (uint)4, IntPtr.Zero);
            _address = new IntPtr(BitConverter.ToInt32(buffer,0));

            for (int i = 0; i < Offsets.Length; i++)
            {
                ReadProcessMemory(_handleProcess, _address, buffer, (uint)4, IntPtr.Zero);
                _address = new IntPtr(BitConverter.ToInt32(buffer, 0));
            }
            return _address;
        }

        public int getInt(IntPtr address)
        {
            byte[] buffer = new byte[4];
            ReadProcessMemory(_handleProcess, address, buffer, (uint)4, IntPtr.Zero);
            return BitConverter.ToInt32(buffer, 0);
        }

    }

Zum auslesen benutze ich jetzt das Form_Load Event mit zwei verschiedenen ansätzen:
Code:
        private void Form1_Load(object sender, EventArgs e)
        {

            // 1
            NFXMemory memReader = new NFXMemory("Client");
            IntPtr ammoPtr = memReader.GetPointer(new int[] { 0x0003CDD0, 0x38, 0x8, 0x18, 0x8, 0x98});
            int ammoValue = memReader.getInt(ammoPtr);
            Console.WriteLine(ammoValue);

            //2
            IntPtr ammoAddr = memReader._baseAdress;
            ammoAddr = IntPtr.Add(ammoAddr, 0x0003CDD0);
            ammoAddr = IntPtr.Add(ammoAddr, 0x38);
            ammoAddr = IntPtr.Add(ammoAddr, 0x8);
            ammoAddr = IntPtr.Add(ammoAddr, 0x18);
            ammoAddr = IntPtr.Add(ammoAddr, 0x8);
            ammoAddr = IntPtr.Add(ammoAddr, 0x98);
            int am = memReader.getInt(ammoAddr);
            Console.WriteLine(am);
        }
Bei beiden kommt 0 raus..
Hat einer ne Idee was ich falsch mache ?
06/03/2013 20:42 dready#2
Debuggen, auch wenns fies klingt, fang lieber jetzt damit an als später, dann wirst auch sehen ab wann das ganze nichtmehr genau hinhaut.
So vom drüberschauen her würd ich sagen, du list die Baseadresse aus als wäre es ein Pointer, dabei ist die Baseadresse bereits der erste Wert auf den du was draufrechnen musst. Wenn ichs richtig im Kopf hab
06/04/2013 00:33 MrSm!th#3
Nein, sollte sie eigentlich nicht sein. Maximal die Module Base muss man auf die Base addieren.
06/04/2013 05:18 dready#4
Hast natürlich vollkomm recht, hab mich mieserable ausgedrückt, was ich meinte war das hier:

Code:
 _baseAdress = _process.MainModule.BaseAddress;
Hier setzt er baseAdress auf die Module Base

etwas später:

Code:
            IntPtr _address = _baseAdress;
            ReadProcessMemory(_handleProcess, _address, buffer, (uint)4, IntPtr.Zero);
            _address = new IntPtr(BitConverter.ToInt32(buffer,0));
Hier liest er die ModuleBase aus und setzt mit diesen Werten die neue Adresse

Oder bin ich gerad total aufm Holzweg ? +g+
06/04/2013 14:50 MrSm!th#5
Jo, das ist natürlich quatsch.
06/04/2013 16:56 SwarN#6
Zu deiner 2 Methode diese ist im Ansatz schon falsch.

Deiner Ansicht hast du eine Baseadresse und addierst einfach nach und nach die Offset's drauf. Dass ist nicht korrekt. Also deine Variante ist:
Baseadresse + Offset1 + Offset2 + Offset3 ... = Eine Adresse die du ausließt = Dein Ammo

Der richtige Weg ist:

Game.exe + Baseadresse = Auslesen1
Auslesen1 + Offset1 = Auslesen2
Auslesen2 + Offset 2 = ....

Bis zum letzten dass ist dann dein Ammo.

Man sieht's auch sehr schön auf dem Bild das du gepostet hast von der CheatEngine,
dort sind auch Haargenau die einzelnen Schritte des jeweiligen Auslesens aufgeführt.

Wenn du es dann durchdebuggst siehst du auch ( evtl. den Taschenrechner hernehmen und von DEZ in HEX manuell rechnen ) dass du die selben werte bekommst wie du in der CheatEngine auch siehst.
So findest du auch mal einen Fehler, wenn du debuggst und mal nicht die selben Zahlen kommen wie in der CheatEngine.


In deinem 1. Versuch machst du es Ansatzweiße richtig, aber in der Funktion "GetPointer(int[] Offsets)" addierst du keine Offsets auf die eig. Adresse. Kann also auch nicht klappen.

Ein Tipp von mir, versuchs ersteinmal einfacher und nicht gleich alles in Funktionen unterteilen, dass ist zwar schön und gut aber wenn du dich selber nicht mehr auskennst, machts auch keinen Sinn. Bau erst alles in einem schaus dir an verstehs und teils dann in Funktionen auf.
06/05/2013 19:53 Bluespide#7
Quote:
Originally Posted by N(fx) View Post
Bei beiden kommt 0 raus..
Hat einer ne Idee was ich falsch mache ?
Projekt auf x86 gestellt?

[Only registered and activated users can see links. Click Here To Register...]