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 


[Java] ReadProcessMemory and base module address

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
Sadret
How do I cheat?
Reputation: 0

Joined: 17 Jan 2021
Posts: 2

PostPosted: Sun Jan 17, 2021 3:58 pm    Post subject: [Java] ReadProcessMemory and base module address Reply with quote

Hi,
like so many others I have problems with ReadProcessMemory and the base module address. Because there are so many issues about this, it's hard to find those that apply to me via the board search. I found out some things, but there are still questions. So this is my situation.

A few years ago, I wrote a program that monitored some memory addresses of a game. It was quiet simple, there was an address which's value pointed to another address, I added one offset, done:
Code:

ptr = OpenProcess(0x0010, processId)
address = ReadProcessMemory(ptr, 0x012D5A90)
value = ReadProcessMemory(ptr, address + 0x7CD8)

This is just pseudo-code, because I actually use a Java wrapper for that.
The initial address 0x012D5A90 I did get from somewhere else, not CE related.

A few months ago, there was a big update of the game and my tool stopped working. The game also changed to 64 bit, if that matters. So now I decided to use CE to recreate my program.
I used the pointer scan tool to search for the correct pointer/address. As expected, I found something like this:
Base Address: Game.exe+02099b08
Offset 0: 984
// no other offsets
Points to: 1E89B96BDD4

Naturally, I expected the following to work:
Code:

ptr = OpenProcess(0x0010, processId)
address = ReadProcessMemory(ptr, 0x02099b08)
value = ReadProcessMemory(ptr, address + 0x984)


But it doesn't, it gives unrelated data. So I started searching and found this board. Here, everyone is talking about getting the base module address of the process. As far as I understood, this is the memory address of the process in the main memory. But why do we need it? Doesn't ReadProcessMemory already take an address that is relative to the process' memory?

As my program worked fine before, I am really expecting that I just need to change the two numbers 0x012D5A90 and 0x7CD8, so that it will work again. How do I get these numbers out of CE?

Thanks in advance for any help.

EDIT:

@ Dark Byte: this only answers one of my three questions, right? I'd still like to know what this base address is and what ReadProcessMemory takes as an argument.

@ atom0s: Thanks for the hint.

After updating my JNA to 5.6.0, I used Module32... to get the base address. I had to adjust some things to 64 bit, but now it is running. Demo is below.

The base address seems to be static, is that safe to assume? This would fit my approach of the earlier (32 bit) version of the game.


Last edited by Sadret on Mon Jan 18, 2021 8:20 am; edited 2 times in total
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 470

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

PostPosted: Sun Jan 17, 2021 5:32 pm    Post subject: Reply with quote

https://forum.cheatengine.org/viewtopic.php?p=5280115#5280115
_________________
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
atom0s
Moderator
Reputation: 205

Joined: 25 Jan 2006
Posts: 8587
Location: 127.0.0.1

PostPosted: Mon Jan 18, 2021 4:59 am    Post subject: Reply with quote

You need to make sure your code is accounting for the fact that things are 64bit. Pointers/address will require 8 bytes of space instead of 4. In most cases, people tend to overlook that and still attempt to read their pointers as if it were 32bit and land up using the wrong addresses/offsets.

Rather than pseudo code as well, better to post your real code if you have issues with something code related. Can help us help you better.

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Sadret
How do I cheat?
Reputation: 0

Joined: 17 Jan 2021
Posts: 2

PostPosted: Mon Jan 18, 2021 8:08 am    Post subject: Reply with quote

For anyone else who is using Java/JNA and needs an example implementation, here you go.
Attention: this is only for 64 bit programs.
Requirements: JNA and JNA platform (tested with 5.6.0).

Helper methods:
Code:

   public static int findProcessId(String processName) {
      Tlhelp32.PROCESSENTRY32.ByReference processInfo = new Tlhelp32.PROCESSENTRY32.ByReference();
      WinNT.HANDLE processesSnapshot = Kernel32.INSTANCE.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPPROCESS, new DWORD(0L));

      try {
         Kernel32.INSTANCE.Process32First(processesSnapshot, processInfo);

         do
            if (processName.equals(Native.toString(processInfo.szExeFile)))
               return processInfo.th32ProcessID.intValue();
         while (Kernel32.INSTANCE.Process32Next(processesSnapshot, processInfo));

         return 0;
      } finally {
         Kernel32.INSTANCE.CloseHandle(processesSnapshot);
      }
   }

   public static Pointer findModuleBase(long pid, String moduleName) {
      Tlhelp32.MODULEENTRY32W.ByReference moduleInfo = new Tlhelp32.MODULEENTRY32W.ByReference();
      WinNT.HANDLE processesSnapshot = Kernel32.INSTANCE.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPMODULE, new DWORD(pid));
      try {
         Kernel32.INSTANCE.Module32FirstW(processesSnapshot, moduleInfo);

         do
            if (String.valueOf(moduleInfo.szExePath).contains(moduleName))
               return moduleInfo.modBaseAddr;
         while (Kernel32.INSTANCE.Module32NextW(processesSnapshot, moduleInfo));

         return Pointer.NULL;
      } finally {
         Kernel32.INSTANCE.CloseHandle(processesSnapshot);
      }
   }

   public static int readIntFromMemory(int pid, Pointer address) {
      HANDLE handle = Kernel32.INSTANCE.OpenProcess(0x0010, true, pid);

      Memory output = new Memory(4);
      Kernel32.INSTANCE.ReadProcessMemory(handle, address, output, 4, null);

      return output.getInt(0);
   }

   public static Pointer readPointerFromMemory(long pid, Pointer address) {
      HANDLE handle = Kernel32.INSTANCE.OpenProcess(0x0010, true, (int) pid);

      Memory output = new Memory(8);
      Kernel32.INSTANCE.ReadProcessMemory(handle, address, output, 8, null);

      return new Pointer(output.getLong(0));
   }


Usage:
Let's say CE gave you:
Base Address: game.exe + 0x02099b08
Offset 0: 0x8e4
and no other offsets.
Code:

String processName = "game.exe";
int address = 0x02099b08;
int offset = 0x8e4;

int pid = Process.findProcessId(processName);
Pointer baseAddress = Process.findModuleBase(pid, processName);
Pointer pointer = Process.readPointerFromMemory(pid, baseAddress.share(address));
int value = Process.readIntFromMemory(pid, pointer.share(offset));


For more information on what the kernel methods do and what the arguments are, you can look at the officical microsoft docs.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine 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