-
Notifications
You must be signed in to change notification settings - Fork 167
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
Realm Obfuscation (Unity + Local Database) #3574
Comments
➤ PM Bot commented: Jira ticket: RNET-1134 |
What tool are you using for obfuscation? I guess the main question is if it's running before or after the Realm weaver, because if it's running after, I would expect things to work just fine. One thing we do use reflection for is the generated |
Hi Nikola, Many thanks for the reply. The tool (that I'm currently evaluating) is the Beebyte obfuscator. There are others under consideration, but let's stick with this one for now. If I extract the woven 'proxy' from the Mono DLL, the class & property names are clearly obfuscated, which I had assumed to mean the obfuscation was occurring after weaving (during build) If it helps, I can send the 'proxy' of a test Realm object before (i.e., weaved in the Unity editor) and after (i.e., weaved during build). If so, let me know where to E-mail it to. As for RealmSchema, I don't believe that would be the issue. The Realm package is (from what I can tell) stored in a separate assembly that is currently un-obfuscated. I wanted to get the basics working before turning to obfuscating third party tools. Looking at the obfuscation translation table, the only reference to Realm (other than my own classes) is RealmModuleInitializer |
Yeah, it'd be helpful if you could share those dlls to nikola.irinchev@mongodb.com. I'm assuming you're using the source generator based models - i.e. your models implement
RealmSchema property. This is not a real solution as regenerating the file will remove your changes, but we could at least try and see if it works.
One thing I can see that won't work correctly is property change notifications. Those use strings generated at compile time, so if you take advantage of it, after obfuscation, the names in the property change event handler won't match the obfuscated names of the class. |
OK, let me do some more research (with RealmSchema) and I'll message back in the next day or two. In answer to your question, yes I'm using IRealmObject and not inheriting from RealmObject I quickly looked at the Realm "C:\Users<user>\AppData\Local\Temp\VSGeneratedDocuments<id>\ClassName_generated.cs" proxy file and could not find the code you posted above. I found the below though, is that what you're referring to?
That was from an IRealmObject decorated with MapTo attributes (for the obfuscated names) As for the property change events, that may not be an issue here. I'm using mapped names that would otherwise match the obfuscated names. That said, I'm not using those events (yet) so haven't proved that theory. Thanks again for the rapid response, it's much appreciated. |
Hi Nikola, I've looked a little deeper into the RealmSchema suggestion and I think you're right, this could be the issue. Going on your code link above, Realm is looking for a field called "RealmSchema" by means of a magic string. I rebuilt the app in question with Realm obfuscation enabled and the static property now looks like this (extracted from a Mono build using dotPeek)...
We can see the obfuscator has renamed "RealmSchema" to "MPCIFIMONMC" therefore triggering the exception at line 283 from the code link you posted above. Ok, so to test the theory I need to compile the app and somehow exclude the "RealmSchema" field from obfuscation. The obfuscator allows classes to be excluded by means of an editor setting or an attribute. Class members can only be excluded by means of an attribute. So the only way to exclude "RealmSchema" from obfuscation is by using an attribute. Unfortunately custom attributes don't carry across to the woven proxies and even if they did, the "RealmSchema" field is not something under control of the app. Assuming the attribute could somehow be added, the obfuscator supports custom attributes [Skip] & [SkipRename] that do similar things. So one of those could be added, but obviously they couldn't exist in Realm production. It might be possible to inject one via code in the build pipeline, but I think that'll be a huge amount of work for a simple test. However the obfuscator also supports the standard dot net obfuscation attributes... [System.Reflection.Obfuscation] So Realm could theoretically decorate the "RealmSchema" field with a [System.Reflection.Obfuscation] attribute (that defaults to exclude true) and it'll work for everyone. During the build process, Realm weaving certainly appears to run before obfuscation (according to the console). So even if I could add it before building, I expect it'll be overwritten during build weaving? On-top of that, if I "Find All References" to MyRealmObject in Visual Studio, it shows the generated Realm proxy file, but it's marked as auto generated and is zero bytes. So it looks like there's some VS magic going on there and doesn't appear to be editable. Other possibilities are maybe using nameof() instead of a magic string (to lookup the field) or allowing the magic string value to be customisable somehow. Hopefully this all helps, but if there's anything else you need just say and I'll do what I can. |
Hey sorry for the delay, I had a family thing end of last week. The problem with I'll try and update the generator to add |
Hey @nirinchev Many thanks for the update. Understood about using nameof(). I dived deeper into the code yesterday and see what you mean. You're just dealing with Type at that point and trying to have even minimal strong typing, would likely involve substantial changes. Thanks so much for taking the time to implement a potential workaround, it's really appreciated. I'm using the tarball package (V12.0.0) so not sure if it's possible to send an updated version of that? It might be easier to send the relevant updated DLL (i.e., in the library package cache) but have a feeling Unity will restore any cache files (from the package) if they detect hash deltas. Either way, I'll send you a mail and include some extra obfuscator info that may be of help. |
Hey, really sorry for the delay here - this fell a bit between the cracks. I've tried adding the attribute and built this package - can you give it a shot and see if that fixes the obfuscation problems: https://drive.google.com/file/d/1qgu3YfUktWajHk_d9OWGkRYbmStPQF6J/view?usp=share_link |
Hey @nirinchev No problems at all, assumed this was low priority. So I've just run a very quick test and it appears to have addressed the issue above...
So far so good :-) That said, I've only tested very limited functionality (e.g., reading, writing, deleting, compacting) for one record type, not multiple types and not property change events etc. So I need to perform wider tests, but this is a step in the right direction. Going forward (and assuming this does resolve the issue) is this something that Realm would be comfortable committing to production? At the very least, it would be nice if another external developer (either using the same or another Obfuscator) could confirm these findings. Thanks so much for all your efforts so far, it's greatly appreciated. PS: When I have time in the next week, I'll post an example of an obfuscated RealmSchema property. |
Yes, we'd be happy to merge that PR - it's fairly trivial one and I don't see risks for regressions there. |
Great, thanks! I have a (full) Realm obfuscated build on a device now and will test it over the next week and report back. |
Quick update... performed further tests on both Mono & IL2CPP (device) builds and so far so good. Zero issues to report. Will test some more over the weekend, so by early next week I'll be able to report final results. But it's looking good. |
Hey @nirinchev Testing over the weekend uncovered zero issues with obfuscated Realms (Mono & IL2CPP builds) but with some caveats...
So with that in mind, this change gets the thumbs up from me. That said, I would personally label obfuscation support as experimental for the time being (if at all). But it's a great step in the right direction (and a very worthwhile feature addition to Realm imho) Anything else you need, please just ask and I'll try and help out as best as possible. Thanks again for all your time & effort with this, it's greatly appreciated :-) |
Hey, thanks for the thorough testing done - I'll move forward and get that merged and ready for next official release. One thing I'm curious is if you're explicitly specifying the schema in your realm configuration - i.e. do you have something like: var config = new RealmConfiguration
{
schema = new[] { typeof(Foo), typeof(Bar) }
} Based on some guesswork, I had assumed that without it, you would get an empty schema, but perhaps I've missed something. As for the status of obfuscation support - we'll likely release as is and not explicitly document it as it's not a topic that has come up often enough. It's a best-effort type of support and we'd be happy to work with you and other members of the community to fix bugs and/or add annotations as long as they're general-purpose enough. |
Yes that's exactly how I'm declaring Realm types. But once the codebase is obfuscated (during build) you'll end up with something like this...
Realm proxy class method & property names will also be obfuscated (as above) On-top of that, persisted properties are also decorated with MapTo attributes (set to equally obfuscated names) Re obfuscation support, I think that's a very sensible way forward. To support the numerous obfuscation tools out there across all aspects of database management would be a big undertaking imo. That's what I liked about the Obfuscation attribute approach as it's Dot Net generic, albeit obfuscators aren't obligated to support it. Thanks again for everything and I'll post again if there's anything further to add. |
Problem
Hello!
I've recently integrated obfuscation into an application and hit a number of issues, mostly regarding Realm objects (i.e., IRealmObject)
The Realms are encrypted (no issues there) but I am also wanting to obfuscate Realm object & property names.
Initially I tried to use the obfuscation tool to achieve this (so the obfuscator changed the woven Realm 'proxy' classes) but this resulted in the following issue...
https://www.mongodb.com/docs/atlas/device-sdks/sdk/dotnet/troubleshooting/#resolve-a--no-properties-in-class--exception
After much trial and error, the only way I can obfuscate the Realm aspect of the app is to...
But the limitation\issue with this approach is that...
The obfuscation tool that I'm using obfuscates mostly by means of attributes. I had hoped these would carry across to their counterparts on the woven 'proxies' but this doesn't seem to be the case.
So I'm wondering if there is a known workaround? If not, could this be considered for a feature request please?
Solution
Couldn't the woven 'proxies' be generated using the mapped names? They currently do, but only as attributes with literal strings. Class & property names still use their un-mapped names.
Alternatives
I'm considering a brute force approach of using explicit obfuscated names (for Realm objects & properties) but this means uncompiled code becomes far less readable and is really an absolute last resort.
How important is this improvement for you?
Would be a major improvement
Feature would mainly be used with
Local Database only
The text was updated successfully, but these errors were encountered: