[Help] Exp/Money in RPG (Anode Heart)

Memory scanning, code injection, debugger internals and other gamemodding related discussion
Post Reply
Valatros
Expert Cheater
Expert Cheater
Posts: 140
Joined: Tue Mar 07, 2017 11:16 pm
Reputation: 27

[Help] Exp/Money in RPG (Anode Heart)

Post by Valatros »

Alright, so I've gone through the 100 and 200 series on gamehackings youtube tutorial, and honestly that's normally enough for me. I either can do the basic stuff I'm trying to do, or by the time I give up someone else has done it. I am now trying to create cheats for a game called Anode Heart, a monster-catching RPG.

But trying to make a multiplier for this game, be it money or exp, is confusing the heck out of me. I can ghetto workaround the need for a multiplier directly changing values or what have you, but I'd like to understand what's going on and improve, so... i'm reaching out hoping someone can help me understand what's happening. We'll focus on money as I try to explain my confusion/difficulty because exp has some other weirdness with how it's split/distributed to a party.

Finding money is easy, 4 bit, quick search, easy change. Do a find-what-writes, only one thing does when i shop, fight and win some money, whatever; it's always

Code: Select all

mov [rdi+000000E0],eax
. So it's moving the value "eax" into the address rdi+e0, makes sense, okay, let's find where it figures out eax. A quick glance shows no obvious changes to 'eax' prior, as pictured here:

Code: Select all

27C38DFE6FB - 05 04030150           - add eax,50010304 { 1342243588 }
27C38DFE700 - 00 00                 - add [rax],al
27C38DFE702 - 00 00                 - add [rax],al
27C38DFE704 - 00 00                 - add [rax],al
27C38DFE706 - 00 00                 - add [rax],al
27C38DFE708 - 00 00                 - add [rax],al
27C38DFE70A - 00 00                 - add [rax],al
27C38DFE70C - 00 00                 - add [rax],al
27C38DFE70E - 00 00                 - add [rax],al
27C38DFE710 - 55                    - push rbp
27C38DFE711 - 48 8B EC              - mov rbp,rsp
27C38DFE714 - 48 83 EC 30           - sub rsp,30 { 48 }
27C38DFE718 - 48 89 7D F8           - mov [rbp-08],rdi
27C38DFE71C - 48 8B F9              - mov rdi,rcx
27C38DFE71F - 48 89 55 F0           - mov [rbp-10],rdx
27C38DFE723 - 48 63 8F E0000000     - movsxd  rcx,dword ptr [rdi+000000E0]
27C38DFE72A - 03 4D F0              - add ecx,[rbp-10]
27C38DFE72D - 33 D2                 - xor edx,edx
27C38DFE72F - 41 B8 FFC99A3B        - mov r8d,3B9AC9FF { 0.00 }
27C38DFE735 - 90                    - nop 
27C38DFE736 - 49 BB 401D1F127C020000 - mov r11,0000027C121F1D40 { (686588744) }
27C38DFE740 - 41 FF D3              - call r11
27C38DFE743 - 89 87 E0000000        - mov [rdi+000000E0],eax

there's one a little above where i can show on one page, but it adds a huge number to eax where i only gained 150 bits (money), so it can't/shouldn't be that.

However, I can see one line that after a google, seems likely to be key to the issue. The one where it says "call r11". Please help me if my google has failed me, but "call r11" makes it move to the opcode at address r11. Hypothetically that should just be the part of the code where things are happening, so I should go there to see what's going on. Back in my "find what writes to" i can see in the more information page "R11=0000027C121F1D40", so it should be going to that address. Right click in memory viewer, Go to address, 27C121F1D40, aaand... i'm taken to this:

Code: Select all

27C121F1D40 - 48 83 EC 28           - sub rsp,28 { 40 }
27C121F1D44 - 48 89 34 24           - mov [rsp],rsi
27C121F1D48 - 48 89 7C 24 08        - mov [rsp+08],rdi
27C121F1D4D - 4C 89 7C 24 10        - mov [rsp+10],r15
27C121F1D52 - 4C 8B F9              - mov r15,rcx
27C121F1D55 - 48 8B FA              - mov rdi,rdx
27C121F1D58 - 49 8B F0              - mov rsi,r8
27C121F1D5B - 44 3B FF              - cmp r15d,edi
27C121F1D5E - 40 0F9C C0            - setl al
27C121F1D62 - 48 0FB6 C0            - movzx rax,al
27C121F1D66 - 48 0FB6 C0            - movzx rax,al
27C121F1D6A - 85 C0                 - test eax,eax
27C121F1D6C - 74 05                 - je 27C121F1D73
27C121F1D6E - 4C 8B FF              - mov r15,rdi
27C121F1D71 - EB 1B                 - jmp 27C121F1D8E
27C121F1D73 - 44 3B FE              - cmp r15d,esi
27C121F1D76 - 40 0F9F C0            - setg al
27C121F1D7A - 48 0FB6 C0            - movzx rax,al
27C121F1D7E - 48 0FB6 C0            - movzx rax,al
27C121F1D82 - 40 88 44 24 18        - mov [rsp+18],al
27C121F1D87 - 85 C0                 - test eax,eax
27C121F1D89 - 74 03                 - je 27C121F1D8E
27C121F1D8B - 4C 8B FE              - mov r15,rsi
27C121F1D8E - 44 89 7C 24 20        - mov [rsp+20],r15d
27C121F1D93 - 49 8B C7              - mov rax,r15
27C121F1D96 - 48 8B 34 24           - mov rsi,[rsp]
27C121F1D9A - 48 8B 7C 24 08        - mov rdi,[rsp+08]
27C121F1D9F - 4C 8B 7C 24 10        - mov r15,[rsp+10]
27C121F1DA4 - 48 83 C4 28           - add rsp,28 { 40 }
27C121F1DA8 - C3                    - ret 
27C121F1DA9 - 00 00                 - add [rax],al
27C121F1DAB - 00 00                 - add [rax],al
27C121F1DAD - 00 00                 - add [rax],al
27C121F1DAF - 00 01                 - add [rcx],al
27C121F1DB1 - 04 01                 - add al,01 { 1 }
27C121F1DB3 - 00 04 42              - add [rdx+rax*2],al
27C121F1DB6 - 00 00                 - add [rax],al
27C121F1DB8 - 00 00                 - add [rax],al
27C121F1DBA - 00 00                 - add [rax],al
From here I am at an absolute loss. It's taking 28 from 'rsp', and eax, my value of interest, is only being checked if it's zero (or am i misunderstanding the "test eax,eax" line?). I've been googling around trying to make sense of what I'm seeing and failing tragically. Of possible interest, when I was following a similar rabbit hole for how exp is added, I came across the same "call r11" nonsense which leads to the exact same address. However, interestingly the exp is added one at a time and was added four times when I gained four exp.

Code: Select all

27C38DFC407 - BA 01000000           - mov edx,00000001 { 1 }
27C38DFC40C - 66 90                 - nop 2
27C38DFC40E - 49 BB 401D1F127C020000 - mov r11,0000027C121F1D40 { (686588744) }
27C38DFC418 - 41 FF D3              - call r11
27C38DFC41B - 4C 8B F8              - mov r15,rax
27C38DFC41E - 49 8B 46 68           - mov rax,[r14+68]
27C38DFC422 - 48 63 88 A0000000     - movsxd  rcx,dword ptr [rax+000000A0]
27C38DFC429 - 41 03 CF              - add ecx,r15d
27C38DFC42C - 89 88 A0000000        - mov [rax+000000A0],ecx
I actually see it adding the exp there, r15d is 1, r15 being 000000001 and if i remember right from my youtube the "d" is just telling it to only look at the one part of the address to save resources. I don't have any clue how to find where it decides how many times to repeat that loop of adding "one" though, and i'm only like... 80% confident in my interpretation.

Is there anyone who can break down if i'm misunderstanding something with how it works to begin with, or how that bit of code after the "call r11" actually works? I'm not even certain i've properly understood what call r11 is doing, and because it never seems to change the eax i was after I don't know where to begin...

Dodging12
Noobzor
Noobzor
Posts: 14
Joined: Tue Oct 15, 2019 2:01 am
Reputation: 0

Re: [Help] Exp/Money in RPG (Anode Heart)

Post by Dodging12 »

Did you ever make progress on this, by chance? Thanks for outlining your thought process as well.

Dodging12
Noobzor
Noobzor
Posts: 14
Joined: Tue Oct 15, 2019 2:01 am
Reputation: 0

Re: [Help] Exp/Money in RPG (Anode Heart)

Post by Dodging12 »

Meant to update with some research I'd done, since I was playing this game a couple months ago. First, enable mono since this is a Unity game. This lets you know that the AddMoney function is where your `mov rdi+E0, eax` instruction is happening.


A few lines above that, you'll see

Code: Select all

