Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

References to value types are created incorrectly #421

Open
vfsfitvnm opened this issue Oct 29, 2023 Discussed in #420 · 6 comments
Open

References to value types are created incorrectly #421

vfsfitvnm opened this issue Oct 29, 2023 Discussed in #420 · 6 comments
Labels
bug Something isn't working

Comments

@vfsfitvnm
Copy link
Owner

Discussed in #420

Originally posted by keinPlan October 28, 2023
got a problem with a function (UnityVersion 2021.3.22f1).

if i'm calling the function the parameter seems to be passed in a wrong format.

// The Function
System.Void Init(Rk.Rubens.Map.StartMarchCrypt& action);

// STRUCT
struct Rk.Rubens.Map.StartMarchCrypt : System.ValueType
{
    Rk.Rubens.IAtom StartPoint; // 0x10
    Rk.Rubens.IAtom TargetAtom; // 0x18
    System.UInt32 OilCount; // 0x20
    Rk.IList<Rk.Rubens.IAtomHero> TakeHeroes; // 0x28
    System.UInt32 ApproxFinishTime; // 0x30
    System.Void .ctor(Rk.Rubens.IAtom startPoint, Rk.Rubens.IAtom targetAtom, System.UInt32 oilCount, Rk.IList<Rk.Rubens.IAtomHero> takeHeroes, System.UInt32 approxFinishTime); // 0x03682ea0
}

i did replace the implementaion and just read the data from the handle passed:

GAME CALLING:
Handle: ->Rk.Rubens.Map.StartMarchCrypt
HandleType: 0xc2814eeca0
MemDump 7xuint64:

  1967449137824 	// StartPoint
  1968403908576 	// TargetAtom
  1			// OilCount
  1969275494240		// TakeHeroes
  1698436712		// ApproxFinishTime  --- struct Rk.Rubens.Map.StartMarchCrypt END 
  1968609456641	
  8011462212112905538

ME CALLING:
Handle: ->Rk.Rubens.Map.StartMarchCrypt
HandleType: 0x1ca52c92180
MemDump 7xuint64:

  1966467562432 	// il2cpp pointer ? 
  0			// il2cpp pointer ? 
  1962936266352 	// StartPoint
  1968403908576 	// TargetAtom
  1 			// OilCount
  1967398819952 	// TakeHeroes
  30 			// ApproxFinishTime --- struct Rk.Rubens.Map.StartMarchCrypt END 

also can't read fields of struct the game created... but if reading direct from memory the data are there but without the il2cpp pointers at the start.

currently i just overwritte the il2cpp pointer @ the begining of the struct with the struct data befor passing it to the function ... messy but seems to work

@vfsfitvnm vfsfitvnm added the bug Something isn't working label Oct 29, 2023
@vfsfitvnm vfsfitvnm changed the title Something is wrong with structs References to value types are created incorrectly Oct 29, 2023
@vfsfitvnm
Copy link
Owner Author

I'm not 100% the following findings are related to this issue, however, it looks I incorrectly create references:

Given the following IL2CPP code

// System.Int32 System.Decimal::Compare(System.Decimal,System.Decimal)
IL2CPP_EXTERN_C IL2CPP_METHOD_ATTR int32_t Decimal_Compare_m90C94AD2C713181DF0E92B3B6F9D56BD494E862C (Decimal_t44EE9DA309A1BF848308DE4DDFC070CAE6D95EE8  ___d10, Decimal_t44EE9DA309A1BF848308DE4DDFC070CAE6D95EE8  ___d21, const RuntimeMethod* method)
{
	static bool s_Il2CppMethodInitialized;
	if (!s_Il2CppMethodInitialized)
	{
		il2cpp_codegen_initialize_method (Decimal_Compare_m90C94AD2C713181DF0E92B3B6F9D56BD494E862C_MetadataUsageId);
		s_Il2CppMethodInitialized = true;
	}
	{
		IL2CPP_RUNTIME_CLASS_INIT(Decimal_t44EE9DA309A1BF848308DE4DDFC070CAE6D95EE8_il2cpp_TypeInfo_var);
		int32_t L_0 = Decimal_FCallCompare_mC72E1B2721A5D80C32071FE8180EC96259A0A6EA((Decimal_t44EE9DA309A1BF848308DE4DDFC070CAE6D95EE8 *)(&___d10), (Decimal_t44EE9DA309A1BF848308DE4DDFC070CAE6D95EE8 *)(&___d21), /*hidden argument*/NULL);
		return L_0;
	}
}
// System.Int32 System.Decimal::FCallCompare(System.Decimal&,System.Decimal&)
IL2CPP_EXTERN_C IL2CPP_METHOD_ATTR int32_t Decimal_FCallCompare_mC72E1B2721A5D80C32071FE8180EC96259A0A6EA (Decimal_t44EE9DA309A1BF848308DE4DDFC070CAE6D95EE8 * ___d10, Decimal_t44EE9DA309A1BF848308DE4DDFC070CAE6D95EE8 * ___d21, const RuntimeMethod* method)
{
	typedef int32_t (*Decimal_FCallCompare_mC72E1B2721A5D80C32071FE8180EC96259A0A6EA_ftn) (Decimal_t44EE9DA309A1BF848308DE4DDFC070CAE6D95EE8 *, Decimal_t44EE9DA309A1BF848308DE4DDFC070CAE6D95EE8 *);
	using namespace il2cpp::icalls;
	return  ((Decimal_FCallCompare_mC72E1B2721A5D80C32071FE8180EC96259A0A6EA_ftn)mscorlib::System::Decimal::FCallCompare) (___d10, ___d21);
}

