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 


Using ReadMem Properly

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
++METHOS
I post too much
Reputation: 92

Joined: 29 Oct 2010
Posts: 4197

PostPosted: Sun Feb 06, 2022 4:59 am    Post subject: Using ReadMem Properly Reply with quote

I am trying to make a script more compatible. I think readmem is what I am supposed to be using, but I am not sure because I have never used it. Looking at examples for readmem, I can only seem to understand parts of its usage:

This is the original script:

Code:
aobscanmodule(aob_ped_density,sdhdship.exe,F3??????????????F3??????????????F3??????????????0F54??????????0F2F??????????76)
alloc(newmem_ped_density,1024,sdhdship.exe)

label(return_ped_density)
label(originalcode_ped_density)
label(ped_density_address)

registersymbol(aob_ped_density)
registersymbol(ped_density_address)


newmem_ped_density:
  push rdi
  lea rdi,[sdhdship.exe+207B21C]
  mov [ped_density_address],rdi
  pop rdi

originalcode_ped_density:
  movss xmm0,[sdhdship.exe+207B21C]
  jmp return_ped_density

ped_density_address:
  dq 0

aob_ped_density:
  jmp newmem_ped_density
  nop 3
return_ped_density:


[DISABLE]
dealloc(newmem_ped_density)
aob_ped_density:
  db F3 0F 10 05 F8 2B C6 01

unregistersymbol(aob_ped_density)
unregistersymbol(ped_density_address)



This is my attempt at incorporating newmem:


Code:
aobscanmodule(aob_ped_density,sdhdship.exe,F3??????????????F3??????????????F3??????????????0F54??????????0F2F??????????76)
alloc(newmem_ped_density,1024,sdhdship.exe)
alloc(pdbytes,8)

label(return_ped_density)
label(originalcode_ped_density)
label(ped_density_address)
label(pdbytes)

registersymbol(aob_ped_density)
registersymbol(ped_density_address)


newmem_ped_density:
  push rdi
  lea rdi,[pdbytes+4]                //lea rdi,[sdhdship.exe+207B21C]
  mov [ped_density_address],rdi
  pop rdi

originalcode_ped_density:
  movss xmm0,[pdbytes+4]             //movss xmm0,[sdhdship.exe+207B21C]
jmp return_ped_density

ped_density_address:
  dq 0

pdbytes:
  readmem(aob_ped_density,8)

aob_ped_density:
  jmp newmem_ped_density
  nop 3
return_ped_density:


[DISABLE]
dealloc(newmem_ped_density)
aob_ped_density:
  readmem(aob_ped_density,8)        //db F3 0F 10 05 F8 2B C6 01

unregistersymbol(aob_ped_density)
unregistersymbol(ped_density_address)


Am I even close?

Thanks.
Back to top
View user's profile Send private message
TheyCallMeTim13
Wiki Contributor
Reputation: 51

Joined: 24 Feb 2017
Posts: 976
Location: Pluto

PostPosted: Sun Feb 06, 2022 5:59 am    Post subject: Reply with quote

You want to read the stored bytes when disabling, so you'll need to register the symbol. And I'd deallocate after reading the memory, but I think CE actually handles deallocation the way it needs to be so either one might work.
Code:

label(pdbytes)
registersymbol(pdbytes)
//...
pdbytes:
  readmem(aob_ped_density,8)
//...
[DISABLE]
aob_ped_density:
  readmem(pdbytes,8)
dealloc(newmem_ped_density)
//...

_________________
Back to top
View user's profile Send private message Visit poster's website
++METHOS
I post too much
Reputation: 92

Joined: 29 Oct 2010
Posts: 4197

PostPosted: Sun Feb 06, 2022 6:49 am    Post subject: Reply with quote

Thank you. I appreciate your help with this.

I have made some changes. Now, the script will activate and will deactivate correctly, with original bytes unaltered upon disable. Which is good. Unfortunately, the correct address is not being stored, and the originalcode is not correct:

