Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


[.NET] Pointer to Address Lookup

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming
View previous topic :: View next topic  
Author Message
Polynomial
Grandmaster Cheater
Reputation: 5

Joined: 17 Feb 2008
Posts: 524
Location: Inside the Intel CET shadow stack

PostPosted: Mon Aug 10, 2009 8:55 am    Post subject: [.NET] Pointer to Address Lookup Reply with quote

This is a simple bit of code to make looking up addresses from pointers really easy.

First you'll need to add the API reference for ReadProcessMemory for this to work. Here it is:

VB.NET
Code:
    <DllImport("kernel32.dll", SetLastError:=True)> _
     Public Shared Function ReadProcessMemory( _
       ByVal hProcess As IntPtr, _
       ByVal lpBaseAddress As IntPtr, _
       <Out()> ByVal lpBuffer() As Byte, _
       ByVal dwSize As Integer, _
       ByRef lpNumberOfBytesRead As Integer) As Boolean
    End Function


C#
Code:
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out()] byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead);


And this is the code I wrote to look up an address from a pointer and a list of offsets:

VB.NET
Code:
    Private Function FindAddress(ByVal pHandle As IntPtr, ByVal BaseAddress As IntPtr, ByVal StaticPointer As IntPtr, ByVal Offsets() As IntPtr) As IntPtr
        ' Create a buffer that is 4 bytes on a 32-bit system or 8 bytes on a 64-bit system.
        Dim tmp(IntPtr.Size - 1) As Byte
        Dim Address As IntPtr = BaseAddress
        ' We must check for 32-bit vs 64-bit.
        If IntPtr.Size = 4 Then
            Address = New IntPtr(Address.ToInt32 + StaticPointer.ToInt32)
        Else
            Address = New IntPtr(Address.ToInt64 + StaticPointer.ToInt64)
        End If
        ' Loop through each offset to find the address
        For i As Integer = 0 To Offsets.Length - 1
            ReadProcessMemory(pHandle, Address, tmp, IntPtr.Size, 0)
            If IntPtr.Size = 4 Then
                Address = BitConverter.ToInt32(tmp, 0) + Offsets(i).ToInt32()
            Else
                Address = BitConverter.ToInt64(tmp, 0) + Offsets(i).ToInt64()
            End If
        Next
        Return Address
    End Function


C#
Code:
private IntPtr FindAddress(IntPtr pHandle, IntPtr BaseAddress, IntPtr StaticPointer, IntPtr[] Offsets)
{
    // Create a buffer that is 4 bytes on a 32-bit system or 8 bytes on a 64-bit system.
    byte[] tmp = new byte[IntPtr.Size];
    IntPtr Address = BaseAddress;
    // We must check for 32-bit vs 64-bit.
    if (IntPtr.Size == 4) {
        Address = new IntPtr(Address.ToInt32 + StaticPointer.ToInt32);
    }
    else {
        Address = new IntPtr(Address.ToInt64 + StaticPointer.ToInt64);
    }
    // Loop through each offset to find the address
    for (int i = 0; i < Offsets.Length; i++) {
        ReadProcessMemory(pHandle, Address, tmp, IntPtr.Size, 0);
        if (IntPtr.Size == 4) {
            Address = BitConverter.ToInt32(tmp, 0) + Offsets(i).ToInt32();
        }
        else {
            Address = BitConverter.ToInt64(tmp, 0) + Offsets(i).ToInt64();
        }
    }
    return Address;
}




Here's how you use it:
1) Get a hande to the process. I personally use the Process class to find the process I need (Process.GetProcessesByName) and then read from the Handle property.
2) Get the base address of the process, which is usually 0x400000 (&H400000 in VB.NET). You can use Process.MainModule.BaseAddress property to get the address if you want to.
3) Create an array of offsets for each pointer. If CE's pointer scan returns 0x0062B688 + 0xC, 0x38, create an array whose values are 0xC and 0x38. The StaticPointer parameter in this case would be 0x0062B688.

Here's an example:

VB.NET
Code:

