Загрузка...

Деобфускация JavaScript при помощи AST. Часть 1.

Тема в разделе Уроки создана пользователем ElevenGate 13 сен 2020. (поднята 13 сен 2020) 2504 просмотра

Загрузка...
  1. ElevenGate
    ElevenGate Автор темы 13 сен 2020 Заблокирован(а) 14 27 май 2020
    Всем привет, я хочу рассказать вам о возможностях трансформации AST в контексте JS.

    Зачем это нужно? В основном, чтобы избавиться от рутины по трансформации кода.Помимо этого, такие манипуляции позволяют минимизировать количество допускаемых ошибок во время ручно манипуляции, а так же имеют свои преимущества по сравнению с регулярными выражениями.
    Это будет цикл статей, которые направлены на то, чтобы заинтересовать вас и показать что-то новое.
    Многие сайты обфусцируют свои файлы для того, чтобы вам было сложнее в них разобраться и понять как они работают.
    Обфускация так же проходит при помощи AST трансформации кода - открыв любой open source обфускатор вы можете в этом легко убедиться.
    Чем тебе не угодил beautifier.io, de4js, jsnice и прочие?
    Дело в том что они не поддерживают многие виды обфускаций, как, например, те, что используются на https://obfuscator.io

    Таким образом, я собираюсь показать вам некоторые примеры деобфускации при помощи AST трансформаций, на примере своего кода, пропущенного через obfuscator.io;
    В общем клин клином выбивается))
    Код в виде текста прикреплен в конце.
    В данной части будет продемонстрировано как из массива строк и функции, которая из него вытаскивает нужные строки, заменить вызовы функций на эквивалентные литералы.
    Код манипуляций будет простым, чтобы больше людей могли понять о чем речь.
    Код
    Бонусом я дам модуль для преобразования console['log'] в console.log.
    Мы будем делать из:
    [IMG]

    делать такой код:
    [IMG]
    Рассмотрев код, можно сделать вывод что функция, которая вытаскивает строки называется _0x3d28, массив строк под именем _0x4dfe,
    а за ним идет iife функция перемешивания.

    Разберем функцию _0x3d28 :
    [IMG]
    На вход подается 2 аргумента, второй из которых нигде не используется.
    Затем второй аргумент(индекс) преобразуется в число путем вычитания 0x0 что является нулем.
    После этого объявляется и возвращается переменная, которая равна индексу из массива строк(объявлен первой строкой).
    Чистый вариант:
    [IMG]

    Рассмотрим iife функцию:
    [IMG]
    Она вызывается сразу после объявления с аргументами - массив строк и число на которое нужно сдвинуть массив.
    Суть данной функции в том, что она сдвигает начальные элементы массива в конец, пока число, на которое нужно сдвинуть массив, не будет равно 0.
    Push и shift мутируют массив, так что не важно что она возвращает.

    Ее чистый вариант будет выглядеть примерно так:
    [IMG]

    И так инициализация массива происходит путем объявления переменной с массивом и аншафла строк. Данные из нее получаем путем выполнения функции, которая на вход получает индекс.

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

    Теперь напишем манипулятор.
    Я предлагаю использовать nodejs модули:
    meriyah для парсинга и преобразования кода в дерево, которая,
    astring для генерации текстового кода из AST,
    и astray для манипуляций с деревом.

    Установить их можно при помощи команды:
    npm i astray astring meriyah
    Перед этим прописав инициализацию(хороший тон):
    npm init
    Так же нам понадобится fs для чтения и записи файлов.
    Импортировать модули, а так же прочесть файл и сгенерировать для него дерево можно данным кодом:
    [IMG]

    Готовый манипулятор будет выглядеть как то так:
    [IMG]
    Многие траверсеры AST работают по паттерну visitor, поэтому каждый вызов функции(CallExpression) будет передаваться в нашу функцию.
    В самой функции мы проверяем вызов функции - что вызывается и с какими аргументами и если он удовлетворяем нашим хотелкам - возвращаем новую ноду в виде простой строки, вместо вызова функции.

    Мини пояснение:
    [IMG]

    Чтобы это работало нужно определить getValue - это просто переименованная _0x3d28, для нашего же удобства;

    Все! Мы изменили код))
    Осталось его сохранить - пишем в файл то, что вернет astring:
    Код
    writeFileSync("./output.js", generate(AST));
    В output будет уже измененный код. В нем уже можно удалить весь код который относится к инициализации массива и получению из него переменной, потому что он там более не используется.

    Для ренейминга переменных я предлагаю использовать модуль для vscode: https://marketplace.visualstudio.com/items?itemName=cmstead.jsrefactor
    Он переименовывает все идентификаторы указанной переменной, обращая внимание на scope.
    Финальная и чуть измененная(модульная) версия будет состоять из 2 файлов (cори за пастбин):
    index js: https://pastebin.com/VpgpWFay
    ASTmodules js: https://pastebin.com/QnwnUKEF
    Код
    Итог: в файл input.js помещаете ваш код, запускаете через node index скрипт, в output.js получаете изменненый.
    Понять почему именно такой код мы написали, вам так же поможет https://astexplorer.net. В него можно совать куски валидного кода, и он будет распаршивать их в AST, наглядно показывая результат.

    Так же могу порекомендовать великолепный плейграунд для js кода - quokka js. Желательно Pro версию, в ней больше возможностей.

    Для лучшего экспириенса во время деобфускации и в целом программирования можно пользоваться дебаггингом с брейкпоинтами в vscode. (Попробуйте нажать F5)

    Автор: https://t.me/elevengate
    Предложения по оформлению, что интересно по теме - пишите тут.
     
  2. petral2002
    petral2002 28 ноя 2020 0 18 ноя 2018
    нет кода ASTmodules js
     
  3. lonely_femboy
    lonely_femboy 6 мар 2022 сыграй мне реквием 227 21 фев 2020
    +Rep, но [IMG]
     
Top