The Story Behind

Parent Previous Next

The Story Behind.

Why was it necessary to develop a new software protection technology, and how did it happen?

This is the story of how SCRAMBLECODE came about. Hopefully it will provide you with a good understanding of the fundamental goals and ideas, it is based upon, and some insight into the experiences, thoughts and decisions related to the development.

The Problem.

Question: How can we safely execute our software applications and services in potentially unsafe environments?

Many have probably at some point thought about protecting some small part of a software application, just to discover, that this is not an easy task. The more you read about, how crackers can rip an application apart in just some hours or a few days, the more discouraged one might become.

Most available software protection schemes are based on the premise of trying to outsmart the cracker, usually by applying some sort of trick to build an "impenetrable wall". Trying to be smarter than the cracker is doomed to fail. No matter the complexity of the tricks applied, sooner or later a cracker will break the shield or circumvent it and get access to the machine code in memory in an unprotected pristine form, thereby making analysis and modifications possible. Many of these security schemes are described later as General Safety Measures.

A few solutions offer a more advanced protection by inserting small virtual machines into the executable to replace a section of assembler instructions. Using this kind of Low-level VM Protection offers a higher degree of security for the replaced functionality, but it must be carefully examined, how it is done, otherwise this technique can provide a false sense of security, because the cracker can get a lot of information from monitoring what happens "around" the protected functions, which can lead to attacks that try to bypass or overrule certain functionality.

Several Hardware Rooted Security schemes have also been introduced to market. These provide powerful capabilities with regards to platform integrity, cryptography protection, memory encryption etc. However, the requirements for the underlying architecture and setup can be quite demanding, and it may rule out many legacy systems.

The Solution.

SCRAMBLECODE came about in the pursue to find a better solution.

At first the initial questions were:

These questions seemed like the obvious problems to solve, but pretty soon it also became obvious, that this approach would probably lead to the exact same solutions, which others had already created.

And then a new strategy emerged for a secure solution based on these two fundamental ideas:

  1. Don't protect the executable machine code.
    Remove all secrets from the machine code by letting it implement a high-level virtual machine, which executes compiled bytecode as virtual assembler instructions. The native machine code does not contain any vital information for a cracker, because it has no prior knowledge of the separate bytecode to be executed. It is the millions of memory events during execution, the cracker must analyze and make complex interpretations of - trying to put the events into a context of virtual instructions performing a full blown program.

  2. Don't prevent crackers from having full memory access.
    Instead break everything into thousands or even millions of small encrypted pieces, that are extremely complex to understand and virtually impossible to modify.

These fundamental ideas can also be expressed as a High-level VM Security solution, using the term high-level because the secure bytecode originates from the source code, in contrast to Low-level VM Protection that uses small virtual machines which originate from the lowest level (the machine code).

SCRAMBLECODE is based on these ideas but adds even more security:

The most important aspect is probably, that this approach does not try to outsmart a cracker. Aside from complex mathematics due to RSA authentication, it does not involve clever tricks. Instead it raises the cost for the cracker severely by using randomized combinations of thousands or even millions of encryption events which together form the pieces of a big puzzle. The randomization furthermore generates different pieces on each compilation and each execution.

Combining Multiple Strategies

Most protection schemes offer an outside-in security approach to create a shield around the code and memory. No matter the strength of the shield, it can be broken, and once penetrated it offers no further security.

SCRAMBLECODE, on the other hand, protects using an inside-out scheme, where every generated instruction and variable is encrypted individually, starting security at the very core of the program and relying on no outside protective assistance.

It is two very different and complementary approaches, that each can provide strong protection, but when used together may raise the security level significantly. This is described in more detail in Real Life Safety and What SCRAMBLECODE Adds.

Design Considerations.

Once the SCRAMBLECODE solution was defined at a conceptual level, identifying the key elements of the design came next.

It was important that the SCRAMBLECODE programming language would be very intuitive and easy to learn for the average user. The language should also be well documented and target the development of well structured type safe code.

The compiler should produce encrypted bytecode based on virtual instructions, which were only understandable to a single virtual machine, providing each customer with their own unique execution engine for which only they could produce bytecode. The bytecode should not contain meta data or any kind of run time information. The compiled bytecode and the virtual machine should be easy to distribute and royalty free.

