Some Slightly Advanced help: Game runs scripts thr code in VCRuntime Please read.

G

gideon25

Expert Cheater
Table Maker
Joined
Mar 20, 2017
Messages
438
Ok, so the game is called Spacebourne and I would really like to be able to make a proper table. The problem comes from it running everything important from a few opcodes in VCRuntime. And those opcodes access A LOT. So
we have this here (highlighted is our "offensive" code:


So I do a Break and Tracewith conditions with my money address and here I see:


And there is my money amount 55821 or DA0D. So I click on the code just past that first return to see where it goes and I get to this:


Highlighted is the call. So what would be my NEXT step. I mean do I try to get my compares from the address runnunig in Vcruntime? Like using dissect data compare cause I doubt the registers are good for compares. ALSO, do I try to inject AFTER the call to VCruntime or before the call? And where should I get my compares? I would LOOOVVE to take myself to the next level with this so any specific help would be VERY appreciated. I have attached the break and tracefile for anyone who , might want to look at it. THANKS
 

Attachments

cfemen

cfemen

RCE Fanatics
Talents
Table Maker
Joined
Feb 15, 2019
Messages
627
hey,
( at first : i dont have the game, this is about UE4 and MemCopy in generaly)

the call on +75B9AB is used many times, you can see that with a "Find out what addresses this instruction accesses"

call will lead to several functions, and eventually to a call to the MemCopy.

your money address is on RDX (in the MemCopy)
before the call( on +75B9AB ) the registers get parameters
look at +795B995 -> add r8,r15
usually r8 contains the address that will be used on RDX in the MemCopy.

you can use a condition breakpoint(Ctrl+B) -> R8 == 0xRDX_From_MemCopy
now the breakpoint will only break if R8 is holding the address of your money.

so now you can look for a compare.
maybe the stack
maybe some register

or you can backtrace R8.
in your case:
movsxd r8,[RCX+44] -> backtrace this
add r8,15

RCX+44 moves to R8, and something on RCX, and so on.

you know the X64 Calling Convention?

register RCX,RDX,R8,R9 and then stack will be used to give Bool,Short,Int,Long,String,Pointer parameters to functions/methods

one of this registers at the prologue will hold a address that contains the [RCX+44] address.
copy the value of this register.

coz something is calling this function with parameters.
and this parameters are most likely used for more than only this function.
use the stack to find out what is calling, go to this address, and use a condition breakpoint(before the call) on the register that was used to hold the adddress at the prologue of the function.
most likely this call will also be a RAX+xx call.
with the condition breakpoint you can trace every function that is called related to money, and eventually you will find a unqiue function.

inject at this spot and alloc 8 byte to copy the address of the register that is used for the condition breakpoint.

this address can now be used as CMP at the +75B9AB spot ( the address from the prologue parameter register is now usually on R14 or similar)

thats just one of the ways, maybe the call on +75B9AB leads to a function that is already unique if you do a breakpoint on R8 with the RDX MemCopy Address.

i hope this helps you to trace things/ finding related functions / use condition breakpoints :)
 
T

TheByteSize

Expert Cheater
Fearless Donors
Joined
Mar 4, 2017
Messages
241
This remind me of Octopath. That game use UE4 and did same thing.
Since a Break and Trace would lag the game in shared function so here is what I do to help remove the lag until the address is accessed.
I would do injection at this code:
Code:
<i>
</i>mov rax,[rcx]
mov rdx,r9
I assuming the r9 contains the address and pass to rdx right before it call for VCRuntime.
Your injection would looks something like this.
Code:
<i>
</i>newmem:
mov rax,[rcx]
cmp r9,  [address of value]  //ex: cmp r9,16E0E416B54
jne code
mov rdx,r9  //  <-- do a break here.

code:
mov rdx,r9
jmp return
This will help remove the lag on your game until that address get accessed.
Once the game stop(break mode), copy address that RAX has and trace What Access that Address then add a Break and Trace on +75B9B1(jmp call right after return from VCRuntime) then hit F9(un-break game). Now you got two windows with two different methods that trace a same address at the same time. You should find the cross-path somewhere.

Basically, the game read value from Primary place holder then pass it to temporary place holder(in Octopath, it pass the value couple more times) before that value reach the main Procedure/Function that does calculation. So, you would need to do manually break and trace couple times if necessary.

There might be better way to trace it but I do not know.
 
G

gideon25

Expert Cheater
Table Maker
Joined
Mar 20, 2017
Messages
438
cfemen said:
hey,
( at first : i dont have the game, this is about UE4 and MemCopy in generaly)

the call on +75B9AB is used many times, you can see that with a "Find out what addresses this instruction accesses"

call will lead to several functions, and eventually to a call to the MemCopy.

your money address is on RDX (in the MemCopy)
before the call( on +75B9AB ) the registers get parameters
look at +795B995 -> add r8,r15
usually r8 contains the address that will be used on RDX in the MemCopy.

you can use a condition breakpoint(Ctrl+B) -> R8 == 0xRDX_From_MemCopy
now the breakpoint will only break if R8 is holding the address of your money.

so now you can look for a compare.
maybe the stack
maybe some register

or you can backtrace R8.
in your case:
movsxd r8,[RCX+44] -> backtrace this
add r8,15

RCX+44 moves to R8, and something on RCX, and so on.

you know the X64 Calling Convention?

register RCX,RDX,R8,R9 and then stack will be used to give Bool,Short,Int,Long,String,Pointer parameters to functions/methods

one of this registers at the prologue will hold a address that contains the [RCX+44] address.
copy the value of this register.

coz something is calling this function with parameters.
and this parameters are most likely used for more than only this function.
use the stack to find out what is calling, go to this address, and use a condition breakpoint(before the call) on the register that was used to hold the adddress at the prologue of the function.
most likely this call will also be a RAX+xx call.
with the condition breakpoint you can trace every function that is called related to money, and eventually you will find a unqiue function.

inject at this spot and alloc 8 byte to copy the address of the register that is used for the condition breakpoint.

this address can now be used as CMP at the +75B9AB spot ( the address from the prologue parameter register is now usually on R14 or similar)

thats just one of the ways, maybe the call on +75B9AB leads to a function that is already unique if you do a breakpoint on R8 with the RDX MemCopy Address.

i hope this helps you to trace things/ finding related functions / use condition breakpoints :)
I haet to have to ask but could you clean the instructions up a bit and be more specific. That would be GREAT! There are really VERYYY few totorials about this specific theng.
 
G

gideon25

Expert Cheater
Table Maker
Joined
Mar 20, 2017
Messages
438
Yea definitely nee a bit more help. This one is tough!
 
cfemen

cfemen

RCE Fanatics
Talents
Table Maker
Joined
Feb 15, 2019
Messages
627
examples for anyone who is interested

CMP example before the MemCopy:
stack compare would also be possible, but will break at every game update, so how to do a solid CMP?

inject at ASPv3-Win64-Shipping.exe+75B9AB before the MemCopy

R8 contains the address of the money.
RBX contains the struct of the shop

RBX+9B contains always the string "price} TY"

copy the byte for the string into a script, move it to RCX

check is RBX valid?
if yes:
move to RDX the RBX+9B address

call string compare

if return is 0:
move R8 to pMoney

pMoney now contains a pointer to money if the player opens any shop.
the CMP is solid, unless the devs are changing something on the shop struct.

complete script:
Code:
<i>
</i>
[ENABLE]

aobscanmodule(aobBeforeMem,ASPv3-Win64-Shipping.exe,FF 90 C0 02 00 00 E9 ** ** ** ** 48 8B 41 18) // should be unique
alloc(newmem,$1000,"ASPv3-Win64-Shipping.exe"+75C54B)

label(code)
label(return)
label(priceString)

alloc(pMoney,8)
registersymbol(pMoney)

newmem:

code:
  push rcx
  push rdx
  push rax
  mov rcx,priceString
  test rbx,rbx
  je ending
  lea rdx,[rbx]
  add rdx,9B
  call strcmp
  cmp eax,0
  jne ending
  mov [pMoney],r8
  ending:
  pop rax
  pop rdx
  pop rcx
  call qword ptr [rax+000002C0]
  jmp return

priceString:
db 70 72 69 63 65 7D 20 54 59 00

aobBeforeMem:
  jmp newmem
  nop
return:
registersymbol(aobBeforeMem)

[DISABLE]

aobBeforeMem:
  db FF 90 C0 02 00 00

unregistersymbol(aobBeforeMem)
dealloc(newmem)
//

second method:

backtrace R8 to find a spot that is money only (i already explained it at my last post)
inject at the spot and add the offset thats added on R8(before the MemCopy)
move it to pMoney and you will have a pointer to money without opening a shop:
Code:
<i>
</i>
aobscanmodule(aobMoney,ASPv3-Win64-Shipping.exe,48 8B 01 48 8D 54 24 20 FF 90 30 06 00 00 EB) // should be unique
alloc(newmem,$1000,"ASPv3-Win64-Shipping.exe"+155F1F5)

label(code)
label(return)
alloc(pMoney,8)
registersymbol(pMoney)

newmem:

code:
  push rcx
  add rcx,AB4
  mov [pMoney],rcx
  pop rcx
  mov rax,[rcx]
  lea rdx,[rsp+20]
  jmp return

aobMoney:
  jmp newmem
  nop 3
return:
registersymbol(aobMoney)

[DISABLE]

aobMoney:
  db 48 8B 01 48 8D 54 24 20

unregistersymbol(aobMoney)
dealloc(newmem)
thats it :)
 
G

gideon25

Expert Cheater
Table Maker
Joined
Mar 20, 2017
Messages
438
OK so lets look at my attempt to find current energy. First I used my save pointer and find out what write to it:

then I pause game and put a condition breakpoint with RDX using my current energy address:

I get this and we we see that RDX is the address of my current energy.


You noted Earlier that here before going to MEMCopy RDX is actually R8.. So I should go back up here somewhere and do a break and trace on R8 but it should be a conditional break and trace like the others i just did (using my current energy address)? And where should I start the trace in here:[/b]


I feel like I'm missing something..
 
G

gideon25

Expert Cheater
Table Maker
Joined
Mar 20, 2017
Messages
438
Please remember Im JUST learning this stuff so please tell me if ts as conditional break and on what (the register thay contains my current energy for instance). Thanks MAN, This could take my to a whole new level of understanding!
 
notpikachu

notpikachu

Cheater
Fearless Donors
Joined
Apr 1, 2020
Messages
47
Just for the hell of it, I download the game and do some backtracing. Apparently, the easiest value to find is energy as you can shoot it to reduce it and increase naturally by regen. The 100% energy on screen is virtual but somehow I traced it back to VCRuntime :shock: . So, after some testing, the real value would be 400(float) = 100%. Then again, I did saw 400 somewhere in the stack at the 100% function but we already past that :dry: . So, after all the ranting...I arrived right after the ret from VCRuntime.



I'm gonna assume that it will work for other things too such as money and stuffs.
And, create a simple code for energy (tested working on 1.4.8)
Code:
<?xml version="1.0" encoding="utf-8"?>
<CheatTable>
  <CheatEntries>
    <CheatEntry>
      10
      <Description>"InfiniteEnergy"</Description>
      <LastState/>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]
aobscanmodule(energy,ASPv3-Win64-Shipping.exe,4D 03 C7 4C 89 46 38) // should be unique
alloc(newmem,$1000,energy)
label(code)
label(return)
newmem:
  cmp r8,9f8
  jne code
  add r8,r15
  mov [r8],(float)400.0
  mov [rsi+38],r8
  jmp return
code:
  add r8,r15
  mov [rsi+38],r8
  jmp return
energy:
  jmp newmem
  nop 2
return:
registersymbol(energy)
[DISABLE]
energy:
  db 4D 03 C7 4C 89 46 38
unregistersymbol(energy)
dealloc(newmem)

</AssemblerScript>
    </CheatEntry>
  </CheatEntries>
</CheatTable>
Edit1: Nice game btw, never know this game even exist.

Best Regards,
notpikachu
 
G

gideon25

Expert Cheater
Table Maker
Joined
Mar 20, 2017
Messages
438
notpikachu said:
Best Regards,
notpikachu
NICE! In the screenshot you mentioned tracing back all the way until you find the right address that only has access to energy (or to a few addresses). Can you do that with some screenshots and explainations? I ask cause I've been dying to see someone do it steup by step with screenshots explaining things or a video explaining things. And I would really like to see it done on a complicated engine like what this game uses.
 
notpikachu

notpikachu

Cheater
Fearless Donors
Joined
Apr 1, 2020
Messages
47
gideon25 said:
NICE! In the screenshot you mentioned tracing back all the way until you find the right address that only has access to energy (or to a few addresses). Can you do that with some screenshots and explainations? I ask cause I've been dying to see someone do it steup by step with screenshots explaining things or a video explaining things. And I would really like to see it done on a complicated engine like what this game uses.
Its all depend on how you are willing to dig deeper, but going deeper doesn't mean it will yield something. It also depend on the game engine, heck even the same game engine, sometimes the dev strip or add some wacky stuff to their own games. Just for example, last week I reverse nexomon(old game in my hardrive), unity engine, has encryption n stuff, after some dirty bypass and backtracing, the item quantity real values was swimming between the stack and address of registers :| , so for what it worth, its all good times :lol: .

Now, in this case, I did go deeper, but the base address changes way too different than my previous finding. Here's some picture.





Here's a code without compare :~
Code:
<?xml version="1.0" encoding="utf-8"?>
<CheatTable>
  <CheatEntries>
    <CheatEntry>
      15
      <Description>"InfiniteEnergy2"</Description>
      <LastState/>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]
aobscanmodule(energy2,ASPv3-Win64-Shipping.exe,48 8B 01 F2 0F 11 44 24 40 FF 90 B8) // should be unique
alloc(newmem,$1000,energy2)
label(code)
label(return)
newmem:
  mov [rcx+9f8],(float)400.0
  mov rax,[rcx]
  movsd [rsp+40],xmm0
  jmp return
code:
  mov rax,[rcx]
  movsd [rsp+40],xmm0
  jmp return
energy2:
  jmp newmem
  nop 4
return:
registersymbol(energy2)
[DISABLE]
energy2:
  db 48 8B 01 F2 0F 11 44 24 40
unregistersymbol(energy2)
dealloc(newmem)

</AssemblerScript>
    </CheatEntry>
  </CheatEntries>
</CheatTable>
Someone probably can do this wayyy better than me, if so, I don't mind any good advice :) .

Best Regards,
notpikachu
 
G

gideon25

Expert Cheater
Table Maker
Joined
Mar 20, 2017
Messages
438
notpikachu said:
Its all depend on how you are willing to dig deeper, but going deeper doesn't mean it will yield something. It also depend on the game engine, heck even the same game engine, sometimes the dev strip or add some wacky stuff to their own games. Just for example, last week I reverse nexomon(old game in my hardrive), unity engine, has encryption n stuff, after some dirty bypass and backtracing, the item quantity real values was swimming between the stack and address of registers :| , so for what it worth, its all good times :lol: .

Now, in this case, I did go deeper, but the base address changes way too different than my previous finding. Here's some picture.





Here's a code without compare :~
Code:
<?xml version="1.0" encoding="utf-8"?>
<CheatTable>
  <CheatEntries>
    <CheatEntry>
      15
      <Description>"InfiniteEnergy2"</Description>
      <LastState/>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]
aobscanmodule(energy2,ASPv3-Win64-Shipping.exe,48 8B 01 F2 0F 11 44 24 40 FF 90 B8) // should be unique
alloc(newmem,$1000,energy2)
label(code)
label(return)
newmem:
  mov [rcx+9f8],(float)400.0
  mov rax,[rcx]
  movsd [rsp+40],xmm0
  jmp return
code:
  mov rax,[rcx]
  movsd [rsp+40],xmm0
  jmp return
energy2:
  jmp newmem
  nop 4
return:
registersymbol(energy2)
[DISABLE]
energy2:
  db 48 8B 01 F2 0F 11 44 24 40
unregistersymbol(energy2)
dealloc(newmem)

</AssemblerScript>
    </CheatEntry>
  </CheatEntries>
</CheatTable>
Someone probably can do this wayyy better than me, if so, I don't mind any good advice :) .

Best Regards,
notpikachu
Ah, so you got lucky that you did not have to back trace (somehow) into a different function, and then maybe another one, etc. Thanks! Every little bit helps! Yea with this and some other stuff I am gradually learning more and more. Its strange, I'll get lost on a technique or skill (maybe for a long time) but then something *clicks* in my mind and I finally start to get it a little bit. Hopefully that happens with complex back tracing. Thanks again!
 
notpikachu

notpikachu

Cheater
Fearless Donors
Joined
Apr 1, 2020
Messages
47
Nah, I did backtrace like three functions after that ;) . The base address is almost the same, like only difference in hundred, but I guess I give up the chase after I found the for sure method.
 
G

gideon25

Expert Cheater
Table Maker
Joined
Mar 20, 2017
Messages
438
notpikachu said:
Nah, I did backtrace like three functions after that ;) . The base address is almost the same, like only difference in hundred, but I guess I give up the chase after I found the for sure method.
Just curious, but Im doing another one very similar:


and I cannot get it to break and trace on my address above this line:
Shieldwall-Win64-Shipping.exe+6D46E8 - 4C 89 46 38 - mov [rsi+38],r8

using either R8 or r15..
 
notpikachu

notpikachu

Cheater
Fearless Donors
Joined
Apr 1, 2020
Messages
47
Judging by the name, a different game? First, not all game work the same. Then again, what do u mean, cannot break and trace? Is it empty break and trace outcome without condition, or do you put some conditional break and trace? As the game is quite small, Shieldwall yeah? I download it and try break and trace. No problem here :?

 
Top