 |
Cheat Engine The Official Site of Cheat Engine
|
| View previous topic :: View next topic |
| Author |
Message |
cheat_me Newbie cheater
Reputation: 0
Joined: 18 Aug 2012 Posts: 10
|
Posted: Wed Jun 17, 2015 11:26 pm Post subject: Pausing the process when writing |
|
|
| When CE executes a cheat script with [ENABLE] / [DISABLE] sections, it overwrites machine instructions in the process memory. But does CE pauses the process during this overwrite? Because I am having a non persistent crash in a game at the moment the cheat is DISABLED. If the process is not paused, the game may try to execute that part of code which CE has not yet finished writing to. And therefore the code will be in a wrong state.
|
|
| Back to top |
|
 |
Profound_Darkness Newbie cheater
Reputation: 0
Joined: 21 May 2015 Posts: 23
|
Posted: Thu Jun 18, 2015 1:47 am Post subject: |
|
|
I was having something similar...
I don't actually know how CE does things, I suspect that it (somehow) keeps an eye on execution and if your memory isn't being executed CE will allow the dealloc (finishes disabling the cheat).
On the other hand it could just be coincidence that crashes aren't more common... The game, ideally, spends most of it's time outside of your code/injection area so if your code is taking longer to run and/or the sequence you overwrite with injection is executed FREQUENTLY the odds go up for a crash.
I had some code execution (call) to another script's memory that if I were in that other script/memory the return could (usually did) crash since the return pointed to null memory.
The first thing I tried, MUCH simpler, was to globalalloc... well most of the memory I was using. Same for memory with variables (symbols) that might need to get passed around. I didn't really like this...
I ended up writing a Lua script that was executed in the disable section. It wrote a 1 into memory (variable) that the asm code had access to and the lua code would sleep (blocking, repeat until) while waiting for that value to go to 0.
In the asm code at the end of any and all call chains or jumps I set the value of that variable to 0 (always).
Works like a charm.
If you end up going this route, error() in Lua will prevent the cheat from disabling. I mention this as it's a good idea to give up waiting after a while (due to bug in code or game is being debugged) otherwise CE will end up stuck (and it sucks if you haven't saved recently ).
There could be some other possibilities for the crash, from my limited experience, but I don't know what was the cause exactly in those cases.
Edit:
Went ahead and posted an example of what I'm doing in Lua, it might have some bugs still...
I've tweaked the code from my original to operate entirely within a single script instead of spread out over multiple scripts... This is tweaked to be for just one script but it doesn't take much to make it work for multiple scripts/variables...
I didn't test the code as it is here...
(I was quite sleepy when I stripped out some elements, one of which was key, if someone else uses the code, this has the aspect added back in, not tested).
| Code: |
[ENABLE]
{$lua}
shutdownTryCount = 0
function scriptShutdown(leaveVar,jumpVar)
local waitLimit = 100
local waitInterval = 10
-- multiply those together to get total wait time.
if (readInteger(leaveVar) ~= 0) then
error("Error with shutdown, another script is waiting?")
end
writeInteger(jumpVar,0)
writeInteger(leaveVar,1)
repeat
shutdownTryCount = shutdownTryCount + 1
if (shutdownTryCount > waitLimit) then
writeInteger(leaveVar,0)
shutdownTryCount = 0
error("Error waiting on asm to clear variable, most oft seen while debugging.")
end
sleep(waitInterval)
until (readInteger(leaveVar) == 0)
shutdownTryCount = 0
end
{$asm}
// all the usual enable stuff...
alloc(mainMem)
label(dontWork)
label(returnhere)
label(dScriptShutdown)
registersymbol(dScriptShutdown)
label(dDoWork)
registersymbol(dDoWork)
mainMem:
cmp [dDoJump],0
je dontWork
// some code and stuff maybe with calls or jumps...
//end of the code just before going back to the game
dontWork:
mov [dScriptShutdown],0
jmp returnhere
//... inside some memory...
dScriptShutdown:
dd 0
dDoWork
dd 1
// whatever else you've got
[DISABLE]
{$lua}
scriptShutdown("dScriptShutdown","dDoWork")
{$asm}
// all the usual stuff like dealloc and unregistersymbol
|
Last edited by Profound_Darkness on Thu Jun 18, 2015 11:15 am; edited 1 time in total |
|
| Back to top |
|
 |
Dark Byte Site Admin
Reputation: 473
Joined: 09 May 2003 Posts: 25909 Location: The netherlands
|
Posted: Thu Jun 18, 2015 2:48 am Post subject: |
|
|
aa scripts are written as blocks in the order they appear(while a block is written the game is locked/paused)
if the jump to newmem is above the newmem block, then first the jmp will be written, and a while later newmem will be filled.
That means that if you don't want to crash, put the implementation of newmem first (just like the code injection example)
_________________
Tools give you results. Knowledge gives you control.
Like my help? Join me on Patreon so i can keep helping |
|
| Back to top |
|
 |
cheat_me Newbie cheater
Reputation: 0
Joined: 18 Aug 2012 Posts: 10
|
Posted: Thu Jun 18, 2015 7:54 am Post subject: |
|
|
The crash occurs not when I enable but rather when I DISABLE the cheat. The code looks like this
| Code: |
[ENABLE]
globalalloc(god_mem,2048)
label(returnhere)
god_mem:
test eax,eax
//mov [esi+28],eax
jmp returnhere
"game.exe"+18610C:
jmp god_mem
returnhere:
[DISABLE]
"game.exe"+18610C:
test eax,eax
mov [esi+28],eax
|
In this script I skip the instruction that writes unit HP to memory. Sometimes when the game script has to kill a unit (by scenario) and cannot do it, it starts to run the Main Loop without the delay, so the CPU is at 100%, the game freezes and waits till the unit dies (which never occurs). When this happens I disable the cheat, and a CRASH occurs.
But when I rewrite my script into this
| Code: |
[ENABLE]
globalalloc(god_mem,2048)
label(returnhere)
god_mem:
test eax,eax
//mov [esi+28],eax
jmp returnhere
"game.exe"+18610C:
jmp god_mem
returnhere:
[DISABLE]
globalalloc(god_mem_disabled,2048)
label(returnhere)
god_mem_disabled:
test eax,eax
mov [esi+28],eax
jmp returnhere
"game.exe"+18610C:
jmp god_mem_disabled
returnhere:
|
The crash DOES NOT occur. The unit dies, the game unfreezes and runs normally.
So my guess was, that process is paused when writing each single instruction, and is not paused between writing multiple instructions. As you can see, in the first code in the DISABLE part I write 2 instructions. In the latter I write only JMP.
|
|
| 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
|
|