Help! il2cpp c++ creating generics

PeteSpencer

Platinian
Original poster
Oct 20, 2023
14
0
1
35
Hey,
I am new to GameHacking and new to c++. So possibly I am just not good enough to understand whats going on.

The goal:
The game I am trying to mod is full of protobufs. One often used types is Google.protobuf.Collections.RepeatedField
I want to create a new working instance of a RepeatedField<Glyph>

First steps:
I made my first stepts in Frida to get a view of whats happaning ingame.
I got a working solution thankfully with the option to `inflate` with the `frida-il2cpp-bridge`.

The code for my specific RepeatedField looks like this:
JavaScript:
  class RepeatedFieldGlyphs extends BaseWrapper {
    constructor(instace?: Il2Cpp.Object) {
      let obj: Il2Cpp.Object;
      if (instace) {
        obj = instace;
      } else {
        const newInstance = RepeatedFieldGlyphs.Klass.initialize().alloc();
        newInstance.method('.ctor').invoke();
        obj = newInstance;
      }
      super(obj);
    }

    @Cacheable()
    static get Klass() {
      return getClass('RepeatedField`1', 'Google.Protobuf')?.inflate(Glyph.Klass)!;
    }

    add = (glyph: Glyph) => {
      this.object.method('Add').invoke(glyph.object);
    };
  }

  const myRepeatedField = new RepeatedFieldGlyphs(); // just creates a new instance
Magic Inflation `return getClass('RepeatedField`1', 'Google.Protobuf')?.inflate(Glyph.Klass)!;`

I know that the compiled code in c++ actually have no generics like RepeatedField with generics. But If I log out the class and namespace it returns also RepeatedField`1 by the namespace: `Google.protobuf.Collections.RepeatedField`.
My try to do so in c++ with some il2cpp-api-function help looks terrible for now. But this is my try:


C++:
        auto assemblyGoogleProtobuf = il2cpp_domain_assembly_open(domain, "Google.Protobuf");
        auto googleProtoImage = il2cpp_assembly_get_image(assemblyGoogleProtobuf);

        auto assemblyGameCore = il2cpp_domain_assembly_open(domain, "Game.Core");
        auto assemblyGameCoreImage = il2cpp_assembly_get_image(assemblyGameCore);

        Il2CppClass* repeatedFieldClass = il2cpp_class_from_name(googleProtoImage, "Google.Protobuf.Collections", "RepeatedField`1");
        if (repeatedFieldClass) {
            LOGD("repeatedFieldClass found: %i", repeatedFieldClass->is_generic);
            const MethodInfo* constructor = il2cpp_class_get_method_from_name(repeatedFieldClass, ".ctor", 0);
            if (constructor) {
                LOGD("constructor found");
                Il2CppClass* genericType = il2cpp_class_from_name(assemblyGameCoreImage, "Game.Core.Rpc.RpcUtil", "PKNEMGEEPLL");

                if (genericType) {
                    LOGD("Type found");
                    Il2CppArray* typeArgs = il2cpp_array_new(genericType, 1);

                    LOGD("create new instance");
                    Il2CppObject* instanceRepeated = il2cpp_object_new(repeatedFieldClass);
                    void* constructorParameters[1] = { typeArgs };
                    LOGD("invoking constructor");
                    // Its crashing while invoking the constructor
                    il2cpp_runtime_invoke(constructor, instanceRepeated, constructorParameters, nullptr);

                    LOGD("instance of class: %s", instanceRepeated->klass->name);
                }
            }
        }
I see the first error is that RepeatedField`1 has no constructor params.
But how to inflate or create a RepeatedField of a specific type anyway?

I really would like to know how to do so :(
Don't want to stick to frida-scripts xD


#Discord: pete.spencer
 
Last edited:

mIsmanXP

Approved Modder
Approved Modder
Feb 20, 2022
207
10,558
1,193
Republic of Indonesia
Does il2cpp_runtime_invoke work for normal method?
I never actually got it working so i just cast the methodPointer to function pointer


C++:
    using Invoker = T (*)(Il2CppObject *, MethodInfo *);
    //auto address = _getHookedMap((uintptr_t)this->methodPointer); //edited
    auto address = this->methodPointer; //this = MethodInfo
    auto invoker = reinterpret_cast<Invoker>(address);
    return invoker(instance, this);
 
Last edited:
  • Like
Reactions: PeteSpencer

PeteSpencer

Platinian
Original poster
Oct 20, 2023
14
0
1
35
That looks awesome and really helpful. Will give you feedback later. Thank you very mich for sharing!