Obfuscate

5. Деобфускация Obfuscator.IO

Автор сайта Obfuscator.IO ищет программы, которые способны деобфусцировать созданный на этом сервисе код и постоянно меняет, исправляет обфускацию, в результате чего инструменты по деобфускации перестают работать. Поэтому инструменты автоматической деобфускации (включая de4js) обычно отстают от самой последней версии, то есть могут деобфусцировать код созданный ранее на Obfuscator.IO, но не могут деобфусцировать последнюю версию кода. Но это не означает, что это надёжный инструмент чтобы обезопасить свой исходный код — регулярно появляются проекты, которые обходят все методы деобфускации. К тому же, специалисты на заказ могут деобфусцировать любой код.

Preserving metadata tokens

Sometimes in rare cases, you’d want to preserve the metadata tokens. Use or . Also consider using since it won’t remove any types and methods added by the obfuscator. Another useful option is . If used, the renamer won’t create Param rows for method parameters that don’t have a Param row. That way the ParamPtr table won’t be added to your assemblies. Peverify has a bug and doesn’t support it (you’ll see lots of «errors»).

The #Strings, #US and #Blob heaps can also be preserved by using , , and respectively. Of these three, is the most useful one since instruction and directly reference the #US heap.

should be used if the obfuscator adds extra data at the end of signatures that it uses for its own purpose, eg. as decryption keys. Confuser is one obfuscator that does this.

preserves all important tokens but will also enable , and .

If it’s detected as an unknown (unsupported) obfuscator (or if you force it with ), all tokens are preserved, including the #US heap and any extra data at the end of signatures. Also, no obfuscator types, fields or methods are removed.

Preserve all important tokens, #US, #Blob, extra sig data.

Preserve all important tokens, #US, #Blob, extra sig data and don’t remove types/fields added by the obfuscator

Preserve all important tokens, #US, #Blob, extra sig data and don’t create extra Param rows to prevent the ParamPtr table from being created.

Preserve all important tokens except the Param tokens.

Методы

1. Преобразование данных

Одним из наиболее важных элементов обфускации является преобразование данных, используемых программой, в иную форму, оказывающее минимальное виляние на производительность кода, но значительно усложняющее хакерам возможность обратного инжинирнга. 

2. Обфускация потока управления кодом

Обфускация потока управления может быть выполнена путем изменения порядка операторов выполнения программы. Изменение графа управления путем вставки произвольных инструкций перехода и преобразования древовидных условных конструкций в плоские операторы переключения, как показано на следующей диаграмме.

3. Обфускация адресов

Данный метод изменяет структура хранения данных, так чтобы усложнить их использование. Например алгоритм, может выбирать случайными адреса данных в памяти, а также относительные расстояния между различными элементами данных. Данный подход примечателен тем, что даже если злоумышленник и сможет «декодировать» данные, используемые приложением на каком-то конкретном устройстве, то на других устройствах он всё равно не сможет воспроизвести свой успех.

4. Регулярное обновление кода

Этот метод предотвращает атаки, регулярно выпуская обновления обфусцированного программного обеспечения. Своевременные замены частей существующего программного обеспечения новыми обфусцированными экземплярами, могут вынудить злоумышленника отказаться от существующего результата обратного анализа, так как усилия по взлому кода в таком случае могут превысить получаемую от этого ценность.

5. Обфускация инструкций ассемблера

Преобразование и изменение ассемблерного когда также может затруднить процесс обратного инжиниринга. Одним из таких методов является использование перекрывающихся инструкций (jump-in-a-middle), в результате чего дизассемблер может произвести неправильный вывод. Ассемблерный код также может быть усилен против проникновения за счёт включения бесполезных управляющих операторов и прочего мусорного кода. 

6. Обфускация отладочной информации

Отладочную информацию можно использовать для обратного проектирования программы, поэтому важно блокировать несанкционированный доступ к данным отладки. Инструменты обфускации достигают этого, изменяя номера строк и имена файлов в отладочных данных или полностью удаляя из программы отладочную информацию