' I'm assuming p is a Process object that represents the game process.
Dim pID As IntPtr = p.Handle
Dim base As IntPtr = p.MainModule.BaseAddress
' Our static pointer...
Dim sptr as IntPtr = &H62B688
' And our offsets...
Dim offsets() As IntPtr = {&HC, &H38}
Dim addr As IntPtr = FindAddress(pID, base, sptr, offsets)


C#
Code:
// I'm assuming p is a Process object that represents the game process.
IntPtr pID = p.Handle;
IntPtr @base = p.MainModule.BaseAddress;
// Our static pointer...
IntPtr sptr = 0x62b688;
// And our offsets...
IntPtr[] offsets = { 0xc, 0x38 };
IntPtr addr = FindAddress(pID, @base, sptr, offsets);


And that's it. This method has saved me loads of time when creating trainers.

Just a warning: I wrote the original in VB.NET and the C# code was automatically generated by a converter, I haven't tested it. I've looked it through and it seems OK though.
Back to top
View user's profile Send private message
Odecey
Master Cheater
Reputation: 1

Joined: 19 Apr 2007
Posts: 259
Location: Scandinavia

PostPosted: Mon Aug 10, 2009 1:11 pm    Post subject: Reply with quote

Good job, although a very similiar method has already been posted here.
_________________
Never confuse activity with productivity. You can be busy without a purpose, but what's the point?- Rick Warren
Back to top
View user's profile Send private message MSN Messenger
Polynomial
Grandmaster Cheater
Reputation: 5

Joined: 17 Feb 2008
Posts: 524
Location: Inside the Intel CET shadow stack

PostPosted: Tue Aug 11, 2009 2:28 pm    Post subject: Reply with quote

I hadn't spotted that one. This one is for C# and VB.NET though, so it's useful for people that have more experience with .NET languages.
_________________
It's not fun unless every exploit mitigation is enabled.
Please do not reply to my posts with LLM-generated slop; I consider it to be an insult to my time.
Back to top
View user's profile Send private message
arktikk
How do I cheat?
Reputation: 0

Joined: 09 Feb 2011
Posts: 2

PostPosted: Wed Feb 09, 2011 10:04 pm    Post subject: Reply with quote

Sorry to bump such an old topic, but I can't seem to find any method out there that works for me. I tried PMing burningmace instead of bumping this, but I don't meet a post requirement I suppose.

I have also tried that youtube tutorial posted somewhere on this forum, and it reads 4 byte pointers perfectly...just not multi-level ones.

Okay so basically, I followed the tutorial exactly, copying and pasting the declarations and functions, but I cant manage to read the data? Im using VS 2010, Win7 x64, and I'm pretty new to vb.net.

I'd really appreciate some help on this. Smile

Here is my exact code:

Code:
Imports System.Runtime.InteropServices

Public Class form1
 
    <DllImport("kernel32.dll", SetLastError:=True)> _
    Public Shared Function ReadProcessMemory( _
       ByVal hProcess As IntPtr, _
       ByVal lpBaseAddress As IntPtr, _
       <Out()> ByVal lpBuffer() As Byte, _
       ByVal dwSize As Integer, _
       ByRef lpNumberOfBytesRead As Integer) As Boolean
    End Function

     Private Function FindAddress(ByVal pHandle As IntPtr, ByVal BaseAddress As IntPtr, ByVal StaticPointer As IntPtr, ByVal Offsets() As IntPtr) As IntPtr
        ' Create a buffer that is 4 bytes on a 32-bit system or 8 bytes on a 64-bit system.
        Dim tmp(IntPtr.Size - 1) As Byte
        Dim Address As IntPtr = BaseAddress
        ' We must check for 32-bit vs 64-bit.
        If IntPtr.Size = 4 Then
            Address = New IntPtr(Address.ToInt32 + StaticPointer.ToInt32)
        Else
            Address = New IntPtr(Address.ToInt64 + StaticPointer.ToInt64)
        End If
        ' Loop through each offset to find the address
        For i As Integer = 0 To Offsets.Length - 1
            ReadProcessMemory(pHandle, Address, tmp, IntPtr.Size, 0)
            If IntPtr.Size = 4 Then
                Address = BitConverter.ToInt32(tmp, 0) + Offsets(i).ToInt32()
            Else
                Address = BitConverter.ToInt64(tmp, 0) + Offsets(i).ToInt64()
            End If
        Next
        Return Address
    End Function


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim p As Process() = Process.GetProcessesByName("processname")
        ' I'm assuming p is a Process object that represents the game process.
        Dim pID As IntPtr = p(0).Handle
        Dim base As IntPtr = p(0).MainModule.BaseAddress
        ' Our static pointer...
        Dim sptr As IntPtr = &HD9DE08
        ' And our offsets...
        Dim offsets() As IntPtr = {&H0, &H75}
        Dim addr As IntPtr = FindAddress(pID, base, sptr, offsets)
    End Sub
