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

Post here (make sure thread doesn't exist first) any type of tutorials: text, images, videos or oriented discussions on specific games. No online-related discussions/posts OR warez!
User avatar
hysspy
Table Makers
Table Makers
Posts: 307
Joined: Thu Aug 24, 2017 6:09 pm
Reputation: 90

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

Post by hysspy » Wed May 23, 2018 4:05 am

[QUOTE="Sup3rshokwav3, post: 46702, member: 17551"]I did everything the exact way but the - don't change into numbers[/QUOTE]

Yeap that's true just like sir [USER=12587]@SunBeam[/USER] said, the pointer that the scan found aren't stable pointer :D

Let's wait solutions from sir [USER=12587]@SunBeam[/USER] ;)
Image

User avatar
SunBeam
Administration
Administration
Posts: 1725
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 355

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

Post by SunBeam » Wed May 23, 2018 12:06 pm

Alright. Got the game, installed, played a bit, then started investigating (note I'll be using [B]Telerik[/B]'s [B]JustDecompiler[/B] and [B]Cheat Engine[/B]). Fired up CE and found my gold amount while at this screen:



[IMG]https://i.imgur.com/BIuKxlD.png[/IMG]



Now, debugging the [B]Gold Coins[/B] amount shows this in the debug pane (all this happened while purchasing something):



[IMG]https://i.imgur.com/EU6pMrG.png[/IMG]



Combined with Mono, I can see which functions each of those lines belongs to:

[LIST]

[*]TG_InfoPanelController:UpdateInfo (0x518 offset)

[*]TG_StatsUpgradePanel:InfoBuyButtonDownFunction (0x9C offset)

[*]TG_LabUIManager:BuySomething (0x1B,0x24 offsets)

[*]TG_LabUIManager:UpdateMoneyText (0xA8 offset)

[*]etc.

[/LIST]

You get the idea.



The location where a [B]write[/B] happens is [I]TG_LabUIManager:BuySomething[/I] function. So.. Ctrl+G > TG_LabUIManager:BuySomething [Enter]. F5 to set a breakpoint at the function's prologue.



Notes:

[LIST]

[*]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)

[*]use [I]hardware breakpoints[/I]

[*]set game in [B]windowed mode[/B]

[/LIST]

And we see this:



[IMG]https://i.imgur.com/4sHHkg8.png[/IMG]



The yellow highlighted area is what gets executed on [I]write[/I] when we buy something (4th line in the previous screenshot, if you remember?). Try to buy something and trace the code as CE breaks:



[IMG]https://i.imgur.com/8QuKFRP.png[/IMG]



[SIZE=2](see it in full screen)[/SIZE]



So now:

[LIST]

[*]my purchase costs 1400 Gold

[*]RDX is a function parameter, its value being 0x578 (1400 in decimal)

[*]I stopped tracing at a base pointer (mov rax,[B][15088608][/B])

[*]the game code then uses this pointer + an offset (0xC4) to get to Gold Amount ([I]mov [rax+000000C4],ecx[/I])

[/LIST]

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 ;)



Resume game (if you've set a breakpoint and game got frozen) and let's fire up Mono > Dissect mono:



[IMG]https://i.imgur.com/eH9e3rO.png[/IMG]



Remember our function? [B]TG_LabUIManager:BuySomething[/B]. Find it in [I]Assembly-CSharp[/I] tree. Here it is for me:



[IMG]https://i.imgur.com/QoNN12A.png[/IMG]



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 [I]Buy Something (cost int.)[/I].. well.. that's our parameter :) Still no information on that pointer. But we at least learned of the function's parameter.



Time to run this through JustDecompiler. Open tool up and drag'n'drop [B]Assembly-CSharp.dll[/B] onto it (it's in [I]Infectonator3_DataManaged[/I] subfolder). And find this exact function in the [I][/I] references:



[IMG]https://i.imgur.com/QhkIi26.png[/IMG]



And I found it here:



[IMG]https://i.imgur.com/D9gmVEQ.png[/IMG]



If you now check the function I mentioned, you will see that:



[code=cpp]

public void BuySomething(int cost)

{

TG_Static.gameData.UseMoney(cost);

this.UpdateMoneyText(cost, false);

if (TG_Static.tutorialState == TG_Static.TutorialState.NONE)

{

TG_Static.gameData.AddGameStatisticProgress(TG_GameStatisticData.ConvertToKey(TG_GameStatisticType.SPEND_COIN, string.Empty), (float)cost);

this.CheckMissionProgress(true);

}

}

[/code]





TG_Static.gameData.UseMoney(cost);



So our pointer will most likely be of [I]TG_GameData [/I]type and can be further reviewed in TG_Static namespace. Let's go there with CE:



[IMG]https://i.imgur.com/6NpBx6i.png[/IMG]



What you probably didn't know is you can have CE resolve this for you. Right-click on the selected line and do this:



[IMG]https://i.imgur.com/MlXTVo0.png[/IMG]



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:



[IMG]https://i.imgur.com/737KVjF.png[/IMG]



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:

[LIST]

[*]find out where this pointer is actively used; to do that, you'll need to debug it on access

[*]use the function I referenced with offset to read-up the pointer from the ASM

[/LIST]

Let's do the second one:



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):



[code]

TG_LabUIManager:BuySomething+10 - 48 8B 04 25 B8D67803 - mov rax,[0378D6B8] { [36A97D68] }

[/code]





2) If you look at the bytes, starting from the 4th, you will see our pointer backwards: xx xx xx xx [B]B8 D6 78 03 [/B](to be read as 0378D6D8).



3) Normally, if CE wouldn't be gay this time around as well, you would be able to do this:



[IMG]https://i.imgur.com/2QBfrem.png[/IMG]



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:

[LIST]

[*]Memory Viewer > Ctrl+L

[*]Lua window opens

[/LIST]

Reproduce this:



[IMG]https://i.imgur.com/o0m7ttw.png[/IMG]



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,

Sun
Last edited by SunBeam on Thu Jan 01, 1970 12:00 am, edited 1 time in total.

User avatar
SunBeam
Administration
Administration
Posts: 1725
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 355

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

Post by SunBeam » Wed May 23, 2018 12:29 pm

Try out this table. I've added a function that would scan the [B]TG_LabUIManager:BuySomething[/B] function for the location of this line:



[img]https://i.imgur.com/HKGnuII.png[/img]



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 :)



The script will then do the regular and register a symbol to that pointer. You can now use [B]pGameData[/B] + 0xC4 to get to [B]Gold Coins[/B] :P



[img]https://i.imgur.com/MLkK09g.png[/img]



^ Already in the table.



BR,

Sun

User avatar
SunBeam
Administration
Administration
Posts: 1725
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 355

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

Post by SunBeam » Wed May 23, 2018 2:10 pm

Correction: CE isn't gay. It's just resolving [B]static fields[/B] 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 [URL='https://github.com/cheat-engine/cheat-engine/issues/221']issue[/URL].



Here's the [B]x64[/B] variant which would resolve that pointer:



[code]

[ENABLE]



alloc( TG_Static.gameData.threadstart, 0x1000 )

createthread( TG_Static.gameData.threadstart )

registersymbol( TG_Static.gameData.threadstart )

label( classname )

label( namespace )

label( assemblyname )

label( fieldname )

label( status )

label( domain )

label( assembly )

label( field )

label( TG_Static.gameData )

registersymbol( TG_Static.gameData )

label( TG_Static.gameData.threadexit )



TG_Static.gameData.threadstart:

sub rsp,28

mov [TG_Static.gameData],0

call mono.mono_get_root_domain

test rax,rax

je TG_Static.gameData.threadexit

mov [domain],rax

mov rcx,rax

call mono.mono_thread_attach

mov rdx,status

mov rcx,assemblyname

call mono.mono_assembly_load_with_partial_name

test rax,rax

je TG_Static.gameData.threadexit

mov rcx,rax

call mono.mono_assembly_get_image

test rax,rax

je TG_Static.gameData.threadexit

mov [assembly], rax

mov r8,classname

mov rdx,namespace

mov rcx,rax

call mono.mono_class_from_name_case

test rax,rax

je TG_Static.gameData.threadexit

mov rdx,fieldname

mov rcx,eax

call mono.mono_class_get_field_from_name

test rax,rax

je TG_Static.gameData.threadexit

mov [field],rax

mov rcx,rax

call mono.mono_field_get_parent

test rax,rax

je TG_Static.gameData.threadexit

mov rdx,rax

mov rcx,[domain]

call mono.mono_class_vtable

test rax,rax

je TG_Static.gameData.threadexit

mov rcx,rax

call mono.mono_vtable_get_static_field_data

test rax,rax

je TG_Static.gameData.threadexit

mov rbx,rax

mov rcx,[field]

call mono.mono_field_get_offset

add rbx,rax

mov [TG_Static.gameData],rbx

TG_Static.gameData.threadexit:

add rsp,28

ret



//////////////////

// Data section //

//////////////////



TG_Static.gameData:

dq 0

assemblyname:

db 'Assembly-CSharp',0

namespace:

db '',0

classname:

db 'TG_Static',0

fieldname:

db 'gameData',0

status:

dq 0

domain:

dq 0

assembly:

dq 0

field:

dq 0



[DISABLE]



unregistersymbol( TG_Static.gameData )

dealloc( TG_Static.gameData.threadstart )

unregistersymbol( TG_Static.gameData.threadstart )

[/code]





[IMG]https://i.imgur.com/4E2InRo.png[/IMG]



So now you can do this:



[IMG]https://i.imgur.com/aRZtx1A.png[/IMG]



There you have it, 2 methods to deal with this :p



In the future, when you want to resolve x64 Mono static fields, just do:



[IMG]https://i.imgur.com/MlXTVo0.png[/IMG]



Then copy-paste my script and fix the [B][I]strings[/I][/B] accordingly (as per the ones you want resolved); these:



[code]

assemblyname:

db 'Assembly-CSharp',0

namespace:

db '',0

classname:

db 'TG_Static',0

fieldname:

db 'gameData',0

[/code]





BR,

Sun
Last edited by SunBeam on Wed May 23, 2018 2:31 pm, edited 4 times in total.

User avatar
SunBeam
Administration
Administration
Posts: 1725
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 355

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

Post by SunBeam » Wed May 23, 2018 2:39 pm

..and [B]DNA[/B] is at [B]0xCC[/B] offset:



[img]https://i.imgur.com/5nC1ZEp.png[/img]



BR,

Sun

User avatar
hysspy
Table Makers
Table Makers
Posts: 307
Joined: Thu Aug 24, 2017 6:09 pm
Reputation: 90

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

Post by hysspy » Wed May 23, 2018 6:42 pm

[QUOTE="SunBeam, post: 46734, member: 12587"]..and [B]DNA[/B] is at [B]0xCC[/B] offset:



[IMG]https://i.imgur.com/5nC1ZEp.png[/IMG]



BR,

Sun[/QUOTE]

Wew sir, this is amazing :D Really Thank you sir [USER=12587]@SunBeam[/USER] ;)
Image

Post Reply

Who is online

Users browsing this forum: No registered users