N =>

netshrink

netshrink — netshrink is an exe packer aka executable compressor, application password protector and virtual DLL binder for Windows & Linux .NET applications.

NetFuscate

NetFuscate — NETFuscate is a .NET obfuscator and a .NET code protection tool that offers protection against reverse engineering of your code.

NETGuard

NETGuard — NETGuard.IO will decompose your file, encrypt your strings, data, resources, methods, will perform numerous runtime-based verifications to ensure a fully-shielded security for
your file. The list of feature can be founded on our official documentation page.

NET Reactor

NET Reactor — NET Reactor is a powerful .NET code protection and software licensing system which completely stops any decompiling.

❱ Installation

There are two ways of getting a working copy of Obfuscapk on your own computer: either
by or by
in a environment. In both cases, the first thing to do is to get a local
copy of this repository, so open up a terminal in the directory where you want to save
the project and clone the repository:

$ git clone https://github.com/ClaudiuGeorgiu/Obfuscapk.git

Docker image

Prerequisites

This is the suggested way of installing Obfuscapk, since the only requirement is to
have a recent version of Docker installed:

$ docker --version
Docker version 19.03.0, build aeac949

Official Docker Hub image

$ # Download the Docker image.
$ docker pull claudiugeorgiu/obfuscapk
$ # Give it a shorter name.
$ docker tag claudiugeorgiu/obfuscapk obfuscapk

Install

If you downloaded the official image from Docker Hub, you are ready to use the tool so
go ahead and check the , otherwise execute the following
command in the previously created directory (the folder containing the
) to build the Docker image:

$ # Make sure to run the command in Obfuscapk/src/ directory.
$ # It will take some time to download and install all the dependencies.
$ docker build -t obfuscapk .

When the Docker image is ready, make a quick test to check that everything was
installed correctly:

$ docker run --rm -it obfuscapk --help
usage: python3 -m obfuscapk.cli  -o OBFUSCATOR  
...

Obfuscapk is now ready to be used, see the for more
information.

Prerequisites

$ apktool
Apktool v2.5.0 - a tool for reengineering Android apk files
...
$ apksigner
Usage:  apksigner <command> 
        apksigner --version
        apksigner --help
...
$ zipalign
Zip alignment utility
Copyright (C) 2009 The Android Open Source Project
...

To install and use you need a recent version of Java.
and are included in the Android SDK. The location of the
executables can also be specified through the following environment variables:
, and (e.g., in Ubuntu, run
before running Obfuscapk in the same
terminal).

Apart from the above tools, the only requirement of this project is a working
(at least ) installation (along with its package manager ).

Install

Run the following commands in the main directory of the project () to
install the needed dependencies:

$ # Make sure to run the commands in Obfuscapk/ directory.

$ # The usage of a virtual environment is highly recommended, e.g., virtualenv.
$ # If not using virtualenv (https://virtualenv.pypa.io/), skip the next 2 lines.
$ virtualenv -p python3 venv
$ source venv/bin/activate

$ # Install Obfuscapk's requirements.
$ python3 -m pip install -r src/requirements.txt

After the requirements are installed, make a quick test to check that everything works
correctly:

$ cd src/
$ # The following command has to be executed always from Obfuscapk/src/ directory
$ # or by adding Obfuscapk/src/ directory to PYTHONPATH environment variable.
$ python3 -m obfuscapk.cli --help
usage: python3 -m obfuscapk.cli  -o OBFUSCATOR  
...

Obfuscapk is now ready to be used, see the for more
information.

Utilization

Certain languages like Java and .NET can be easily decompiled into readable source code. Code obfuscation is a process that makes your application binaries harder to read with a decompiler. It’s an important tool for protecting your business’s intellectual property.

Why Obfuscate Code?

Compiled languages like C++ get converted directly to bytecode. The only way to reverse engineer how they work is with a disassembler, which is an arduous and complicated process. It’s not impossible, but trying to infer high level application logic from a stream of assembly language is hard.

On the other hand, languages like C# and Java aren’t compiled for any particular operating system. Rather, they’re compiled to an intermediary language, like .NET’s MSIL. The intermediary language is similar to assembly, but it can be easily converted back into the source code. This means that if you have a public DLL or executable that your business is distributing, anyone with a copy of your executable can open it up in a .NET decompiler like dotPeek, and directly read (and copy) your source code.

Code obfuscation can’t prevent this process—any .NET DLL can be plugged into a decompiler. What obfuscation does do is use a number of tricks to make the source code annoying as hell to read and debug.

The simplest form of this is entity renaming. It’s common practice to properly name variables, methods, classes, and parameters according to what they do. But you don’t have to, and technically there’s nothing stopping you from naming them with a series of lowercase L’s and I’s, or random combinations of Chinese unicode characters. To the computer, there’s no issue, but it’s completely illegible to a human:

An basic obfuscator will handle this process automatically, taking the output from the build, and converting it to something that’s a lot harder to read. There’s no performance hit compared to non-obfuscated code

More advanced obfuscators can go further, and actually change the structure of your source code. This includes replacing control structures with more complicated but semantically identical syntax. They can also insert dummy code that doesn’t do anything except confuse the decompiler. The effect of this is that it makes your source look like spaghetti code, making it more annoying to read.

Another common focus is hiding strings from decompilers. In managed executables, you can search for strings like error messages to locate sections of code. String obfuscation replaces strings with encoded messages, which are decrypted at runtime, making it impossible to search for them from a decompiler. This usually comes with a performance penalty.

Other Options: Convert to a Compiled Language

Converting one programming language to another isn’t an entirely crazy idea—Unity uses IL2CPP, a converter that transforms .NET code into compiled C++ bytecode. It’s a lot more performant, but it also helps secure games against easy cracking, which is crucial for an environment plagued by piracy and cheaters.

Microsoft has CoreRT, an experimental .NET Core runtime using Ahead-Of-Time compilation, though it isn’t ready for production use.

Should You Obfuscate?

If you’re deploying code in untrusted environments where you want to protect your source code, you should almost always use at least a basic obfuscator to rename functions, methods, and properties to make decompiling take a bit more effort.

If you really need nobody to be able to decompile your app, you can use a more intrusive obfuscator, but really you should consider if the problem would be better solved by switching to a language that doesn’t have this issue, such as C++ or Rust.

Dynamically decrypting strings

Although supports a lot of obfuscators, there’s still some it doesn’t support. To decrypt strings, you’ll first need to figure out which method or methods decrypt strings. To get the method token of these string decrypters, you can use ILDASM with the ‘show metadata tokens’ option enabled. A method token is a 32-bit number and begins with 06, eg. 06012345.

This command will load assembly file1.dll into memory by calling . When it detects calls to the two string decrypters (06012345 and 060ABCDE), it will call them by creating a dynamic method, and save the result (the decrypted string). The call to the string decrypter will be removed and the decrypted string will be in its place.

Since the assembly is loaded and executed, make sure you run this in a sandbox if you suspect the file to be malware.

❱ Usage

From now on, Obfuscapk will be considered as an executable available as ,
so you need to adapt the commands according to how you installed the tool:

  • Docker image: a local directory containing the application to obfuscate has to be
    mounted to in the container (e.g., the current directory ), so the
    command:

    $ obfuscapk 

    becomes:

    $ docker run --rm -it -u $(id -u):$(id -g) -v "${PWD}":"/workdir" obfuscapk 
  • From source: every instruction has to be executed from the
    directory (or by adding directory to environment
    variable) and the command:

    $ obfuscapk 

    becomes:

    $ python3 -m obfuscapk.cli 

Let’s start by looking at the help message:

$ obfuscapk --help
obfuscapk  -o OBFUSCATOR     
           
            
          <APK_FILE>

There are two mandatory parameters: , the path (relative or absolute) to
the apk file to obfuscate and the list with the names of the obfuscation techniques to
apply (specified with a option that can be used multiple times, e.g.,
). The other optional arguments are as
follows:

  • is used to set the working directory where to save the intermediate files
    (generated by ). If not specified, a directory named
    is created in the same directory as the input application. This can be useful for
    debugging purposes, but if it’s not needed it can be set to a temporary directory
    (e.g., ).

  • is used to set the path of the destination file: the apk file generated
    by the obfuscation process (e.g., ). If not
    specified, the final obfuscated file will be saved inside the working directory.
    Note: existing files will be overwritten without any warning.

  • is a flag for ignoring known third party libraries during the obfuscation
    process, to use fewer resources, to increase performances and to reduce the risk of
    errors. The
    list of libraries
    to ignore is adapted from LiteRadar project.

  • is a flag for showing progress bars during the obfuscation operations. When
    using the tool in batch operations/automatic builds it’s convenient to have progress
    bars disabled, otherwise this flag should be enabled to see the obfuscation progress.

  • is needed only when using obfuscator, to set the API
    key to be used when communicating with Virus Total.

  • , ,
    and can be used to specify a
    custom keystore (needed for the apk signing). If is used,
    and must be specified too, while
    is needed only if the chosen key has a different password from the keystore password.
    By default (when is not specified), a
    keystore bundled with Obfuscapk
    is used for the signing operations.

  • is a path to a file which includes
    package names to be ignored. All the classes inside those packages will not be
    obfuscated when this option is used. The file should have one package name per line as
    shown in the example below:

  • is a flag for use aapt2 option to rebuild app when using apktool.

Let’s consider now a simple working example to see how Obfuscapk works:

$ # original.apk is a valid Android apk file.
$ obfuscapk -o RandomManifest -o Rebuild -o NewAlignment -o NewSignature original.apk

When running the above command, this is what happens behind the scenes:

  • since no working directory was specified, a new working directory
    () is created in the same location as (this can
    be useful to inspect the files/manifest/resources in case of errors)

  • some checks are performed to make sure that all the needed files/executables are
    available and ready to be used

  • the actual obfuscation process begins: the specified obfuscators are executed
    (in order) one by one until there’s no obfuscator left or until an error is encountered

    • when running the first obfuscator, is decompiled with
      and the results are stored into the working directory

    • since the first obfuscator is , the entries in the decompiled
      Android manifest are reordered randomly (without breaking the structures)

    • obfuscator simply rebuilds the application (now with the modified
      manifest) using , and since no output file was specified, the resulting
      apk file is saved in the working directory created before

    • obfuscator uses tool to align the resulting apk file

    • obfuscator signs the newly created apk file with a custom
      certificate contained in a
      keystore bundled with Obfuscapk
      (though a different keystore can be specified with the parameter)

  • when all the obfuscators have been executed without errors, the resulting obfuscated
    apk file can be found in , signed,
    aligned and ready to be installed into a device/emulator

As seen in the previous example, , and
obfuscators are always needed to complete an obfuscation operation, to build the final
obfuscated apk. They are not actual obfuscation techniques, but they are needed in the
build process and so they are included in the list of obfuscators to keep the overall
architecture modular.

Not working as expected? See
FAQ and
troubleshooting.

Obfuscated code

Luyten + Procyon

Without

public class HelloWorld {
    public HelloWorld() {
        super();
    }
    
    public static void main(final String[] args) {
        System.out.println("Hello World");
        for (int i = ; i < 10; ++i) {
            System.out.println(i);
        }
    }
}
public class HelloWorld {
    
    public static void main(final String[] array) {
        // invokedynamic(1:(Ljava/io/PrintStream;Ljava/lang/String;)V, invokedynamic(0:()Ljava/io/PrintStream;), HelloWorld.llII])
        float lllllllIlIllIII = HelloWorld.lllI[];
        while (llIll((int)lllllllIlIllIII, HelloWorld.lllI)) {
            // invokedynamic(2:(Ljava/io/PrintStream;I)V, invokedynamic(0:()Ljava/io/PrintStream;), lllllllIlIllIII)
            ++lllllllIlIllIII;
            "".length();
            if (" ".length() == (" ".length() << ("   ".length() << " ".length()) & ~(" ".length() << ("   ".length() << " ".length())))) {
                throw null;
            }
        }
    }
    
}

❱ Architecture

Obfuscapk is designed to be modular and easy to extend, so it’s built using a
plugin system. Consequently, every obfuscator is
a plugin that inherits from an abstract
base class
and needs to implement the method . When the tool starts processing a new
Android application file, it creates an
obfuscation object
to store all the needed information (e.g., the location of the decompiled code)
and the internal state of the operations (e.g., the list of already used obfuscators).
Then the obfuscation object is passed, as a parameter to the method, to all
the active plugins/obfuscators (in sequence) to be processed and modified. The list and
the order of the active plugins is specified through .

The tool is easily extensible with new obfuscators: it’s enough to add the source code
implementing the obfuscation technique and the plugin metadata (a
file) in the

directory (take a simple existing obfuscator like

as a starting example). The tool will detect automatically the new plugin, so no
further configuration is needed (the new plugin will be treated like all the other
plugins bundled with the tool).

August 2015

ADVobfuscator code has been updated for Visual Studio 2015. ADVobfuscator is now compatible with the RTM release of Visual Studio 2015 (previous versions or CTP releases are not). The whitepaper is not yet updated. The code has also been modified in order to avoid problems with optimization and . with defeats obfuscation (because it optimizes too much) and sometimes generates wrong code (not clear yet if it is a bug in or in ADVobfuscator).

How to use it?

First you have to follow the requirements below. Then, you just have to include ADVobfuscator header files and use macros such as to protect your strings or function calls.

Look at the examples in the folder.

Виды обфускации

Преобразования бывают четырех видов:

  • лексическая обфускация;
  • преобразование данных;
  • преобразование управления;
  • профилактическая обфускация.

Лексическая обфускация — замена названий переменных и функций. Например, понятная раннее final_cost превращается в бездушную f5rq. Или вот ещё сравните:

А если переменных не две, а полтора десятка? Читать и понимать такое сложно. Этот вид обфускации простой для быстрого применения, но малоэффективный: меняются только названия методов, а общая схема работы остается неизменной. Современные IDE умеют искать использования методов в коде, это очень упрощает анализ обфусцированного кода. Обход такой обфускации вопрос времени.

Преобразование данных более сложная и эффективная операция. Она включает в себя изменение и создание новых типов данных и применение к ним комбинаторики. Например, число 9 можно представить, как 10000000001 (количество нулей), 210019 (двоичное число между идентификаторами начала и конца), 32 (32) и ещё огромным количеством способов. Или замена выражения i=1 для простого цикла перечисления на i0=21 c последующим представлением через другие константы — i=i0/i1-i2, где i1=7, i2=2. Что касается типов данных, то в простейшем случае можно представлять 32-битные числовые данные перемножением 16-битным на некоторую переменную со значением 16.

Преобразование управления — нарушение естественного хода программы, для чего используются непрозрачные предикаты. То есть это случай, когда результат исполняемых действий трудно предугадать в ходе заданной процедуры. В простейшем случае это создание дополнительных блоков кода: в одном выполняются вычисления, в другом происходит наследование, а в каком-то общем — несколько ложных операций, лишь одна из которых действительная. В более сложных ситуациях создаётся комплексная карта замещений и трансформаций, до неузнаваемости меняющих общую структуру кода.

Профилактическая обфускация защищает ваш код от деобфускации специальными программами-деобфускаторами

Они основываются на обнаружении неиспользуемых кусков кода, нахождении наиболее сложных структур (фрагментов максимальной важности) и анализе статистических и динамических данных. Именно борьба с этими операциями — наиболее сложный и эффективный процесс обфускации

Здесь необходимо максимально точно подойти к анализу исходных данных, задействовать максимум предоставленных ресурсов, учесть подходы потенциальных оппонентов.

Без опыта ручной обфускации создать непроходимый лабиринт не получится, требуется помощь специалистов. В сети можно отыскать массу бесплатных, платных и взломанных обфускаторов. Последний вид наиболее бесполезен: программа защиты, не способная защитить себя — сомнительный выбор. Бесплатные обфускаторы неплохи, но в силу своего распространения имеют универсальный и не самый сложный подход. Плюс, надежность процедуры запутывания также можно поставить под вопрос — если программа легко доступна, то ее алгоритмы несложно проанализировать и найти обратный алгоритм. Поэтому, если вы действительно собрались хорошо заработать на своем коде — не пожалейте денег на организацию грамотной обфускации.

Хорошо запутанная программа, закрытая надёжным паролем — уже головная боль для потенциального взломщика. Но и обфускация еще не финальный оплот защиты.

В следующей части — защита от отладчиков, протекторы, лицензии и программы слежения.

 А тем, кто определился с тем, что хочет стать программистом, рекомендуем профессию «Веб-разработчик».

Debug Builds

Debug builds are very special: Compiler do not have (and do not most of the time) respect statement such as or . All optimizations are also, by default, disabled. Compilers are doing this for a good reason: let you debug, single step, etc.

As a consequence, ADVobfuscator is not compatible with Debug builds. It works only for Release builds.

Compatibility

ADVobfuscator has been tested with:

  • Xcode (LLVM) 8.1.0 under Mac OS X 10.12
  • GCC 7.2.0 under Debian 10 (buster — testing)
  • Visual Studio 2017 (15.3.3) under Windows 10
  • Boost 1.65.0

Other compilers are probably compatible if they are compliant.

Future Directions

These are ideas for the next few months:

  • Switch to and . It will simplify some parts of the code and is now well supported by compilers such as and
  • Try to better support Visual Studio 2015, but only if it does not implies a restructuring of the code
  • Introduce White Box Cryptography (AES in particular). Still in my mind but I am not very active for the moment
  • Is my code compatible with ASLR? In fact, I don’t konw and I have to solve this (I need it for another project)
  • Apply the techniques used in into
  • )ntroduce Unit Testing

Files and Folders

Files and Folders Description
This file
ADVobfuscator library
Examples of using ADVobfuscator
Make file that build all the examples
Example of using ADVobfuscator to obfuscate strings
Example of using ADVobfuscator to obfuscate function calls
Example of using ADVobfuscator to obfuscate function calls triggered by a predicate
My talks and white papers
Code memtionned in the documents

Lib

Files Description
Generate list of indexes at compile time (0, 1, 2, … N)
Template to generate Finite State Machines at compile time
Generate a pseudo-random number at compile time
Obfuscated string — version 4 — Random encryption algorithm
Obfuscate function call
Obfuscate function call, execute a FSM based on a predicate
Project for Apple Xcode
Visual Studio 2015 Solution

DocCode

Files Description
Compute factorial at compile time
Compute fibonacci sequence at compile time
Obfuscated string — version 1
Obfuscated string — version 2 — Remove truncation
Obfuscated string — version 3 — Random key
Obfuscated string — version 4 — Random encryption algorithm

Examples

Files Description
Debugger detection, implemented for Mac OS X and iOS. It is used by (FSM)
Debugger detection, declaration
Samples
Simple makefile for
Visual Studio 2017 Solution
Xcode workspace

Written by Sebastien Andrivet — Copyright 2010-2017 Sebastien Andrivet.