End Class


The actual offset is only 75, but when I put that in VS I get an error saying I can't use 1-Dimensional arrays, so I added &H0.

If I try using MsgBox(addr) or setting a textbox/label to it, I get an error saying "Cannot convert prompt to string" or something. How am I supposed to be able to read the value?

Thanks again, I'm sorry if I wasn't supposed to bump such an old thread.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 471

Joined: 09 May 2003
Posts: 25813
Location: The netherlands

PostPosted: Thu Feb 10, 2011 8:16 am    Post subject: Reply with quote

Try compiling your .net app as 32-bit only

Using IntPtr.Size is the wrong method.
Guess what happens when building it for 64-bit and targeting a 32-bit process (like most games are)

use IsWow64Process to figure out if it's a 32 or 64 bit process you're dealing with and adjust the pointersizes accordingly

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
arktikk
How do I cheat?
Reputation: 0

Joined: 09 Feb 2011
Posts: 2

PostPosted: Thu Feb 10, 2011 4:41 pm    Post subject: Reply with quote

Whats odd was, to even get the baseaddress, I had to compile for "AnyCPU" or I'd get an error where it says "cannot access 64 bit program from 32 bit program," or it may have been the other way around. I got this error even when I tried to get baseaddress from something like 32bit Spy++.

Instead of using
Code:
Address = New IntPtr(Address.ToInt32 + StaticPointer.ToInt64)

and
Code:
Address = BitConverter.ToInt32(tmp, 0) + Offsets(i).ToInt64()

I switched them both to ToInt32, and I no longer get the "prompt to string" error, however it does give me a pretty obscure address.

Its giving me the intptr as 15038163, which is e576d3 in hex. The final address is SUPPOSED to be 02BC9AC5. (45914821 in decimal)

I really have no clue what is going on with this.

In case it matters, I'm getting a base address of 4194304 which looks right, at least to me.
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 205

Joined: 25 Jan 2006
Posts: 8587
Location: 127.0.0.1

PostPosted: Fri Feb 11, 2011 12:06 pm    Post subject: Reply with quote

If the target you're hacking is 64bit, you need to be consistent and use 64bit types in your application as well or you will get issues like the one you are getting.

Also, AnyCPU doesn't mean the application will properly convert things for you, you will have to specifically use 64bit types when 64bit is the target and so on. You are better off specifically compiling for x64 and making sure all your types are 64bit compliant.

ToInt32 is invalid for x64 applications, you should be using ToInt64 for all your variables that you require converting to.

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Polynomial
Grandmaster Cheater
Reputation: 5

Joined: 17 Feb 2008
Posts: 524
Location: Inside the Intel CET shadow stack

PostPosted: Sat Feb 19, 2011 4:41 am    Post subject: Reply with quote

My apologies. My code naively assumes all processes on an x64 OS are 64-bit.

Check out this URL for the IsWow64Process API definition for .NET: http://pinvoke.net/default.aspx/kernel32/IsWow64Process.html

Simplest way to check in C# is this...
Code:
bool is64 = false;
IsWow64Process(procObj.Handle, out is64);

_________________
It's not fun unless every exploit mitigation is enabled.
Please do not reply to my posts with LLM-generated slop; I consider it to be an insult to my time.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites