Page 1 of 1

Mono related lua invoke or asm call C# System.String constructor

Posted: Thu Dec 01, 2022 2:56 pm
by peddroelm
I'm trying to add some extra feedback to some Character Info panels for a game that uses IL2CPP ( this would've probably taken 5 minutes with DNSPY otherwise ) ...

Image

Managed to get the parameters of interest calling a mono function that supplies them from ASM ( I'm calling a AOB signature of the function )


// Try call_1
lea r9,[rbp+30] // orig
lea r8,[rbp-50] // orig
mov edx,0000005
mov rcx,rdi
call AOB_BM_f_CharacterInformationsTooltip_getStatInformations

//SAVE [rbp+30] COURAGE !!
mov edx, [rbp+30]
mov [CbtUI_Hover_Courage_Agility_Params], edx // Courage

// Try call_2
lea r9,[rbp+30] // orig
lea r8,[rbp-50] // orig
mov edx,0000001
mov rcx,rdi
call AOB_BM_f_CharacterInformationsTooltip_getStatInformations

//SAVE [rbp+30] AGILITY !!
mov edx, [rbp+30]
mov [CbtUI_Hover_Courage_Agility_Params+4], edx // Agility


those parameters get to lua and I can make lua print this string in console when hovering units in combat


function CbtUI_Hover_Courage_Agility(params)

local Courage = readInteger(params)
local Agility = readInteger(params+0x4)
local CharacterInformationsTooltip = readQword(params+0x100)

local Character = readQword(CharacterInformationsTooltip + 0x160)
local Character_Level = readInteger( readQword(Character + 0x138) +0x40)

print(string.format("LvL:%2d Courage:%2d Agility:%2d", Character_Level, Courage, Agility))
-- sample lua console output
-- LvL: 5 Courage: 9 Agility:14
-- LvL: 3 Courage:30 Agility: 9
-- LvL: 3 Courage:30 Agility: 9

end


But of course I don't want this string in the lua console.. I want it to the

CharacterInformationsTooltip.m_characterLevel(textmeshpro).m_text.Value

to display seamlessly in game when hovering combat units

Image

And here I'm kid of stuck ... I could SIMPLY OVERWRITE CharacterInformationsTooltip.m_characterLevel(textmeshpro).m_text.Value with a Shorter or equal string ..
I can get its address :
UnicodeStringAddr = readQword( readQword( readQword(CharacterInformationsTooltip + 0x90) + 0xC8) + 0x14)

Problem is my string WILL BE LONGER ! (high risk of overwritting stuff ..)

The game does call TMPro.TMP_Text.set_text before ..

// SIMPLER TO INVOKE IN LUA ??

//CALL TMPro.TMP_text.set_text

// R9 or Rax used for calling setText of object using virtual function table

// arguments
// RCX ptr to TextMeshPro object that displays Unit LvL string
// RDX ptr SYSTEM.String object with my unicode string
// R8 get loaded offset of setText addr + 0x8

// call qword ptr [R9+530] // r9 = [[rsi + 90]] where RSI pointer to the CharacterInformationsTooltip
// [RSI+90] ptr to TextMeshPro object that displays Unit LvL string


Problem1
how do I call a constructor of System.String in ASM ? (randomly dig trough traces till I stumble upon an example ? Build c# project and see how the constructor call translates into ASM ? ) ..
To make the string.object argument to be able to call settext from ASM.

Problem2
is it simpler to mono invoke this set text from lua ? (doubt) ..
The parameter is a unicode string which I have.. Do I really need to go digging for functions/method ids when I can easily access the actual function address from my injection point ?

If I put a breakpoint when the hover window is active to get the function settext function addr could I invoke it from LUA engine for test purpose while the game is frozen for test purpose ? Doesn't sound right .. Will probably need to attempt the monoinvokes from my lua script that concatenates the string ..and crash crash crash :) ...

EDIT
Problem3
Simpler still ?
- make a mock? string object struct to pass as argument and see if it works


0 copy the addr pointer from an actual string.object I have access to (should be common for all system.string objects ?)
0x10 put strlen
0x14 put the unicode str

pass address of this struct in rdx , call set text and pray :))

Re: Mono related lua invoke or asm call C# System.String constructor

Posted: Thu Dec 01, 2022 5:49 pm
by peddroelm
What I call an Absolute WIN :P

Image
Image

The UI in this game doesn't auto rescale/ resize with sting length .. Sigh .. Will have to live with shortened string C%2d A%2d

Solution 3 was it ..

fakeSystemString:
dq 0 // vtable ptr
dq 0 // 0
dd 0 // 4 byte strlen
dq 1 // utf-16 string hopefully shorter than 7x10
dq 2
dq 3
dq 4
dq 5
dq 6
dq 7
dq 8
dq 9
dq 10


local str = string.format("LvL:%2d Courage:%2d Agility:%2d", Character_Level, Courage, Agility)

local m_textTextMesh = readQword(CharacterInformationsTooltip + 0x90)
local SystemStringVtable = readQword(readQword(m_textTextMesh + 0xC8))

writeQword(FakeSystemString, SystemStringVtable)
writeInteger(FakeSystemString+0x10, string.len(str) )
writeString(FakeSystemString+0x14 , str, 1)


and set text asm call
// call qword ptr [R9+530] // r9 = [[rdi + 90]] where RDI pointer to the CharacterInformationsTooltip
// [RDI+90] ptr to TextMeshPro object that displays Unit LvL string

mov rcx, [rdi+90] // CharacterInformationsTooltip.m_characterLevel textmeshpro
mov rdx, fakeSystemString
mov r9, [rcx]
mov r8, [r9+538]
call qword ptr [r9+530]



EDIT:
Just occurred to me that the CharacterInformationsTooltip.m_characterDescription HAS ROOM FOR for example 238! characters of pure fluff text ! .. I CAN replace that with A LOT of useful hidden STATS !
Image
description text NOT shown when buffs/debuffs/status effects in play :( .. Maybe I can do something bout that ..

Re: Mono related lua invoke or asm call C# System.String constructor

Posted: Wed Feb 22, 2023 2:40 pm
by Strigger
hey thanks for posting your solution, i'm trying to read and write string in il2cpp game, the game itself is obfuscated so i can't use mono dissect to find which variable i'm looking for, atleast your fake string gave me an idea, thanks again