Защита ваших приложений xamarin с помощью dotfuscator

Python

After installing, to beautify using Python:

$ js-beautify file.js

Beautified output goes to by default.

To use as a library is simple:

import jsbeautifier
res = jsbeautifier.beautify('your javascript string')
res = jsbeautifier.beautify_file('some_file.js')

…or, to specify some options:

opts = jsbeautifier.default_options()
opts.indent_size = 2
opts.space_in_empty_paren = True
res = jsbeautifier.beautify('some javascript', opts)

The configuration option names are the same as the CLI names but with underscores instead of dashes. The example above would be set on the command-line as .

Options

These are the command-line flags for both Python and JS scripts:

Which correspond to the underscored option keys for both library interfaces

defaults per CLI options

{
    "indent_size": 4,
    "indent_char": " ",
    "indent_with_tabs": false,
    "editorconfig": false,
    "eol": "\n",
    "end_with_newline": false,
    "indent_level": ,
    "preserve_newlines": true,
    "max_preserve_newlines": 10,
    "space_in_paren": false,
    "space_in_empty_paren": false,
    "jslint_happy": false,
    "space_after_anon_function": false,
    "space_after_named_function": false,
    "brace_style": "collapse",
    "unindent_chained_methods": false,
    "break_chained_methods": false,
    "keep_array_indentation": false,
    "unescape_strings": false,
    "wrap_line_length": ,
    "e4x": false,
    "comma_first": false,
    "operator_position": "before-newline",
    "indent_empty_lines": false,
    "templating": 
}

defaults not exposed in the cli

{
  "eval_code": false,
  "space_before_conditional": true
}

Notice not all defaults are exposed via the CLI. Historically, the Python and
JS APIs have not been 100% identical. There are still a
few other additional cases keeping us from 100% API-compatibility.

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.

Node.js JavaScript

When installed globally, the beautifier provides an executable script. The beautified result is sent to unless otherwise configured.

$ js-beautify foo.js

To use as a library (after install locally), import and call the appropriate beautifier method for javascript (js), css, or html. All three method signatures are . is the string of code to be beautified. options is an object with the settings you would like used to beautify the code.

The configuration option names are the same as the CLI names but with underscores instead of dashes. For example, would be .

var beautify = require('js-beautify').js,
    fs = require('fs');

fs.readFile('foo.js', 'utf8', function (err, data) {
    if (err) {
        throw err;
    }
    console.log(beautify(data, { indent_size: 2, space_in_empty_paren: true }));
});

Что такое обфускация в JavaScript?

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

К примеру, есть код: 

function hello(name) {
    console.log('Hello, ' + name);
}
hello('New user');

Теперь рассмотрим тот же код, запутанный онлайн-обфускатором JavaScript:

eval(function(p,a,c,k,e,d){e=function(c){returnc};if(!''.replace(/^/,String)){while(c--){d=k||c}k=}];e=function(){return'\\w+'};c=1};while(c--){if(k){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k)}}return p}('3 0(1){2.4(\'5, \'+1)}0(\'7 6\');',8,8,'hello|name|console|function|log|Hello|user|New'.split('|'),0,{}))

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

Directives

Directives let you control the behavior of the Beautifier from within your source files. Directives are placed in comments inside the file. Directives are in the format in CSS and JavaScript. In HTML they are formatted as .

Ignore directive

The directive makes the beautifier completely ignore part of a file, treating it as literal text that is not parsed.
The input below will remain unchanged after beautification:

