|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
Autem Expert Cheater Reputation: 1
Joined: 30 Jan 2023 Posts: 119
|
Posted: Tue May 23, 2023 7:09 pm Post subject: How can this script disable itself after 1 usage? |
|
|
I'd like the below script to disable itself and revert everything back to normal as soon as ONE instance runs through the modified/enabled newmem section. Whether it takes 1 hour of being activated or just 3 seconds, I only want the script to basically wait until it's used 1 time and then disable itself immediately to avoid any possible follow up data being influenced.
I've tried a few variations on how I think it's possible to call lua inline with asm but it's not working. How should I write the part that force disables everything after 1 usage?
Code: | [ENABLE]
aobscanmodule(INJECT,WWE2K23_x64.exe,C5 F8 2F 73 34) // should be unique
alloc(newmem,$1000,INJECT)
label(code)
label(return)
newmem:
mov [rbx+34],(float)0.0
vcomiss xmm6,[rbx+34]
code:
db C5 F8 2F 73 34 //My attempt to return the bytes to normal myself before auto disable
Luacall(memrec.Active=false) //My attempt to auto self disable and then unregister/dealloc below
unregistersymbol(INJECT)
dealloc(newmem)
jmp return
INJECT:
jmp newmem
return:
registersymbol(INJECT)
[DISABLE]
INJECT:
db C5 F8 2F 73 34
unregistersymbol(INJECT)
dealloc(newmem)
{
// ORIGINAL CODE - INJECTION POINT: WWE2K23_x64.exe+C9404C
WWE2K23_x64.exe+C9401C: C5 FA 5E 43 30 - vdivss xmm0,xmm0,[rbx+30]
WWE2K23_x64.exe+C94021: C5 FA 11 4B 34 - vmovss [rbx+34],xmm1
WWE2K23_x64.exe+C94026: E8 B5 82 60 FF - call WWE2K23_x64.AK::SoundEngine::StartProfilerCapture+3340
WWE2K23_x64.exe+C9402B: C5 F8 28 D0 - vmovaps xmm2,xmm0
WWE2K23_x64.exe+C9402F: C5 F8 57 C0 - vxorps xmm0,xmm0,xmm0
WWE2K23_x64.exe+C94033: C5 FA 10 CA - vmovss xmm1,xmm0,xmm2
WWE2K23_x64.exe+C94037: C5 E0 57 DB - vxorps xmm3,xmm3,xmm3
WWE2K23_x64.exe+C9403B: C5 F2 5F CB - vmaxss xmm1,xmm1,xmm3
WWE2K23_x64.exe+C9403F: C5 F2 5D 0D 8D 22 59 02 - vminss xmm1,xmm1,[WWE2K23_x64.exe+32262D4]
WWE2K23_x64.exe+C94047: C5 FA 11 4B 60 - vmovss [rbx+60],xmm1
// ---------- INJECTING HERE ----------
WWE2K23_x64.exe+C9404C: C5 F8 2F 73 34 - vcomiss xmm6,[rbx+34]
// ---------- DONE INJECTING ----------
WWE2K23_x64.exe+C94051: C5 F8 28 74 24 20 - vmovaps xmm6,[rsp+20]
WWE2K23_x64.exe+C94057: 48 8B 7C 24 40 - mov rdi,[rsp+40]
WWE2K23_x64.exe+C9405C: 72 12 - jb WWE2K23_x64.exe+C94070
WWE2K23_x64.exe+C9405E: 48 8B 03 - mov rax,[rbx]
WWE2K23_x64.exe+C94061: 48 8B CB - mov rcx,rbx
WWE2K23_x64.exe+C94064: 48 83 C4 30 - add rsp,30
WWE2K23_x64.exe+C94068: 5B - pop rbx
WWE2K23_x64.exe+C94069: 48 FF A0 98 00 00 00 - jmp qword ptr [rax+00000098]
WWE2K23_x64.exe+C94070: 48 83 C4 30 - add rsp,30
WWE2K23_x64.exe+C94074: 5B - pop rbx
} |
|
|
Back to top |
|
|
++METHOS I post too much Reputation: 92
Joined: 29 Oct 2010 Posts: 4197
|
Posted: Tue May 23, 2023 7:36 pm Post subject: |
|
|
You can use lua, or you can simply create a boolean that resets to 0 after you enable it.
Code: |
//stuff
label(trigger)
registersymbol(trigger)
newmem:
cmp byte ptr [trigger],1
je code
jmp originalcode
code:
mov byte ptr [trigger],0
//manipulation code
//stuff
trigger:
db 0
//stuff |
Then set up the cheat so that when it activates, it sets the trigger value to 1.
You can manually add an address inside of your cheat table, with trigger as the address, then change data type to byte. Assign a hotkey to set value to 1.
|
|
Back to top |
|
|
cooleko Grandmaster Cheater Reputation: 11
Joined: 04 May 2016 Posts: 717
|
Posted: Tue May 23, 2023 8:07 pm Post subject: |
|
|
I'd just use LUA, condition the jump from executing the newcode on whether a flag is set, set the flag within the newcode, and have the script erase everything once the flag is set, too.
newcode:
cmp [flag], 1
je skip
//Code you want to execute once
mov [flag], 1
skip:
//Originalcode
Then have the timer the LUA code set up check the flag as well and write over the jump, clean out the code cave, reset the flag, and turn off the timer that is checking on the flag.
If it has to be in AA, it would be interesting to try:
push eax
mov eax, 0xC5F82F7334 //Note: bytes may be out of order
mov [INJECT], eax //Note: making this up
pop eax
return
I have never attempted this so I would be surprised if it did work. It won't clean up the code cave and you may not have to register any symbols since you only are using them once and you may be able to overwrite all the preceding instructions of the code cave with the last write. So there would be evidence left, but not evidence of what was done or where it was done, just some stray lines of code seeming to reference itself. You will introduce a memory leak if this runs multiple times.
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 140
Joined: 06 Jul 2014 Posts: 4289
|
Posted: Tue May 23, 2023 8:11 pm Post subject: |
|
|
You're looking for {$luacode}, but that's a terrible idea. The disable section deallocates newmem. What do you think happens if the {$luacode} block returns to memory that's been deallocated?
Everything between the `code:` label and `jmp newmem` shouldn't be there. I think I see what you're trying to do, and the AutoAssembler doesn't work that way.
I'd use a breakpoint.
Code: | {$lua}
if syntaxcheck then return end
local injectAddr = getAddress'WWE2K23_x64.exe+C9404C'
[ENABLE]
debug_setBreakpoint(injectAddr, function()
writeFloat(RBX+0x34, 0)
createTimer(100, function() memrec.Active = false end)
debug_removeBreakpoint(injectAddr)
debug_continueFromBreakpoint(co_run)
end)
[DISABLE]
debug_removeBreakpoint(injectAddr)
|
If you really want to use a code injection, look into the various existing solutions for running code only once. Simply using a flag should suffice. (use cmpxchg if you want to be technically correct in a multithreaded context)
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
Autem Expert Cheater Reputation: 1
Joined: 30 Jan 2023 Posts: 119
|
Posted: Tue May 23, 2023 9:13 pm Post subject: |
|
|
The boolean trigger idea from Methos seems to be working in my early trials. Thanks for the idea.
I wonder tho if a breakpoint like Penguin suggests would actually be better as far as eliminating any slim chance of more than 1 execution sneaking thru at the same time? Or would the result be identical either way?
ParkourPenguin wrote: | The disable section deallocates newmem. |
The reason I put them there is I thought when using memrec.Active=false it would mean the 'disable' part of a script doesn't get executed, meaning I should include those db restoration and dealloc steps if I were going to be using memrec.Active=false?
|
|
Back to top |
|
|
++METHOS I post too much Reputation: 92
Joined: 29 Oct 2010 Posts: 4197
|
Posted: Tue May 23, 2023 9:54 pm Post subject: |
|
|
Autem wrote: | as far as eliminating any slim chance of more than 1 execution sneaking thru at the same time? | -As far as I understand, that shouldn't happen unless you erroneously initiate the trigger more than once via hotkey or similar. Hopefully, someone can correct me if I am wrong.
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 140
Joined: 06 Jul 2014 Posts: 4289
|
Posted: Wed May 24, 2023 12:26 am Post subject: |
|
|
Technically speaking, there would be a race condition between the `cmp` and the `mov`. If thread1 executes the `cmp`, gets preempted before the `mov`, and thread2 executes the `cmp`, then both thread1 and thread2 will run the code that was only suppose to be run once.
This is a common problem in concurrent systems. If you want to know more about concurrency, I'd recommend "C++ Concurrency in Action" by Anthony Williams. It's a little dated for C++, but there's still a lot to be learned from it.
The odds of this happening in practice are negligible. It's probably single-threaded, and even if it isn't, it might happen once in several billion times.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
wayden Cheater Reputation: 0
Joined: 09 Dec 2020 Posts: 27
|
Posted: Fri Jul 14, 2023 5:30 am Post subject: |
|
|
I use a way following your first idea, reseting bytes before disabling
and a bit of lua to auto disable, im not sure if it's a good way to do it but it seems to work
for that i got 2 scripts
-one main containing my reset function and allocating memory for itself and any other script that i would want to inject at the same InjectionPoint
and for the "variable" used to store the ResetBytes + regestering symbols
-And the other one containing the actual scipts i want to run only once
The main one looks something like this
Code: |
[ENABLE]
alloc(DevMods,$1000) //i removed third parameter because i don't really get what it is used for and it sometimes causes warning
define(FT_ResetFunc,DevMods+08) //manually choose where you register your code you have to take care to not overwrite your own code
define(RB_ResetFunc,DevMods+2D)
define(FT_GiveItem,DevMods+3C)
registersymbol(DevMods)
registersymbol(FT_ResetFunc)
registersymbol(RB_ResetFunc)
registersymbol(InjectionPoint)
define(InjectionPoint,GameHandler:UpdateFrame+50c)
registersymbol(FT_GiveItem)
RB_ResetFunc:
db 66 0F 1F 84 00 00 00 00 00
FT_ResetFunc:
push rax //save rax
mov rax, qword ptr[RB_ResetFunc] //moves the reset bytes into rax
mov qword [InjectionPoint], rax //moves reset bytes at the injection point (equivalent to being at injection point and doing db 66 0F 1F 84 00 00 00 00 00)
pop rax //restore rax
jmp InjectionPoint
[DISABLE]
unregistersymbol(InjectionPoint)
unregistersymbol(FT_ResetFunc)
unregistersymbol(RB_ResetFunc)
unregistersymbol(FT_GiveItem)
dealloc(DevMods)
|
The Actual Script that i want to run only once :
Code: |
{$lua}
if not syntaxcheck then
synchronize(createTimer,50,memrec.setActive,false) //waits 50ms before disabling script
end
{$asm}
[ENABLE]
FT_GiveItem:
mov rcx,rsi
lea rbp,[rbp]
mov r11,GameHandler:GiveItems //do your thing
call r11
jmp FT_ResetFunc //call the reset Function
InjectionPoint: //it's the injection point declared in the main script
jmp FT_GiveItem
[DISABLE]
//nothing happens on disable because everything it's managed from main script and bytes are already reseted
|
i like this way because i don't have to alloc memory for each one of my scripts just got a main one where i can manage manually where they are stored in the main scripts memory
and it doesn't use any flags so the entry in cheat table list is really disabled and there is no cmp to do and if you have mutiple script that you want to run only once you can inject them at the exact same point and just jmp to the resetfunction
|
|
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
|
|