Zelix Klassmaster

Sergun73

Member
Licensed User
Longtime User
After spending a couple of days playing with Zelix Klassmaster, trial edition, I managed to successfully obfuscate all my critical libs with it.

So I thought I'd outline the process - if you need an obfuscation, read on.

First, I did not obfuscate ALL my B4A project, only critical part of it that I have chosen.

If you need to achieve the same, separate your code logic leaving non-critical, business-logic or UI code in B4A (in VB) - this won't be obfuscated, and place all your critical functionality (or even strings) into separate libraries.

Those separate libraries can either be built from B4A (starting from v2.50) or in Java with Eclipse (I used both types of libs). Next, apply Zelix to your MyLib.Jar, and place the obfuscated library (call it MyLibZ.Jar) into B4A's \Libraries folder. If you need to obfuscate several libraries, obfuscate them all in one run, or otherwise there will be naming collision (all of packages will be 'a', but you need 'a', 'b', 'c' ...).

Next, create your MyLibZ.xml from the existing MyLib.xml, and edit its text: make sure your methods and fields have DesignerName attribute that keeps the old name - if the attribute is missing, just add it. In the same time, manually replace the renamed names in your new xml file with the obfuscated names that you can find in ChangeLog.txt, produced by Zelix.

For example,

ChangeLog says:
Class: MyPackage.MyClass => a.g
MethodsOf: MyPackage.MyClass
private void MyMethod(int) => f

Your original XML says:
<class>
<name>MyPackage.MyClass</name>
<shortname>MyClass</shortname>
<method>
<name>MyMethod</name>

Create a copy of that xml, and edit it as:
<class>
<name>a.g</name>
<shortname>MyClass</shortname>
<method>
<name DesignerName="MyMethod">f</name>

The 'shortname' and 'DesignerName' are like a bridge from the names that B4A sees (MyClass, MyMethod) into internal obfuscated names, which are now different (a, g, f).

Next, from B4A, refresh your libs list and you'll see MyLibZ.Jar next to your MyLib.Jar. Un-check the old lib, check the new one. All the method/field names stay the same as in the original VB code - no need to update it: B4A relies on DesignerName, not on the actual (obfuscated) name within the JAR - and that name is the same. Package name is different, but B4A relies on 'shortname' - and it stays the same. Thus, all you really need is to uncheck the original lib and check the protected one - nothing else.

Next, recompile your project. Test it, make sure all runs as before.

I ran a test in my project - a CPU-intensive operation took 4 min. on my device with the original code, 4 min. 10 sec with the Zelix-obfuscated code using 'light' obfuscation (only names) and 4 min. 18 sec. with the heavy Zelix obfuscation (code-flow, exception, strings). In no way I'm benchmarking Zelix - I only needed an indication on how it penalises my own project, that's all; at least I'm happy the time didn't double.

Once you disassemble your compiled project, you'll see that your non-obfuscated (non-important) code calls obfuscated methods from your protected libraries - e.g. f() instead of MyMethod() while in the source code it's still MyMethod().

A bit of a hassle at first, but once you know what you are doing, once your batch files are correct, it's really a quick process. In fact, you are having a choice of what code to protect and what code can stay un-protected. For instance, there is no need to protect (and thus, slow down) standard libraries or libs that are shared on this forum - you need to mention them anyway.

Zelix may encrypt all the strings in your code (option 'encryptStringLiterals'), thus you may simply detach all your important strings into a separate class, compile it with B4A (>= 2.50) into a separate lib, and obfuscate that lib (just in case, I've excluded getObject, _process_globals, mostCurrent from obfuscation as B4A might use them). Once decompiled (I only tried jd-gui.exe and jad.exe), the obfuscated code that used 'aggressive' or code-flow obfuscation mode will have apparently failed/unrecognised opcodes, or non-existent labels etc., so even though it's not impossible to learn what the code is doing (there is no 100% protection anyway), at least it can't be copy-pasted into another project, can't be reconstructed, and therefore, stolen or have its strings recovered.

To explain better, I tried Stringer to encrypt my strings, but then I could still easily copy-paste the decompiled Java code into a separate tool, run it, and recover all the strings from my code. With Zelix, I can't do that anymore as the code is 'broken' so I can't reconstruct its logic, and thus, can't recover the strings. Not always - in some places I could still see and read the original code, follow its logic, but in other places, especially where the strings were used, there was practically a mess, especially for jd-gui.exe, showing 80% of the code as red 'rubbish'. jad.exe was handling it better, but still missing an opcode here and there, or placing some weird 'missing-block' labels.

My libs are all fairly large, but now the whole process really takes seconds, and does not require any changes in my B4A project which now only handles business logic and all UI stuff, apart from pointing it to use the 'Z' libraries instead of the original ones or vice versa. Well, I'm actually still using the built-in vvv-obfuscator for it, but its scope is very limited - I can still see all my unprotected code, but since it's non-important, I don't care. The code that really matters is covered with Zelix.

The only hassle in this process is manual patching of XML files, especially if you have dozens of methods/fields to rename, but that process can also be automated if you need to use it often.

Zelix might also shrink your code, but I've used UCDetect on my java libs, so all unneeded code was already stripped, thus no gain in size in my case.

Hope this info helps.
 
Top