|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
Mac99 Newbie cheater Reputation: 0
Joined: 13 Sep 2022 Posts: 14
|
Posted: Tue Sep 13, 2022 3:25 pm Post subject: Mono Adress for Code injection ends in wrong position |
|
|
I am not new to cheat engine, but this is my first time trying to make a persistent code injection.
I am doing this on a fairly new game called Disney Dreamlight Valley which is based on Unity. I've a found an instruction that accesses the Player's Stamina. On the base of the address of this instruction, I want to do a code injection and thus change the stamina. In my test example, I just wanted to do a code injection that shouldn't change anything. Unfortunately, my injected code end up in the wrong address and crashes the game.
The targeted instruction is "cmp [rcx+00000088],edx" which follows a Mono "address". The name of the Mono address is "Meta.ProfilePlayer.HasEnoughMana" and with a offset of 2 it hits my targeted instruction.
Maybe I am completely misunderstanding how code injection works in cheat engine, so I need the help of an experienced person.
This is my code
Code: |
define(address,Meta.ProfilePlayer.HasEnoughMana)
[ENABLE]
alloc(newmem,$1000)
label(code)
label(return)
newmem:
code:
cmp [rcx+00000088],edx
jmp return
address+2:
jmp code
nop
return:
registersymbol(address)
dealloc(newmem)
[DISABLE]
address+02:
db 89 83 88 00 00 00
unregistersymbol(address)
dealloc(newmem)
{
// ORIGINAL CODE - INJECTION POINT: GameAssembly.dll+93D7BD
GameAssembly.dll+93D78E: E8 6D E6 A6 FF - call GameAssembly.dll+3ABE00
GameAssembly.dll+93D793: 48 8D 0D 36 A3 19 04 - lea rcx,[GameAssembly.dll+4AD7AD0]
GameAssembly.dll+93D79A: E8 61 E6 A6 FF - call GameAssembly.dll+3ABE00
GameAssembly.dll+93D79F: C6 05 3C DF 51 04 01 - mov byte ptr [GameAssembly.dll+4E5B6E2],01
GameAssembly.dll+93D7A6: 48 89 7C 24 60 - mov [rsp+60],rdi
GameAssembly.dll+93D7AB: 8B B3 88 00 00 00 - mov esi,[rbx+00000088]
GameAssembly.dll+93D7B1: 3B F5 - cmp esi,ebp
GameAssembly.dll+93D7B3: 0F 8C A7 00 00 00 - jl GameAssembly.dll+93D860
GameAssembly.dll+93D7B9: 8B C6 - mov eax,esi
GameAssembly.dll+93D7BB: 2B C5 - sub eax,ebp
// ---------- INJECTING HERE ----------
GameAssembly.dll+93D7BD: 89 83 88 00 00 00 - mov [rbx+00000088],eax
// ---------- DONE INJECTING ----------
GameAssembly.dll+93D7C3: 48 8B 0D 06 A3 19 04 - mov rcx,[GameAssembly.dll+4AD7AD0]
GameAssembly.dll+93D7CA: E8 71 E7 A6 FF - call GameAssembly.dll+3ABF40
GameAssembly.dll+93D7CF: 33 D2 - xor edx,edx
GameAssembly.dll+93D7D1: 48 8B C8 - mov rcx,rax
GameAssembly.dll+93D7D4: 48 8B F8 - mov rdi,rax
GameAssembly.dll+93D7D7: E8 94 B6 AA FF - call System.Text.EncoderExceptionFallbackBuffer..ctor
GameAssembly.dll+93D7DC: 48 85 FF - test rdi,rdi
GameAssembly.dll+93D7DF: 0F 84 96 00 00 00 - je GameAssembly.dll+93D87B
GameAssembly.dll+93D7E5: 89 6F 10 - mov [rdi+10],ebp
GameAssembly.dll+93D7E8: 48 8B AC 24 80 00 00 00 - mov rbp,[rsp+00000080]
}
|
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 138
Joined: 06 Jul 2014 Posts: 4275
|
Posted: Tue Sep 13, 2022 4:00 pm Post subject: |
|
|
Just use a template. Highlight the instruction in the disassembler, open up an Auto Assembler window, and select Template -> AOB Injection
If you don't want to do an aobscan, use the full injection template instead.
alloc should have a third parameter in 64-bit targets. (avoids rip-relative addressing problems)
The original instruction appears to be `mov`, not `cmp`
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
Mac99 Newbie cheater Reputation: 0
Joined: 13 Sep 2022 Posts: 14
|
Posted: Wed Sep 14, 2022 2:18 am Post subject: |
|
|
I've tried an aob injection, but I've never found any pair of instructions that is unique enough.
I also don't know how to even select the right instruction when aob scan tries to match more than one instruction, where my desirable instruction is one of them.
The Original Code used to change another instruction, but since then I've changed the instruction. Since aob didn't work, I tried a code injection with the Mono address as a base.
|
|
Back to top |
|
|
panraven Grandmaster Cheater Reputation: 54
Joined: 01 Oct 2008 Posts: 941
|
Posted: Wed Sep 14, 2022 4:01 am Post subject: |
|
|
Try change
Code: |
define(address,Meta.ProfilePlayer.HasEnoughMana)
[ENABLE]
alloc(newmem,$1000)
|
to
Code: |
[ENABLE]
//// 'address' SHOULD USE a more UNIQUE NAME
AOBScanRegion(address,Meta.ProfilePlayer.HasEnoughMana,Meta.ProfilePlayer.HasEnoughMana+100, ?? ?? 89 83 88 00 00 00) //// ^ [89 83 88 00 00 00] shoudl be your original code of 'cmp [rcx+00000088],edx'
alloc(newmem,$1000,address)
|
The aobscan assure the right pattern, and 3rd parameter of 'alloc' set to 'address' have a NEAR cave so that the jmp instruction is 5 bytes long.
If the function has no overloaded, it should work.
_________________
- Retarded. |
|
Back to top |
|
|
Mac99 Newbie cheater Reputation: 0
Joined: 13 Sep 2022 Posts: 14
|
Posted: Wed Sep 14, 2022 11:38 am Post subject: |
|
|
Thx for your help, I got it working, but it seems like code injection doesn't work in this game the way it is normally used.
I've tried several instructions that change Gold, Stamina, Dreamlight and whenever I use code injection I just change the displayed value not the real value.
I've also checked that this is also the instruction that reads the real value, not the displayed one.
I really don't know what to do at this point.
|
|
Back to top |
|
|
cooleko Grandmaster Cheater Reputation: 11
Joined: 04 May 2016 Posts: 717
|
Posted: Wed Sep 14, 2022 2:40 pm Post subject: |
|
|
Half the time that happens you just need the change the value it is writing from instead of the value it is writing to. The rest of the time you need to backtrace the instructions to find where the originating value is stored to change it at the source.
For example if it was mov eax, ebx. You could write into eax and have it not work because the game uses ebx, so you should write ebx instead.
|
|
Back to top |
|
|
Mac99 Newbie cheater Reputation: 0
Joined: 13 Sep 2022 Posts: 14
|
Posted: Wed Sep 14, 2022 5:54 pm Post subject: |
|
|
cooleko wrote: | Half the time that happens you just need the change the value it is writing from instead of the value it is writing to. The rest of the time you need to backtrace the instructions to find where the originating value is stored to change it at the source.
For example if it was mov eax, ebx. You could write into eax and have it not work because the game uses ebx, so you should write ebx instead. |
That is a good idea, but I can't get the variable to be stored in my pointer. Somehow, my pointer is never defined.
I thought that in a mov eax, ebx both variables have the same byte length.
So the defined bytes for my pointer shouldn't change.
I also checked the temporary variable (r15) for storing ebx is also always 0 so I don't accidentaly overwrite anything.
Maybe my way of saving ebx in a pointer is just old school and there is a better method.
Maybe you got a good advice for me?
Code: |
[ENABLE]
aobscanmodule(INJECT1,GameAssembly.dll,FF CC CC CC CC 48 89 51 28 C3) // should be unique
alloc(newmem,$1000,INJECT1)
label(code)
label(return)
globalalloc(gold,4)
newmem:
code:
push r15
mov r15, gold
mov [r15],rdx
pop r15
mov [rcx+28],rdx
ret
jmp return
INJECT1+05:
jmp newmem
return:
registersymbol(INJECT1)
[DISABLE]
INJECT1+05:
db 48 89 51 28 C3
unregistersymbol(INJECT1)
dealloc(newmem)
{
// ORIGINAL CODE - INJECTION POINT: 7FF889191920
7FF88919190D: CC - int 3
7FF88919190E: CC - int 3
7FF88919190F: CC - int 3
7FF889191910: 48 83 C1 18 - add rcx,18
7FF889191914: 48 89 11 - mov [rcx],rdx
7FF889191917: E9 64 A0 EA FF - jmp 7FF88903B980
7FF88919191C: CC - int 3
7FF88919191D: CC - int 3
7FF88919191E: CC - int 3
7FF88919191F: CC - int 3
// ---------- INJECTING HERE ----------
7FF889191920: 48 89 51 28 - mov [rcx+28],rdx
// ---------- DONE INJECTING ----------
7FF889191924: C3 - ret
7FF889191925: CC - int 3
7FF889191926: CC - int 3
7FF889191927: CC - int 3
7FF889191928: CC - int 3
7FF889191929: CC - int 3
7FF88919192A: CC - int 3
7FF88919192B: CC - int 3
7FF88919192C: CC - int 3
7FF88919192D: CC - int 3
} |
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 138
Joined: 06 Jul 2014 Posts: 4275
|
Posted: Wed Sep 14, 2022 7:28 pm Post subject: |
|
|
`globalalloc(gold,4)` - rdx is 64 bits (8 bytes)
You're saving the value rdx and not the address rcx
The memory record should be a pointer- base address is gold, only offset is 28
Remember to activate the script and do whatever you need to do in game for the code injection to run
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
Mac99 Newbie cheater Reputation: 0
Joined: 13 Sep 2022 Posts: 14
|
Posted: Sat Sep 17, 2022 8:53 am Post subject: |
|
|
ParkourPenguin wrote: | `globalalloc(gold,4)` - rdx is 64 bits (8 bytes)
You're saving the value rdx and not the address rcx
The memory record should be a pointer- base address is gold, only offset is 28
Remember to activate the script and do whatever you need to do in game for the code injection to run |
When I look up the value for rdx in the assembler code as a pointer address it's always undefinded (?), so rdx doesn't seem to be a pointer to address nor does it hold any reasonable value.
The real issue it seems to me is that the methods for gold, mana and stamina are called by the real value and the displayed values.
When the last method call was for the displayed value, I always get the fake value mapped in my pointer.
I've tried to find some registers that differ to make sure I only save a pointer to the real value,
but after every game restart there is too much randomness in it.
I've invested a lot of time now and learned a lot about cheat engine, but whatever method I tried, it never succeeded.
It's really frustrating, and it might the end to my short experience since I don't see any solution anymore.
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 138
Joined: 06 Jul 2014 Posts: 4275
|
Posted: Sat Sep 17, 2022 9:39 am Post subject: |
|
|
Mac99 wrote: | When I look up the value for rdx in the assembler code as a pointer address it's always undefinded (?), so rdx doesn't seem to be a pointer to address nor does it hold any reasonable value.
|
ParkourPenguin wrote: | You're saving the value rdx and not the address rcx | AKA: rcx is the pointer you want
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
Mac99 Newbie cheater Reputation: 0
Joined: 13 Sep 2022 Posts: 14
|
Posted: Sat Sep 17, 2022 11:59 am Post subject: |
|
|
ParkourPenguin wrote: | Mac99 wrote: | When I look up the value for rdx in the assembler code as a pointer address it's always undefinded (?), so rdx doesn't seem to be a pointer to address nor does it hold any reasonable value.
|
ParkourPenguin wrote: | You're saving the value rdx and not the address rcx | AKA: rcx is the pointer you want |
Yes, rcx is the pointer to the memory address where my value is stored.
Issue still is that this method gets called multiple times, so this method as well as my injected code gets called multiple times with different rcx.
Some hold wrong pointers that I don't want, and only one of them is the right pointer.
rdx is the value that gets written in rcx. I've wondered why rdx is such a big hex value, that as pointer points to nowhere, it isn't a pointer.
rdx is just coded in UINT32 as well as rcx which means the last only the 4 digits are the value I want. You probably can see in the image my try to get some sense in the value of rdx.
I need a safe indication that tells my code this is the rcx value that points to the right address.
I've tried to scan for commonalities among the register values but not success.
Description: |
|
Filesize: |
241.15 KB |
Viewed: |
1869 Time(s) |
|
|
|
Back to top |
|
|
panraven Grandmaster Cheater Reputation: 54
Joined: 01 Oct 2008 Posts: 941
|
Posted: Sat Sep 17, 2022 4:05 pm Post subject: |
|
|
I'm not sure, if rcx is an instance of a class, may [rcx] be point to the vtable of the class?
I don't know if il2cpp can get the vtable by name, but I think if above is true, you can alternatively log this [rcx] from the target class's unique function eg, Update()? Then you can compare the logged vtable with the [rcx] in your inject point.
_________________
- Retarded. |
|
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
|
|