Не вся­кую защиту нуж­но ломать с помощью дизас­сем­бле­ра. Иног­да дос­таточ­но открыть DevTools, изу­чить JavaScript фрон­тенда и понять, как при­ложе­ние при­нима­ет решение о бло­киров­ке. Мы иссле­дуем лицен­зион­ный механизм Java-при­ложе­ния с веб‑интерфей­сом, раз­берем­ся в архи­тек­туре Angular и NgRx, а заод­но про­верим, нас­коль­ко полезен искусс­твен­ный интеллект при ана­лизе минифи­циро­ван­ного кода.

warning

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

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

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

Раз­берем сфор­мулиро­ван­ный мною выше прин­цип на при­мере неко­его при­ложе­ния, при заг­рузке тре­бующе­го акти­вацию (онлайн или офлайн). Исполня­емый файл при­ложе­ния не пред­став­ляет для нас ни малей­шего инте­реса, пос­коль­ку име­ет кро­хот­ный (мень­ше мегабай­та) раз­мер и нево­ору­жен­ным (но нат­рениро­ван­ным) гла­зом опоз­нает­ся как лаун­чер для огромно­го (око­ло гигабай­та) JAR-аппле­та, лежаще­го в под­папке /app рабоче­го катало­га прог­раммы.

Од­нако не будем пока торопить­ся раз­бирать его на клас­сы, как мы мно­гок­ратно делали в стать­ях «Гряз­ный Джо. Взла­мыва­ем Java-при­ложе­ния с помощью dirtyJOE», «Без­защит­ная Java. Лома­ем Java bytecode encryption», «Су­ровая жаба. Изу­чаем защиту Excelsior JET для прог­рамм на Java», наша задача сегод­ня зна­читель­но про­ще.

Чис­то ради при­кола наж­мем Ctrl-Alt-Del на откры­том акти­ваци­онном окне, что­бы пос­мотреть спи­сок задач, порож­даемых нашей прог­раммой. А порож­дает она (помимо кро­хот­ного лоаде­ра, пожира­юще­го самый минимум ресур­сов) целую кучу про­цес­сов под наз­вани­ем Java Chrominium Embedded Framework (JCEF) Helper, реали­зуемых модулем jcef_helper.exe из под­папки /jcef-bundle прог­рам­мно­го катало­га.

Гугл говорит нам, что этот фрей­мворк поз­воля­ет Java-при­ложе­ниям встра­ивать ком­понен­ты пол­ноцен­ного веб‑бра­узе­ра (на базе движ­ка Chromium) пря­мо в свой интерфейс. То есть мы видим клас­сичес­кий фрон­тенд, реали­зован­ный на осно­ве веб‑при­ложе­ния. Мы стал­кивались с подоб­ным, нап­ример, в статье «В обход стра­жи. Отла­жива­ем код на PHP, упа­кован­ный SourceGuardian», одна­ко там при­ложе­ние запус­калось непос­редс­твен­но из веб‑бра­узе­ра, а сей­час бра­узер встро­ен пря­мо в Java-апплет.

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

Что­бы пос­мотреть HTML-код, который отоб­ража­ет jcef_helper.exe, нам нуж­но получить дос­туп к стан­дар­тным инс­тру­мен­там раз­работ­чика Chromium (DevTools). Поэто­му пред­ста­вим, что перед нами обыч­ный бра­узер Google Crome, в котором откры­та веб‑стра­ница.

К сожале­нию, пра­вый клик мышью внут­ри окна не работа­ет, одна­ко нажатие кла­виши F12 раз­работ­чики заб­локиро­вать забыли. С этим нам очень повез­ло, пос­коль­ку в про­тив­ном слу­чае нам приш­лось бы нас­тра­ивать отла­доч­ный порт для уда­лен­ной отладки через обыч­ный бра­узер, а это тот еще гемор­рой. Но в нашем при­мере мы идем прос­тым путем, и нажатие F12 вызыва­ет нам окно Development tools, в котором мы сра­зу откры­ваем вклад­ку Sources.

Мы видим, что окно акти­вации пред­став­ляет собой локаль­ную веб‑стра­ницу, хра­нящу­юся по адре­су http://localhost:8072/en-US/user/license-activation-wizard. Она динами­чес­ки собира­ется при помощи скрип­тов сбор­щиком модулей WebPack. К сожале­нию, эта стра­ница защище­на от меж­сай­товых зап­росов или тре­бует авто­риза­ции, поэто­му зай­ти на нее из сис­темно­го веб‑бра­узе­ра не получит­ся. При­дет­ся доволь­ство­вать­ся открыв­шимся отладчи­ком Development tools, нам его впол­не дос­таточ­но.

Нас инте­ресу­ет код JS-скрип­тов, фор­миру­ющих эту стра­ницу. Напоми­наю, мы тес­тиру­ем гипоте­зу о том, что про­вер­ка лицен­зии и заг­рузка акти­ваци­онно­го окна находит­ся имен­но в упо­мяну­тых скрип­тах, а зна­чит, откру­чива­ется путем прос­той прав­ки тек­сто­вого JS-кода.

За­дача не такая три­виаль­ная, как мог­ло бы показать­ся на пер­вый взгляд, — как вид­но из скрин­шота, код ском­пилиро­ван, опти­мизи­рован, миними­зиро­ван и раз­бит на так называ­емые чан­ки. В пра­вой час­ти скри­на мы видим один такой фраг­мент кода, собс­твен­но, и реали­зующе­го окно акти­вации, — 804.30ceda3d3520d8ea.js. Если мы поп­росим ИИ удов­летво­рить наш инте­рес отно­ситель­но заголов­ка это­го модуля (в общем‑то, типово­го), то он нам объ­яснит, что:

  • "use strict"; — стро­гий режим JavaScript. Он вклю­чает улуч­шенную про­вер­ку оши­бок, зап­реща­ет исполь­зование уста­рев­ших син­такси­чес­ких конс­трук­ций и повыша­ет про­изво­дитель­ность кода;
  • self.webpackChunkalx — гло­баль­ный мас­сив (в кон­тек­сте window или Worker), который Webpack исполь­зует для хра­нения и син­хро­низа­ции всех час­тей (чан­ков) при­ложе­ния;
  • self.webpackChunkalx || [] — защит­ная ини­циали­зация. Если мас­сив уже сущес­тву­ет, код исполь­зует его. Если нет, соз­дает новый пус­той мас­сив. Это пре­дот­вра­щает ошиб­ки при заг­рузке скрип­тов в слу­чай­ном поряд­ке;
  • .push([[804], { 75804: (...) => {...} }]) — добав­ление нового модуля в сис­тему сбор­щика.

По­ка не будем забивать себе голову эти­ми глу­пос­тями, нас инте­ресу­ет мес­то, в котором про­исхо­дит обра­щение по адре­су user/license-activation-wizard. Вос­поль­зовав­шись гло­баль­ным поис­ком пря­мо в окне раз­работ­чика, находим очень похожий код в модуле 480.7c8d50d85606ddd0.js.

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

Продолжение доступно только участникам

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    1 Комментарий
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии