Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Auto Assembler - declare and assign to variable

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
TTR
How do I cheat?
Reputation: 0

Joined: 04 May 2020
Posts: 4

PostPosted: Mon May 04, 2020 12:32 pm    Post subject: Auto Assembler - declare and assign to variable Reply with quote

Hi everyone,

I'm coming from a background with Java, C#, PHP, etc. I have done a little bit of MIPS assembly but that's about it.
Having some serious issues declaring variables in Auto-Assembler. Can anyone point me in the right direction? All I want to do is store the value of some address in a variable that I can then re-use in my address list.

Here's a couple examples I have tried:

Code:

define(address,"OutSpy.dll"+49378E)
define(bytes,E9 6D C8 BB E6 0F 1F 00)

[ENABLE]

assert(address,bytes)
alloc(newmem,$1000)

alloc(pTest, 4)

label(pTest)

registersymbol(pTest)

label(return)

newmem:

pTest:
  dd ebp-0C
  lea eax,[ebp-0C]
  mov edx,OutSpy.dll+493A78
  jmp return

address:
  jmp newmem
  nop 3
return:

[DISABLE]

address:
  db bytes
  // lea eax,[ebp-0C]
  // mov edx,OutSpy.dll+493A78

unregistersymbol(pTest)
unregistersymbol(newmem)
dealloc(newmem)


Code:

define(address,"OutSpy.dll"+49378E)
define(bytes,E9 6D C8 BB E6 0F 1F 00)

[ENABLE]

assert(address,bytes)
alloc(newmem,$1000)
registersymbol(newmem)
define(pTest, newmem+100)
registersymbol(pTest)

label(return)

newmem:
  mov [pTest], ebp-0C
  lea eax,[ebp-0C]
  mov edx,OutSpy.dll+493A78
  jmp return

address:
  jmp newmem
  nop 3
return:

[DISABLE]

address:
  db bytes
  // lea eax,[ebp-0C]
  // mov edx,OutSpy.dll+493A78

unregistersymbol(pTest)
unregistersymbol(newmem)
dealloc(newmem)


Here's a working one, which I have no idea why it works:

Code:

aobscan(INJECT,48 63 80 D0 00 00 00 85 C0 0F 84) // should be unique
registersymbol(INJECT)
alloc(newmem,$1000,18893394898)
registersymbol(newmem)
define(pTime,newmem+100)
registersymbol(pTime)

newmem:
  mov [pTime], rax
  movsxd  rax,dword ptr [rax+000000D0]
  jmp return

INJECT:
  jmp newmem
  nop
  nop

return:

[DISABLE]

INJECT:
  db 48 63 80 D0 00 00 00

unregistersymbol(pTime)
unregistersymbol(newmem)
unregistersymbol(INJECT)
dealloc(newmem)


Why does the one with pTime work but not the one with pTest?

I tried searching around, I have the cheatengine documentation bookmarked. Feeling a bit clueless here.

Any insight?
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4702

PostPosted: Mon May 04, 2020 1:28 pm    Post subject: Reply with quote

1st code:
Code:
dd ebp-0C
"dd" is a pseudoinstruction that takes a doubleword (32 bit) literal and writes its byte representation to the location dd is placed at. The bytes dd generates are not code and should not be executed.
ebp-OC is not a literal - it's a register and some arithmetic. This is like the difference between a literal and a variable in higher level programming languages.
Examples of literals:
Code:
dd 12             // 0C 00 00 00
dd -3             // FD FF FF FF
dd (float)15.0    // 00 00 70 41
dd (double32h)7.3 // 33 33 1D 40 - I learned this existed just now

2nd code:
Code:
mov [pTest], ebp-0C
That instruction is of the form "MOV r/m32,r32" (opcode 0x89; see an instruction reference). The r32 source operand is just a 32-bit register: you're not allowed to do arithmetic there.

3rd code:
Just want to point out you swapped from 32-bit code to 64-bit code.

"mov [pTime],rax " is fine; however, I don't know why this works:
Code:
define(pTime,newmem+100)
registersymbol(pTime)

"define" basically replaces every instance of pTime with "newmem+100". This doesn't affect registersymbol, but even so, the symbol pTime isn't assigned any address in the script.
Maybe CE does some magic to make that work. Regardless, IMO this would be the more canonical way:
Code:
...
label(pTime)
registersymbol(pTime)
...
newmem+100:
pTime:
  dq 0  // rax is 64-bit -> use dq (declare quadword); ebp is 32-bit -> use dd

(you could also use a separate alloc for pTime)

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
TTR
How do I cheat?
Reputation: 0

Joined: 04 May 2020
Posts: 4

PostPosted: Mon May 04, 2020 2:37 pm    Post subject: Reply with quote

