 |
Cheat Engine The Official Site of Cheat Engine
|
| 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
|
Posted: Mon Aug 10, 2009 8:55 am Post subject: [.NET] Pointer to Address Lookup |
|
|
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 |
|
 |
Odecey Master Cheater
Reputation: 1
Joined: 19 Apr 2007 Posts: 259 Location: Scandinavia
|
Posted: Mon Aug 10, 2009 1:11 pm Post subject: |
|
|
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 |
|
 |
Polynomial Grandmaster Cheater
Reputation: 5
Joined: 17 Feb 2008 Posts: 524 Location: Inside the Intel CET shadow stack
|
Posted: Tue Aug 11, 2009 2:28 pm Post subject: |
|
|
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 |
|
 |
arktikk How do I cheat?
Reputation: 0
Joined: 09 Feb 2011 Posts: 2
|
Posted: Wed Feb 09, 2011 10:04 pm Post subject: |
|
|
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.
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 |
|
 |
Dark Byte Site Admin
Reputation: 470
Joined: 09 May 2003 Posts: 25812 Location: The netherlands
|
Posted: Thu Feb 10, 2011 8:16 am Post subject: |
|
|
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 |
|
 |
arktikk How do I cheat?
Reputation: 0
Joined: 09 Feb 2011 Posts: 2
|
Posted: Thu Feb 10, 2011 4:41 pm Post subject: |
|
|
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 |
|
 |
atom0s Moderator
Reputation: 205
Joined: 25 Jan 2006 Posts: 8587 Location: 127.0.0.1
|
Posted: Fri Feb 11, 2011 12:06 pm Post subject: |
|
|
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 |
|
 |
Polynomial Grandmaster Cheater
Reputation: 5
Joined: 17 Feb 2008 Posts: 524 Location: Inside the Intel CET shadow stack
|
Posted: Sat Feb 19, 2011 4:41 am Post subject: |
|
|
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 |
|
 |
|
|
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
|
|