the following script

Il2Cpp.perform(() => {
    const Decimal = Il2Cpp.corlib.class("System.Decimal");

    const x = Decimal.alloc().unbox();
    x.method(".ctor").invoke(44);

    const offset = Il2Cpp.corlib.class("System.Int32").valueTypeSize * 2;

    console.log("Direct:", x.handle.add(offset).readInt());
    console.log("frida-il2cpp-bridge reference:", Il2Cpp.reference(x).handle.add(offset).readInt());

    Interceptor.attach(Decimal.method("FCallCompare").virtualAddress, args => {
        console.log("IL2CPP reference:", args[0].add(offset).readInt());
    });

    x.method("CompareTo").overload(Decimal.type.name).invoke(x);
});

logs

Direct: 44
frida-il2cpp-bridge reference: 0 !!! WRONG
IL2CPP reference: 44

@vfsfitvnm
Copy link
Owner Author

@keinPlan
Could you test if the commit above fixes the issue for you? I don't know how you are invoking that method, by the way, so I'm unsure whether this is related to your issue!

@keinPlan
Copy link

No didn't help still got the offset in the object created by me.

Thats the code i use for testing:

    var parameter = _types.StartMarchCrypt.alloc();
    // .ctor(Rk.Rubens.IAtom startPoint, Rk.Rubens.IAtom targetAtom, System.UInt32 oilCount, Rk.IList<Rk.Rubens.IAtomHero> takeHeroes, System.UInt32 approxFinishTime);
    parameter.method(".ctor").invoke(
        // Rk.Rubens.IAtom startPoint
        playerHometown.obj,
        // Rk.Rubens.IAtom targetAtom,
        targets[0].Atom,
        // System.UInt32 oilCount,
        1,
        // Rk.IList<Rk.Rubens.IAtomHero> takeHeroes,
        heroList,
        // System.UInt32 approxFinishTime
        10,
    );

    var cmd = diContainer.method<Il2Cpp.Object>("Instantiate").inflate(_types.StartMarchCryptCommand).invoke(new NativePointer(0));
 
     cmd.method("Init").implementation =  (x) => {     
         var t = (x as Il2Cpp.Reference<Il2Cpp.ValueType>).value;
         console.log("Handle:" + t);
         console.log("HandleType:" + t.handle);
     
         console.log("MemDump:")
         var test1 = new DataView(t.handle.readByteArray(48 + 8 + 8) as ArrayBuffer);
         console.log("StartPoint:       " + test1.getBigInt64(0, true))  // StartPoint
         console.log("TargetAtom:       " + test1.getBigInt64(8, true))  // TargetAtom
         console.log("OilCount:         " + test1.getBigInt64(16, true)) // oil
         console.log("TakeHeroes:       " + test1.getBigInt64(24, true)) // TakeHeroes
         console.log("approxFinishTime: " + test1.getBigInt64(32, true)) // approxFinishTime
         console.log(" :                " + test1.getBigInt64(40, true)) 
         console.log(" :                " + test1.getBigInt64(48, true)) 
      
         console.log("-------")        
     };
     
     cmd.method("Init").invoke(parameter);

@vfsfitvnm
Copy link
Owner Author

Init takes a reference to a struct - but you are passing an object instead.
This is how you should invoke it instead:

cmd.method("Init").invoke(Il2Cpp.reference(parameter.unbox()));

@vfsfitvnm
Copy link
Owner Author

@keinPlan Did it work?

@keinPlan
Copy link

keinPlan commented Nov 1, 2023

yes if you do it properly it's working fine
thx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants