How to Attack and Defend

Parent Previous Next

How to Attack and Defend.

As previously described about Real Life Safety, no safeguard measures can ever be 100% secure. This of course also applies to SCRAMBLECODE.


Next is described the possibilities for a malicious attack to succeed. It may seem dangerous to disclose possible attack methods, but a security scheme can only be trusted, if the risk factors are known.


And as described next, the SCRAMBLECODE programmer can raise the cost of cracking to such a high level, that it is simply not worth while for most scenarios.



Attacking the Bytecode.

The strongly protected bytecode can be attacked in 3 different ways:


Conclusion.

Attacking the bytecode is very difficult, and for most real life scenarios probably almost impossible. The bytecode instructions cannot be modified without the private RSA key, and a runtime attack while loading and executing the instructions offers no clear path to get a workable crack going as the memory events can be very different on every execution - like a constantly moving target.



Attacking the VM Engine.

The VM engine for executing the bytecode is based on the High-level VM Security scheme, implemented as an ordinary unprotected native binary in machine code, making it susceptible to being analyzed and cracked. Even though the internal structure of the VM binary contains no valuable secrets to disclose and has no prior knowledge of the bytecode to execute, the native binary can be illegally modified to change the bytecode execution.


However, the possible consequences of an attack on the VM binary in order to compromise the bytecode execution can be prevented by using a defensive programming strategy for the bytecode to provide runtime protection.


Essentially it means adding extra bytecode to raise the defense level.


IMPORTANT: Protection bundled within the bytecode instructions cannot be removed or bypassed by a third party!



Statical Cracks.

It is possible to identify and modify the machine code instructions within the VM binary as a permanent statical crack before execution. This can be done to indirectly compromise some specific bytecode, but will potentially impact any bytecode executed by the VM.


If one analyzes the VM binary while executing some bytecode, it will typically reveal, that certain parts of the binary are used very much, whereas other functional areas are used less or not at all. A simplified diagram of such an analysis could look like this:



If functionality used "Often" or "Very much" (the 2 big pieces) is cracked and changed, the consequences can be extremely difficult to control, because the modified functional parts may be invoked repeatedly and differently by many of the executing instructions, causing the execution to either fail unintentionally somewhere in the execution flow or allow the developer to discover certain behavioral anomalies and abort execution.


"Never used" functionality can of course be modified illegally, but it has no consequences as it is not part of the bytecode execution.


It is the functionality used "Only once" (or only in one way), which can be maliciously exploited for a controllable result. Typically it involves certain specialized instructions - e.g. external calls to the operating system (perhaps related to critical security functions) etc. Functionality like this can be attacked by injecting machine code instructions to tamper with the involved information.


TIP: It is usually only a few of these instructions, that actually risk being exploited. It depends on the circumstances.


How to defend:

An attack such as this can usually be prevented by using a defensive programming strategy for the bytecode. One of the most effective strategies involves using the critical commands in multiple situations for multiple results. It will essentially move functionality used "Only once" into the category of being used "Often".


This can make statical cracks unsuccessful - even for sophisticated attacks made to the loaded image in memory, because this type of protection is bundled within the executed bytecode as an integrated part that can't be peeled off.



Dynamic Cracks.

It is possible to perform runtime attacks by using subtle sophisticated methods to implement conditional cracks, which are only triggered under the right circumstances, typically requiring runtime monitoring and behavioral analysis to identify. The key to succeed requires being able to identify the trigger state during runtime and essentially do this:


IF critical_triggerstate THEN do_sneaky_attack ELSE run_as_usual;


These types of attacks can be implemented in different ways and are usually extremely difficult to detect. Testing the integrity of the VM binary or applying the previously mentioned methods for preventing statical cracks may not be enough.


Carrying out a dynamic attack is not an easy task for ordinary applications in general, and for the VM binary in particular such a task can be extremely difficult and very time consuming to accomplish due to the encrypted randomized memory items and the many instructions that do not require value decryption.


How to defend:

Dynamic attacks can be prevented by making it impossible to repeatedly identify a trigger state.


In order to accomplish this in bytecode, the developer may include variations to reorder and randomize the execution flow, to constantly change the preconditions for a dynamic crack at the logical level.


The developer may also simply decide to recompile and redistribute the bytecode every now and then (even without redeploying the VM binary). When combined with time-limited functionality it shortens the window of opportunity for the cracker. The compiler will completely reorder the internal parts of the bytecode and rebuild all the encryption layers on every compilation. It does not require modification of the source.



Conclusion.

The VM is a native binary that can be attacked just like an ordinary executable. However, the developer can use bytecode to protect the VM binary, taking into account the possible threats of statical and dynamic cracks.


Protection Rooted in Bytecode:

  • An unprotected VM binary can be secured at the exact moment of execution by the bytecode it executes.
  • The level of security can be raised by the developer simply by increasing the defensive nature of the bytecode.
  • Protective measures rooted within the executed instructions cannot be removed or bypassed by a third party.


Please note: This kind of self-protection requires no external assistance. It is completely self-reliant.