 |
Cheat Engine The Official Site of Cheat Engine
|
| View previous topic :: View next topic |
| Author |
Message |
Crockball How do I cheat?
Reputation: 0
Joined: 25 Aug 2024 Posts: 3
|
Posted: Sun Aug 25, 2024 9:25 am Post subject: What is the best way to compare 18 bytes in auto assembler? |
|
|
Hi! I'm hacking a really ancient game, in which I was unable to find a stable pointer to the character object, rather a huge static array with object pointers on the same map (scene?). So I found a stable 18-bytes AOB signature, that (if subsctracted c8b offset) will point to entity start (which I need).
The plan: on calling a spell function go to ebx adress and see if it is indeed points to the main character object, using my stable signature (+ cb8), get 18 bytes from there, compare them and if it is indeed the character object, do not substract the spell counter. But I was unable to do so in pure lua, despite trying I couldn't transfer any information to ($asm), via flag, symbol or otherwise.
So I would like to know how to best do it using auto assembler only. To clarify further, I'll attach a snippet of my code in lua, which could be used to better understand the issue.
| Description: |
|
| Filesize: |
45.22 KB |
| Viewed: |
1976 Time(s) |

|
|
|
| Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4718
|
Posted: Sun Aug 25, 2024 1:42 pm Post subject: |
|
|
{$lua} is for preprocessing- substituting a string that will then be interpreted by the auto assembler.
| Code: | {$lua}
return 'define(foo,1234)'
{$asm}
// same as writing:
define(foo,1234) |
You might be looking for {$luacode}
https://forum.cheatengine.org/viewtopic.php?t=618134
But you really shouldn't be using {$luacode} unless you need to interact with CE itself from the target process. That involves synchronous IPC which is relatively expensive compared to just staying in the game's process.
If you don't like assembly, try {$ccode} instead:
| Code: | alloc(pattern,32)
newmem:
push rax
{$ccode ptr=rbx output=rax}
extern int memcmp(const void *p1, const void *p2, unsigned long long size);
extern unsigned char pattern;
output = memcmp((unsigned char *)ptr + 1976, &pattern, 18);
{$asm}
test eax,eax
...
pop rax
// original code here
jmp return
pattern:
db 43 6F 6E 65 00 00 00 00 44 50 4C 41 59 45 52 33 38 BD |
But if it's just comparing a few bytes in memory against a static pattern, that's easy enough to do in pure assembly
| Code: | newmem:
push rax
mov rax,00000000656E6F43
cmp [rbx+7B8],rax
jne ...
mov rax,33524559414C5044
cmp [rbx+7C0],rax
jne ...
mov eax,BD38
cmp word ptr[rbx+7C8],ax
jne ...
...
pop rax
// original code here
jmp return |
Edit: If the game is 32-bit, the code is different. No 64-bit registers (e.g. use eax instead of rax), memcmp size parameter is unsigned long, and you have to compare 4 bytes at a time for the pure assembly version (but you can directly compare an immediate against a 32-bit memory location)
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
| Back to top |
|
 |
Crockball How do I cheat?
Reputation: 0
Joined: 25 Aug 2024 Posts: 3
|
Posted: Mon Aug 26, 2024 4:32 am Post subject: |
|
|
Many thanks! I tinkered with assembler code for a while, using your code for a reference, and got working solution:
| Code: |
push rcx
mov rcx, 00000000656E6F4E
cmp [rbx+7B8], rcx
jne originalcode
mov rcx, 33524559414C5044
cmp [rbx+7C0], rcx
jne originalcode
mov ecx, BD38
cmp word ptr[rbx+7C8], cx
jne originalcode
jmp exit
originalcode:
and [rsi+08],ax
exit:
pop rcx
test r13d,r13d
jmp returnhere
|
I also checked out C code, and I understand it well enough, but I'm unsure how you initialize
with the actual pattern, that later got itself compared in C block. Should you do it manually in assembly (move chunk in eax, move to adress of allocated memory, update offset and repeat), or is there some other more elegant way?
I had no idea that $lua is not done at injection, but rather on pre-procession, so I was really confused yesterday. Hopefully, by injecting more code on C I'll make higher-level languages to make all of heavy lifting, and leave $asm for control flow only (jmp, je, call etc)
|
|
| Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4718
|
Posted: Mon Aug 26, 2024 11:12 am Post subject: |
|
|
| Crockball wrote: | | I'm unsure how you initialize with the actual pattern, that later got itself compared in C block. | This pair of lines at the bottom:
| Code: | pattern:
db 43 6F 6E 65 00 00 00 00 44 50 4C 41 59 45 52 33 38 BD | `db` writes bytes into memory
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
| Back to top |
|
 |
Csimbi I post too much
Reputation: 97
Joined: 14 Jul 2007 Posts: 3337
|
Posted: Mon Aug 26, 2024 3:07 pm Post subject: |
|
|
I'd try using AOB scan? (scan for the 18 bytes in the memory where the other 18 bytes are)
You can make luacall in ASM
|
|
| Back to top |
|
 |
Crockball How do I cheat?
Reputation: 0
Joined: 25 Aug 2024 Posts: 3
|
Posted: Tue Aug 27, 2024 8:46 am Post subject: |
|
|
| Quote: | | `db` writes bytes into memory |
thanks again, I didn't realize that db was an instruction, I took it for hexadecimal number DB.
| Quote: | | I'd try using AOB scan? (scan for the 18 bytes in the memory where the other 18 bytes are) |
My previous solution (that I've decided to abandon) was:
aobscan as initialise to find pointer to player object in a static array, thus updating symbols, declared in lua, which then passed to auto assembler and make checks on 2 shared function. However due to my unableness to understand why and where static array was updated (and reshuffled), I couldn't find suitable places to inject updateSymbols() function. From what I understand, the game updated static array on save, on load, every few days and every few locations, but each of these cases were not a 100% update situation, so I missed quite a few updates and pointer to character entity (ultimate goal) was lost.
And if you are meaning that I should call aobscan each time I cast the spell, I decided to drop this idea either, because each lua aobscan will freeze the game for about 1 to 1.5 second, and it is possible to cast 10 spells each combat. I have a rather modest setup (ryzen 5 1600), so I've decided that this preformance is unsatisfactory.
or if you mean that I should aobscan to find my signatrue, the issue was not about finding it, but rather putting it to where alloc() has happened.
|
|
| 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
|
|