Local Links

External Links

Contact

Search this site

Arbed - String Obfuscation


(Available in Arbed 1.6 and later)

What it does

  1. Constant values and quoted strings (string literals) will get modified (mangled).
  2. Constants get renamed to end in "_mangled", and a new computed property is added that fetches the renamed constant, decodes it and returns it. The code does cache the value in a static variable so that the decoding occurs only once.
  3. For each mangled string literal, a new line gets added to the beginning of the method, storing the value in a static variable, decoding it alongside. The code that used the string literal gets changed to reference this new variable.

Here's an example of how the code modification works, where the obfuscation is done by converting the string into its Base64 representation:

Before:

dim md as new MessageDialog
md.ActionButton.Caption = "Quit"

After:

static s_Quit as String = DecodeBase64("UXVpdA==").DefineEncoding(Encodings.UTF8) ' "Quit"

dim md as new MessageDialog
md.ActionButton.Caption = s_Quit

While this example uses only the rather easy-to-decypher Base64 encoding, you are free to choose your own encoding and decoding methods, thanks to RbScript.

Limitations

The following strings can not be obfuscated because the program would not compile:

  • Constants used for lib names of declare statements.
  • Constants referenced in UI elements and other places with the "#" prefix.

Furthermore, these types of strings won't be offered for obfuscation out of technical reasons:

  • String literals in code lines that start with "static " (that's how mangled string literals look like).
  • String constants whose name end in _mangled.
  • Constants used as default values in method parameters.
  • Constants used as initial values in properties.
  • Strings literals that are not in actual code but part of a comment.

Therefore, all these types of strings won't be offered for obfuscation.

How To Use

To use this feature, open a project in its Project Editor, then choose Obfuscatable Strings from the Project menu.

A new floating window will appear that shows all strings that can be obfuscated:

Select the strings from the list that you like obfuscated (for a quick test, simply select all), then click the Obfuscate... button, which will get you to the following modal dialog:

The upper edit field lets you enter a RbScript program that performs the encryption of a string, while the lower edit field provides a function call to perform the opposite.

The upper encryption code has to be written entirely in RbScript (you may invoke external shell commands and other tools, though, see below) because it will be executed when pressing the Start button of this dialog.

The lower decryption code, though, allows you only to invoke a function. That function you have to add to your project separately. That'll be the decryption function that reserves the upper script's operation.

In the above example we're using Base64 "encryption", for which RB already provides a built-in function.

You should also remember setting the Encoding of the string back to UTF-8 if the decryption process loses the encoding, because all string constants in Real Studio projects get the UTF-8 encoding by default, and other functions in your project may rely on that fact.

Arbed does not manage (save, load) multiple encryption schemes for you. All it does is to remember your last input into these fields. Therefore, you should maintain a separate text file that contains your used encryption script, decryption function call and decryption code to add to your project so that you won't lose it.

Also note that because the encryption script and decryption calls are added to the selected strings once you press the Start button, you can even use different encryption techniques in your program for different strings.

Developing your own encryption algorithm

Important:

Due to the fact that the encrypted strings still need to appear in the source code, they need to be valid UTF-8 strings. That means that you cannot return strings that contain an arbitrary set of bytes, because byte combinations are not valid in Unicode strings. Therefore, if your encryption code generates strings that consist no only of readable Unicode characters, you should encode them in a text-only format such as Base64, before assigning it to Output.

Obfuscation script reference

The script you write for generating your encrypted strings runs as RbScript code.

The basic functionality of RbScript is described in the Real Studio documentation.

Note that RbScript's language has a few unexpected limitations. For instance, you cannot write:
dim d as new Dictionary
but you need to write:
dim d as Dictionary
d = new Dictionary
Similarly you cannot use:
for i as integer = 0 to 5
but:
dim i as integer
->for i = 0 to 5
However, these restrictions only apply to lines you write at the topmost code level. If you instead place all your code into a "sub" method and call that from a line past the subroutine, the code inside that method does not fall under the above restrictions.

Arbed provides a Context class to the RbScript and thereby adds the following additional functions and properties you can use in the script:

function Input() as String
Returns the string to be encrypted. The standard Input(prompt as String) function does the same.
Output as String
You need to assign the encrypted version of the string to this property
function ShellExecute(cmd as String, ByRef result as String) as Integer
Invokes Shell.Execute, returning its Result and ErrorCode properties.
EndOfLine as String
Returns RB's EndOfLine value
TargetOS as String
Returns "OSX" when Arbed runs on Mac OS X, "Win" on Windows and "Linux" otherwise.
Print (text as String)
Invokes RB's MsgBox(text), but only when using the Check button, not during actual obfuscation (after pressing Start). Should be useful for debugging your script code.
function StrEqual (a as String, b as String) as Boolean
returns true if both strings are equal in their binary representation (like StrComp(a,b,0)=0).

Encryption operations using the |MBS "Utils" plugin:

function EncryptBlowfishMBS(s as String, key as String) as String
See BlowfishMBS class
function DecryptBlowfishMBS(s as String, key as String) as String
Reverse of EncryptBlowfishMBS
function EncryptAESMBS(s as String, key as String, optionalIVector as String = "") as String
See AESMBS class
function DecryptAESMBS(s as String, key as String, optionalIVector as String = "") as String
Reverse of EncryptAESMBS

You can use the following Encode... functions to return encrypted binary data.

function EncodeBase64(s as String) as String
Invokes RB's EncodeBase64(s,0) function
function DecodeBase64(s as String) as String
Invokes RB's DecodeBase64(s) function
function EncodeHex(s as String) as String
Invokes RB's EncodeHex(s,0) function
function DecodeHex(s as String) as String
Invokes RB's DecodeHex(s) function

The de/encryption operations do not set the string's encodings. You can control this yourself with the follow functions:

function DefineAsUTF8(s as String) as String
Returns s.DefineEncoding(Encodings.UTF8).
function ConvertToUTF8(s as String) as String
Returns s.ConvertEncoding(Encodings.UTF8).
function HasEncoding(s as String) as Boolean
Returns s.Encoding <> nil.

You also get two classes: Dictionary and BinaryDict, the latter being like a Dictionary with case-sensitive keys. These classes only work with Strings for keys and values, though (if you really need other types, let me know). The following methods are available on these classes:

  • Constructor()
  • Clone() as Dictionary (or BinaryDict, respectively)
  • Count() as Integer
  • Key(idx as Integer) as String
  • Value(key as String) as String
  • Lookup(key as String, default as String) as String
  • Value(key as String, assigns value as String)

If you require other operations for the script, contact me and I'll see that I add them quickly for you.


Page last modified on 2013-10-16, 09:51 UTC (do)
Powered by PmWiki