Furthermore it should be easy to download and test the solution without having to install any other software. It should be self-contained and not more complicated than download, unzip, run. The trial version should be made easily available and provide the means to thoroughly test all functionality on as many installations and platforms as needed, thus allowing the end-user to test any precondition before buying a license.

And while testing it shouldn't be necessary to involve other programming languages or tools. This indicated that the solution should include a test bench and a debugger.

Finally an assessment was made regarding how much time the average user would spend with SCRAMBLECODE, while developing a typical software product. The conclusion was, that it could very well be perhaps as little as a few percent of their time. For such an infrequent use it is important, the developer does not have to remember lots of details from time to time about files, tools, commands etc. This notion made it imperative to provide a good interface for writing, compiling and testing the source code. Everything should be well organized as projects, which were easy to manage, and with a good overview of the involved files and classes.

Putting all these considerations together led to the conclusion that SCRAMBLECODE should have an Integrated Development Environment (IDE), which packaged the language, documentation, editor, compiler, test bench and debugger as a single all-in-one product.

The Language, Compiler and Execution Engine.

Due to these requirements it was decided, that the SCRAMBLECODE execution engine, compiler and programming language should be developed from scratch without making use of any preexisting technology. Building everything from the ground up would also allow every detail to be designed and implemented with special attention to the security aspects of the Single Target Compilation technology.

The implementation phase started by making a prototype based on a simplified version of the intended language, parser, compiler and execution engine. The prototype was programmed over a few months, and it provided a lot of experience and knowledge.

However, the prototype revealed some less desirable issues with the initial design. Due to this the solution was programmed all over again from the very start. Based on the prior experiences the class structure was changed quite a bit, for example to facilitate a better memory management functionality and an improved language extensibility.

The Integrated Development Environment.

Programming the IDE was a big job. The goal was a small, fast and intuitive IDE, which offered the right amount of functionality in order to work efficiently for most scenarios. It was also important to implement the Single Target Compilation technology as an integrated part, allowing the developer to easily switch among and target multiple VMs.

The IDE includes:

Each part was challenging and time consuming to program from the ground up. The source code editor in particular toke a great deal of effort in order to get a class structure with a fine-grained control of the visual effects for the editor and the debugger.

Writing the documentation turned out to be very time consuming too. Being informative, yet concise, is a constant battle. Many hours have been spent fiddling with just a few sentences or paragraphs, trying to find the most educational way to present some small technical issue. However, once written, it felt good to complete the IDE by integrating the individual help pages to allow the F1 lookup functionality to present content aware help information for the IDE and the source code.

Technical Issues.

In a project of this magnitude many obstacles will inevitably appear. And they did. Most of them were technical problems which usually were enjoyable to solve, but some issues were very time consuming to handle. And perhaps most importantly a few of these issues really challenged the conventional way of thinking.

One of these challenges turned out to be the debugger, because from a security point of view a debugger represents a conflict of interest. It can tell you - but potentially also a cracker - what is going on during execution. It took a good deal of time to finally accept, that real-time monitoring of the execution would represent a significant security risk. The technical details of these considerations and the influence it had on the final design of the debugger are described here.

Another issue was to decide, how big an impact the security functionality should be allowed to have on the execution speed as described here. Nobody wants to sacrifice speed, but the decision was made to prioritize security and sacrifice a certain amount of execution speed in order to reach the highest security level.

Final Remarks.

When creating a new software product, it can be tempting to cut back on functionality in order to get to market quickly. For some projects it is undoubtedly the right path to follow - getting noticed and receiving user feedback early on.

However, it is not possible to conscientiously launch a security solution to market as a work in progress with numerous loose ends. To build and deserve confidence you must deliver quality, which can be verified. This is why everyone is allowed and actually encouraged to test anything, anywhere, before buying a license, in order to verify all requirements are fulfilled.

It was a costly (but good) decision to discard the initial prototype and to start the implementation all over. Developing it again - based on the knowledge gained from the initial work - improved the final result tremendously. The source code became much better structured without last minute afterthoughts scattered all over the place.

Another dilemma involved the IDE and deciding upon the right amount of included tools and functionality. SCRAMBLECODE could have been launched to market earlier on, if some functionality had been simplified or perhaps scheduled for later. However, the decision was made that the IDE should be a complete and intuitive all-in-one environment in order to make it easy to work with - especially for those developers who only uses it on an occasional basis.

And given the fact, that SCRAMBLECODE is used to protect SCRAMBLECODE, the IDE and the tools are appreciated here as well.