- Регистрация
- 16.01.2019
- Сообщения
- 656
- Благодарностей
- 1 061
- Баллы
- 93
Материал, как по мне, получился интересный, но немного технический, поэтому может не всем зайдёт, однако я даже мельком посмотрел на cloudflare, чего изначально в планах совсем не было.
По содержанию:
- Часть 0(текст данной статьи). Эту часть можно рассматривать как введение в то, чем мы будем заниматься.
- Часть 1(первое видео). Здесь мы знакомимся с AST(Abstract Syntax Tree), а также с инструментарием для дальнейшей работы, деобфусцируем PixelScan.net, а ещё кратко рассматриваем разные виды обфускации JavaScript.
- Часть 2(второе видео). Данная часть, наверное, получилась самой интересной, хотя изначально планов по её созданию не было. Здесь мы рассматриваем CloudFlare, его обфускацию, а также автоматизируем извлечение данных для составления первого запроса(Готового решения "CloudFlare POST/GET" нет). Материал данной части полезен не только юным JS-реверсерам, но и людям, которые учатся/любят писать шаблоны на запросах, но пока обходят сложные случаи стороной, потому что не знают к чему подступиться.
- Часть 3(третье видео). В этой части мы связываем получившееся приложение из второй части на NodeJS с ZennoPoster.
В добрый путь....
Обфускация кода, проще говоря, - это "процесс запутывания кода" с целью затруднить анализ программы, однако результат работы одного и того же обфусцированного и не обфусцированного кода должен быть одинаковым.
Под деобфускацией будем понимать обратный процесс ("процесс распутывания кода"), то есть приведения кода к более читабельному виду, чтобы упростить понимание работы программы.
В качестве примера возьмём PixelScan.net, хотя бы потому что он многим знаком, а ещё на нём наглядно можно продемонстрировать некоторые моменты.
Рассматривая скрипты можно сразу заметить парочку интересностей:
- Вместо нормального нейминга переменных у нас какая-то белиберда, соотвественно зачем эта переменная нужна мы можем понять только проследив за тем, как и где она используется. К сожалению, автоматически сделать нормальный смысловой нейминг возможным не представляется. Но, если честно, не так уж это и мешает, а порой, даже помогает. Почему это не страшно, мы поймём немного позже, сейчас пока не будем забегать вперед.
- Большое количество скорее мёртвого кода, то есть такого кода, который никогда не будет выполняться. Эти мысли посещают сразу, когда видим кучу какого-то однообразного барахла, как это:
С некоторым мёртвым кодом замечательно справляются минификаторы(UglifyJs, Google Closure Compiler), а с каким-то придётся повозиться вручную(точнее говоря написать скрипт, который удалит что-то по заданным признакам). Гуглить данную тему можно запросом "Dead code elimination".
- Вишенкой на торте являются фрагменты кода вида x[call(123)]:
Людей, знакомых с JS, сразу посещает мысль о том, что внутри [...] должна находиться строка, ведь конструкция
x['y']
говорит говорит об обращении к свойству 'y'
объекта x
. Мы можем тормознуть скрипт, нажать esc(или открыть вкладку консоли), дабы поработать с консолью в текущем контексте, и убедиться в своей правоте, выполнив несколько вызовов:На самом деле такое сокрытие строк является основной проблемой при работе с данным кодом, ведь мы понятия не имеем что где вызывается, что конкретно делает какой-нибудь фрагмент кода и тд... Например, если бы отчётливо увидели строку кода
window['navigator']['userAgent']
, то могли бы предположить, что в данном месте начинается сбор данных о браузере и на всём, что следует дальше, стоит заострить внимание. Вместо такой строки в данном скрипте мы увидим что-то типа window[x(123)][x(321)]
. Или, например, при ошибках в консоли зеннопостера по типу 'test failed: C4', мы бы могли использовать поиск по тексту скрипта, чтобы посмотреть, где этот test failed выводится, и что это за "C4" такой.
Для того чтобы заменить строкой вызовы функций внутри свойств объекта нужно понять что делает функция и что это за аргумент(об этом ниже в видео). После того, как мы найдём нужную нам информацию, можно приступать к замене данных фрагментов. Но как это сделать?
С одной стороны, для изменения текста программы можно использовать регулярные выражения, но дело в том, что JavaScript немного своеобразный язык программирования, который допускает всякие мыслимые и немыслимые конструкции. Например, введём в консоли
+!+{}
- и результатом будет 1
! Обфускаторы могут этим пользоваться для того, чтобы усложнять нам жизнь. Сходу так и не поймёшь, что это какое-то выражение, а выражение, как известно, может быть вычислено. Следовательно, использование регулярок нам не очень подходит, поэтому лучше использовать что-то другое, а ещё лучше что-то готовое... Это я так плавно вас подвожу к абстрактным синтаксическим деревьям.Для начала стоит немного отойти от темы и понять, что происходит, когда наша программа выполняется, а точнее, какие есть промежуточные представления у нашей программы.
Первый этап - лексический анализ. Программа, которая им занимается известна как лексер/токенайзер(Lexer/Tokenizer). Она призвана разбить наш текст на лексемы(токены), то есть на некие неделимые единицы. Допустим, у нас есть программа, которая состоит из одного объявления переменной:
let a = 2
. Тогда результатом работы токенайзера будет какой-то такой массив(stream of tokens):
Код:
[
{ type: 'Keyword', value: 'let' },
{ type: 'Identifier', value: 'a' },
{ type: 'Punctuator', value: '=' },
{ type: 'Numeric', value: '2' }
]
Но токенайзер не может проверить синтаксически ли корректно написана наша программа, везде ли вы, например, где требуется, поставили
;
. Синтаксическую корректность программы проверяет (как не странно) синтаксический анализатор или, попросту говоря, - парсер. В общем случае целью парсера(в теории) является проверка на синтаксическую корректность, но на практике парсер выдаёт ещё одно промежуточное представление, известное как "Абстрактное синтаксическое дерево"(Abstract Syntax Tree(AST)).Всё, с текстом пока закончили, дальнейший процесс работы лучше всего демонстрировать в видео формате.
Пара слов по качеству записей: в видео иногда есть небольшие проблемы со звуком. За все три части я так и не заметил что наушники были не до конца вставлены в разъём. Также никакого сценария заранее прописано не было(это съело бы уйму времени), соответсвенно много мычания, раздумий, проговаривания чего-то про себя, но всё около-дела пояснено. Получился этакий live-формат. В первой части жёсткие затупы на 47:00 - 1:02:00, поэтому данный фрагмент рекомендую смотреть минимум на 2х, всё остальное тоже советую немного ускорить.
ЧАСТЬ 1. AST, BABEL, PIXELSCAN, OBFUSCATOR.IO
ЧАСТЬ 2. CLOUDFLARE
ЧАСТЬ 3. NODEJS + ZENNOPOSTER
C НАСТУПАЮЩИМ, ZENNOLAB!
Полезные материалы:
Ручная деобфускация JavaScript
В данной статье будут рассмотрены понятия и методы, связанные с обфускацией JS. Здесь также будет представлен ручной подход, который помогает обращать продвинутые приемы обфусцирования, в том числе используемые в самых свежих эксплоитах.
www.securitylab.ru
JavaScript AntiDebugging Tricks :: DoomsDay Vault
List of antidebugging techniques applied to JavaScript (focused on browsers)
x-c3ll.github.io
Step-by-step guide for writing a custom babel transformation | Tan Li Hau
Writing your first babel plugin
lihautan.com
- Тема статьи
- Нестандартные хаки
- Номер конкурса статей
- Шестнадцатый конкурс статей
Вложения
-
2,4 МБ Просмотры: 274
-
2,3 МБ Просмотры: 236
-
2,2 МБ Просмотры: 297
Для запуска проектов требуется программа ZennoPoster или ZennoDroid.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...
Для того чтобы запустить шаблон, откройте нужную программу. Нажмите кнопку «Добавить», и выберите файл проекта, который хотите запустить.
Подробнее о том, где и как выполняется проект.
Последнее редактирование: