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 


How to write a specific amount of 00 bytes to memory

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking
View previous topic :: View next topic  
Author Message
TDWL
Newbie cheater
Reputation: 0

Joined: 28 Jan 2020
Posts: 10

PostPosted: Sat Jan 01, 2022 2:26 pm    Post subject: How to write a specific amount of 00 bytes to memory Reply with quote

Hi, a bit of context. For my AA scripts instead of allocating memory for all of them I like to allocate once and use that memory for all my injections. So I'll normally do something like this:

Code:

[ENABLE]
alloc(myMem,$1000)
registersymbol(myMem)
define(assertionBytes, DE AD BE E7 BE EF 70 70)
registersymbol(assertionBytes)

myMem:
  db assertionBytes

[DISABLE]
dealloc(myMem)
unregistersymbol(myMem)
unregistersymbol(assertionBytes)


for allocating my general memory, and then for my scripts I do:

Code:

[ENABLE]
assert(myMem,assertionBytes)
define(currentMem,myMem+10)

aobscan(infMoney,48 63 8E 74 02 00 00) // should be unique
registersymbol(infMoney)

label(return)

currentMem:
  mov [rsi+274],(int)1000000
  movsxd  rcx,dword ptr [rsi+00000274]
  jmp return

infMoney:
  jmp currentMem
  nop 2
return:

[DISABLE]

infMoney:
  db 48 63 8E 74 02 00 00


unregistersymbol(infMoney)


I know this is not necessary at all but I like it this way.
However, there is a problem when disabling the scripts. As I'm leaving the code I wrote to myMem intact, It sometimes causes problems with the AOB scan. In this case for example I'm doing a scan for 48 63 8E 74 02 00 00, which corresponds to the instruction movsxd rcx,dword ptr [rsi+00000274] which I'm not modifying, so after I disable my script there will now be two results for the AOB scan.
What I want to do to solve this issue is to rewrite with 00 all the bytes I wrote to myMem in the infMoney script. But I'm having trouble achieving this. What I tried was to add a currentMemEnd label like so:
Code:

label(currentMemEnd)

currentMem:
  mov [rsi+274],(int)1000000
  movsxd  rcx,dword ptr [rsi+00000274]
  jmp return
currentMemEnd:

si I could get the ammount of bytes my instructions use by doing currentMemEnd-currentMem. So I added this to my disable section:
Code:

define(rewriteBytes,currentMem-currentMemEnd)
currentMem:
  nop rewriteBytes

But, first of all, this throws and error saying "Not all code is injectable. (Error in line 38 (nop currentMemEnd-ffffffffffffffff):This instruction can't be compiled". And secondly, nop is actually 90 not 00, which still works but isn't what I want because it looks uglier when looking at the allocated memory. I wanted something like db 00 times rewriteBytes.
Ideally I'd like to do it without plain AA code, but not sure if it's possible. If not, a for loop with Lua or C to get my array of 00 bytes should probably work, but I'm also not sure what the syntax for this would be.

Anyways, sorry for the long post and any help is appreciated!
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 457

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

PostPosted: Sat Jan 01, 2022 3:10 pm    Post subject: Reply with quote

I really hope you use the 3th alloc parameter to allocate nearby else your scripts are going to cause issues, as it doesn't look like you're saving 14 bytes for the jmp

anyhow,
Code:

{$lua}
local s='db '
for i=1,bytelength do
  s=s..'0 '
end

return s
{$asm}


will return a db command with 'bytelength' 0's

the only issue is automatically getting the size so you'll have to keep track of that

_________________
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
TDWL
Newbie cheater
Reputation: 0

Joined: 28 Jan 2020
Posts: 10

PostPosted: Sat Jan 01, 2022 4:38 pm    Post subject: Reply with quote

Thanks for the help Dark Byte. Does returning s run the db command automatically, or what should I do with the returned value?
Quote:
the only issue is automatically getting the size so you'll have to keep track of that

For this I was trying to use define(bytelength,currentMem-currentMemEnd), but that doesn't seem to work, could that be done in Lua? (currentMem and currentMemEnd are labels storing the address of the beginning and ending of the injection respectively).

Quote:
I really hope you use the 3th alloc parameter to allocate nearby else your scripts are going to cause issues

I usually do, but this game doesn't have a module name (all instructions just appear as 19C43157470 for example), so I don't really know what I would put as third parameter.
Quote:
as it doesn't look like you're saving 14 bytes for the jmp

I'm not really sure what this means.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 457

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

PostPosted: Sat Jan 01, 2022 5:14 pm    Post subject: Reply with quote

lua blocks get replaced by the string they return. The result then gets parsed by the assembler in the assembler pass


for alloc you can give as 3th parameter the address you're going to overwrite


If you don't allocate nearby the jmp instruction can be 14 bytes long
So if you only restore 5+overhead you're going to get issues

_________________
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
ParkourPenguin
I post too much
Reputation: 138

Joined: 06 Jul 2014
Posts: 4275

PostPosted: Sat Jan 01, 2022 7:52 pm    Post subject: Reply with quote

The "normal" jump instruction takes up 5 bytes: 1 byte for the opcode, and 4 for the 32-bit signed displacement from RIP (address of the next instruction). A 32-bit displacement means it can only jump to addresses within 2 GiB of the next instruction.
The address space of 64-bit processes is far greater than 4 GiB. This means you can't jump to any address you want using that 5-byte jump.

If you try to jump to some place more than 2 GiB away, CE cheats and assembles a pseudoinstruction that will work but takes up 14 bytes of memory. This can obviously cause problems if you weren't expecting the injection point to consume 14 bytes of original code. Even finding a good injection point using a 14-byte jump can be problematic (e.g. can't be any jumps into the middle of the injection point).

This is what the third parameter to alloc solves: CE will allocate memory well within 2 GiB of the specified address so that it can always safely use the 5 byte jump. You can use the result of an aobscan for the third parameter:
Code:
aobscan(foo,xx xx)
alloc(bar,4096,foo)

Using only one alloc, there's no guarantee all your injection points will be within 2 GiB of your code, so you'll have to assume a 14-byte jump.

TDWL wrote:
I know this is not necessary at all but I like it this way.
Why?
_________________
I don't know where I'm going, but I'll figure it out when I get there.
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 Gamehacking 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