- Регистрация
- 16.01.2019
- Сообщения
- 656
- Реакции
- 1 066
- Баллы
- 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. Здесь также будет представлен ручной подход, который помогает обращать продвинутые приемы обфусцирования, в том числе используемые в самых свежих эксплоитах.
JavaScript AntiDebugging Tricks :: DoomsDay Vault
List of antidebugging techniques applied to JavaScript (focused on browsers)
Step-by-step guide for writing a custom babel transformation | Tan Li Hau
Writing your first babel plugin
- Номер конкурса статей
- Шестнадцатый конкурс статей
- Тема статьи
- Нестандартные хаки
Вложения
Последнее редактирование:








Да и куки, которые тоже генерит этот же скрипт клауда как-то надо вытянуть...
Увидел на ютубе, посмотрел залпом, тема развёрнута очень доходчиво. Даже с моими начальными знаниями веб-разработчика, удалось достичь такого результата: