• Welcome to Valhalla Legends Archive.
 

[C#] ReadProcessMemory - Getting life

Started by Insolence, June 29, 2007, 10:21 PM

Previous topic - Next topic

Insolence

I found an AutoIt script example that correctly gets my character's life, however I can't get any C# examples to work correctly.  I've tried tweaking it many ways.

AutoIt:
Func GetStat ($InputBoxAnswer)
    Local $Buffer = DllStructCreate('dword')
    Local $dll[2] = [DllOpen('kernel32.dll')]
    Local $Open = DllCall($Dll[0], 'int', 'OpenProcess', 'int', 0x1F0FFF, 'int', 0, 'int', $pid)
    $dll[1] = $Open[0]
    DllCall($dll[0], 'int', 'ReadProcessMemory', 'int', $dll[1], 'int', $GlobalPlayerUnit, 'ptr', DllStructGetPtr($Buffer), 'int', 4, 'int', '')
    $Pointer1 = '0x' & hex(DllStructGetData($Buffer, 1) + 92)
MsgBox("","", '0x' & hex($GlobalPlayerUnit) & " " & '0x' & hex(DllStructGetData($Buffer, 1)) & " " & $Pointer1)
    DllCall($dll[0], 'int', 'ReadProcessMemory', 'int', $dll[1], 'int', $Pointer1, 'ptr', DllStructGetPtr($Buffer), 'int', 4, 'int', '')
    $Pointer2 = '0x' & hex(DllStructGetData($Buffer, 1) + 36)
    DllCall($dll[0], 'int', 'ReadProcessMemory', 'int', $dll[1], 'int', $Pointer2, 'ptr', DllStructGetPtr($Buffer), 'int', 4, 'int', '')
    $Pointer3 = '0x' & hex(DllStructGetData($Buffer, 1) + $InputBoxAnswer + 31)
    DllCall($dll[0], 'int', 'ReadProcessMemory', 'int', $dll[1], 'int', $Pointer3, 'ptr', DllStructGetPtr($Buffer), 'int', 4, 'int', '')
    $Value = DllStructGetData($Buffer, 1)
    DllClose($dll[0])
    Return $Value
EndFunc


C#:
                int PlayerUnit = 0x6FBCC1E0 + 0x5c;
                AppendText("Initial pointer: " + PlayerUnit.ToString("X") + Environment.NewLine);

                int ptr1 = BigEndianBitConverter.Big.ToInt32(game.Memory.Read(PlayerUnit, 4), 0);
                AppendText("Memory read stage 1: " + ptr1.ToString("X") + Environment.NewLine);

                int ptr2 = BigEndianBitConverter.Big.ToInt32(game.Memory.Read(ptr1 + 0x5C, 4), 0);
                AppendText("Memory read stage 2: " + ptr2.ToString("X") + Environment.NewLine);

                int ptr3 = BigEndianBitConverter.Big.ToInt32(game.Memory.Read(ptr2 + 36, 4), 0);
                AppendText("Memory read stage 3: " + ptr3.ToString("X") + Environment.NewLine);

                int ptr4 = BigEndianBitConverter.Big.ToInt32(game.Memory.Read(ptr3 + 31 + 14, 4), 0);
                AppendText("Memory read stage 4: " + ptr4.ToString("X") + Environment.NewLine);

                AppendText("Memory read life: " + ptr4.ToString() + Environment.NewLine);


C# gets the value 0 at PlayerUnit + 0x5C, where a pointer to the PlayerStat struct should be.  I looked in OllyDbg and this is correct--how is the AutoIt version getting the correct life, while my C# version just gets 0 on the first pointer?

I'm sure C# is reading the memory right--I looked at it in Olly to be sure.

I assume I'm (stupidly) overlooking some fundamental aspect of lower level programming, and I'd appreciate it if someone would point it out.  Thanks :)


PS, if I'm unclear, please let me know and I'll elaborate.

squeegee

I know a lot of members on this forum that would like to see progress on your project

Keep up the good work

Insolence

Whoa, really?--thanks, I appreciate it.  It's not my work though, I'm just using the tools E.T./AntiRush/Rhin/Sting/Agin/etc. provide me.

l2k-Shadow

I don't program in .NET but I don't understand why you are using a big endian class when working on a little endian system?
Quote from: replaced on November 04, 2006, 11:54 AM
I dunno wat it means, someone tell me whats ix86 and pmac?
Can someone send me a working bot source (with bnls support) to my email?  Then help me copy and paste it to my bot? ;D
Já jsem byl určenej abych tady žil,
Dával si ovar, křen a k tomu pivo pil.
Tam by ses povídaj jak prase v žitě měl,
Já nechci před nikym sednout si na prdel.

Já nejsem z USA, já nejsem z USA, já vážně nejsem z USA... a snad se proto na mě nezloběj.

Insolence

Oh, that's part of the tweaking and such that I was trying to do--I tried little first.  Either way, it shouldn't be coming up with 0, right?

Thanks for reading the code, I appreciate it. :)

l2k-Shadow

well can you show us the whole code like with the OpenProcess call and everything?
Quote from: replaced on November 04, 2006, 11:54 AM
I dunno wat it means, someone tell me whats ix86 and pmac?
Can someone send me a working bot source (with bnls support) to my email?  Then help me copy and paste it to my bot? ;D
Já jsem byl určenej abych tady žil,
Dával si ovar, křen a k tomu pivo pil.
Tam by ses povídaj jak prase v žitě měl,
Já nechci před nikym sednout si na prdel.

Já nejsem z USA, já nejsem z USA, já vážně nejsem z USA... a snad se proto na mě nezloběj.

Insolence

No problem, here's the whole memory class:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace ProcessMemoryReaderLib
{
/// <summary>
/// ProcessMemoryReader is a class that enables direct reading a process memory
/// </summary>
class ProcessMemoryReaderApi
{
// constants information can be found in <winnt.h>
[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)
}

// function declarations are found in the MSDN and in <winbase.h>

// HANDLE OpenProcess(
// DWORD dwDesiredAccess,  // access flag
// BOOL bInheritHandle,    // handle inheritance option
// DWORD dwProcessId       // process identifier
// );
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId);

// BOOL CloseHandle(
// HANDLE hObject   // handle to object
// );
[DllImport("kernel32.dll")]
public static extern Int32 CloseHandle(IntPtr hObject);

// BOOL ReadProcessMemory(
// HANDLE hProcess,              // handle to the process
// LPCVOID lpBaseAddress,        // base of memory area
// LPVOID lpBuffer,              // data buffer
// SIZE_T nSize,                 // number of bytes to read
// SIZE_T * lpNumberOfBytesRead  // number of bytes read
// );
[DllImport("kernel32.dll")]
public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,[In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);

// BOOL WriteProcessMemory(
// HANDLE hProcess,                // handle to process
// LPVOID lpBaseAddress,           // base of memory area
// LPCVOID lpBuffer,               // data buffer
// SIZE_T nSize,                   // count of bytes to write
// SIZE_T * lpNumberOfBytesWritten // count of bytes written
// );
[DllImport("kernel32.dll")]
public static extern Int32 WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,[In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesWritten);


}

public class ProcessMemoryReader
{
        private Process m_ReadProcess = null;

        private IntPtr m_hProcess = IntPtr.Zero;

public ProcessMemoryReader(Process proc)
{
            this.m_ReadProcess = proc;

            this.OpenProcess();
}

private void OpenProcess()
{
// m_hProcess = ProcessMemoryReaderApi.OpenProcess(ProcessMemoryReaderApi.PROCESS_VM_READ, 1, (uint)m_ReadProcess.Id);
ProcessMemoryReaderApi.ProcessAccessType access;
access = ProcessMemoryReaderApi.ProcessAccessType.PROCESS_VM_READ
| ProcessMemoryReaderApi.ProcessAccessType.PROCESS_VM_WRITE
| ProcessMemoryReaderApi.ProcessAccessType.PROCESS_VM_OPERATION;
m_hProcess = ProcessMemoryReaderApi.OpenProcess((uint)access, 1, (uint)m_ReadProcess.Id);
}

public void CloseHandle()
{
int iRetValue;
iRetValue = ProcessMemoryReaderApi.CloseHandle(m_hProcess);
if (iRetValue == 0)
throw new Exception("CloseHandle failed");
}

        public byte[] Read(int MemoryAddress, uint bytesToRead)
        {
            int notSavingThis;
            return Read((IntPtr)MemoryAddress, bytesToRead, out notSavingThis);
        }

        public byte[] Read(int MemoryAddress, uint bytesToRead, out int bytesRead)
        {
            return Read((IntPtr)MemoryAddress, bytesToRead, out bytesRead);
        }

public byte[] Read(IntPtr MemoryAddress, uint bytesToRead, out int bytesRead)
{
byte[] buffer = new byte[bytesToRead];

IntPtr ptrBytesRead;
ProcessMemoryReaderApi.ReadProcessMemory(m_hProcess, MemoryAddress, buffer, bytesToRead, out ptrBytesRead);

bytesRead = ptrBytesRead.ToInt32();

return buffer;
}

public void Write(IntPtr MemoryAddress, byte[] bytesToWrite ,out int bytesWritten)
{
IntPtr ptrBytesWritten;
ProcessMemoryReaderApi.WriteProcessMemory(m_hProcess,MemoryAddress,bytesToWrite,(uint)bytesToWrite.Length,out ptrBytesWritten);

bytesWritten = ptrBytesWritten.ToInt32();
}
}
}


Any other questions?--thanks for the lightning fast reply :)

l2k-Shadow

and are you sure OpenProcess is succeeding?
Quote from: replaced on November 04, 2006, 11:54 AM
I dunno wat it means, someone tell me whats ix86 and pmac?
Can someone send me a working bot source (with bnls support) to my email?  Then help me copy and paste it to my bot? ;D
Já jsem byl určenej abych tady žil,
Dával si ovar, křen a k tomu pivo pil.
Tam by ses povídaj jak prase v žitě měl,
Já nechci před nikym sednout si na prdel.

Já nejsem z USA, já nejsem z USA, já vážně nejsem z USA... a snad se proto na mě nezloběj.

Insolence

I'm sure it's reading memory correctly, because I look at the bytes in Olly and they're the same.

l)ragon

what game you doing this for anyways, i might check into it tomorrow sometime.
*^~·.,¸¸,.·´¯`·.,¸¸,.-·~^*ˆ¨¯¯¨ˆ*^~·.,l)ragon,.-·~^*ˆ¨¯¯¨ˆ*^~·.,¸¸,.·´¯`·.,¸¸,.-·~^*

Insolence


Smarter

Quote from: Insolence on June 29, 2007, 10:21 PM
I found an AutoIt script example that correctly gets my character's life, however I can't get any C# examples to work correctly.  I've tried tweaking it many ways.

AutoIt:
Func GetStat ($InputBoxAnswer)
    Local $Buffer = DllStructCreate('dword')
    Local $dll[2] = [DllOpen('kernel32.dll')]
    Local $Open = DllCall($Dll[0], 'int', 'OpenProcess', 'int', 0x1F0FFF, 'int', 0, 'int', $pid)
    $dll[1] = $Open[0]
    DllCall($dll[0], 'int', 'ReadProcessMemory', 'int', $dll[1], 'int', $GlobalPlayerUnit, 'ptr', DllStructGetPtr($Buffer), 'int', 4, 'int', '')
    $Pointer1 = '0x' & hex(DllStructGetData($Buffer, 1) + 92)
MsgBox("","", '0x' & hex($GlobalPlayerUnit) & " " & '0x' & hex(DllStructGetData($Buffer, 1)) & " " & $Pointer1)
    DllCall($dll[0], 'int', 'ReadProcessMemory', 'int', $dll[1], 'int', $Pointer1, 'ptr', DllStructGetPtr($Buffer), 'int', 4, 'int', '')
    $Pointer2 = '0x' & hex(DllStructGetData($Buffer, 1) + 36)
    DllCall($dll[0], 'int', 'ReadProcessMemory', 'int', $dll[1], 'int', $Pointer2, 'ptr', DllStructGetPtr($Buffer), 'int', 4, 'int', '')
    $Pointer3 = '0x' & hex(DllStructGetData($Buffer, 1) + $InputBoxAnswer + 31)
    DllCall($dll[0], 'int', 'ReadProcessMemory', 'int', $dll[1], 'int', $Pointer3, 'ptr', DllStructGetPtr($Buffer), 'int', 4, 'int', '')
    $Value = DllStructGetData($Buffer, 1)
    DllClose($dll[0])
    Return $Value
EndFunc


C#:
                int PlayerUnit = 0x6FBCC1E0 + 0x5c;
                AppendText("Initial pointer: " + PlayerUnit.ToString("X") + Environment.NewLine);

                int ptr1 = BigEndianBitConverter.Big.ToInt32(game.Memory.Read(PlayerUnit, 4), 0);
                AppendText("Memory read stage 1: " + ptr1.ToString("X") + Environment.NewLine);

                int ptr2 = BigEndianBitConverter.Big.ToInt32(game.Memory.Read(ptr1 + 0x5C, 4), 0);
                AppendText("Memory read stage 2: " + ptr2.ToString("X") + Environment.NewLine);

                int ptr3 = BigEndianBitConverter.Big.ToInt32(game.Memory.Read(ptr2 + 36, 4), 0);
                AppendText("Memory read stage 3: " + ptr3.ToString("X") + Environment.NewLine);

                int ptr4 = BigEndianBitConverter.Big.ToInt32(game.Memory.Read(ptr3 + 31 + 14, 4), 0);
                AppendText("Memory read stage 4: " + ptr4.ToString("X") + Environment.NewLine);

                AppendText("Memory read life: " + ptr4.ToString() + Environment.NewLine);


C# gets the value 0 at PlayerUnit + 0x5C, where a pointer to the PlayerStat struct should be.  I looked in OllyDbg and this is correct--how is the AutoIt version getting the correct life, while my C# version just gets 0 on the first pointer?

I'm sure C# is reading the memory right--I looked at it in Olly to be sure.

I assume I'm (stupidly) overlooking some fundamental aspect of lower level programming, and I'd appreciate it if someone would point it out.  Thanks :)


PS, if I'm unclear, please let me know and I'll elaborate.

Well, I have never gotten into calling outside dlls in C#, I always tried to be sure to use a .NET version of whatever API I wanted to call.... but if I understand correctly, your problem is: PlayerUnit + 0x5c is returning zero, but I don't see where your even doing that, int PlayerUnit = 0x6FBCC1E0 + 0x5c; is all I see. Maybe i'm missing something?
Since '99

BrutalNet.Net

Insolence

QuoteI don't see where your even doing that, int PlayerUnit = 0x6FBCC1E0 + 0x5c; is all I see. Maybe i'm missing something?
Quoteint ptr1 = BigEndianBitConverter.Big.ToInt32(game.Memory.Read(PlayerUnit, 4), 0);
Bold should be reading that location--I'm pretty sure that's how it should be done.

Thanks for trying :)

Smarter

#13
Hmmm. So ptr1 simply returns zero? Have you tried stepping through the program, with autos open and seeing exactly what is happening?

Edit: Local $Buffer = DllStructCreate('dword') - Could it be a varible type problem, in the AutoIt scipt, it's creating a DWORD (byte), and your creating an integer. Your also adding two bytes as an integer: nt PlayerUnit = 0x6FBCC1E0 + 0x5c.
Since '99

BrutalNet.Net

Insolence

What are "autos"?

Like I said, I looked at the memory dump, and 0x6FBCC1E0 + 0x5c is 0x00 00 00 00.