Obfu-VBA

1 What is Obfuscation ?

Obfuscation is generally speaking an operation that consists in hiding the meaning of a piece of information, in making it ambiguous, deceiving or just hard to understand.

In the IT context, obfuscation is used to protect the intellectual property of a software in making its source code incomprehensible (for human thought) while keeping it compilable or interpretable for a computer.

Excel-VBA applications are particularly concerned by this issue : VBA source code is embedded in the workbook that contains the application. The password protection to the VBA code is insignificant since a few softwares from the market can open Excel files and are able to give access to the VBA code regardless of the password.

Obfu-VBA uses the 3 following methods to obfuscate VBA code of Excel Applications : removal of comments, removal of coding style (white lines, indentation and instructions on several lines) and renaming of the identifiers (variables, constantes, functions, procedures, parameters, modules, classes, userforms and controls).

2 Way of use

Obfu-VBA does not work straight on the Excel workbook that holds your VBA application. Here are the successive steps needed to obfuscate your application :

1 Create 1 input folder that will contain the objects you will export from your application and 1 output folder that will contain obfuscated objects.

2 Export all modules, class modules and userforms from your VBA project into the input folder : your application being opened in Excel, from the Excel VBA editor, do a right-click on each object containing VBA code and select "Export to a file..." (see the figure opposite). Then you can close your workbook.

3 Open in Excel the Obfu-VBA workbook, fullfill needed parameters (see chapter 3.1) and launch the process -that may last several minutes, depending on the size of the files to process.

4 Create a new workbook in Excel, copy if needed the sheets of your former workbook, import from Excel VBA editor the obfuscated objects contained in the output folder.

5 The creation of an obfuscated version of your Excel-VBA application is over. What you have to do then is check it works properly : first save it on the disk, run compiler (VBA editor -> Debug menu -> Compile) and fully test its smooth functioning.

Export a file

In case of trouble (compilation fails, execution aborts, running does not conform to the original, obfuscation is not thorough), the first thing to do is to check that the recommandations of Obfu-VBA (see chapter 3.5) are followed. Once it is made, you can contact ToolOscope for support or evolution request.

3 Obfu-VBA application

3.1 The Project worksheet

Project worksheet

This worksheet is the command interface of Obfu-VBA. Cells to be filled by the user are on yellow background (numbered in red from 2 to 9). Each of these cells has a comment that describes the expected content. These comments are resumed in the frame beside.

Once all input data have been entered, the user clicks on the "Launch Obfu-VBA" button to get process running, in 2 stages.

At each step, Obfu-VBA reads successively all input modules (7) that must be present in the input folder (5). During the second step, obfuscated modules are written in the output folder (6). The user can monitor the progress of the process by looking at the numbers of read and written lines displayed on the worksheet.

Names of .bas modules and .cls classes are darkened. Names of .frm userforms .frm are darkened too but not the names of the files that contain them. During the import of the obfuscated userforms, the names of files disappear.

You can duplicate that worksheet in the Obfu-VBA workbook, to keep one command sheet per project, for example. So, when you modify the clear source code of your projects and want to obfuscate them again, you won't waste time to parameter folders, modules... in Obfu-VBA.

Cells comments

1 You can duplicate this sheet in the same workbook as many times as you have different VBA projects to process.

2 Fill in the name of the sheet that contains reserved words.
Optional. If blank, reserved words may not be obfuscated as well, but performances may be reduced.
If filled in, the sheet must exist in the same workbook.

3 Fill in the name of the sheet that will show the code and the detected types of variables (65530 maximum lines).
Optional. If blank, the code will not be shown.
If filled in, the sheet must exist in the same workbook.

4 Fill in the name of the sheet that will show the mapping table between clear and obfuscated identifiers.
Optional. If blank, the mapping table will not be shown.
If filled in, the sheet must exist in the same workbook.

5 Fill in the path of the folder that contains the VBA files to get processed, previously exported from Excel.
Mandatory.

6 Fill in the path of the folder that will contain the obfuscated VBA files. These files will have to be manually import in a new Excel workbook to rebuild your application.
Mandatory.

7 Fill in this column the names of the VBA files exported from your Excel application, without their extension. These files have to be placed in the "Input" folder.
64 maximum files + memory limit of Excel-VBA projects.