Code:
aobscanmodule(aob_ped_density,sdhdship.exe,F3??????????????F3??????????????F3??????????????0F54??????????0F2F??????????76)
alloc(newmem_ped_density,1024,sdhdship.exe)
//alloc(pdbytes,8)

label(return_ped_density)
label(originalcode_ped_density)
label(ped_density_address)
label(pdbytes)

registersymbol(aob_ped_density)
registersymbol(ped_density_address)
registersymbol(pdbytes)


newmem_ped_density:
  push rdi
  lea rdi,[pdbytes+4]                //correct address of [sdhdship.exe+207B21C] is not getting stored
  mov [ped_density_address],rdi
  pop rdi

originalcode_ped_density:
  movss xmm0,[pdbytes+4]             //Same as above
jmp return_ped_density

ped_density_address:
  dq 0

pdbytes:
  readmem(aob_ped_density,8)

aob_ped_density:
  jmp newmem_ped_density
  nop 3
return_ped_density:


[DISABLE]
aob_ped_density:
  readmem(pdbytes,8)        //db F3 0F 10 05 F8 2B C6 01
//dealloc(pdbytes)
dealloc(newmem_ped_density)

unregistersymbol(aob_ped_density)
unregistersymbol(ped_density_address)
unregistersymbol(pdbytes)


Is what I am trying to do even possible? Thanks, again.
Back to top
View user's profile Send private message
TheyCallMeTim13
Wiki Contributor
Reputation: 51

Joined: 24 Feb 2017
Posts: 976
Location: Pluto

PostPosted: Sun Feb 06, 2022 7:08 am    Post subject: This post has 1 review(s) Reply with quote

That's because of how x64 bit processes work, the address is actually the 4 bytes as a signed integer + the instruction address at the end of the 4 bytes.

I actually use this Lua function to get an address stored in opcode.
Code:

----
---- Calculates the address stored in opcode if 64 bit, or reads the address if 32 bit.
----
---- getOpcodeAddress(address)
----
---- Parameters:
----    address : number - string :
----       The address of the opcode the stored address is.
---- Return:
----    number :
----       The address stored at the given opcode address.
function getOpcodeAddress(address)
   address = getAddress(address)
   if targetIs64Bit() then
      local os = readInteger(address, true) or 0
      return address + 4 + os
   else
      return readInteger(address)
   end
end
registerLuaFunctionHighlight('getOpcodeAddress')


Basically it reads the 4 bytes as a signed integer, then adds the value of the 4 bytes + the address passed (were the 4 bytes are) + 4 (to get to the end of where the bytes are stored.

EDIT: to make this work you have to do the AOB scan in lua. Or enable the AA script to get the AOB address and register it's symbol, then enable the Lua script calling this function.

As for the original code that gets executed in the AA script you can use reassemble.
https://wiki.cheatengine.org/index.php?title=Auto_Assembler:reassemble

_________________
Back to top
View user's profile Send private message Visit poster's website
++METHOS
I post too much
Reputation: 92

Joined: 29 Oct 2010
Posts: 4197

PostPosted: Sun Feb 06, 2022 7:28 am    Post subject: Reply with quote

TheyCallMeTim13, thank you for your help with this. A lot of this is over my head, I'm afraid. I unfortunately do not know lua. I wonder if there is a way to do this all in assembly? I could try using lua, but I would need help with implementation, such as an example to study that is similar.

Regarding reassemble, I wonder how this works if/when the address offset changes to something unknown? Maybe I do not fully understand its usage.

I appreciate your help with this. Maybe I will need to just settle with what I have.

Thanks.
Back to top
View user's profile Send private message
panraven
Grandmaster Cheater
Reputation: 62

Joined: 01 Oct 2008
Posts: 958

PostPosted: Sun Feb 06, 2022 8:29 am    Post subject: Reply with quote

Just a note, the second parameter (num of bytes to read from and write to) is in decimal (no prefix # need), so if more than 9 bytes, remember it is in decimal.
_________________
- Retarded.
Back to top
View user's profile Send private message
++METHOS
I post too much
Reputation: 92

Joined: 29 Oct 2010
Posts: 4197

PostPosted: Sun Feb 06, 2022 8:37 am    Post subject: Reply with quote

You mean, in the case of readmem(pdbytes,8), the 8 is in decimal format? Or something else?
Back to top
View user's profile Send private message
TheyCallMeTim13
Wiki Contributor
Reputation: 51

Joined: 24 Feb 2017
Posts: 976
Location: Pluto

PostPosted: Sun Feb 06, 2022 9:18 am    Post subject: Reply with quote

You could look for another spot where that static address gets accessed and moved to a registry. Say something like "mov rax,[game.exe+DEADBEEF]". Then you could use reassemble to add that to your script, it would require a second aob scan. But you could then make a script like this.

Code:
aobscanmodule(aob_ped_density,sdhdship.exe,F3??????????????F3??????????????F3??????????????0F54??????????0F2F??????????76)
aobscanmodule(aob_ped_density_2,sdhdship.exe,...)
alloc(newmem_ped_density,1024,sdhdship.exe)
//alloc(pdbytes,8)

label(return_ped_density)
label(originalcode_ped_density)
label(ped_density_address)
label(pdbytes)

registersymbol(aob_ped_density)
registersymbol(ped_density_address)
registersymbol(pdbytes)


newmem_ped_density:
  push rax
  reassemble(aob_ped_density_2)
  mov [ped_density_address],rax
  pop rax

originalcode_ped_density:
  reassemble(aob_ped_density)
jmp return_ped_density

ped_density_address:
  dq 0

pdbytes:
  readmem(aob_ped_density,8)

aob_ped_density:
  jmp newmem_ped_density
  nop 3
return_ped_density:


[DISABLE]
aob_ped_density:
  readmem(pdbytes,8)        //db F3 0F 10 05 F8 2B C6 01
//dealloc(pdbytes)
dealloc(newmem_ped_density)

unregistersymbol(aob_ped_density)
unregistersymbol(ped_density_address)
unregistersymbol(pdbytes)

_________________
Back to top
View user's profile Send private message Visit poster's website
panraven
Grandmaster Cheater
Reputation: 62

Joined: 01 Oct 2008
Posts: 958

PostPosted: Sun Feb 06, 2022 9:54 am    Post subject: This post has 1 review(s) Reply with quote

++METHOS wrote:
You mean, in the case of readmem(pdbytes,Cool, the 8 is in decimal format? Or something else?


Yes, it is in decimal format, matter only when it is more than 9.

btw, my try on the script, assume the instruction at aob_ped_density is rip-address as movss xmm0,[-some-rip-address-], not test and may be some typo

Code:

aobscanmodule(aob_ped_density,sdhdship.exe,F3??????????????F3??????????????F3??????????????0F54??????????0F2F??????????76)
alloc(newmem_ped_density,1024,sdhdship.exe)
alloc(pdbytes,8)

label(return_ped_density)
label(originalcode_ped_density)
label(ped_density_address)
label(pdbytes)

registersymbol(aob_ped_density)
registersymbol(ped_density_address)


newmem_ped_density:
  push rdi
  push  rsi
  mov   rdi,aob_ped_density+8 /// where the 4-bytes rip END
  mov   rsi,pdbytes+4 /// where the 4-bytes rip START at the COPY of aob_ped_density == pdbytes
  movsxd   rsi,[rsi]/// rsi get the signed relative offset at rdi-4 of the original instruction, ADDED, same as movsxd   rsi,dword ptr[rsi]
  add  rdi,rsi /// now rdi is the absolute of the rip-address
  mov rsi,ped_density_address /// use this format in case, it is outside 2g range
  mov [rsi],rdi /// ped_density_address now has its content store above absolute address
  pop rsi
  pop  rdi

originalcode_ped_density:
{
  movss xmm0,[pdbytes+4]             //movss xmm0,[sdhdship.exe+207B21C]
}
//// -- original code option 1
reassemble(aob_ped_density)  /// use reassemble, may fail if there is an rip address outside 2g range of the cave
//// -- original code option 2, manually construct the address and the instruction, use above assume the instruct as movss xmm0,[-some-rip-address-] safe outside 2g range
  push    rdi
  mov    rdi,ped_density_address
  mov    rdi,[rdi] /// get the absolute address
  movss xmm0,[rdi]
  pop   rdi

jmp return_ped_density

ped_density_address:
  dq 0

pdbytes:
  readmem(aob_ped_density,8)


aob_ped_density:
  jmp newmem_ped_density
  nop 3
return_ped_density:


[DISABLE]
dealloc(newmem_ped_density)
aob_ped_density:
  readmem(aob_ped_density,8)        //db F3 0F 10 05 F8 2B C6 01

unregistersymbol(aob_ped_density)
unregistersymbol(ped_density_address)


Another note, recent ce's alloc may fail if third parameter (address hint) is provided and if ce cannot alloc a memory near the address hint.
Older behavior is the alloc wont fail just ignore the address hint.

What it means is that, any alloc in recent CE may fail with an address hint. (More likely for mono game, it seems as the game scale larger<ie. use more memory etc>, more likely happend)
For most realizable code, don't use address hint and use 14-byes jump in 64-bit game.

_________________
- Retarded.


Last edited by panraven on Sun Feb 06, 2022 10:04 am; edited 1 time in total
Back to top
View user's profile Send private message
++METHOS
I post too much
Reputation: 92

Joined: 29 Oct 2010
Posts: 4197

PostPosted: Sun Feb 06, 2022 9:55 am    Post subject: Reply with quote

@TheyCallMeTim13 - Thank you for replying, I really appreciate it.

This brings up a few more questions. Please bear with me.

When using:

Code:

newmem_ped_density:
  push rax
  reassemble(aob_ped_density_2)
  mov [ped_density_address],rax
  pop rax


You are not defining which bytes of aob_ped_density_2 are reassembled, is that right?
You are also not moving anything into rax, is that right?
I am curious how CE knows which bytes to move, and how those bytes are getting pushed into rax. Is it such that reassemble only applies to addresses and not the entire instruction? That does not seem likely given that you are using it in lieu of the originalcode_ped_density bytes.

I also do not understand that, if CE can do this:

Code:

originalcode_ped_density:
  reassemble(aob_ped_density)
jmp return_ped_density


...and interpret the addressing correctly, then how are we not able to extract a portion of that data for use when loading the static address into rax?

Regarding the other point of a secondary instance of the static address being used throughout the function, this seems like a reasonable concession, but may not be suitable for all cases, so it would be better to have a universal solution.

Also, if the static address was moved into a registry somewhere else, would we still need to use reassemble? Could we just inject after the instruction and pull that data from the registry as-is? Even so, it seems like a solution that would not always be viable.

Thanks.

EDIT: @panraven, your post was not yet visible. I will read it now. Thanks.

EDIT2: @panraven, I think you are very close. I was not able to activate your script as-is. CE will not let me alloc(pdbytes,8) for some reason. However, if I comment out the allocation, and instead use registersymbol, I am able to activate the script and it /appears/ to be working. I will need to examine more closely to be sure. However, upon disabling the script, the target crashes. I am not sure why.

As a side note, your solution makes my brain hurt. I understand parts, but not all of it. I will need to study it more to try to understand.


Code:

[ENABLE]

aobscanmodule(aob_ped_density,sdhdship.exe,F3??????????????F3??????????????F3??????????????0F54??????????0F2F??????????76)
alloc(newmem_ped_density,1024,sdhdship.exe)
//alloc(pdbytes,8)

label(return_ped_density)
label(originalcode_ped_density)
label(ped_density_address)
label(pdbytes)

registersymbol(aob_ped_density)
registersymbol(ped_density_address)
registersymbol(pdbytes)


newmem_ped_density:
  push rdi
  push rsi
  mov rdi,aob_ped_density+8 /// where the 4-bytes rip END
  mov rsi,pdbytes+4 /// where the 4-bytes rip START at the COPY of aob_ped_density == pdbytes
  movsxd rsi,[rsi]/// rsi get the signed relative offset at rdi-4 of the original instruction
  add rdi,rsi /// now rdi is the absolute of the rip-address
  mov rsi,ped_density_address /// use this format in case, it is outside 2g range
  mov [rsi],rdi /// ped_density_address now has its content store above absolute address
  pop rsi
  pop rdi

originalcode_ped_density:

//movss xmm0,[sdhdship.exe+207B21C]

//// -- original code option 1
//reassemble(aob_ped_density)     /// use reassemble, may fail if there is an rip address outside 2g range of the cave
//// -- original code option 2, manually construct the address and the instruction, use above assume the instruct as movss xmm0,[-some-rip-address-] safe outside 2g range

  push rdi
  mov rdi,ped_density_address
  mov rdi,[rdi] /// get the absolute address
  movss xmm0,[rdi]
  pop rdi

jmp return_ped_density

ped_density_address:
  dq 0

pdbytes:
  readmem(aob_ped_density,8)


aob_ped_density:
  jmp newmem_ped_density
  nop 3
return_ped_density:


[DISABLE]
dealloc(newmem_ped_density)
aob_ped_density:
  readmem(aob_ped_density,8)        //db F3 0F 10 05 F8 2B C6 01

unregistersymbol(aob_ped_density)
unregistersymbol(ped_density_address)
unregistersymbol(pdbytes)


Thank you for your help. I really appreciate it.
Back to top
View user's profile Send private message
panraven
Grandmaster Cheater
Reputation: 62

Joined: 01 Oct 2008
Posts: 958

PostPosted: Sun Feb 06, 2022 10:57 am    Post subject: Reply with quote

@" the target crashes"

When enabled, check if the address store at "ped_density_address" is the right address. If not, may add a trace and break on the cave (or a few instruction above the inject point) to see where go wrong.

_________________
- Retarded.
Back to top
View user's profile Send private message
++METHOS
I post too much
Reputation: 92

Joined: 29 Oct 2010
Posts: 4197

PostPosted: Sun Feb 06, 2022 11:10 am    Post subject: Reply with quote

The address being stored at ped_density_address is correct.
Thanks.
Back to top
View user's profile Send private message
panraven
Grandmaster Cheater
Reputation: 62

Joined: 01 Oct 2008
Posts: 958

PostPosted: Sun Feb 06, 2022 11:21 am    Post subject: Reply with quote

This Wink
Code:

[DISABLE]
dealloc(newmem_ped_density)
aob_ped_density:
  readmem(aob_ped_density,8)        //db F3 0F 10 05 F8 2B C6 01
///   readmem(aob_ped_density,8)  should be readmem(pdbytes,8)


btw, I'm not sure if dealloc order matter, may put the dealloc at last so that we can sure 'pdbytes' (as part of newmem_ped_density ) is still there when readmem/restore the original bytes.

_________________
- Retarded.


Last edited by panraven on Sun Feb 06, 2022 11:28 am; edited 1 time in total
Back to top
View user's profile Send private message
++METHOS
I post too much
Reputation: 92

Joined: 29 Oct 2010
Posts: 4197

PostPosted: Sun Feb 06, 2022 11:27 am    Post subject: Reply with quote

That did it. Awesome! Thanks so much.

I actually thought that it needed to be the other way around, but it wasn't working:

Code:
pdbytes:
  readmem(aob_ped_density,8)


Thank you all for your help. I really appreciate it.

Now I need to study this more and try to apply it to other scripts.
I will +rep you guys when I can. I won't forget. Thanks so much.
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