Infectonator 3 [Tutorial How to use/open .PTR file]

hysspy

hysspy

Expert Cheater
Table Maker
Joined
Aug 24, 2017
Messages
307
I did everything the exact way but the - don't change into numbers
<br />
Yeap that's true just like sir @SunBeam said, the pointer that the scan found aren't stable pointer :D<br />
Let's wait solutions from sir @SunBeam ;)
 
SunBeam

SunBeam

Administrator
Staff member
Administrator
Joined
Feb 4, 2018
Messages
3,481
Alright. Got the game, installed, played a bit, then started investigating (note I'll be using Telerik's JustDecompiler and Cheat Engine). Fired up CE and found my gold amount while at this screen:<br />
<br />
<br />
<br />
Now, debugging the Gold Coins amount shows this in the debug pane (all this happened while purchasing something):<br />
<br />
<br />
<br />
Combined with Mono, I can see which functions each of those lines belongs to:<br />
  • <br />
  • TG_InfoPanelController:UpdateInfo (0x518 offset)<br />
  • TG_StatsUpgradePanel:InfoBuyButtonDownFunction (0x9C offset)<br />
  • TG_LabUIManager:BuySomething (0x1B,0x24 offsets)<br />
  • TG_LabUIManager:UpdateMoneyText (0xA8 offset)<br />
  • etc.<br />
<br />
You get the idea.<br />
<br />
The location where a write happens is TG_LabUIManager:BuySomething function. So.. Ctrl+G > TG_LabUIManager:BuySomething [Enter]. F5 to set a breakpoint at the function's prologue.<br />
<br />
Notes:<br />
  • <br />
  • when you enable a breakpoint, Mono will get disabled - aka you won't see symbols anymore - if that happens, main CE GUI > Mono > Activate mono features)<br />
  • use hardware breakpoints<br />
  • set game in windowed mode<br />
<br />
And we see this:<br />
<br />
<br />
<br />
The yellow highlighted area is what gets executed on write when we buy something (4th line in the previous screenshot, if you remember?). Try to buy something and trace the code as CE breaks:<br />
<br />
<br />
<br />
(see it in full screen)<br />
<br />
So now:<br />
  • <br />
  • my purchase costs 1400 Gold<br />
  • RDX is a function parameter, its value being 0x578 (1400 in decimal)<br />
  • I stopped tracing at a base pointer (mov rax,[15088608])<br />
  • the game code then uses this pointer + an offset (0xC4) to get to Gold Amount (mov [rax+000000C4],ecx)<br />
<br />
So having said that, there's really no reason to use Pointer Scan to find a stable pointer for gold (same logic can be applied to.. uhh.. DNA?). Now let's find out more about this pointer, as CE doesn't say much. On my end, it's 15088608 (on yours it will be different). We want to find a symbol that would take me, you, anyone to its valid reference on each one's PCs ;)<br />
<br />
Resume game (if you've set a breakpoint and game got frozen) and let's fire up Mono > Dissect mono:<br />
<br />
<br />
<br />
Remember our function? TG_LabUIManager:BuySomething. Find it in Assembly-CSharp tree. Here it is for me:<br />
<br />
<br />
<br />
If you now check the 2nd bullet above, where I said RDX is a function parameter.. and then check the blue-yellow highlighted line where it says Buy Something (cost int.).. well.. that's our parameter :) Still no information on that pointer. But we at least learned of the function's parameter.<br />
<br />
Time to run this through JustDecompiler. Open tool up and drag'n'drop Assembly-CSharp.dll onto it (it's in Infectonator3_DataManaged subfolder). And find this exact function in the <Default namespace> references:<br />
<br />
<br />
<br />
And I found it here:<br />
<br />
<br />
<br />
If you now check the function I mentioned, you will see that:<br />
<br />
C++:
<br />
public void BuySomething(int cost)<br />
{<br />
    TG_Static.gameData.UseMoney(cost);<br />
    this.UpdateMoneyText(cost, false);<br />
    if (TG_Static.tutorialState == TG_Static.TutorialState.NONE)<br />
    {<br />
        TG_Static.gameData.AddGameStatisticProgress(TG_GameStatisticData.ConvertToKey(TG_GameStatisticType.SPEND_COIN, string.Empty), (float)cost);<br />
        this.CheckMissionProgress(true);<br />
    }<br />
}<br />
<br />
<br />
<br />
TG_Static.gameData.UseMoney(cost);<br />
<br />
So our pointer will most likely be of TG_GameData type and can be further reviewed in TG_Static namespace. Let's go there with CE:<br />
<br />
<br />
<br />
What you probably didn't know is you can have CE resolve this for you. Right-click on the selected line and do this:<br />
<br />
<br />
<br />
A new script will be added automatically to your table. Just enable it. Normally, CE should pick-up the pointer for you and resolve it; however, since it's acting like a fag, this is what you'll see:<br />
<br />
<br />
<br />
Furthermore, if you disable and re-enable the script, the game will crash. So what's next you'll ask? We have several options to tackle this:<br />
  • <br />
  • find out where this pointer is actively used; to do that, you'll need to debug it on access<br />
  • use the function I referenced with offset to read-up the pointer from the ASM<br />
<br />
Let's do the second one:<br />
<br />
1) Back to our function, Ctrl+G > TG_LabUIManager:BuySomething. Double-click on TG_LabUIManager:BuySomething+10 line. On my end I see this (you will see different):<br />
<br />
Code:
<br />
TG_LabUIManager:BuySomething+10 - 48 8B 04 25 B8D67803  - mov rax,[0378D6B8] { [36A97D68] }<br />
<br />
<br />
<br />
2) If you look at the bytes, starting from the 4th, you will see our pointer backwards: xx xx xx xx B8 D6 78 03 (to be read as 0378D6D8).<br />
<br />
3) Normally, if CE wouldn't be gay this time around as well, you would be able to do this:<br />
<br />
<br />
<br />
And pointer would be valid. We will have to make use of some Lua to be able to properly read the pointer and use it ourselves ;) I'll explain in the below:<br />
  • <br />
  • Memory Viewer > Ctrl+L<br />
  • Lua window opens<br />
<br />
Reproduce this:<br />
<br />
<br />
<br />
What this does is to fetch the function address from the symbols list, apply 0x10 offset, then offset by 0x4, read the pointer from that offset, then offset by 0xC4 and read Gold amount as hexa or decimal.<br />
<br />
BR,<br />
Sun
 
SunBeam

SunBeam

Administrator
Staff member
Administrator
Joined
Feb 4, 2018
Messages
3,481
Try out this table. I've added a function that would scan the TG_LabUIManager:BuySomething function for the location of this line:<br />
<br />
<br />
<br />
Reason for this is people often play various versions of the game, where the JIT-ed code is either compiled differently or that line is at a different offset. The scan function will find that line for you :)<br />
<br />
The script will then do the regular and register a symbol to that pointer. You can now use pGameData + 0xC4 to get to Gold Coins :p<br />
<br />
<br />
<br />
^ Already in the table.<br />
<br />
BR,<br />
Sun
 
SunBeam

SunBeam

Administrator
Staff member
Administrator
Joined
Feb 4, 2018
Messages
3,481
Correction: CE isn't gay. It's just resolving static fields with the available option doesn't take into account if a game is x86 or x64. It will always add to list the x86 script. See this issue.<br />
<br />
Here's the x64 variant which would resolve that pointer:<br />
<br />
Code:
<br />
[ENABLE]<br />
<br />
alloc( TG_Static.gameData.threadstart, 0x1000 )<br />
createthread( TG_Static.gameData.threadstart )<br />
registersymbol( TG_Static.gameData.threadstart )<br />
label( classname )<br />
label( namespace )<br />
label( assemblyname )<br />
label( fieldname )<br />
label( status )<br />
label( domain )<br />
label( assembly )<br />
label( field )<br />
label( TG_Static.gameData )<br />
registersymbol( TG_Static.gameData )<br />
label( TG_Static.gameData.threadexit )<br />
<br />
TG_Static.gameData.threadstart:<br />
sub rsp,28<br />
mov [TG_Static.gameData],0<br />
call mono.mono_get_root_domain<br />
test rax,rax<br />
je TG_Static.gameData.threadexit<br />
  mov [domain],rax<br />
  mov rcx,rax<br />
  call mono.mono_thread_attach<br />
  mov rdx,status<br />
  mov rcx,assemblyname<br />
  call mono.mono_assembly_load_with_partial_name<br />
  test rax,rax<br />
  je TG_Static.gameData.threadexit<br />
    mov rcx,rax<br />
    call mono.mono_assembly_get_image<br />
    test rax,rax<br />
    je TG_Static.gameData.threadexit<br />
      mov [assembly], rax<br />
      mov r8,classname<br />
      mov rdx,namespace<br />
      mov rcx,rax<br />
      call mono.mono_class_from_name_case<br />
      test rax,rax<br />
      je TG_Static.gameData.threadexit<br />
        mov rdx,fieldname<br />
        mov rcx,eax<br />
        call mono.mono_class_get_field_from_name<br />
        test rax,rax<br />
        je TG_Static.gameData.threadexit<br />
          mov [field],rax<br />
          mov rcx,rax<br />
          call mono.mono_field_get_parent<br />
          test rax,rax<br />
          je TG_Static.gameData.threadexit<br />
            mov rdx,rax<br />
            mov rcx,[domain]<br />
            call mono.mono_class_vtable<br />
            test rax,rax<br />
            je TG_Static.gameData.threadexit<br />
              mov rcx,rax<br />
              call mono.mono_vtable_get_static_field_data<br />
              test rax,rax<br />
              je TG_Static.gameData.threadexit<br />
                mov rbx,rax<br />
                mov rcx,[field]<br />
                call mono.mono_field_get_offset<br />
                add rbx,rax<br />
                mov [TG_Static.gameData],rbx<br />
TG_Static.gameData.threadexit:<br />
add rsp,28<br />
ret<br />
<br />
//////////////////<br />
// Data section //<br />
//////////////////<br />
<br />
TG_Static.gameData:<br />
dq 0<br />
assemblyname:<br />
db 'Assembly-CSharp',0<br />
namespace:<br />
db '',0<br />
classname:<br />
db 'TG_Static',0<br />
fieldname:<br />
db 'gameData',0<br />
status:<br />
dq 0<br />
domain:<br />
dq 0<br />
assembly:<br />
dq 0<br />
field:<br />
dq 0<br />
<br />
[DISABLE]<br />
<br />
unregistersymbol( TG_Static.gameData )<br />
dealloc( TG_Static.gameData.threadstart )<br />
unregistersymbol( TG_Static.gameData.threadstart )<br />
<br />
<br />
<br />
<br />
<br />
So now you can do this:<br />
<br />
<br />
<br />
There you have it, 2 methods to deal with this :p<br />
<br />
In the future, when you want to resolve x64 Mono static fields, just do:<br />
<br />
<br />
<br />
Then copy-paste my script and fix the strings accordingly (as per the ones you want resolved); these:<br />
<br />
Code:
<br />
assemblyname:<br />
db 'Assembly-CSharp',0<br />
namespace:<br />
db '',0<br />
classname:<br />
db 'TG_Static',0<br />
fieldname:<br />
db 'gameData',0<br />
<br />
<br />
<br />
BR,<br />
Sun
 
SunBeam

SunBeam

Administrator
Staff member
Administrator
Joined
Feb 4, 2018
Messages
3,481
..and DNA is at 0xCC offset:<br />
<br />
<br />
<br />
BR,<br />
Sun
 
Top