add ecx,[rbp-10]
. If you set a breakpoint there, you'll see that the memory at [rbp-10] contains the amount that you're subtracting or adding to your money total. So if you just multiply that (being aware that it will be negative when you're buying items, and positive for other actions that add to your money), you're set.

In the end, this worked:

Code: Select all

usemono()

[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat



aobscanregion(INJECT,Player:AddMoney+000, Player:AddMoney+42, 03 4D F0 33 D2) // should be unique
alloc(newmem,$1000,INJECT)

label(code)
label(return)
label(positive_case)

newmem:
push eax
mov eax, [rbp-10] // Save amount to add/subtract into eax
cmp eax, 0
jge positive_case

neg eax // Buying items adds money instead of subtracting it

positive_case:
imul eax, #2
mov [rbp-10],eax // store the multiplied value back into rbp-10
pop eax // restore eax
add ecx,[rbp-10]
xor edx,edx
jmp return

code:
  add ecx,[rbp-10]
  xor edx,edx
  jmp return

INJECT:
  jmp newmem
return:
registersymbol(INJECT)

[DISABLE]
//code from here till the end of the code will be used to disable the cheat
INJECT:
  db 03 4D F0 33 D2

unregistersymbol(INJECT)
dealloc(newmem)

User avatar
Send
Expert Cheater
Expert Cheater
Posts: 838
Joined: Fri Feb 02, 2018 5:58 pm
Reputation: 601

Re: [Help] Exp/Money in RPG (Anode Heart)

Post by Send »

Valatros wrote:
Mon Jan 15, 2024 9:28 pm
Dodging12 wrote:
Mon Nov 18, 2024 5:31 pm
Only have access to the demo. Throw a breakpoint on Player:get_Instance+## (instructions should be 'mov rax,[rax+offset]` if it hasn't changed in the full game.) Breakpoint will trigger immediately. GameState is held in RAX.

Image

Copy the register address.
Turn off breakpoint, run game.
Ctrl+D to open dissect. Structures -> Define New Structure.
Expand Player at +28 (Demo)
Money is held at +E0 (Demo)

Image


Here's a script that grabs the money and allows you to edit it in real-time. May need to be adjusted for full game.

Code: Select all

<?xml version="1.0" encoding="utf-8"?>
<CheatTable>
  <CheatEntries>
    <CheatEntry>
      <ID>0</ID>
      <Description>"Grab Money Data"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>//Send
define(address,Player:get_Instance+1b)
define(bytes,48 8B 40 10 48 8B 40 28)

[ENABLE]

assert(address,bytes)
alloc(newmem,$1000,Player:get_Instance+1b)
registersymbol(money)
label(code return)

newmem:
mov [money],rax

code:
  mov rax,[rax+10]
  mov rax,[rax+28]
  jmp return

money:
dq 0

address:
  jmp newmem
  nop 3
return:

[DISABLE]

address:
  db bytes

unregistersymbol(*)
dealloc(*)

</AssemblerScript>
      <CheatEntries>
        <CheatEntry>
          <ID>1</ID>
          <Description>"Money"</Description>
          <VariableType>4 Bytes</VariableType>
          <Address>[money]+10</Address>
          <Offsets>
            <Offset>E0</Offset>
            <Offset>28</Offset>
          </Offsets>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
  </CheatEntries>
</CheatTable>


Dodging12
Noobzor
Noobzor
Posts: 14
Joined: Tue Oct 15, 2019 2:01 am
Reputation: 0

Re: [Help] Exp/Money in RPG (Anode Heart)

Post by Dodging12 »

Send wrote:
Mon Nov 18, 2024 6:30 pm
Valatros wrote:
Mon Jan 15, 2024 9:28 pm
Dodging12 wrote:
Mon Nov 18, 2024 5:31 pm
Only have access to the demo. Throw a breakpoint on Player:get_Instance+## (instructions should be 'mov rax,[rax+offset]` if it hasn't changed in the full game.) Breakpoint will trigger immediately. GameState is held in RAX.

Image

Copy the register address.
Turn off breakpoint, run game.
Ctrl+D to open dissect. Structures -> Define New Structure.
Expand Player at +28 (Demo)
Money is held at +E0 (Demo)

Image



Here's a script that grabs the money and allows you to edit it in real-time. May need to be adjusted for full game.


Thanks. I also found the player instance, but OP asked for a multiplier and I figured it made sense to edit the AddMoney function to add a multiple of the initial amount instead. Do you know a way to do that more efficiently by chance?

Post Reply

Who is online

Users browsing this forum: No registered users