Hi! Did I understand it right that kotlin-reflect ...
# reflect
i
Hi! Did I understand it right that kotlin-reflect extracts information about class (for example member names) from its
@Metadata
annotation? Because I can extract class member original names even if ProGuard/R8 has obfusacted the class. Does it make reverse engineering easier because bytecode of the class contains information about its members in
@Metadata
annotation?
d
Yes,
@Metadata
contains detailed information about the class. You can test what exactly is contained using https://github.com/JetBrains/kotlin/blob/master/libraries/kotlinx-metadata/jvm/ReadMe.md
i
The library you pointed is working with .class files but I mean reflection working at runtime. Does reflection use the same mechanism?
d
Yes, reflection also reads data from the metadata descriptor.
i
Does it break the idea of code obfuscation? Because possible attacker can extract all information about class. For instance with the library from above.
d
You would have to instruct your obfuscator to remove @Metadata.
i
But what if using some library like Moshi or another that works with reflection? For example
primaryConstructor
property of
KClass
returns
null
if
@Metadata
is shrinked by ProGuard/R8. So Moshi will not work in that conditions.
d
That is true.
primaryConstructor
will work after obfuscation, because constructors cannot be renamed. But other reflective operations will fail anyways, because the names in
@Metadata
do not match the actual names of your members anymore.
i
primaryConstructor
returns
null
because flag indicating primary constructor is also inside
@Metadata
annotation. But if I try to get class properties with, for example,
declaredMemberProperties
the I get properties with their original names even if ProGuard/R8 turned and
@Metadata
is preserved.
d
Yes, you will get them, but accessing them (e.g. calling
get()
) is probably not going to work, because it cant find the actual field/method to access
i
Yes, you’re right. Just checked it out in test project.
But it’s quite confusing
d
Obfuscation has many problems, you have to be aware of them. Reflection is always a problematic area
i
So it seems that I need to
-keep
all class members without any obfuscation to get it work properly.
d
It depends on what you want to achieve exactly.
i
I am working on library like Moshi but not for JSON. So I need to serialize/deserialize instances to/from some representation. My library does it in runtime via reflection. So if I keep
@Metadata
annotation but allow R8 to rename class members it won’t work because of reason you’ve described above (https://kotlinlang.slack.com/archives/C0AVAB92L/p1578659941007300?thread_ts=1578657597.005400&cid=C0AVAB92L)
d
Yes, if you use reflection at runtime you do need to keep those members.
i
To be more precise - not only keep members but their names too
d
Yes, that's what I meant, sorry
i
Thank you for fast and complete responses. I figured out what I want.
t
@int02h the latest ProGuard beta has extended support for processing Kotlin metadata so that you don't need to keep classes/members that you want to reflect on anymore: https://www.guardsquare.com/en/products/proguard/proguard-manual-kotlin-beta maybe that's useful for your case?
i
@Tim Van Den Broecke looks exciting. But I develop for Android and thus I use R8 instead of ProGuard actually. R8 seems to be completely compatible with ProGuard but this feature is in beta right now so I’m not sure when it become available in R8. But thank you. I will keep my eye on the updates of ProGuard/R8.