A blog that accompanies our progress creating this product

This article is about obfuscation and protection against hacking.

Copy protection can’t be complete without some sort of obfuscation. The Wikipedia definition of Obfuscation is:

Obfuscation is the willful obscuring of the intended meaning of communication, usually by making the message confusing, ambiguous, or difficult to understand. The obfuscation might be unintentional or intentional (although intent usually is connoted), and is accomplished with circumlocution (talking around the subject), the use of jargon (technical language of a profession), and the use of an argot (ingroup language) of little communicative value to outsiders”

When applying this to software copy protection, our goal is to prevent a hacker from using reverse engineering methods, or more simple, hacking a protected application (which can even be examining the strings and other resources within the application).

Preventing that is done in several layers:

Source code obfuscation – if various elements of the source code and resources are obfuscated before the program is built, the built program will be obfuscated.

Binary obfuscation – manipulating the executable whilst making it hard to reverse engineer. That is usually done by making changes in the executable and yet preserving its format so it can still be executed (obviously if you encrypt an entire executable, you will reach the goal of making it impossible to reverse engineer but with the price of ruining the executable (PE) format in a way that will make it impossible to run it.

So clearly you need to make enough changes and manipulation to make it next to impossible to hack and reverse engineer and yet preserve the PE structure so it will still be a valid executable.

One solution to this problem is packing the executable by another executable (“loader”). I personally find this approach problematic. First, anti viruses detect a packer + loader as malicious code. Second, it complicates the process of protecting a program while we, at Secured Globe, Inc. aim to make it as simple as possible. The mechanism of storing parts of a program encrypted and decrypting these parts during run-time can be embedded as part of the program itself without having to wrap it entirely. For example, all resources can be stored as binary encrypted data or even stored as encrypted data without using the mechanism of resources which can easily be hacked using dedicated tools. Also all strings can be kept encrypted and decrypted during run-time. Strings reveal a lot of information about an application, its credentials (for example a server to which the program connects to, etc.).

Michael Haephrati published an article with source code about string obfuscation. We have examined a source code level obfuscation system and put aside the fact it is really a hard and exhausting work to obfuscate a c++ source code, the results are quite good.

The following code segment:

for (i=0; i < M.length; i++){
   // Adjust position of clock hands
   var ML=(ns)?document.layers['nsMinutes'+i]:ieMinutes[i].style;
   ML.top=y[i]+HandY+(i*HandHeight)*Math.sin(min)+scrll;
   ML.left=x[i]+HandX+(i*HandWidth)*Math.cos(min);
 }

will be changed to

for(O79=0;O79<l6x.length;O79++){var O63=(l70)?document.layers["nsM
\151\156u\164\145s"+O79]:ieMinutes[O79].style;O63.top=l61[O79]+O76+(O79*O75)
*Math.sin(O51)+l73;O63.left=l75[O79]+l77+(O79*l76)*Math.cos(O51);}

Focusing in c++, the features supported by Semantic Designs are:

  • Output encoding in ASCII, European ASCII, or UNICODE
  • No changes to the your C++ compilation or execution procedurs or environment
  • User definable list of preserved names
  • Predefined list of reserved identifiers for C++ standard libraries provided
  • Can preserve most preprocessor conditionals and macro calls in obfuscated source
  • Option to neatly format C++ source code to aid development before obfuscation.
  • Output encoding in ASCII, European ASCII, or UNICODE
  • Command line and GUI interfaces

To explain further, our goal is to disguise the following elements: API calls, variables, function names, program flow, as they also reveal a lot (as strings and resources do) and should be changed to meaningless names. That can be done in house by a simple search-replace taken place just before the final generation of the Release version, and right after all code changes are made and all tests are completed.

While the process of hiding and disguising strings, resources, variables and functions with in the program is quite straight forward, when it comes to calling an API function, things become more complex since you want to obfuscate an API call and yet have the operating system respond to it…

One way of doing it is as follow: Instead of calling the API function directly, we use

GetProcAddress(hModule,reinterpret_cast<const char*>(reinterpret_cast<int>(szName) ^ MASK)); 

Then you build on top of it a function that receives an encrypted name of the API function, decrypts it during runtime and return the address of the real (decrypted) API function name. In our example, the encryption method is a simple XOR but of course any ecryption can be used as long as it is straight forward to decrypt it during runtime.

Next, the program calls the function at the returned address without specifying its name in any way. As a result, it will be hard to find this call by examining the obfuscated executable.

Obfuscating an application won’t do any good if a hacker is trying to break it using a debugger, so anti-debug techniques are also required. For example: we can assume that if a debugger is ran, various actions that we can measure the time they take, will take more time to be completed, so one way is to measure them and compare the results.

Of course we can check the existence of a pre-defined list of process names which we know are associated with know debuggers.

We can digitally sign various parts of our program and compare it to an ad-hoc generated signature during runtime, so in case a manual change was made by a hacker we will detect it.

The most efficient protection is creating a virtual machine during runtime and running the program code in it. This VM should be a custom one not known to others so it will be impossible to debug it without knowing how it works and impossible to find out how it works without debugging it. That will lead the average hacker to a dead end.

 

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: