Защита HTML - это миф!
Хакер, номер #099, стр. 078 (март 2007 года)
Автор этой статьи, W[4Fh]LF , сайт его не работает, поэтому не указываю.
Статья хорошая. Описывает как можно использовать DOM в совокупности с мозгами.
Спасибо тебе, чувак!
Итак, сама статья:
Защита HTML - это миф!
Я думаю, каждый читатель пользовался такими сервисами, как slil.ru или depositfiles.com. Вот и мне часто приходится обращаться к ним. Но я не всегда могу позволить себе насладиться шириной своего канала (если, конечно, не прибегать к помощи универсального народного средства - вазелина - примечание редактора), прежде всего, потому, что или трафик для моей страны исчерпан, или вовсе поставлено ограничение в 500 байт в секунду для иностранных IP. Но это же смешно! При ширине канала в несколько мегабит я должен качать со скоростью 30 байт в минуту? Не собираясь с этим мириться, я придумал для себя решение - использовать прокси-серверы с IP, принадлежащим другой стране. Найти такие прокси не проблема, и я постоянно брал их со странички одного сайта. Но недавно мне это все порядком надоело, и я решил автоматизировать этот процесс, написав программу, которая сама утягивает html-страничку со списком прокси-серверов и выдергивает оттуда нужные данные - IP:PORT. Написал, протестировал локально - все работает, натравил на нужную страничку - никакого результата. Пошел браузером смотреть код этой паги - и действительно, никаких IP:PORT там нет, а на их месте незамысловатые скрипты. Защита от таких халявщиков, как я, стало быть. Что ж, сегодня мы разгромим в пух и прах все такие псевдозащиты.
О чем мы будем говорить?
В начале мы поговорим о том, что это за защиты, какие методы они используют. Дадим определение основным понятиям. Далее я немного расскажу об объектной модели браузеров (COM), после чего, отталкиваясь от этой модели, мы найдем универсальное решение, которое сводит на нет смысл всех подобных защит.
Обфускатор
Я взял на себя смелость привести определение этого термина из Wikipedia.
Обфускатор (англ. obfuscator) - инструментальное программное обеспечение, позволяющее предотвратить или значительно осложнить обратную разработку программы, даже при наличии исходного кода. В процессе обфускации, исходный код преобразуется в запутанный код, намного менее читаемый и понятный человеку.
Все прочие случаи я не рассматриваю, сфокусируемся на применении обфускаторов для защиты html. Действительно, содержимое страницы, представленное, как правило, в виде html, всегда открыто, и его всегда можно спокойно прочесть. Но люди привыкли усложнять друг другу жизнь, и поэтому были придуманы обфускаторы и обфускация, которые усложняют разбор текста.
Давай попробуем разобрать простейший пример. Есть у нас вот такой html:
1 2 3 |
<b>Хакер</b> |
Что мы видим при этом на экране? Правильно, слово «Хакер». Немного усложним этот пример:
1 2 3 |
<b>Х</b> <b>а</b> <b>к</b> <b>е</b> <b>р</b> |
Согласись, не сразу сообразишь, что это за слово такое. Хотя результат обработки будет тем же, мы увидим все тоже слово. Сейчас мы как раз провели обфускацию исходного текста.
Впрочем, такие методы не получили широкого распространения по ряду причин. Во-первых, слишком большой прирост в размере. Во-вторых, на обработку такого кода нужно гораздо больше времени, да и эффективность невелика. Зато получили распространение другие методы, основанные на использовании небольших скриптов-врезок, написанных на JS или VBS (чаще все же на JS). В этих врезках в закодированном виде находится исходный участок html-страницы; имена переменных, как правило, тоже изменены на случайные; код максимально запутан. И вот это уже по-настоящему сбивает с толку. Простейший пример такой защиты приведен ниже:
1 2 3 4 5 6 7 8 9 10 11 |
<html> <body> <script> var s = "Jgnnq\"Yqtnf#"; for(i = 0; i < s.length; i++) document.write(String.fromCharCode(s.charCodeAt(i)-2)); </script> </body> </html> |
Попробуй сохранить этот текст в html-файл и запустить. На экране ты увидишь строку «Hello World!», которой в этом примере даже и не пахнет. Вывод этой строки - результат работы вышеприведенного скрипта. Согласись, неплохая защита от дурака? Но мы-то не дураки :). Именно с такой проблемой я столкнулся, когда хотел написать граббер прокси-серверов. На той странице был применен похожий прием, и поэтому мой парсер не увидел нужной мне информации. Можно, конечно, было бы усложнить парсер, и он бы все что надо увидел, но мне стало лень.
Впрочем, это лишь самые простые случаи; бывают и вовсе клинические, где html-содержимое превращено в настоящий фарш - ничего не разобрать и хочется сразу закрыть окошко с исходным кодом.
Объектная модель IE
Движок этого браузера в принципе не является тайной, интерфейсы открыты и описаны в MSDN, что в определенных ситуациях позволяет использовать его как довольно мощное средство. Наверное, любой программист использовал компонент WebBrowser, отмечая, что это довольно удобное средство. Весь движок и все интерфейсы сосредоточены в двух библиотеках: shdocvw.dll и mshtml.dll.
На самом деле, вся страница, которая загружена с помощью IE, - это набор независимых объектов. Каждый из них может иметь своего «родителя» и «наследника»; каждый объект описывается своим интерфейсов; каждый интерфейс содержит методы и свойства, которые характерны для данного объекта. Другими словами, две эти библиотеки - это COM-библиотеки. Архитектура и принципы COM довольно сложны и не могут быть изложены в рамках одной статьи. Поэтому сейчас нам важно уяснить лишь, что страница - это набор объектов, каждый из которых описывается отдельным интерфейсом - набором методов и свойств этого объекта, и мы можем получить доступ к этим методам.
Псевдозащиты
Хочу сделать небольшое отступление и рассказать о том, что нам на сегодняшний момент предлагает рынок. Набрав в поисковике «Protect HTML», я получаю кучу ссылок на буржуйские сайты, которые пытаются впарить эти «защиты». Перейдя по первой ссылке, я оказываюсь на сайте www.protect-html.com, который предлагает купить за $99,49 свой продукт под названием Advanced HTML Protector. Есть возможность скачать Trial Version - качаю. Для примера я сохранил у себя код страницы http://ya.ru и решил отдать его этому чуду, которое якобы может от чего-то защитить. Этот Advanced HTML Protector обфусцирует и превращает двухкилобайтную страницу поисковика в пятнадцатикилобайтную. Запускаю - с виду абсолютно аналогичная страница. Заглядываю в код - бог ты мой… Что он с ним сделал? Полная каша, что-то разобрать кажется нереальным…
В принципе, исследование одного такого протектора труда не составляет. Можно найти логику в этом коде, проследить порядок действий и написать деобфускатор и дешифратор для такой защиты. Но зачем? Существует универсальный метод, который позволяет обойти абсолютно все подобные защиты. Он до предела прост и легок в реализации, как, впрочем, и все гениальное ;). Но обо всем по порядку.
Развязка
Я не стал зацикливаться на проблеме с автоматическим вытягиванием прокси-серверов с той странички и, отложив ее решение на потом в силу занятости, благополучно про нее забыл. Одним вечером я вел беседу по ICQ с моим другом nerezus'om. Разговор зашел на тему защиты содержимого страничек в Интернете, и он сказал, что в таких защитах смысла нет, ведь все, что мы видим на экране, - это результат интерпретации, который хранится в памяти браузера, и значит, до него можно как-то добраться.
Тут нужно сделать отступление и сказать, в каком порядке идет обработка защищенных страниц. То, что мы видим, когда нажимаем в браузере «Вид -> Просмотр HTML-кода», - это исходный код страницы, в котором все скрипты еще не обработаны. То есть интерпретация, а значит, и декодирование данных в исходный вид, не произошли, а на экране мы при этом видим вполне нормальную страницу, где весь код и скрипты были проинтерпретированы. Отсюда следует, что где-то в памяти браузера должна храниться страница, которая, помимо всех скриптов, скрывающих первоначальное содержимое страницы, содержит и результат интерпретации, то есть исходный код. Как оказалось позже, такая страница в памяти, действительно, хранится, и более того - до нее можно спокойно добраться!!!
Nerezus кинул мне такой незамысловатый скрипт:
1 2 3 |
javascript:alert(document.getElementsByTagName('html')[0].innerHTML); |
Я открыл в браузере пример со строкой «Hello World!», который был приведен выше, и вставил в адресную строку этот небольшой javascript. При этом на экране я увидел сообщение, показывающее мне содержимое страницы, заключенное между тегами и . Но не то, на которое предлагает посмотреть браузер, а то, которое содержит в себе, помимо скриптов, и результат их интерпретации.
Программная реализация
Итак, универсальное решение было найдено! Причем именно универсальное, для любого типа подобных защит, так как архитектура современных браузеров такова, что никакая защита не может скрыть то, что будет изображено на экране позже, а значит, и противодействие одной строчке кода найти невозможно. Одна строка сводит на нет смысл всех этих защит, которые буржуи пытаются впарить нам за большие деньги.
Но таскать с собой этот скрипт и втыкать его в нужные окна совсем неудобно. Так в нем отпадает всякий смысл, потому что если уж я зашел на страницу, то зачем мне видеть ее реальный исходный код, когда я могу скопировать необходимые мне данные прямо со страницы?
Я быстро сообразил и переписал этот код на Delphi, используя компонент TWebBrowser. Далее я приведу код и дам небольшие комментарии. При этом на форме должны находиться TWebBrowser и TMemo. А в секцию uses следует прописать SHDocVw_TLB и MSHTML_TLB.
1 2 3 |
Memo1.Text := (WebBrowser1.ControlInterface.Document as IHTMLDocument2).body.outerHTML; |
Это все! Да, это действительно так просто, минимум кода и максимум результата. Помнишь, я говорил, что html-страница в памяти - это набор объектов и каждый объект описывает интерфейс? Так вот основополагающим интерфейсом для всей страницы является IHTMLDocument2. В этой одной строке кода мы откастовываем документ в памяти относительно данного интерфейса, это позволит нам дальше работать с его методами. Среди прочих есть метод под названием body, который возвращает указатель на интерфейс под названием IHTMLElement. В свою очередь, этот интерфейс обеспечивает доступ к методу outerHTML, а этот метод возвращает код проинтерпретированной и обработанной страницы. Но не весь код, а только ту его часть, что находится между тегами и , а это именно то, что обязательно увидит конечный пользователь.
Нам известно и то, что все скрипты, которые содержат зашифрованное тело страницы, находятся между тегами и . Это значит, что если мы вырежем все такие участки, то получим максимально чистый код, так как после интерпретации эти участки страницы теряют всякий смысл и превращаются в мусор. Одно «но» - наряду с ненужными кусками, можно вырезать и действительно нужные скрипты, которые имеют отношение к первоначальной странице.
Также хочу отметить, что есть метод outerText, который показывает лишь текстовые данные, заключенные между какими-либо тегами. Именно этот метод мне пригодился, когда я все-таки дописал свой граббер прокси-серверов.
Эпилог
Итак, все защиты побеждены. Мы нашли универсальный и максимально простой метод, который и никогда ни от кого не скрывался. Его существование, однако, не мешает буржуям зарабатывать деньги посредством убеждения клиентов в том, что их защита действительно что-то защищает. Чтобы показать, насколько она бесполезна, наша команда выпустила небольшую утилиту под названием Universal javascript Decoder (официальная страничка - http://hunger.ru/releases/jsdecoder). Она немного более продвинутая, но в ее основе лежит все та же простая и незамысловатая строка кода, которая, по сути, делает всю работу за нас.
Я отдал на растерзание нашей утилите главную страничку Яндекса, которая была защищена с помощью Advanced HTML Protector, и на выходе я получил первоначальный «очищенный» html-код.
WARNING
Автор статьи не несет ответственности ни за что, он просто написал эту статью 🙂
Author: | Tags: /
| Rating:
3 comments.
Write a comment