Assembler question

Post your topics and discussions here that you can't find a good section for.
Post Reply
beguiler
Cheater
Cheater
Posts: 35
Joined: Sun Mar 19, 2017 1:31 pm
Reputation: 11

Assembler question

Post by beguiler » Fri Sep 21, 2018 11:26 pm

I was using aobscan to get memory address for a money pointer in a 64bit game and came across this weird issue that doesn't seem to make sense so I was hoping someone here could explain it for me.

Getting the memory location was easy it's a simple 4 byte value but the game is 64bit so the address is a double word and is stored in a 64bit register (RCX). When I looked for what access the memory location I found it really quick and it looked like it would be a simple thing to add one line to the code to get me the address whenever I wanted.

So I tried the following:

Code: Select all

newmem:
mov [_basePtr],rcx  //the code I added. Address I want is in RCX, so a simply copy to my variable

code:
mov eax,[rcx+000000C0]
jmp return
and in cheat engine, the script wouldn't enable. So I did the following to get around it:

Code: Select all

newmem:
push rax  //save what is in rax to stack
mov rax,rcx //copy address I want to rax register
mov [_basePtr],rax  //copy rax value to my variable
pop rax //restore the original content of rax

code:
mov eax,[rcx+000000C0]
jmp return
and this time it works as expected. So my question is why didn't the initial code work? Is there some reason I cannot copy the RCX to my variable? I am not familiar with the inner workings of x86 assembly but it seemed straight forward enough to copy a value of a 64bit register but for some reason it couldn't do it.

User avatar
TheyCallMeTim13
Administration
Administration
Posts: 1141
Joined: Fri Mar 03, 2017 12:31 am
Reputation: 202
Contact:

Re: Assembler question

Post by TheyCallMeTim13 » Fri Sep 21, 2018 11:45 pm

beguiler wrote:
Fri Sep 21, 2018 11:26 pm
I was using aobscan to get memory address for a money pointer in a 64bit game and came across this weird issue that doesn't seem to make sense so I was hoping someone here could explain it for me.

Getting the memory location was easy it's a simple 4 byte value but the game is 64bit so the address is a double word and is stored in a 64bit register (RCX). When I looked for what access the memory location I found it really quick and it looked like it would be a simple thing to add one line to the code to get me the address whenever I wanted.

So I tried the following:

Code: Select all

newmem:
mov [_basePtr],rcx  //the code I added. Address I want is in RCX, so a simply copy to my variable

code:
mov eax,[rcx+000000C0]
jmp return
and in cheat engine, the script wouldn't enable. So I did the following to get around it:

Code: Select all

newmem:
push rax  //save what is in rax to stack
mov rax,rcx //copy address I want to rax register
mov [_basePtr],rax  //copy rax value to my variable
pop rax //restore the original content of rax

code:
mov eax,[rcx+000000C0]
jmp return
and this time it works as expected. So my question is why didn't the initial code work? Is there some reason I cannot copy the RCX to my variable? I am not familiar with the inner workings of x86 assembly but it seemed straight forward enough to copy a value of a 64bit register but for some reason it couldn't do it.
Both are valid, seems like there was an error somewhere else in the script.

EDIT:
Like Kalas pointed out, make sure it's not JITed code (i.e.: you have to spend money for the code to be compiled).

User avatar
Kalas
Fearless Donors
Fearless Donors
Posts: 609
Joined: Fri Mar 03, 2017 9:49 am
Reputation: 96

Re: Assembler question

Post by Kalas » Fri Sep 21, 2018 11:51 pm

Just a quick question, is this game a unity based engine?
If so make sure the mono features are enabled so you can activate the cheat/script.

If you registered a symbol make sure you unregistered it.

Post full code too so we can gather more information 🙍
Check us out!: MegaDev

Join Discord: Discord

beguiler
Cheater
Cheater
Posts: 35
Joined: Sun Mar 19, 2017 1:31 pm
Reputation: 11

Re: Assembler question

Post by beguiler » Sat Sep 22, 2018 4:26 am

I think it's unreal engine (Bard's Tale 4). I'll attach the table but there is only one thing in it.
Attachments
BardsTale4.CT
(3.44 KiB) Downloaded 19 times

User avatar
TheyCallMeTim13
Administration
Administration
Posts: 1141
Joined: Fri Mar 03, 2017 12:31 am
Reputation: 202
Contact:

Re: Assembler question

Post by TheyCallMeTim13 » Sat Sep 22, 2018 5:28 am

Best I can figure is you fixed whatever it was when you added the move to RAX, try it again without the added push move and pop.

It could have been that you changed the size of the memory allocated with globalAlloc after it was already allocated, this can prevent the script from enabling because it's already allocated so the size can't change.

beguiler
Cheater
Cheater
Posts: 35
Joined: Sun Mar 19, 2017 1:31 pm
Reputation: 11

Re: Assembler question

Post by beguiler » Sat Sep 22, 2018 7:15 am

Yeah the table does work as it is now, but it's using 4 lines of code for something that should be one. I have tried commenting out the working code and just doing it with a direct copy of RCX, but it never enables in that condition. I thought that maybe there might be some reason for it I didn't know about because I have limited assembly language experience in general. Oh well not a big deal, I was just curious.

User avatar
Kalas
Fearless Donors
Fearless Donors
Posts: 609
Joined: Fri Mar 03, 2017 9:49 am
Reputation: 96

Re: Assembler question

Post by Kalas » Sat Sep 22, 2018 12:12 pm

I usually do:

Code: Select all

{ Game   : BardsTale4-Win64-Shipping.exe
  Version: 
  Date   : 2018-09-21


  This script does blah blah blah
}

[ENABLE]

aobscanmodule(GetPtr,BardsTale4-Win64-Shipping.exe,8B 81 C0 00 00 00 41 89) // should be unique
alloc(newmem,$128,"BardsTale4-Win64-Shipping.exe")

label(code)
label(return)

label(MoneyPtr)
registersymbol(MoneyPtr)

newmem:
  mov [MoneyPtr],rcx

code:
  mov eax,[rcx+000000C0]
  jmp return

MoneyPtr:
  dq 0

GetPtr:
  jmp newmem
  nop
return:
registersymbol(GetPtr)

[DISABLE]

GetPtr:
  db 8B 81 C0 00 00 00

unregistersymbol(GetPtr)
unregistersymbol(MoneyPtr)
dealloc(newmem)

{
// ORIGINAL CODE - INJECTION POINT: "BardsTale4-Win64-Shipping.exe"+34F6A5

"BardsTale4-Win64-Shipping.exe"+34F681: 4C 89 4A 20              -  mov [rdx+20],r9
"BardsTale4-Win64-Shipping.exe"+34F685: 48 8B 81 B0 01 00 00     -  mov rax,[rcx+000001B0]
"BardsTale4-Win64-Shipping.exe"+34F68C: 49 89 00                 -  mov [r8],rax
"BardsTale4-Win64-Shipping.exe"+34F68F: C3                       -  ret 
"BardsTale4-Win64-Shipping.exe"+34F690: 48 8B 42 20              -  mov rax,[rdx+20]
"BardsTale4-Win64-Shipping.exe"+34F694: 45 33 C9                 -  xor r9d,r9d
"BardsTale4-Win64-Shipping.exe"+34F697: 48 85 C0                 -  test rax,rax
"BardsTale4-Win64-Shipping.exe"+34F69A: 41 0F 95 C1              -  setne r9l
"BardsTale4-Win64-Shipping.exe"+34F69E: 4C 03 C8                 -  add r9,rax
"BardsTale4-Win64-Shipping.exe"+34F6A1: 4C 89 4A 20              -  mov [rdx+20],r9
// ---------- INJECTING HERE ----------
"BardsTale4-Win64-Shipping.exe"+34F6A5: 8B 81 C0 00 00 00        -  mov eax,[rcx+000000C0]
// ---------- DONE INJECTING  ----------
"BardsTale4-Win64-Shipping.exe"+34F6AB: 41 89 00                 -  mov [r8],eax
"BardsTale4-Win64-Shipping.exe"+34F6AE: C3                       -  ret 
"BardsTale4-Win64-Shipping.exe"+34F6AF: CC                       -  int 3 
"BardsTale4-Win64-Shipping.exe"+34F6B0: 48 8B 42 20              -  mov rax,[rdx+20]
"BardsTale4-Win64-Shipping.exe"+34F6B4: 45 33 C9                 -  xor r9d,r9d
"BardsTale4-Win64-Shipping.exe"+34F6B7: 48 85 C0                 -  test rax,rax
"BardsTale4-Win64-Shipping.exe"+34F6BA: 41 0F 95 C1              -  setne r9l
"BardsTale4-Win64-Shipping.exe"+34F6BE: 4C 03 C8                 -  add r9,rax
"BardsTale4-Win64-Shipping.exe"+34F6C1: 4C 89 4A 20              -  mov [rdx+20],r9
"BardsTale4-Win64-Shipping.exe"+34F6C5: 8B 81 E0 00 00 00        -  mov eax,[rcx+000000E0]
}
Check us out!: MegaDev

Join Discord: Discord

beguiler
Cheater
Cheater
Posts: 35
Joined: Sun Mar 19, 2017 1:31 pm
Reputation: 11

Re: Assembler question

Post by beguiler » Sat Sep 22, 2018 1:44 pm

Interesting @Kalas, your method works. It looks like it might be related to the globalalloc call.

JohnFK
Cheater
Cheater
Posts: 29
Joined: Tue Aug 29, 2017 10:50 am
Reputation: 8

Re: Assembler question

Post by JohnFK » Mon Sep 24, 2018 9:51 pm

You shouldn't use globalalloc on 64bit targets. In worst case it allocates memory in 32bit range where the injection is allocated in 64bit or vice versa making your memory pointer become too far. Perhaps Dark Byte will add a nearby parameter to it same as the alloc command in the future.

I think globalalloc only makes sense actually when dealing with calls because even when a memory pointer is shared between scripts a simple alloc works fine (unless it suffers by the same issue above where allocation and script injection is too far away from each other).

//edit: Also when looking at CE source you see that globalalloc gets overwritten as well when declared twice. Dark Byte might be able to tell cases where this command makes sense, but for me it rather looks like a leftover from older days and only remains for compatiblity reasons.

beguiler
Cheater
Cheater
Posts: 35
Joined: Sun Mar 19, 2017 1:31 pm
Reputation: 11

Re: Assembler question

Post by beguiler » Mon Sep 24, 2018 10:43 pm

Well that's good to know. I have always used globalalloc mainly because I learned to use CE from an old tutorial a long time ago that used it so I just kept using it. I never ran into an issue before but I don't think I have ever used it till now with a 64bit program.

Eric
Hall of Famer
Hall of Famer
Posts: 67
Joined: Thu Mar 02, 2017 11:01 pm
Reputation: 15

Re: Assembler question

Post by Eric » Thu Sep 27, 2018 9:24 pm

globalalloc already has support for the prefered memory region parameter

JohnFK
Cheater
Cheater
Posts: 29
Joined: Tue Aug 29, 2017 10:50 am
Reputation: 8

Re: Assembler question

Post by JohnFK » Fri Sep 28, 2018 8:28 am

Nice, perhaps you might want to update the wiki sometime as it does no show the prefered parameter option:

https://wiki.cheatengine.org/index.php? ... lobalAlloc

Post Reply

Who is online

Users browsing this forum: No registered users