8 Fill in the extension of each VBA file named in the cell to the left :
- cls for ModuleClass,
- bas for Modules,
- frm for UserForms.

9 Fill in this column the identifiers that must not be obfuscated.
Optional.

3.2 Reserved words

This optional input worksheet contains reserved key-words of VBA language. It can be improved in case of lacks.

Obfu-VBA analyses each word encountered in the code to process in order to determine if it has to be darkened. This keyword list saves time during processing.

Only the identifiers explicitely declared in your project will be darkened. Therefore, this reserved word list is not discriminatory.

Reserved words

3.3 The identifiers mapping table

mapping table

During processing, Obfu-VBA digs out all identifiers declared in your project and relates each identifier to a darkened one. If the name of the mapping table sheet is parametered in the command worksheet, Obfu-VBA returns for each identifier its clear name, its darkened name, its type and its container in the case of a member of a class or a user type, according to its scope (project, module or local).

3.4 The read code worksheet

analysed code

Obfu-VBA writes on this worksheet (if its name is defined on the command sheet) the read and analysed code - identifiers separated from other characters. Obfu-VBA shows the kind it has detected below each identifier, on 2 lines : label, reserved keyword, variable, function... and the type of the container.

3.5 The Help worksheet

This sheet contains recommandations about the source code to process :

4 Example : ObfuTest application

ObfuTest application

The ObfuTest small application does nothing important and has been written to test and show the functioning of Obfu-VBA. It consists of 1 code module, 1 class module and 1 userform, whose original and obfuscated versions are shown below.

Feuille Projet

4.1 Class module "MyClass.cls"

Source Code
VERSION 1.0 CLASS BEGIN MultiUse = -1 'True END Attribute VB_Name = "MyClass" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = False Attribute VB_Exposed = False Option Explicit Const MYCONST1 = "toto" Const MYCONST2 = 3 Private mvar1 As String Private mvar2 As Long Public mvar3 As Boolean 'pour test de Me Rem constructeur : son nom ne doit pas être obfuscaté Private Sub Class_Initialize() mvar1 = MYCONST1 mvar2 = MYCONST2 Me.mvar3 = False End Sub Rem destructeur : son nom ne doit pas être obfuscaté Private Sub Class_Terminate() MsgBox "Object of class MyClass destroyed !" End Sub Friend Property Let var1(parm1 As String) mvar1 = parm1 End Property Friend Property Get var1() As String var1 = mvar1 End Property Friend Property Let var2(parm1 As Long) mvar2 = parm1 End Property Friend Property Get var2() As Long mvar2 = var2 End Property
Obfuscated code
VERSION 1.0 CLASS BEGIN MultiUse = -1 END Attribute VB_Name = "F1" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = False Attribute VB_Exposed = False Option Explicit Const F12 = "toto" Const F13 = 3 Private F14 As String Private F15 As Long Public F2 As Boolean Private Sub Class_Initialize() F14 = F12 F15 = F13 Me.F2 = False End Sub Private Sub Class_Terminate() MsgBox "Object of class MyClass destroyed !" End Sub Friend Property Let F3(F16 As String) F14 = F16 End Property Friend Property Get F3() As String F3 = F14 End Property Friend Property Let F4(F16 As Long) F15 = F16 End Property Friend Property Get F4() As Long F15 = F4 End Property

4.2 Code module "MyModule.bas"