// Use ignore when the content is not parsable in the current language, JavaScript in this case.
var a =  1;
/* beautify ignore:start */
 {This is some strange{template language{using open-braces?
/* beautify ignore:end */

Preserve directive

NOTE: this directive only works in HTML and JavaScript, not CSS.

The directive makes the Beautifier parse and then keep the existing formatting of a section of code.

The input below will remain unchanged after beautification:

// Use preserve when the content is valid syntax in the current language, JavaScript in this case.
// This will parse the code and preserve the existing formatting.
/* beautify preserve:start */
{
    browserName: 'internet explorer',
    platform:    'Windows 7',
    version:     '8'
}
/* beautify preserve:end */

License

You are free to use this in any way you want, in case you find this useful or working for you but you must keep the copyright notice and license. (MIT)

Credits

  • Created by Einar Lielmanis, einar@beautifier.io
  • Python version flourished by Stefano Sanfilippo a.little.coder@gmail.com
  • Command-line for node.js by Daniel Stockman daniel.stockman@gmail.com
  • Maintained and expanded by Liam Newman bitwiseman@beautifier.io

Thanks also to Jason Diamond, Patrick Hof, Nochum Sossonko, Andreas Schneider, Dave
Vasilevsky, Vital Batmanov, Ron Baldwin, Gabriel Harrison, Chris J. Shull,
Mathias Bynens, Vittorio Gambaletta and others.

(README.md: js-beautify@1.14.0)

Как это работает

Большинство методов обфускации преобразуют следующие аспектов кода:

• Данные: делают элементы кода похожими на то, чем они не являются

• Поток кода: выставляют исполняемую логику программы абсурдной или даже недетерминированной

• Структура формата: применяют различное форматирование данных, переименование идентификаторов, удаление комментариев кода и т.д.

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

При обфускации кода, важно правильно оценить, какие части когда можно эффективно запутать. Следует избегать обфускации кода, критичного относительно производительности

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;
            }
        }
    }
    
}

О статье

Статья рассчитана на ознакомление с темой оптимизации сборок Android приложений. В статье:

  • . Обозначим общие требования к сборкам мобильных приложений;

  • . Поговорим о том, как приложения собираются и как этот процесс можно оптимизировать;

  • . Познакомимся с ProGuard и тем, как он оптимизирует сборки;

  • . Углубимся в проблему обфускации кода;

  • . Узнаем, что такое D8, R8 и обозначим их место в процессе сборки.

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

4. JavaScript online deobfuscator deobfuscatejavascript.com

Service Address: http://deobfuscatejavascript.com/

The source code of this service is not hosted on GitHub, but this product is also open source, since all operations are performed in the browser, and the deobfuscation functions are located in the file http://deobfuscatejavascript.com/deobfuscate.js.

The code analyzed by this tool will be executed in your browser. This tool is designed only to intercept calls made by the eval() and write() functions, which are commonly used as the final function in malicious JavaScript scripts. Some malicious scripts may not use these features and therefore may infect your browser.

This tool is designed to help analysts deobfuscate malicious JavasSripts. It does not interpret HTML, so any HTML must be removed to properly deobfuscate the code. The script also should not contain syntax errors to get the correct results.

Black holes, landing pages, and exploit kits use obfuscation to hide code intent while reducing the chance of detection. When the scripts are packaged, the source code becomes data, and the visible code becomes a deobfuscation procedure. At run time, the data is unpacked by the subroutine, and the result is a string that must be processed as code to execute. This tool during the deobfuscation procedure returns this line of code, but does not start its execution. The resulting code is shown with syntax highlighting.

What is obfuscation?

Obfuscation is source code modification as a result it becomes difficult to read and understand, but so that its functionality does not change. Obfuscation is used for source code in interpreted (rather than compiled) programming languages. That is, it is JavaScript, PHP, obfuscation can be used for HTML (although it is a markup language, not a programming language), CSS and others, programs on which do not compile, but run in plain text.

Obfuscation is especially relevant for JavaScript, because, unlike, for example, PHP that runs on the web server, JavaScript is loaded into the browser and each user can have access to scripts.

Obfuscation uses different tricks. One of them is the removal of spaces. This is called code minify and is used not only to obfuscate, but to speed up script downloads. As a side effect, this code is really hard to figure out.

Often during obfuscation, the code turns into a meaningless set of functions and lines that cannot be understood, but which ultimately do exactly the same thing as the source code. But there are really amazing examples of obfuscation, for example, JSFuck can display any JavaScript code with just the following six characters []()!+

For example, the following code is workable JavaScript code:

[]+[])]+(]+[]])+]]+(![]+[])+!+[]]+(!![]+[])]+(!![]+[])+!+[]+!+[]]+(!![]+[])]]+[])]+(]+[]
])+]]+(![]+[])+!+[]]+(!![]+[])]+(!![]+[])+!+[]+!+[]]+
(!![]+[])]]+[])+!+[]+!+[]]+(!![]+[]+[])]+(]+[]])+]]+(![]+[])+!+[]]+(!![]+[])]+(!![]+[])+!+[]+!+[]]+(!!+[])]])+]]+([]]+[])]+(![]+[])+!+[]+!+[]]+(!![]
+[])]+(!![]+[])]+([]]+[])]+([]+[])]+(]+[]])+]]+(![]+[])+!+[]]+(!![]+[])]+(!![]+[])+!+[]+!+[]]+(!!
[]+[])]]+[])+!+[]+!+[]]+(!![]+[])]+(!![]+[]+[])]+(]+[]])+]]+(![]+[])+!+[]]+(!![]+[])]+(!![]+[])+!++!+[]]+(!![]+[])]])+]]+(!![]+[])]]((![]+[])]+(!+[])+!+[]]+(!![]+[])+!+[]+!+[]]+(!![]+[])]+(!![]+[])]+(!
[]+[]+[])]+(]+[]])+]]+(![]+[])+!+[]]+(!![]+[])
]+(!![]+[])+!+[]+!+[]]+(!![]+[])]])+!+[]+]]+]+(
!![]+[]+[])]+(]+[]])+]]+(![]+[])+!+[]]+(!![]+)]+(!![]+[])+!+[]+!+[]]+(!![]+[])]])+!+[]+]])()

Obfuscation is used by both legitimate users who want to protect their ideas and their code from theft, and hackers to make it difficult to analyze their methods and programs.

Parse Modern JavaScript

JavaScript is a fast-evolving language. This means that tools must keep pace with the development of new syntax in order to stay useful. In practice, this is kept in check by the fact that not all clients support the new features and users may not be using the newest versions. To reach the most users possible, legitimate websites and attackers are incentivised to limit their use of the latest syntax. Some ES6 language features are useful when used to generate more readable code output. For example, marking inferred constant variables with the keyword serves as an indicator to the reader of the de-obfuscated code.

Input Output
var a = 1; const a = 1;
var b = a + a; const b = 2;

D8, R8

При изучении вопроса оптимизации сборок Android приложений можно наткнуться на эти две аббревиатуры. Разберёмся, что они значат и какое отношение имеют к оптимизации  сборок, PG и Android в целом.

Небольшой спойлер. До погружения в вопрос оптимизации сборок, я думал, что использую ProGuard.

Вспомним:

ProGuard, ProGuard, ProGuard… Оказывается, что фактически я использовал R8 (начиная с AGP версии 3.4). Также я думал, что использую DX, но фактически использовал D8 (начиная с AGP версии 3.2).

Почему так вышло? Читайте далее.

D8

Определение

Что такое D8? Google (его создатели) позиционирует D8 как dex компилятор нового поколения.

К слову. Он используется по умолчанию . Именно поэтому я не заметил его появление в своей жизни: всего лишь обновил AGP, а тут вот что. Урок — читайте release notes продуктов, которые используете.

Мотивация

Зачем он нужен? Вспомним схему встраивания  PG при сборке приложения. .dex файл компилируется DX компилятором.

Вырезка из схемы сборки Android приложения: этапы java (kotlin), dex компиляции

Так выглядел процесс компиляции .dex до появления D8

Обратите внимание на количество шагов: 2 — для Kotlin кода, 3 — для Java

Что стало после появления D8:

Схема этапов сборки при использовании D8

D8 вобрал себя этап desugar, тем самым сократил общее число шагов компиляции: 2 — для Kotlin кода, 2 — для Java.. К чему это привело?

D8 vs DX

Google приводить сравнительный анализ компиляторов DX (используемый по умолчанию до появления D8) и нового D8

Обратите внимание:

  • D8 ощутимо быстрее компилирует исходный код;

  • Размер выходного .dex немного меньше при использовании D8.

Сравнение размеров выходных .dex файлов при использовании DX и D8. Небольшое преимущество D8Сравнение скорости компиляции .dex файлов при использовании DX и D8. Победа D8: время сократилось на треть

R8

Определение

R8, как и D8, разрабатывается Google и также связан со сборкой Android приложений. Но R8 — не .dex компилятор, он — оптимизатор.

R8 используется по умолчанию вместо PG. Тут я опять удивился положению вещей. Особенно потому, что раньше я писал правила для ProGuard, а понимает их R8. 10 очков Google за хорошую совместимость c PG правилами. Повторяю урок — читайте release notes продуктов, которые используете.

Мотивация

Посмотрим, чем мотивировал себя Google при разработке этого оптимизатора. Так выглядел процесс сборки до появления R8.

Схема этапов сборки при использовании PG

Так он стал выглядеть после:

Схема этапов сборки при использовании R8

История схожа с D8: оптимизировать процесс сборки за счет сокращения промежуточных этапов. Но! Вспомните еще один момент, чей ProGuard?  —  GuardSquare, а чей R8? — Google. Отсюда можно сделать еще один вывод о мотивации Google к созданию R8 — замена сторонней технологии свой собственной. И тут родился конфликт…

R8 vs ProGuard

Появилось две статьи (сначала от Google, потом о GuardSquare) со сравнительным анализом R8 и ProGuard.

Вкратце, о чем пишет Google:

  • R8 (в комбинации с D8) в compact и full режимах почти в 2 раза быстрее “шринкует” и компилирует .dex.

  • Размер выходного .dex немного меньше, чем у PG.

Сравнение скорости выполнения shrink и dex компиляцииСравнение размеров выходных dex файлов

Не нужно забывать, что Google, как владелец Android, имеет бОльшее влияние на развитие платформы и сопутствующих технологий. Именно поэтому они могут позволить себе заменить DX компилятор на D8 (один из основных этапов (см. раздел Оптимизация сборки) и встроить сверху R8.

Также GuardSquare утверждает, что ProGuard работает быстрее при малом количестве итераций, но тут стоит сделать одно замечание: чем меньше итераций, тем меньше оптимизаций, как следствие бОльший размер .apk, менее оптимизированный код.

Стоит отдать должное GuardSquare за то, что их продукт разрабатывается более 15 лет, в то время как R8 стал доступен в лишь 2018.

Резюме

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

Подведем итоги:

  • Задача, сторонние сервисы, мобильное приложение — вот компоненты, от которых зависит итоговый размер приложения, скорость его работы и безопасность его использования. Требования, предъявляемые к каждой из этих компонент,  определяют итоговое решение.

  • Процесс сборки Android приложений состоит из основных этапов: java / kotlin компиляция, dex компиляция. Между основными этапами определены строгие контракты, поддерживая которые можно встроить дополнительные этапы. Например, оптимизация кода, ресурсов.

  • Оптимизация сборки в общем случае состоит из этапов: сокращение кода, ресурсов (память); оптимизация кода (скорость); обфускация (безопасность).

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

  • ProGuard — java байт-код оптимизатор, способный оптимизировать сборки Android приложений. Разработан GuardSquare.

  • D8, R8 — технологии, разработанные Google, призванные улучшить процесс сборки (D8) и ее оптимизации (R8). R8 — позиционируется как замена ProGuard. Что использовать в итоге — решать вам.

Зачем это нужно?

Как известно, одним из основных методов взлома программного обеспечения является исследование кода, полученного в результате работы дизассемблера на предмет уязвимостей. На основе такого когда нетрудно, например, составить программу генерации ключей активации коммерческого программного обеспечения или, наоборот, внести в исполняемый файл изменение — патч, позволяющий злоумышленникам отключить «нежелательные» модули исходной программы.

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

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

Нужно ли обфусцировать код?

Основным условием использования обфускатора является то, что ваш исходный код в JavaScript должен стать недоступным для чтения. Когда же это может понадобиться? Приведем несколько реальных примеров, когда код обязательно должен быть запутан.

Когда вы продаете шаблон сайта

На рынке шаблонов веб-сайтов важно защитить вашу работу. К примеру, на Themeforest пользователям перед покупкой доступен предварительный просмотр шаблона

Это означает, что в своей работе вы будете использовать HTML, CSS и JS. Поэтому, если не обфусцируете код, каждый сможет загрузить ресурсы из предварительного просмотра вашего веб-сайта и работать с ними, не покупая шаблон.

Когда вы используете JavaScript в браузерных играх

Если вы разрабатываете видеоигры в браузере с использованием любого игрового движка JavaScript, то вам наверняка захочется защитить код от чтения другими программистами или кого-то, кто попытается нарушить правила в вашей игре. С помощью обфускатора код будет намного сложнее понять.

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.