Thanks for your help ParkourPenguin.

I understand a bit better now. So from what I gathered, dd cannot be used to set a memory address to a "dynamic value". It needs hard-coded bytes/values.

In 2nd code, if I wanted to put the value of ebp-0C inside pTest how would I do that?
Would I first put ebp-0C inside a register? Am I allowed to do that? What does the "m" stand for in r/m32?

Nice catch, guess you noticed from the extra registers. Yeah the first two were for a 32 bit application and the 3rd one was for a 64bit game.
3rd code, honestly I don't know how it works either and I tried using it in other scripts which never works. Very strange.

In the first example, I have an alloc(pTest, 4). If I remove the pTest label and replace dd ebp-0C with mov [pTest], ebp-0C, it still fails to compile. With an error like: mov [0000000+100],ebp-0C cannot compile.
Is that because I'm trying to do a mov r/m32,r32? How do I avoid doing that?

I don't understand why you're doing a dq 0 with pTime. Wouldn't that initialize it to 0 instead of storing the value of rax inside it?
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4702

PostPosted: Mon May 04, 2020 6:30 pm    Post subject: Reply with quote

TTR wrote:
In 2nd code, if I wanted to put the value of ebp-0C inside pTest how would I do that?
Would I first put ebp-0C inside a register? Am I allowed to do that? What does the "m" stand for in r/m32?
In that specific injection point, I'd do this:
Code:
newmem:
  lea eax,[ebp-0C]
  mov [pTest],eax
  mov edx,OutSpy.dll+493A78
  jmp return
That lea instruction is really convenient to have as part of the original code. It basically says "eax = ebp-0C".
In other circumstances, it's usually fine to just get the register itself (i.e. ebp) and apply the offset (i.e. 0x0C) later on. For example, add a memory record as a pointer with the base address of "pTest" and a L1 offset of "0C".
If you must overwrite a register yourself, use push/pop to back it up unless you can see reason not to (e.g. game overwrites the value later).

"r/m32" basically means a 32-bit register or memory location. In this case "[pTest]" is a 32-bit memory location.

TTR wrote:
In the first example, I have an alloc(pTest, 4). If I remove the pTest label and replace dd ebp-0C with mov [pTest], ebp-0C, it still fails to compile. With an error like: mov [0000000+100],ebp-0C cannot compile.
Is that because I'm trying to do a mov r/m32,r32? How do I avoid doing that?
It fails to compile for the same reason as the second code: you can't do arithmetic there. You can't have "ebp-0C", only "ebp". There does not exist an instruction that can do the operation you're trying to do: you must use several instructions to do that. (as shown previously w/ lea then mov)
As an aside, you don't need to call label(...) on symbols introduced with an alloc(...).

TTR wrote:
I don't understand why you're doing a dq 0 with pTime. Wouldn't that initialize it to 0 instead of storing the value of rax inside it?
It'll get initialized to 0 anyway even without that there. The code you write in the code injection to copy the address doesn't happen immediately- it'll only happen at the game's convenience.
Explicitly initializing it to 0 is superfluous, but it isn't a bad habit to have. If you're using multiple values like this:
Code:
label(value1)
label(value2)
label(value3)

newmem+800:
value1:
  dd 0
value2:
  dq 0
value3:
  dd 0
Then each symbol refers to a unique address: the second 4 bytes after the first, and the third 8 bytes after the second. If those dd / dq instructions weren't there, they'd all have the same address.
Reordering the way values are laid out in memory becomes as simple as copying and pasting a couple lines.
If memory is reused between script invocations (e.g. globalalloc), it might be nice to initialize memory to a known state when the script starts.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
TTR
How do I cheat?
Reputation: 0

Joined: 04 May 2020
Posts: 4

PostPosted: Mon May 04, 2020 8:36 pm    Post subject: Reply with quote

Thank you for your detailed answer! I understand my mistake a lot better now. And more importantly, how to fix it.

My problem was that I was trying to do arithmetic in the second part of the mov. I think I was confused because the lea uses arithmetic in its call.
I'm still a bit confused. It seems like some instructions let me do it and others don't.
I'm so used to chaining function calls. Lol.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4702

PostPosted: Mon May 04, 2020 10:13 pm    Post subject: Reply with quote

Addressing memory (stuff between square brackets) is generally the only time you can do arithmetic in operands. Even then, you're still limited.

Look at assembly and you'll notice patterns eventually.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
TTR
How do I cheat?
Reputation: 0

Joined: 04 May 2020
Posts: 4

PostPosted: Tue May 05, 2020 1:20 pm    Post subject: Reply with quote

Thank you ParkourPenguin. You were very helpful.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites