|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
Sarge411 Newbie cheater Reputation: 0
Joined: 21 Apr 2018 Posts: 21
|
Posted: Wed Apr 25, 2018 2:30 pm Post subject: Cannot disable AA script |
|
|
This is a followup on this topic
forum[dot]cheatengine[dot]org[slash]viewtopic[dot]php?p=5738370
I've written a script that should set the player's health to 0 upon enabling and back to its original value upon re-enabling:
Code: |
{ Game : Duke3dw.exe
Version:
Date : 2018-04-25
Author : Sarge411
This script does blah blah blah
}
[ENABLE]
aobscanmodule(INJECT,Duke3dw.exe,0F BF 54 91 0A) // should be unique
alloc(newmem,$1000)
alloc(healthValue, 4)
alloc(healthAddress, 4)
registersymbol(healthValue)
registersymbol(healthAddress)
healthValue:
dd 0
healthAddress:
dd 0
label(code)
label(return)
newmem:
// Duke dies
pushfd
push eax
push ebx
mov eax, 0
mov ebx, 0
lea eax, [ecx+edx*4+0A]
// Save health address
mov [healthAddress], eax
mov bx, [eax]
mov [healthValue], bx
mov ebx, 0
mov [eax], bx
pop ebx
pop eax
popfd
code:
movsx edx,word ptr [ecx+edx*4+0A]
jmp return
INJECT:
jmp newmem
return:
registersymbol(INJECT)
[DISABLE]
// Duke lives
// pushfd
// push eax
// push ebx
// mov eax, 0
// mov ebx, 0
// mov bx, [healthValue]
// mov eax, [healthAddress]
// mov [eax], bx
// pop ebx
// pop eax
// popfd
INJECT:
db 0F BF 54 91 0A
unregistersymbol(INJECT)
dealloc(newmem)
unregistersymbol(healthValue)
dealloc(healthValue)
unregistersymbol(healthAddress)
dealloc(healthAddress)
{
// ORIGINAL CODE - INJECTION POINT: "Duke3dw.exe"+4C65C
"Duke3dw.exe"+4C62D: 0F BF 83 E6 02 00 00 - movsx eax,word ptr [ebx+000002E6]
"Duke3dw.exe"+4C634: B9 D4 70 D0 00 - mov ecx,Duke3dw.exe+9070D4
"Duke3dw.exe"+4C639: 8D 14 80 - lea edx,[eax+eax*4]
"Duke3dw.exe"+4C63C: 8D 14 50 - lea edx,[eax+edx*2]
"Duke3dw.exe"+4C63F: 66 8B 83 F6 02 00 00 - mov ax,[ebx+000002F6]
"Duke3dw.exe"+4C646: 66 C1 F8 08 - sar ax,08
"Duke3dw.exe"+4C64A: 66 29 44 91 0A - sub [ecx+edx*4+0A],ax
"Duke3dw.exe"+4C64F: 0F BF 83 E6 02 00 00 - movsx eax,word ptr [ebx+000002E6]
"Duke3dw.exe"+4C656: 8D 14 80 - lea edx,[eax+eax*4]
"Duke3dw.exe"+4C659: 8D 14 50 - lea edx,[eax+edx*2]
// ---------- INJECTING HERE ----------
"Duke3dw.exe"+4C65C: 0F BF 54 91 0A - movsx edx,word ptr [ecx+edx*4+0A]
// ---------- DONE INJECTING ----------
"Duke3dw.exe"+4C661: 0F BF 83 96 02 00 00 - movsx eax,word ptr [ebx+00000296]
"Duke3dw.exe"+4C668: 89 D6 - mov esi,edx
"Duke3dw.exe"+4C66A: 29 C6 - sub esi,eax
"Duke3dw.exe"+4C66C: 79 7A - jns Duke3dw.exe+4C6E8
"Duke3dw.exe"+4C66E: 66 C7 83 F6 02 00 00 00 00 - mov word ptr [ebx+000002F6],0000
"Duke3dw.exe"+4C677: 66 83 BB 36 03 00 00 00 - cmp word ptr [ebx+00000336],00
"Duke3dw.exe"+4C67F: 7E 49 - jle Duke3dw.exe+4C6CA
"Duke3dw.exe"+4C681: E8 5A 7A 02 00 - call Duke3dw.exe+740E0
"Duke3dw.exe"+4C686: BF 1E 00 00 00 - mov edi,0000001E
"Duke3dw.exe"+4C68B: 99 - cdq
}
|
The script works as expected when enabled (health set to 0, player dies) but remains enabled when any of the instructions passed the DISABLE label are un-commented.
Why doesn't CE execute that code? (when the script gets activated and stuck the player remains dead even though the character becomes playable if health is restored from CE).
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 138
Joined: 06 Jul 2014 Posts: 4275
|
Posted: Wed Apr 25, 2018 2:57 pm Post subject: |
|
|
Sarge411 wrote: | ...and back to its original value upon re-enabling |
Did you mean disabling?
Sarge411 wrote: | Why doesn't CE execute that code? |
CE doesn't execute any of that code (enable or disable section). CE writes that code to the target's memory which the target might execute eventually.
CE can execute Lua code in an AA script.
Code: | [DISABLE]
{$lua}
writeSmallInteger('[healthAddress]', readSmallInteger('healthValue'))
{$asm}
//... | {$lua} blocks are executed before pretty much everything else in the script, so the dealloc / unregistersymbol statements won't affect it.
Since the code in the enable section is presumably executed multiple times by the target, [healthValue] will likely be 0 when the disable section is executed. One way to fix this is to see if [healthValue] is nonzero and, if so, don't assign to it again.
You should also probably check if [healthValue] is nonzero in the disable section, but that would only be a problem if the target never executed the code in the enable section.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
Sarge411 Newbie cheater Reputation: 0
Joined: 21 Apr 2018 Posts: 21
|
Posted: Wed Apr 25, 2018 4:55 pm Post subject: |
|
|
ParkourPenguin wrote: |
Did you mean disabling?
|
Yes.
ParkourPenguin wrote: |
CE doesn't execute any of that code (enable or disable section). CE writes that code to the target's memory which the target might execute eventually.
|
But this means that everything following the DISABLE label is not executed, including deallocations. It's strange that when commenting the instructions after DISABLE the script can be started and stopped.
ParkourPenguin wrote: |
CE can execute Lua code in an AA script.
Code: | [DISABLE]
{$lua}
writeSmallInteger('[healthAddress]', readSmallInteger('healthValue'))
{$asm}
//... | {$lua} blocks are executed before pretty much everything else in the script, so the dealloc / unregistersymbol statements won't affect it.
|
So, if the lua script executes before the instructions after ENABLE doesn't this leave the healthValue and healthAddress variables uninitialized?
I'm not sure how to check their values when running the script. I managed to follow execution and see the valid address and health value loaded into the registers but was not able to follow the changes in memory. How can you check variable values during debugging? I used the memory viewer but it changes on every instruction making it difficult to track a variable's value.
ParkourPenguin wrote: |
Since the code in the enable section is presumably executed multiple times by the target, [healthValue] will likely be 0 when the disable section is executed. One way to fix this is to see if [healthValue] is nonzero and, if so, don't assign to it again.
You should also probably check if [healthValue] is nonzero in the disable section, but that would only be a problem if the target never executed the code in the enable section. |
Trying it now.
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 138
Joined: 06 Jul 2014 Posts: 4275
|
Posted: Wed Apr 25, 2018 5:56 pm Post subject: |
|
|
Sarge411 wrote: | It's strange that when commenting the instructions after DISABLE the script can be started and stopped. |
You didn't specify what address the code in the disable section is being written to. That's a syntax error, and when CE tries to disable the script, it fails.
Sarge411 wrote: | So, if the lua script executes before the instructions after ENABLE doesn't this leave the healthValue and healthAddress variables uninitialized? |
That's more or less what I was referring to in the last sentence of my previous post. The enable section initializes the values to 0, and the code should assign a nonzero value the first time it is run. If it wasn't assigned a nonzero value, the disable section as I wrote it would unconditionally assign 0 (the initial value) to the address. This probably won't happen if the code is run often enough (e.g. once every frame), and it isn't as big of a problem as what happens if the target runs it more than once (you should fix that first).
Sarge411 wrote: | I'm not sure how to check their values when running the script. |
Use a cmp followed by a conditional instruction (i.e. jcc / cmovcc).
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
Sarge411 Newbie cheater Reputation: 0
Joined: 21 Apr 2018 Posts: 21
|
Posted: Thu Apr 26, 2018 3:13 am Post subject: |
|
|
ParkourPenguin wrote: |
You didn't specify what address the code in the disable section is being written to. That's a syntax error, and when CE tries to disable the script, it fails. |
But isn't the value of the healthAddress and healthValue known at this point? Or should the syntax be pointing to somewhere in memory like:
Code: |
[DISABLE]
00D071AB:
<code that writes to healthValue (which is static) after reading from healthAddress>
|
ParkourPenguin wrote: |
That's more or less what I was referring to in the last sentence of my previous post. The enable section initializes the values to 0, and the code should assign a nonzero value the first time it is run. If it wasn't assigned a nonzero value, the disable section as I wrote it would unconditionally assign 0 (the initial value) to the address. This probably won't happen if the code is run often enough (e.g. once every frame), and it isn't as big of a problem as what happens if the target runs it more than once (you should fix that first).
|
So, the lua script runs first when the script is enabled and initializes the values and this happens even on subsequent runs (say the player has an initial life value, runs the script, stops it, takes some damage and then reruns the script, the lua will then rerun and update the healthValue with the current value of the player, no?)
ParkourPenguin wrote: | I'm not sure how to check their values when running the script.
Use a cmp followed by a conditional instruction (i.e. jcc / cmovcc). |
I rewrote the code to check if the values have been set:
Code: |
{ Game : Duke3dw.exe
Version:
Date : 2018-04-25
Author : Sarge411
This script does blah blah blah
}
[ENABLE]
aobscanmodule(INJECT,Duke3dw.exe,0F BF 54 91 0A) // should be unique
alloc(newmem,$1000)
registersymbol(healthValue)
registersymbol(healthAddress)
alloc(healthValue, 4)
alloc(healthAddress, 4)
healthValue:
dd 0
healthAddress:
dd 0
label(code)
label(return)
label(initialized)
label(uninitialized)
newmem:
// Duke dies
pushfd
push eax
push ebx
push ecx
mov eax, 0
mov ebx, 0
mov ecx, 0
// Check if health address and value has been set
mov eax, [healthValue]
cmp eax, 0
je uninitialized
inc ecx
mov eax, [healthAddress]
cmp eax, 0
je uninitialized
inc ecx
cmp ecx, 2
je initialized
uninitialized:
mov eax, 0
lea eax, [ecx+edx*4+0A]
// Save health address
mov [healthAddress], eax
mov bx, [eax]
mov [healthValue], bx
mov ebx, 0
mov [eax], bx
initialized:
pop ecx
pop ebx
pop eax
popfd
code:
movsx edx,word ptr [ecx+edx*4+0A]
jmp return
INJECT:
jmp newmem
return:
registersymbol(INJECT)
[DISABLE]
// Duke lives
//pushfd
//push eax
//push ebx
//mov eax, 0
//mov ebx, 0
//mov bx, [healthValue]
//mov eax, [healthAddress]
//mov [eax], bx
//pop ebx
//pop eax
//popfd
INJECT:
db 0F BF 54 91 0A
unregistersymbol(INJECT)
dealloc(newmem)
unregistersymbol(healthValue)
dealloc(healthValue)
unregistersymbol(healthAddress)
dealloc(healthAddress)
{
// ORIGINAL CODE - INJECTION POINT: "Duke3dw.exe"+4C65C
"Duke3dw.exe"+4C62D: 0F BF 83 E6 02 00 00 - movsx eax,word ptr [ebx+000002E6]
"Duke3dw.exe"+4C634: B9 D4 70 D0 00 - mov ecx,Duke3dw.exe+9070D4
"Duke3dw.exe"+4C639: 8D 14 80 - lea edx,[eax+eax*4]
"Duke3dw.exe"+4C63C: 8D 14 50 - lea edx,[eax+edx*2]
"Duke3dw.exe"+4C63F: 66 8B 83 F6 02 00 00 - mov ax,[ebx+000002F6]
"Duke3dw.exe"+4C646: 66 C1 F8 08 - sar ax,08
"Duke3dw.exe"+4C64A: 66 29 44 91 0A - sub [ecx+edx*4+0A],ax
"Duke3dw.exe"+4C64F: 0F BF 83 E6 02 00 00 - movsx eax,word ptr [ebx+000002E6]
"Duke3dw.exe"+4C656: 8D 14 80 - lea edx,[eax+eax*4]
"Duke3dw.exe"+4C659: 8D 14 50 - lea edx,[eax+edx*2]
// ---------- INJECTING HERE ----------
"Duke3dw.exe"+4C65C: 0F BF 54 91 0A - movsx edx,word ptr [ecx+edx*4+0A]
// ---------- DONE INJECTING ----------
"Duke3dw.exe"+4C661: 0F BF 83 96 02 00 00 - movsx eax,word ptr [ebx+00000296]
"Duke3dw.exe"+4C668: 89 D6 - mov esi,edx
"Duke3dw.exe"+4C66A: 29 C6 - sub esi,eax
"Duke3dw.exe"+4C66C: 79 7A - jns Duke3dw.exe+4C6E8
"Duke3dw.exe"+4C66E: 66 C7 83 F6 02 00 00 00 00 - mov word ptr [ebx+000002F6],0000
"Duke3dw.exe"+4C677: 66 83 BB 36 03 00 00 00 - cmp word ptr [ebx+00000336],00
"Duke3dw.exe"+4C67F: 7E 49 - jle Duke3dw.exe+4C6CA
"Duke3dw.exe"+4C681: E8 5A 7A 02 00 - call Duke3dw.exe+740E0
"Duke3dw.exe"+4C686: BF 1E 00 00 00 - mov edi,0000001E
"Duke3dw.exe"+4C68B: 99 - cdq
}
|
But now the game exits when enabling the cheat.
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 138
Joined: 06 Jul 2014 Posts: 4275
|
Posted: Thu Apr 26, 2018 9:53 am Post subject: |
|
|
Sarge411 wrote: | But isn't the value of the healthAddress and healthValue known at this point? Or should the syntax be pointing to somewhere in memory like:
Code: |
[DISABLE]
00D071AB:
<code that writes to healthValue (which is static) after reading from healthAddress>
|
| That's irrelevant. Read over my previous posts again: CE doesn't execute that code. CE writes that code to the target's memory. In the disable section, you didn't specify any address to write that code to. That is a syntax error.
If you did write it to some address, the target would still execute it on its own terms (maybe not at all). I guess you could call code to run using createthread and deallocate the memory for the code injection in the code injection itself, but that's far more complicated than simply using Lua.
Sarge411 wrote: | So, the lua script runs first when the script is enabled and initializes the values and this happens even on subsequent runs (say the player has an initial life value, runs the script, stops it, takes some damage and then reruns the script, the lua will then rerun and update the healthValue with the current value of the player, no?) |
- The Lua script is in the disable section. It will be run when the script is disabled, not enabled.
- The initial values stored at healthValue and healthAddress are defined by you to be 0 (via the pseudoinstruction "dd 0").
- The Lua script will run when the script is disabled. Beyond that, I don't know what you mean by "subsequent runs."
- Your code injection is what assigns the new value to healthValue; not the Lua script.
Also, I just noticed healthAddress also wouldn't have a valid address if the target never ran your code injection. When the Lua script goes to write something to the address, it wouldn't change anything and therefore wouldn't be a problem (writeSmallInteger doesn't generate an error).
Sarge411 wrote: | I rewrote the code to check if the values have been set:
But now the game exits when enabling the cheat. | It's crashing.
At this point, it really seems like you just copied and pasted everything from somewhere hoping it would work. If you didn't, then you're writing nonsensical code still in the vain hope it works, which isn't much better. You don't know what you're doing regardless.
Try learning by doing something easier and smaller in scope: finish the CE tutorial, follow along with videos on YouTube, download other cheat tables and learn from them, etc.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
Sarge411 Newbie cheater Reputation: 0
Joined: 21 Apr 2018 Posts: 21
|
Posted: Thu Apr 26, 2018 3:05 pm Post subject: |
|
|
ParkourPenguin wrote: |
That's irrelevant. Read over my previous posts again: CE doesn't execute that code. CE writes that code to the target's memory. In the disable section, you didn't specify any address to write that code to. That is a syntax error.
|
I'm not sure if my understanding of code injection is correct. Is this what CE does (in a scenario where an instruction "frequently" accessing a static address is picked as an injection point):
1. Allocate memory in the running process
2. Replace accessing instruction with a jmp to the newly allocated instruction
3. Execute code after ENABLE (provided that execution reaches injection point (the now jmp instruction))
4. Execute original code that was in place of the jmp
5. jmp back to the instruction immediately after the jmp
Is this correct at all?
Now as far as my understanding goes, CE places the code after the DISABLE label to an address in memory defined after DISABLE. This is a working snippet that freezes a counter:
Code: |
define(address,"Duke3dw.exe"+522A2)
define(bytes,48 66 89 83 32 03 00 00)
[DISABLE]
address:
db bytes
// dec eax
// mov [ebx+00000332],ax
|
Does the code write those bytes to the address upon disabling the script?
Code: |
If you did write it to some address, the target would still execute it on its own terms (maybe not at all). I guess you could call code to run using createthread and deallocate the memory for the code injection in the code injection itself, but that's far more complicated than simply using Lua.
|
I still have to look at how CE manages threads (among many other things).
ParkourPenguin wrote: |
- The Lua script is in the disable section. It will be run when the script is disabled, not enabled.
- The initial values stored at healthValue and healthAddress are defined by you to be 0 (via the pseudoinstruction "dd 0").
- The Lua script will run when the script is disabled. Beyond that, I don't know what you mean by "subsequent runs."
- Your code injection is what assigns the new value to healthValue; not the Lua script.
Also, I just noticed healthAddress also wouldn't have a valid address if the target never ran your code injection. When the Lua script goes to write something to the address, it wouldn't change anything and therefore wouldn't be a problem (writeSmallInteger doesn't generate an error).
|
Ok, I think it's clearer now. The idea is that when the lua script gets executed there will always be valid values stored in both healthAddress and healthValue (since the script must first be enabled before being disabled?).
ParkourPenguin wrote: |
At this point, it really seems like you just copied and pasted everything from somewhere hoping it would work. If you didn't, then you're writing nonsensical code still in the vain hope it works, which isn't much better. You don't know what you're doing regardless.
|
I'm struggling with it on my own. I have an asm file in visual studio and am trying to replicate something that works there in CE.
ParkourPenguin wrote: |
Try learning by doing something easier and smaller in scope: finish the CE tutorial, follow along with videos on YouTube, download other cheat tables and learn from them, etc. |
I've been through the x86 tutorial. Looking over lua.
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 138
Joined: 06 Jul 2014 Posts: 4275
|
Posted: Thu Apr 26, 2018 3:55 pm Post subject: |
|
|
Sarge411 wrote: | I'm not sure if my understanding of code injection is correct. Is this what CE does (in a scenario where an instruction "frequently" accessing a static address is picked as an injection point):
1. Allocate memory in the running process
2. Replace accessing instruction with a jmp to the newly allocated instruction
3. Execute code after ENABLE (provided that execution reaches injection point (the now jmp instruction))
4. Execute original code that was in place of the jmp
5. jmp back to the instruction immediately after the jmp |
- Yes, that is what the alloc statement does.
- Yes, that is done by "INJECT:" / "jmp newmem"
- No. Cheat Engine is not executing any of that code. It is only writing that code into the allocated memory so the game can execute it when the game wants to.
- No. (same reasoning as 3)
- That jmp instruction does exist.
Cheat Engine is not executing that code. Cheat Engine writes that code into the game's memory. The game will execute that code when the game was suppose to execute the original instruction(s). I don't know how else to word this so that you understand.
I also believe you're using the term "static address" incorrectly, but that's another discussion. In short, if it's green in the memory view, it's static; if it's black, it's not.
Sarge411 wrote: | Now as far as my understanding goes, CE places the code after the DISABLE label to an address in memory defined after DISABLE. | Everything CE automatically generates in the disable section of a script reverts everything done in the enable section. This involves deallocating memory, unregistering symbols, and restoring the original code that was overwritten by a jmp.
Sarge411 wrote: | I still have to look at how CE manages threads (among many other things). | CE doesn't really manage anything. createthread simply creates a thread in the target process that starts at the specified address.
Sarge411 wrote: | The idea is that when the lua script gets executed there will always be valid values stored in both healthAddress and healthValue (since the script must first be enabled before being disabled?). | The script does have to be enabled before it can be disabled, but that doesn't mean healthAddress and healthValue have nonzero values. Again, Cheat Engine does not execute the code in the enable section. The code in the enable section is only executed by the game when the game was suppose to execute the original instruction(s). By the time you disable the script, the game might have already executed the code, or it might not have. So the values stored in healthAddress and healthValue might be valid or they might still be 0.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
Sarge411 Newbie cheater Reputation: 0
Joined: 21 Apr 2018 Posts: 21
|
Posted: Fri Apr 27, 2018 3:25 pm Post subject: |
|
|
ParkourPenguin wrote: | - Yes, that is what the alloc statement does.
- Yes, that is done by "INJECT:" / "jmp newmem"
- No. Cheat Engine is not executing any of that code. It is only writing that code into the allocated memory so the game can execute it when the game wants to.
- No. (same reasoning as 3)
- That jmp instruction does exist.
Cheat Engine is not executing that code. Cheat Engine writes that code into the game's memory. The game will execute that code when the game was suppose to execute the original instruction(s). I don't know how else to word this so that you understand.
|
Ok, that's clear.
I've reworked the code as you suggested earlier (by using lua to save the health value):
Code: |
[ENABLE]
aobscanmodule(INJECT,Duke3dw.exe,66 29 44 91 0A) // should be unique
alloc(newmem,$1000)
label(code)
label(return)
newmem:
{$lua}
healthAddress = hex_value
healthValue = readInteger(healthAddress)
writeInteger(healthAddress, 0)
{$asm}
code:
sub [ecx+edx*4+0A],ax
jmp return
INJECT:
jmp newmem
return:
registersymbol(INJECT)
[DISABLE]
{$lua}
writeInteger(healthAddress, healthValue)
{$asm}
INJECT:
db 66 29 44 91 0A
unregistersymbol(INJECT)
dealloc(newmem)
|
but now am getting:
Code: |
Error in line
healthAddress = hex_value
This instruction cannot be compiled.
|
ParkourPenguin wrote: |
Everything CE automatically generates in the disable section of a script reverts everything done in the enable section. This involves deallocating memory, unregistering symbols, and restoring the original code that was overwritten by a jmp.
CE doesn't really manage anything. createthread simply creates a thread in the target process that starts at the specified address.
The script does have to be enabled before it can be disabled, but that doesn't mean healthAddress and healthValue have nonzero values. Again, Cheat Engine does not execute the code in the enable section. The code in the enable section is only executed by the game when the game was suppose to execute the original instruction(s). By the time you disable the script, the game might have already executed the code, or it might not have. So the values stored in healthAddress and healthValue might be valid or they might still be 0. |
W.r.t. to the inline lua code in the AA, how are variables treated? Does their scope extend to the entire AA script or is only valid within the lua...asm tags?
For example, if healthValue is set by lua after the script is enabled will the same value be used when it's disabled?
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 138
Joined: 06 Jul 2014 Posts: 4275
|
Posted: Fri Apr 27, 2018 4:26 pm Post subject: |
|
|
Sarge411 wrote: | I've reworked the code as you suggested earlier (by using lua to save the health value) |
I never suggested that, and that would not work. As I have said, CE executes the Lua code, not the game.
If you're curious, that particular error is because you put spaces before the {$lua} and {$asm} lines.
Also, since you changed the injection point, you shouldn't execute the sub instruction after writing 0 to the address.
Sarge411 wrote: | W.r.t. to the inline lua code in the AA, how are variables treated? Does their scope extend to the entire AA script or is only valid within the lua...asm tags?
For example, if healthValue is set by lua after the script is enabled will the same value be used when it's disabled? |
The {$lua} block just executes Lua code. It also does something else, but it's not relevant in this case. Look at a Lua tutorial if you want to learn how Lua works, and look at celua.txt for functions CE provides.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
Sarge411 Newbie cheater Reputation: 0
Joined: 21 Apr 2018 Posts: 21
|
Posted: Sat Apr 28, 2018 1:32 pm Post subject: |
|
|
ParkourPenguin wrote: |
I never suggested that, and that would not work. As I have said, CE executes the Lua code, not the game.
If you're curious, that particular error is because you put spaces before the {$lua} and {$asm} lines.
|
Indentation fixed that error.
ParkourPenguin wrote: |
Also, since you changed the injection point, you shouldn't execute the sub instruction after writing 0 to the address.
|
I now only save the value from healthAddress in healthValue and write 0 to healthAddress when the script is enabled (lua after ENABLE label is executed) and write back the value from healthValue to healthAddress.
Code: |
[ENABLE]
aobscanmodule(INJECT,Duke3dw.exe,66 8B 42 2A 66 89 85 96 02 00 00) // should be unique
alloc(newmem,$1000)
label(code)
label(return)
newmem:
{$lua}
print("Alive 1")
healthAddress = hexval
healthValue = readInteger(healthAddress)
writeInteger(healthAddress, 0)
print("Alive 2")
{$asm}
code:
mov ax,[edx+2A]
mov [ebp+00000296],ax
jmp return
INJECT:
jmp newmem
nop
nop
nop
nop
nop
nop
return:
registersymbol(INJECT)
[DISABLE]
{$lua}
print("Dead 1")
writeInteger(healthAddress, healthValue)
print("Dead 2")
{$asm}
INJECT:
db 66 8B 42 2A 66 89 85 96 02 00 00
unregistersymbol(INJECT)
dealloc(newmem)
|
The code runs (character dies) but the cross doesn't appear as if the cheat is enabled/disabled. When I run it from the editor it gives the following error:
Code: |
Error while scanning for AOB's: INJECT
Error
|
Even though that instruction is still present in memory.
Is it correct that lua scripts are executed before any asm code and are not written to the process' memory? The asm code now handles the injection jmps and nothing more (I think (hope)).
I've picked the injection point an instruction that executes often regardless if the player is dead or alive (but should injection points in the context of running lua scripts matter? as, per my understanding, lua is independent of AA functionality-wise. Why can't ):
Code: |
Alive
--------------------------------------------
0044DD05 - 66 83 3C 85 DE70D000 00 - cmp word ptr [eax*4+00D070DE],00
00452A96 - 66 83 7B 2A 00 - cmp word ptr [ebx+2A],00
0044C64A - 66 29 44 91 0A - sub [ecx+edx*4+0A],ax
0044C65C - 0FBF 54 91 0A - movsx edx,word ptr [ecx+edx*4+0A]
00452AC2 - 66 8B 42 2A - mov ax,[edx+2A] // <== Instruction picked as injection point
00452D22 - 66 83 79 2A 00 - cmp word ptr [ecx+2A],00
004601A3 - 66 83 3C 95 DE70D000 00 - cmp word ptr [edx*4+00D070DE],00
0043207F - 66 83 3C 95 DE70D000 00 - cmp word ptr [edx*4+00D070DE],00
0043671B - 0FBF 50 2A - movsx edx,word ptr [eax+2A]
00431DBA - 66 83 7E 2A 00 - cmp word ptr [esi+2A],00
00438793 - 66 83 3C 85 DE70D000 00 - cmp word ptr [eax*4+00D070DE],00
0042A50E - 66 83 7E 2A 00 - cmp word ptr [esi+2A],00
|
Code: |
Dead
--------------------------------------------
0044DD05 - 66 83 3C 85 DE70D000 00 - cmp word ptr [eax*4+00D070DE],00
00452A96 - 66 83 7B 2A 00 - cmp word ptr [ebx+2A],00
00452AAF - 66 C7 40 2A 0000 - mov word ptr [eax+2A],0000
00452AC2 - 66 8B 42 2A - mov ax,[edx+2A] // <== Instruction picked as injection point
00452D22 - 66 83 79 2A 00 - cmp word ptr [ecx+2A],00
004601A3 - 66 83 3C 95 DE70D000 00 - cmp word ptr [edx*4+00D070DE],00
0043207F - 66 83 3C 95 DE70D000 00 - cmp word ptr [edx*4+00D070DE],00
0043671B - 0FBF 50 2A - movsx edx,word ptr [eax+2A]
00431DBA - 66 83 7E 2A 00 - cmp word ptr [esi+2A],00
00438793 - 66 83 3C 85 DE70D000 00 - cmp word ptr [eax*4+00D070DE],00
|
Quote: |
The {$lua} block just executes Lua code. It also does something else, but it's not relevant in this case. Look at a Lua tutorial if you want to learn how Lua works, and look at celua.txt for functions CE provides. |
I'm looking at it and working on a thread workflow:
1. Start thread when cheat is enabled
2. Always read key values
3. Stop thread on given key
4. If other keys are pressed updated character coordinates
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 138
Joined: 06 Jul 2014 Posts: 4275
|
Posted: Sat Apr 28, 2018 2:58 pm Post subject: |
|
|
Sarge411 wrote: | Is it correct that lua scripts are executed before any asm code and are not written to the process' memory? |
Yes, that is correct.
Sarge411 wrote: | but should injection points in the context of running lua scripts matter? |
No, it doesn't matter. None of the Lua code in that AA script depends on the injection point. You don't even need to use code injection in the first place if you already have the address.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
Sarge411 Newbie cheater Reputation: 0
Joined: 21 Apr 2018 Posts: 21
|
Posted: Sun Apr 29, 2018 3:14 pm Post subject: |
|
|
ParkourPenguin wrote: | Yes, that is correct |
I wrote this lua script:
Code: |
local function initCam()
writeBytes(ZWExitMapAddr, getNops(#ZWExitMapOrigCode))
writeBytes(CamRotWAddr, getNops(#CamWOrigCode))
writeBytes(ZWAddr, getNops(#ZWOrigCode))
writeBytes(YWAddr, getNops(#YWOrigCode))
writeBytes(XWAddr, getNops(#XWOrigCode))
writeBytes(CamUpDnWAddr, getNops(#CamUpDnOrigCode))
print("before read health")
healthVal = readSmallInteger(healthAddr)
print("after read")
print("health addr " .. string.format("%x", healthAddr))
print("value at address " .. healthVal)
writeSmallInteger(healthAddr, 0)
XVal = readInteger(XAddr)
YVal = readInteger(YAddr)
ZVal = readInteger(ZAddr)
end
local camThread = createThread(function(startThread)
initCam()
end)
|
but get
Code: |
attempt to call a nil value (global 'readSmallInteger')
|
Why isn't 'readSmallInteger' defined? I looked at similar threads and the problem was always a typo in the function's name (the health is stored as short in the least significant bytes at healthAddress)
Also, when I use 'readInteger' instead, the value of healthValue remains 0 as it was initialized prior to starting the thread:
Code: |
healthAddr = hex
healthVal = 0
XAddr = hex
YAddr = hex
ZAddr = hex
XVal = 0
YVal = 0
ZVal = 0
|
and not updated.
Is it because initCam() executes in a separate thread and can only read globals from the main thread?
Similarly, CE complained about isKeyPressed. I'm using CE 6.6 x86 build.
Here is the full script (base64):
aHR0cHM6Ly9wYXN0ZS51YnVudHUuY29tL3Avc1I2d1lZM3lwUC8=
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 138
Joined: 06 Jul 2014 Posts: 4275
|
Posted: Sun Apr 29, 2018 4:04 pm Post subject: |
|
|
Several Lua functions were added in CE 6.7. Update to the latest version (or implement the function(s) yourself).
Sarge411 wrote: | Also, when I use 'readInteger' instead, the value of healthValue remains 0 as it was initialized prior to starting the thread |
If the value of the player's health is 0 before the thread is created, it will read 0 from that address and assign 0 to the global healthVal.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
Sarge411 Newbie cheater Reputation: 0
Joined: 21 Apr 2018 Posts: 21
|
Posted: Sun May 06, 2018 1:33 pm Post subject: |
|
|
ParkourPenguin wrote: | Several Lua functions were added in CE 6.7. Update to the latest version (or implement the function(s) yourself). |
I fixed this by adding functions from CE 6.7 but was quite a PITA.
ParkourPenguin wrote: |
If the value of the player's health is 0 before the thread is created, it will read 0 from that address and assign 0 to the global healthVal. |
I'm almost done but it seems that I hit another bump that's related to concurrency. Does lua in CE have any form of syncing primitives? I looked at celua.txt but couldn't find any.
The code is (base64):
Code: |
c2xlZXBUaW1lICAgICAgICAgPSAxNTANCg0KbG9jYWwgY2FtVGhyZWFkID0gY3JlYdipshitVGhyZWFkKGZ1bmN0aW9uKHN0YXJ0VGhyZWFkKQ0KDQogICAgd2hpbGUgdHJ1ZSBkbw0KDQogICAgICAgIGlmIChpc0tleVByZXNzZWQoVktfTlVNUEFEMCkgYW5kIGNhbUlzU3RhcnRlZCA9PSBmYWxzZSkgdGhlbg0KICAgICAgICAgICBpbml0Q2FtKCkNCiAgICAgICAgICAgY2FtSXNTdGFydGVkID0gdHJ1ZQ0KICAgICAgICAgICBzbGVlcChzbGVlcFRpbWUgKQ0KICAgICAgICBlbmQNCg0KICAgICAgICBpZiAoaXNLZXlQcmVzc2VkKFZLX05VTVBBRDApIGFuZCBjYW1Jc1N0YXJ0ZWQgPT0gdHJ1ZSkgdGhlbg0KICAgICAgICAgICByZXN0b3JlQ29kZSgpDQogICAgICAgICAgIGNhbUlzU3RhcnRlZCA9IGZhbHNlDQogICAgICAgICAgIHNsZWVwKHNsZWVwVGltZSkNCiAgICAgICAgZW5kDQoNCiAgICAgICAgaWYgKGNhbUlzU3RhcnRlZCkgdGhlbg0KDQogICAgICAgICAgIGlmIChpc0tleVByZXNzZWQoVktfTlVNUEFEOCkpIHRoZW4NCiAgICAgICAgICAgICAgbW92ZUZXKE1PRElGSUVSKQ0KICAgICAgICAgICBlbmQNCg0KICAgICAgICBlbmQNCiAgICAgICAgc2xlZXAoc2xlZXBUaW1lKQ0KICAgIGVuZCANCmVuZCk=
|
where initCam() and restoreCode() are external to the thread's body/function and are defined globally. Sometimes the cheat works, sometimes it doesn't. It seems as if the initCam() function does not execute entirely. Same goes for restoreCode().
If the newly created thread runs a while loop, what happens to the main thread? Can it be that if CE doesn't read fast enough from memory before it writes to it, an original value is overwritten? E.g. if the health is read but the read doesn't finish before write is called and 0 (the initial value of healthVal) gets written to memory instead?
|
|
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
|
|