Source Code
Attribute VB_Name = "MyModule" Option Explicit Public Type myType mvar1 As String mvar2 As Long mvar3 As Boolean End Type Const MYCONST1 = "MyModule" Const MYCONST2 = 4 Public Type my2ndType mvar2(1 To 5) As myType mvar1 As Boolean End Type Rem sub de test Private Sub monsubPrive(ByRef pparm1 As String, ByVal pparm2 As Boolean, pparm3 As myType) Dim mvar1 As String, lvarA As Boolean, mvar2 As my2ndType pparm3.mvar1 = pparm1 With pparm3 .mvar2 = -3 End With Rem 3 identificateur mvar2 qui désignent tous des variables différentes mvar2.mvar2(5 + pparm3.mvar2).mvar2 = -1234567 lvarA = True mvar1 = MYCONST1 MsgBox "monsubPrive : " & pparm3.mvar1 & " " & mvar1 End Sub Public Sub lance() Dim laClasse As MyClass, var2 As String, mvar1 As myType Set laClasse = New MyClass With ActiveSheet .Cells(2, 2) = "Test démarré" End With Rem ne pas confondre les 2 "var2" laClasse.var2 = 12345 - 1234 var2 = " toto " monsubPrive "test", True, mvar1 MyUserForm.Show End Sub
Obfuscated code
Attribute VB_Name = "F5" Option Explicit Public Type F6 F1 As String F2 As Long F3 As Boolean End Type Const F12 = "MyModule" Const F13 = 4 Public Type F7 F1(1 To 5) As F6 F2 As Boolean End Type Private Sub F14(ByRef F15 As String, ByVal F16 As Boolean, F17 As F6) Dim F18 As String, F19 As Boolean, F1A As F7 F17.F1 = F15 With F17 .F2 = -3 End With F1A.F1(5 + F17.F2).F2 = -1234567 F19 = True F18 = F12 MsgBox "monsubPrive : " & F17.F1 & " " & F18 End Sub Public Sub lance() Dim F15 As F1, F16 As String, F17 As F6 Set F15 = New F1 With ActiveSheet .Cells(2, 2) = "Test démarré" End With F15.F4 = 12345 - 1234 F16 = " toto " F14 "test", True, F17 F8.Show End Sub

4.3 UserForm "MyUserForm.frm"

Source Code
VERSION 5.00 Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} MyUserForm Caption = "Test Obfu-VBA" ClientHeight = 5250 ClientLeft = 45 ClientTop = 345 ClientWidth = 4950 OleObjectBlob = "MyUserForm.frx":0000 StartUpPosition = 1 'CenterOwner End Attribute VB_Name = "MyUserForm" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = True Attribute VB_Exposed = False Option Explicit Private var1 As MyClass Private var2 As myType Private Sub Fermer_Click() Unload MyUserForm End Sub Rem le nom de ce Sub ne doit pas être obfuscaté Private Sub UserForm_Initialize() Label1.Caption = "valeur initialisée par UserForm_Initialize" Set var1 = New MyClass End Sub Private Sub CommandButton1_Click() MsgBox "TextBox2.Value=" & var1.var1 'ne pas confondre l'instance de MyClass avec son membre de même nom Rem les controles peuvent être qualifiés complètement ou pas du tout MyUserForm.MultiPage1.Page2.TextBox2.Value = "-->" & var1.var1 End Sub Private Sub TextBox2_Change() Dim mvar1 As String, var_2 As Integer, _ var_3 As Boolean 'gestion d'une ligne avec caractère de continuation Rem les controles peuvent être qualifiés complètement ou pas du tout var1.var1 = TextBox2.Value Rem gestion du with : ne pas confondre la variable locale mvar1 avec le membre .mvar1 With var2 .mvar1 = "string" .mvar2 = 123456789 .mvar3 = True End With End Sub
Obfuscated code
VERSION 5.00 Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} F8 Caption = "Test Obfu-VBA" ClientHeight = 5250 ClientLeft = 45 ClientTop = 345 ClientWidth = 4950 OleObjectBlob = "MyUserForm.frx":0000 StartUpPosition = 1 End Attribute VB_Name = "F8" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = True Attribute VB_Exposed = False Option Explicit Private F12 As F1 Private F13 As F6 Private Sub F11_Click() Unload F8 End Sub Private Sub UserForm_Initialize() FF.Caption = "valeur initialisée par UserForm_Initialize" Set F12 = New F1 End Sub Private Sub FB_Click() MsgBox "TextBox2.Value=" & F12.F3 F8.FC.FE.F10.Value = "-->" & F12.F3 End Sub Private Sub F10_Change() Dim F14 As String, F15 As Integer, F16 As Boolean F12.F3 = F10.Value With F13 .F1 = "string" .F2 = 123456789 .F3 = True End With End Sub

5 How to get Obfu-VBA ?

ToolOscope proposes to you a Shareware Licence :

For all this, please go to the User Space.

Don't modify this software, don't broadcast it : ToolOscope manages that.


© 2010-2015 by ToolOscope SASU. © 2016-2018 by Arnaud De Rette. All rights reserved