Android Tutorial Code Obfuscation

This tutorial is relevant for B4A and B4J.
During compilation B4A generates Java code which is then compiled with the Java compiler and converted to Dalvik (Android byte code format).
There are tools that allow decompilation of Dalvik byte code into Java code.

The purpose of obfuscation is to make the decompiled code less readable, harder to understand and make it more difficult to extract strings like developer account keys.

It is important to understand how the obfuscator works.
The obfuscator does two things:

Strings obfuscation
Any string written in Process_Globals sub (and only in this sub) will be obfuscated, making it much harder to extract important keys. The strings are defuscated at runtime.
Note that several keys are used during obfuscation including the package name, version name and version code. Modifying these values with the manifest editor will break the defuscation process.

Variables renaming
The names of global variables and subs are converted to meaningless strings. Local variables are not affected as their names are lost anyway during the compilation.
The following identifiers are not renamed:
- Identifiers that contain an underscore (requires for the events handlers).
- Subs that appear in CallSub statements. Only if the sub name appears as a static string then the identifier will be kept as is.
- Designer views names.

Tip: If, for some reason, you need to prevent the obfuscator to rename an identifier you should add an underscore in the identifier name.

A file named ObfuscatorMap.txt will be created under the Objects folder. This file maps the original identifiers names to the obfuscated names. This mapping can be helpful to analyze crash reports.

Activating the obfuscator


There are three modes:
- Debug - in this mode the IDE debugger will connect to the running application (same as the previous Attach debugger option).
- Release - compiles the application without any debugging information.
- Release (obfuscation) - compiles the application and activates the obfuscator.

SS-2012.01.06-19.38.16.png


Pitfalls
Using CallSub with a non-static string.
The following code demonstrates this issue:
B4X:
Sub Activity_Resume
   CallSub("Main", "Test1") 'Works because it is a static string (Test sub will not be renamed)
   Dim subName As String
   subName = "Test2"
   CallSub("Main", subName) 'Skipped at runtime because Test2 sub is renamed
   subName = "Test_3"
   CallSub("Main", subName) 'Works because Test_3 includes an underscore and it will not be renamed.
End Sub
Sub Test1
   Log("a")
End Sub
Sub Test2
   Log("b")
End Sub
Sub Test_3
   Log("c")
End Sub

- LicenseChecker.SetVariableAndValue
This method references a variable using a string. This method will fail if the variable name doesn't include an underscore.
 
Last edited:

ondesic

Active Member
Licensed User
Longtime User
That's great!

1) Can the license sub's name be changed to something besides _Allow, _Error and _DontAllow? These subs are among the most important to obfuscate.

2) I just ran into a bug. My license object is named "trl". I have the following code:

trl.SetVariableAndValue("tester","1356")

If I obfuscate, b4a gives me a bug and says there is no field named "_tester". I am assuming b4a is removing _tester. If I don't obfuscate it runs fine.
 
Last edited:

ondesic

Active Member
Licensed User
Longtime User
In the Map file it shows variables renamed to things like "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv5" and "vvvvvvvvvvvvvvvvvvvvvv7"

If there is a crash it is going to take forever counting v's. Isn't there a shorter way to change names so we can more easily find the appropriate variable?
 

nad

Active Member
Licensed User
Longtime User
"...
- LicenseChecker.SetVariableAndValue
This method references a variable using a string. This method will fail if the variable name doesn't include an underscore.
..."

I am compiling one time, checking after the obfuscation txt file to see the equivalence name i.e vvvvvv4 and then writing it directly

licensechecker.setvariableandvalue("vvvvvv4" ...

after that all the next compiles it works great.
I think it adds a higher level of security as is ofuscated aswell.

Hope is not a mistake?
 

moster67

Expert
Licensed User
Longtime User
Known issues (version 1.80)
The string obfuscation fails with empty strings. This is only relevant to empty strings in Process_Globals as other strings are not obfuscated.
This will be fixed in the next update. Note that by default strings are set to the empty string, therefore you can just remove the empty string assignment.

Erel,

Just wondering if above issue has been fixed in the current beta (1.90) although it shouldn't really be a problem?
 

mcmanu

Active Member
Licensed User
Longtime User
Hi Erel

It seems to me that this issue is not fixed :-(
I get an error when i use release obfuscated
because i use a code modul which contains this -->

Sub Ltrim(Text As String) As String
Do While Left(Text, 1) =" " <-- thats the problem
Text = Right(Text, Len(Text)-1)
Loop
Return Text
End Sub
Sub Rtrim(Text As String) As String
Do While Right(Text, 1) =" "
Text = Left(Text, Len(Text)-1)
Loop
Return Text
End Sub

its the code module from String Functions
for example s.proper

Will this be fixed?
 

mcmanu

Active Member
Licensed User
Longtime User
Hi Erel

Thank you :) so what could i do to Release my app Obfuscate?
I need the code module which i was talking about :)
 

mcmanu

Active Member
Licensed User
Longtime User
This is my error in the log

Compiling code. 2.12

ObfuscatorMap.txt file created in Objects folder.
Compiling layouts code. 0.06
Generating R file. 0.02
Compiling generated Java code. Error
B4A line: 33
Do While Left(Text, 1) =\
javac 1.6.0_26
src\testapp\mcmanu\android\s.java:161: cannot find symbol
symbol : variable _ba
location: class testapp.mcmanu.android.s
while ((_vvvvvvv3(_ba,_text,(long)(1))).equals(" ")) {
^
1 error
 

mc73

Well-Known Member
Licensed User
Longtime User
Compiling code. 2.12

ObfuscatorMap.txt file created in Objects folder.
Compiling layouts code. 0.06
Generating R file. 0.02
Compiling generated Java code. Error
B4A line: 33
Do While Left(Text, 1) =\
javac 1.6.0_26
src\testapp\mcmanu\android\s.java:161: cannot find symbol
symbol : variable _ba
location: class testapp.mcmanu.android.s
while ((_vvvvvvv3(_ba,_text,(long)(1))).equals(" ")) {
^
1 error

In the 's' module, except from 'sub proccess_globals' do you have 'sub globals' too? If yes, try to remove it, and please inform if this helped.
 

mcmanu

Active Member
Licensed User
Longtime User
Nice

You solved one of my biggest Problem :)
Thank you very very much :) Thats Awesome :)

Removing sub globals solved it :)
 
Last edited:

peacemaker

Expert
Licensed User
Longtime User
Strange problem.
B4A 2.01 (beta).
Old project with HttpUtils v.1.04.

Variables:
B4X:
   Dim CallbackActivity As String 'Name of Activity that handles the callbacks.
   Dim CallbackJobDoneSub As String 'Name of the JobDone callback sub.
   Dim CallbackUrlDoneSub As String 'Name of the UrlDone callback sub.
   Dim CallbackIgnoredSub As String   'Name of the callback sub, if service is already running and new job was ignored.

CallbackIgnoredSub is used

B4X:
Sub internalCheckIfCanStart(JobName As String) As Boolean
   If Working Then
      Log("Already working. Request ignored (" & JobName & ")")
      'Raise URL done event
      If CallbackIgnoredSub <> "" Then
         CallSub2(CallbackActivity, CallbackIgnoredSub, JobName)
      End If
      Return False
   End If
...

Sub name is: HttpUtils.CallbackIgnoredSub = "ReSyncSet".

Compilation with obfuscation is OK, but during running (real devices) there is error:

** Service (inet) Start **
httputils_vvvvvvvvvvvv4 (java line: 116)

java.lang.Exception: Sub resyncset was not found.
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:176)
at anywheresoftware.b4a.keywords.Common.CallSub4(Common.java:795)
at anywheresoftware.b4a.keywords.Common.CallSub2(Common.java:780)
at peacemaker.energeniepowermanager.httputils._vvvvvvvvvvvv4(httputils.java:116)
at peacemaker.energeniepowermanager.httputils._vvvvvvvvvvv0(httputils.java:44)
at peacemaker.energeniepowermanager.inet._synctimer_tick(inet.java:592)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:170)
at anywheresoftware.b4a.keywords.Common$4.run(Common.java:881)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at anywheresoftware.b4a.Msgbox.waitForMessage(Msgbox.java:211)
at anywheresoftware.b4a.Msgbox.waitForMessage(Msgbox.java:180)
at anywheresoftware.b4a.keywords.Common.DoEvents(Common.java:367)
at peacemaker.energeniepowermanager.db._service_start(db.java:222)
at peacemaker.energeniepowermanager.db._initdb(db.java:108)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:170)
at anywheresoftware.b4a.keywords.Common$4.run(Common.java:881)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)

Sub name was changed - no use. And debug or non-obfuscated release - no such error.
What's wrong ?
 

mcmanu

Active Member
Licensed User
Longtime User
same problem

I have the same Problem, my functions with httputils dont work anymore with release obfuscate. is it fixed in b4a 2.0?
 
Top