-
Notifications
You must be signed in to change notification settings - Fork 191
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
vitualAddress of generic method #1
Comments
Hi @samogot, thanks for pointing this out. I'll be honest, I absolutely do not have enough knowledge to completely understand how IL's ecosystem works. Also a bit of time has passed since I wrote this.
Generic methods are not really a thing in IL code. Basically, a new method is generated for each class List<T> {
T get(int index);
} becomes class List<int> {
int get(int index);
}
class List<Foo> {
Foo get(int index);
}
// ... In the compiled result,
This is interesting. Does it always happens? Because as far as I can remember, this is not true.
As you said, if you want to get the
I'm sorry, I don't know a thing about closed / open generic methods. I also don't rely on C# methods or types (e.g
IL2CPP's ( |
Now when you gave an example with int and object I understand that most likely several versions of function code will be generated for basic type instatiations (int, boolean, etc.), maybe even for other value-types. Although I believe that for all object types there will be only one version of function code - additional type data is stored as
"closed" is a specific instantiation (ex
I don't entirely agree. The problem isn't between different languages (C# vs IL) but between different runtimes (.NET/Mono/Il2Cpp). Il2Cpp does have MakeGenericType/MakeGenericMethod and it should work as long as parameter types provided in runtime match one of existing instantiations during compile time. I looked into decompiled code of it, but it's too complex to grasp it and reimplement in CModule
To be able to call MakeGenericType.
So basically the root of my problem is how to get this 'instanced' versions. They are not listed in |
Thank you for the further explanation. Generic 'instanced' classes are not listed in By the way, would you post a minimal example to reproduce the "issue" you are facing? I played around with generics too (few months ago), I honestly didn't have any serious problem with them (maybe I didn't dig enough). Thanks! |
class Data {}
inteface InterfaceA<T>
{
public T method0();
}
class ClassA<T> : InterfaceA<T>
{
public T method0() { }
public T method1() { }
}
class ClassB<T>
{
public T method2() { }
}
class ClassBChild : ClassB<Data>
{
}
class ClassC
{
public E method3<E>() { }
public Data method4() { return method3<Data>(); }
}
class Factory
{
public InterfaceA<Data> getA() { return new ClassA<Data>(); }
public ClassBChild getB() {}
public ClassC getC() {}
} Let's say we have classes like this. I want to intercept each method.
PS: I haven't actually tried to compile the code above :) But it should be good enough as a pseudocode to showcase the problem |
No, they aren't. They mostly behaves like an abstract class, an interface only contains method definitions.
Yup, this is how I used to do it:
Also correct:
This also seems correct. Does this "pattern" happens in a common assembly / namespace (e.g. |
I guess any generic container should work. Ideally I'm looking for more robust solution that relies on internal reflection metadata rather than on specific usages of the class from other places (return type, subclasses etc.) Before I found this bridge packet, I used to first extract metadata from |
@samogot Also, please notice that few applications have their However, it should be possible to handle generics better, but unfortunately this Frida module didn't get a decent followage/support to justify the extra required amount of work. Anyway thank you again for pointing this issue out, it's always nice to see people taking care of your things! 😃 |
Ok today I took a closer look, and I remembered why this isn't possible.
Now, these structs (you can see them here) don't contain the information needed to obtain the instanced methods. Sure, there may be spicy data, but keep in mind we don't have the metadata table, so any "indexed" value is just useless ( However, another solution could be:
We should be able to seek all the "instanced" generic classes (like However, it seems impossible to do: |
Finally fixed. See https://github.com/vfsfitvnm/frida-il2cpp-bridge#generics-handling |
Thanks! I'm not actively work on project where I needed that, but it would be helpful if I'll need to do something new there. I went to see how this was implemented. So apparently there were some exposed native il2cpp methods to convert between |
Yep, I just noticed |
I've noticed that
actualPointer
of generic methods and all methods in generic classes are null and it is impossible to do anything with them.As a workaround for methods of generic classes I look for any successor with specified types and take
parent
from it. This doesn't work if the class has no successors or for generic methods.As per https://www.codeproject.com/Articles/22088/Reflecting-on-Generics, there is difference between open and closed generic methods and
actualPointer
is only valid for closed ones. There areSystem.Type.MakeGenericType
andSystem.MethodInfo.MakeGenericMethod
methods to get closed versions from open ones. But is unclear to me how to convert betweenIl2Cpp.Method
/Il2Cpp.Type
andIl2Cpp.Object
of typeSystem.MethodInfo
/System.Type
if this is even possible.System.Type
hasIl2CppType
handle as an internal field, so it will be possible to convert this way, but the other way around is much harder without simple public constructor (I'm even not sure if it's supposed to be constructed or each type is a singleton and there is a global cache for them)Alternatively it should be useful to just list all available closed instantiations and to be able to select one with
Accessor
.Alternatively, as far as I can see, all different instantiations of a method has the same
actualPointer
value, so it would be very convenient to recognize the fact that the method is generic and just pickactualPointer
value from any of instantiations automatically instead of returning null.The text was updated successfully, but these errors were encountered: