C# how to use offsets

11/18/2010 21:05 Janick_#1
So, i'm trying to use the offsets in C#, but i can't find anything usefull on the internet.. I just wanna do it like this, Char name: bla bla , and such stuffs. But i can't find an example on how to do it. ( I know how to get the offsets from sro, just need them to add them into C# and let it show up on a GUI)

Can anybody help me? if you get what i mean..

Janick.
11/18/2010 21:31 LastThief#2
[Only registered and activated users can see links. Click Here To Register...]

but you need to have patience because its long as hell ^^

its public offsets not related to sro
11/19/2010 07:29 lesderid#3
Quote:
Originally Posted by LastThief View Post
[Only registered and activated users can see links. Click Here To Register...]

but you need to have patience because its long as hell ^^

its public offsets not related to sro
I don't see what structs have to do with memory editing lolz.
11/19/2010 10:32 LastThief#4
Quote:
Originally Posted by lesderid View Post
I don't see what structs have to do with memory editing lolz.
i just had this guide on my favorites so i just gave him it that's all i really didn't read it ^^
11/19/2010 12:56 ZeraPain#5
Code:
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace Game.Memory
{
    class Memory
    {
        [DllImport("kernel32.dll")]
        static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Boolean bInheritHandle, UInt32 dwProcessId);
        [DllImport("kernel32.dll")]
        static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
        byte[] lpBuffer, UIntPtr nSize, uint lpNumberOfBytesWritten);

        IntPtr Handle;

        public Memory(string sprocess)
        {
            Process[] Processes = Process.GetProcessesByName(sprocess);
            Process nProcess = Processes[0];
            Handle = OpenProcess(0x10, false, (uint)nProcess.Id);
        }

        public string ReadString(uint pointer) 
        {
            byte[] bytes = new byte[24];

            ReadProcessMemory(Handle, (IntPtr)pointer, bytes, (UIntPtr)24, 0);
            return Encoding.UTF8.GetString(bytes);
        }

        public int ReadOffset(uint pointer, uint offset)
        {
            byte[] bytes = new byte[24];

            uint adress = (uint)ReadPointer(pointer) + offset;
            ReadProcessMemory(Handle, (IntPtr)adress, bytes, (UIntPtr)sizeof(int), 0);
            return BitConverter.ToInt32(bytes, 0);
        }

        public int ReadPointer(uint pointer)
        {
            byte[] bytes = new byte[24];

            ReadProcessMemory(Handle, (IntPtr)pointer, bytes, (UIntPtr)sizeof(int), 0);
            return BitConverter.ToInt32(bytes, 0);
        }
    }
}
11/19/2010 14:47 Janick_#6
Quote:
Originally Posted by ZeraPain View Post
Code:
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace Game.Memory
{
    class Memory
    {
        [DllImport("kernel32.dll")]
        static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Boolean bInheritHandle, UInt32 dwProcessId);
        [DllImport("kernel32.dll")]
        static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
        byte[] lpBuffer, UIntPtr nSize, uint lpNumberOfBytesWritten);

        IntPtr Handle;

        public Memory(string sprocess)
        {
            Process[] Processes = Process.GetProcessesByName(sprocess);
            Process nProcess = Processes[0];
            Handle = OpenProcess(0x10, false, (uint)nProcess.Id);
        }

        public string ReadString(uint pointer) 
        {
            byte[] bytes = new byte[24];

            ReadProcessMemory(Handle, (IntPtr)pointer, bytes, (UIntPtr)24, 0);
            return Encoding.UTF8.GetString(bytes);
        }

        public int ReadOffset(uint pointer, uint offset)
        {
            byte[] bytes = new byte[24];

            uint adress = (uint)ReadPointer(pointer) + offset;
            ReadProcessMemory(Handle, (IntPtr)adress, bytes, (UIntPtr)sizeof(int), 0);
            return BitConverter.ToInt32(bytes, 0);
        }

        public int ReadPointer(uint pointer)
        {
            byte[] bytes = new byte[24];

            ReadProcessMemory(Handle, (IntPtr)pointer, bytes, (UIntPtr)sizeof(int), 0);
            return BitConverter.ToInt32(bytes, 0);
        }
    }
}
Could you or someone explain a bit more about this code?
And tnx everyone for his help^^
11/19/2010 15:18 ZeraPain#7
well now you could create a new class e.g. using the Program.cs
and read the specific memory entries:
(you have to replace the pointers / offsets with them of your sro client)

Code:
using System;
using System.Linq;
using System.Text;
using Game.Memory;

namespace main
{
    class Program
    {
        private static bool exit = false;
  
        static void Main(string[] args)
        {
            while (!exit)
                GetLine(Console.ReadLine());
        }

        private static void GetLine(string cmd)
        {
            Memory mem = new Memory("sro_client");

            switch (cmd)
            {
                case "curhp":
                    int curhp = mem.ReadOffset(0x00A8913C, 0x1D4);
                    Console.WriteLine("Current HP: {0}", curhp);
                    break;
                case "maxhp":
                    int maxhp = mem.ReadPointer(0x00AA0740);
                    Console.WriteLine("Maximum HP: {0}", maxhp);
                    break;
                case "name":
                    string name = mem.ReadString(0x00A9FB98);
                    Console.WriteLine("Charname: {0}", name);
                    break;
                case "exit":
                    exit = true;
                    break;
            }
        }      
    }
}
11/19/2010 16:39 lesderid#8
You have to note that the strings are decoded as UTF-8.
Also, the return type of the ReadOffset/ReadPointer is int (Int32).
11/19/2010 17:01 ZeraPain#9
well you can rewrite them to float or to any other size than 4 byte if needed.
i just wanted to give an example for std. memory reading on sro (most necessary values are 4 byte)
11/20/2010 07:52 lesderid#10
Quote:
Originally Posted by ZeraPain View Post
well you can rewrite them to float or to any other size than 4 byte if needed.
i just wanted to give an example for std. memory reading on sro (most necessary values are 4 byte)
By the posts of the requester, I saw he wasn't really experienced.
That's why I tried to tell you to note these things when you release something to less-experienced people.
11/20/2010 13:42 ZeraPain#11
Quote:
Originally Posted by lesderid View Post
By the posts of the requester, I saw he wasn't really experienced.
That's why I tried to tell you to note these things when you release something to less-experienced people.
i see :)

i would propose to Janick to use autoit if it is just simple memory reading.
this works pretty well, too and you don't need to have much knowledge about programming to create a simple program. As i read on your first post you want to create a gui to display the stats of a character.
simple example using autoit:

Code:
Global $OLD_char, $OLD_hp
Global $Process = _MemoryOpen(WinGetProcess("SRO_Client"))

Global $Pointer_char = 0x00A9FB98
Global $Pointer_Base = 0x00A8913C
Global $Pointer_maxhp = 0x00AA0740
Global $Offset_curhp = 0x1D4

GUICreate("Char Display", 200, 100)
GUICtrlCreateLabel("Charname:", 10, 20)
$Label_char = GUICtrlCreateLabel("", 70, 20, 100)
GUICtrlCreateLabel("HP:", 10, 40)
$Label_hp = GUICtrlCreateLabel("", 70, 40, 100)
GUISetState()

While 1
	Switch GUIGetMsg()
		Case -3
			Exit
	EndSwitch
	_CharUpdate()
WEnd

Func _CharUpdate()
	Local $READ_char, $READ_maxhp, $READ_Base, $READ_curhp
	$READ_char = _MemoryRead($Pointer_char, $Process, "char[40]")
	$READ_maxhp = _MemoryRead($Pointer_maxhp, $Process)
	$READ_Base = _MemoryRead($Pointer_Base, $Process)
	$READ_curhp = _MemoryRead($READ_Base + $Offset_curhp, $Process)

	If $READ_char <> $OLD_char Then
		$OLD_char = $READ_char
		GUICtrlSetData($Label_char, $READ_char)
	EndIf
	If $READ_curhp <> $OLD_hp Then
		$OLD_hp = $READ_curhp
		GUICtrlSetData($Label_hp, $READ_curhp & " / " & $READ_maxhp)
	EndIf
EndFunc

Func _MemoryOpen($iv_Pid, $iv_DesiredAccess = 0x1F0FFF, $iv_InheritHandle = 1)
	Local $ah_Handle[2] = [DllOpen('kernel32.dll')]
	Local $av_OpenProcess = DllCall($ah_Handle[0], 'int', 'OpenProcess', 'int', $iv_DesiredAccess, 'int', $iv_InheritHandle, 'int', $iv_Pid)
	$ah_Handle[1] = $av_OpenProcess[0]
	Return $ah_Handle
EndFunc   ;==>_MemoryOpen

Func _MemoryRead($iv_Address, $ah_Handle, $sv_Type = 'dword')
	Local $v_Buffer = DllStructCreate($sv_Type)
	DllCall($ah_Handle[0], 'int', 'ReadProcessMemory', 'int', $ah_Handle[1], 'int', $iv_Address, 'ptr', DllStructGetPtr($v_Buffer), 'int', DllStructGetSize($v_Buffer), 'int', '')
	Local $v_Value = DllStructGetData($v_Buffer, 1)
	Return $v_Value
EndFunc   ;==>_MemoryRead
11/20/2010 19:26 Janick_#12
Ty for everyone's help, and well i don't wanna use autoit because i wanna continue learning C# and make more programs with it^^ and yes im not really experienced yet. Would be great if you can help me a bit with the program i wanna make and maybe make some instructions from what is what and stuff it would be great.
11/20/2010 19:55 ZeraPain#13
Code with comments...

Program.cs

Code:
using System;
using System.Linq;
using System.Text;

//include namespace Game.Memory
using Game.Memory;

namespace main
{
    class Program
    {
        //Creating var
        private static bool exit = false;
    
        //Main function (runs on program start)
        static void Main(string[] args)
        {
            //As long as exit is not true..
            while (!exit)
                //Call function GetLine with Console Input
                GetLine(Console.ReadLine());
        }

        //GetLine function
        private static void GetLine(string cmd)
        {
            //Create object of class Memory
            Memory mem = new Memory("sro_client");

            //Switch Console input
            switch (cmd)
            {
                //If Console input = curhp
                case "curhp":
                    //Call function ReadOffset of the mem object (returns int)
                    int curhp = mem.ReadOffset(0x00A8913C, 0x1D4);
                    //Output the result
                    Console.WriteLine("Current HP: {0}", curhp);
                    break;
                //If Console input = maxhp
                case "maxhp":
                    //Call function ReadOffset of the mem object (returns int)
                    int maxhp = mem.ReadPointer(0x00AA0740);
                    //Output the result
                    Console.WriteLine("Maximum HP: {0}", maxhp);
                    break;
                //If Console input = name 
                case "name":
                    //Call function ReadOffset of the mem object (returns string)
                    string name = mem.ReadString(0x00A9FB98);
                    //Output the result
                    Console.WriteLine("Charname: {0}", name);
                    break;
                //If Console input = exit
                case "exit":
                    //Set exit true (program terminates)
                    exit = true;
                    break;
            }
        }      
    }
}
Memory.cs

Code:
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace Game.Memory
{
    class Memory
    {
        //import kernel32 and create OpenProcess and ReadProcess functions
        [DllImport("kernel32.dll")]
        static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Boolean bInheritHandle, UInt32 dwProcessId);
        [DllImport("kernel32.dll")]
        static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
        byte[] lpBuffer, UIntPtr nSize, uint lpNumberOfBytesWritten);

        //Create handle
        IntPtr Handle;

        //constructor
        public Memory(string sprocess)
        {
            //Get the specific process
            Process[] Processes = Process.GetProcessesByName(sprocess);
            Process nProcess = Processes[0];
            //access to the process
            Handle = OpenProcess(0x10, false, (uint)nProcess.Id);
        }

        //function ReadString (returns string value)
        public string ReadString(uint pointer) 
        {
            //Create bytearray
            byte[] bytes = new byte[24];

            //Read the specific address within the process
            ReadProcessMemory(Handle, (IntPtr)pointer, bytes, (UIntPtr)24, 0);
            //Return the result as UTF8 String
            return Encoding.UTF8.GetString(bytes);
        }

        //function ReadOffset (returns int value)
        public int ReadOffset(uint pointer, uint offset)
        {
            //Create bytearray
            byte[] bytes = new byte[24];

            //Creating the address (reading the Base and add the offset)
            uint adress = (uint)ReadPointer(pointer) + offset;
            //Reading the specific address within the process
            ReadProcessMemory(Handle, (IntPtr)adress, bytes, (UIntPtr)sizeof(int), 0);
            //Return the result as 4 byte int
            return BitConverter.ToInt32(bytes, 0);
        }

        //function ReadPointer (returns int value)
        public int ReadPointer(uint pointer)
        {
            //Create bytearray
            byte[] bytes = new byte[24];

            //Reading the specific address within the process
            ReadProcessMemory(Handle, (IntPtr)pointer, bytes, (UIntPtr)sizeof(int), 0);
            //Return the result as 4 byte int
            return BitConverter.ToInt32(bytes, 0);
        }
    }
}
11/21/2010 08:08 lesderid#14
Quote:
Originally Posted by ZeraPain View Post
Code with comments...

Program.cs

Code:
//Cool code
Memory.cs

Code:
//More cool code
Nice but it's becoming a bit "Add one to i", isn't it?
For example:
Code:
            //Create bytearray
            byte[] bytes = new byte[24];
11/21/2010 11:45 ZeraPain#15
just wanted to be sure that everything is explained :)