вторник, октября 24, 2006

Популярная механика: Потеть и списывать всласть

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

- сам алгоритм, изложенный во всех профессиональных учебниках и используемый ежедневно массой людей; ни на

- буковки, которыми я набрал этот Яваскрипт, равно как и на электроны, ислученные ЭЛТ моего монитора в процессе работы;

я решил, что безвестный коллега по цеху, сделав Ctrl-C/Ctrl-V, не совершил ничего предосудительного. Его попросили реализовать классическую схему подсчётов, «как у вон тех». Перед ним был выбор: написать всё с нуля (чистая совесть и ещё один изобретённый велосипед) или взять готовое (здравый смысл). Он выбрал второе, и я его поддерживаю. Единственное, что о чём я его попросил — вернуть в код мой комментарий с именем и координатами.

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

Возьмём онлайновый калькулятор специфических расчётов с некоего (реально существующего) сайта. Пытаемся взглянуть на код... Фиг вам! Там фреймы; при попытке открыть ссылку нужного нам фрейма напрямую мы получаем страницу со словами «Копирование запрещено!». Посмотреть исходник по контекстному меню тоже нельзя: нажатие правой кнопки мыши перехватывается яваскриптом: «Sorry, that function is disabled».

Обходятся эти навороты обидно просто. Откроем блокнот, Файл — Открыть... — и вводим как имя файла известный нам URL Очень Тайной Страницы. Смешно, правда? Весь оберегаемый код попадает в блокнот.

Что внутри?

Несложный и ясный код, но он... нигде не вызывается :-) А при расчётах вызываются таинственные функции xxx(), yyy() и т. п. Где они определены? А не видно!

Ладно, просто сохраним страницу на свой сервер и откроем в браузере. Оба-на! Опять «Копирование запрещено!».

Исследуя исходник ещё раз, находим место, где собака зарыта:

<script language="JavaScript"><!--
function Decode() {
d("4!--4sqhbqd34pghb cmVq=< pusq="0nQJ9QBMSU034t34cfuh" cb6jq="">

Дальше ещё на экран такой белиберды, в которой чистым русским языком читается и строка «Копирование запрещено!». Очевидно, эта функция восстанавливает зашифрованную часто кода, где проверяется текущий адрес страницы (и если он неверен, то «Копирование запрещено!») и определяются функции-призраки xxx() сотоварищи.

Функции Decode и её напарник codeIt восстановят недостающий код только внутри браузера и модифицируют страницу так, что она станет работоспособной. Вот этот момент в исходнике:

<script language="JavaScript"><!--
Decode();document.write(ky);//--></script>

Расшифрованный функцией Decode() код внутри браузера хранится в переменной ky. Вот она, ахиллесова пята. Создаём новую страницу, копируем в неё пару функций Decode()/codeIt() вместе с махинациями над переменной ky, но выводим содержимое этой переменной не в текст документа, а в поле формы <textarea>:

<form name="form1">>
<textarea name="textarea" cols="100" rows="50"></textarea>
</form>
<SCRIPT LANGUAGE="JavaScript"><!--
Decode(); document.form1.textarea.value=ky;</SCRIPT>

Открываем эту страничку в браузере — и что мы видим в текстовом поле? :-)

<!--<CENTER><FONT SIZE=4 FACE="Helvetica"><B><SPAN
style="background-color: #000000"><font color=#FF0000>U</font><font
color=#FF3300>N</font><font color=#FF6600>R</font><font
color=#FF9900>E</font><font color=#FFCC00>G</font><font
color=#FFFF00>I</font><font color=#CCFF00>S</font><font
color=#99FF00>T</font><font color=#66FF00>E</font><font
color=#33FF00>R</font><font color=#00FF00>E</font><font
color=#00FF33>D</font><font color=#00FF66> </font><font
color=#00FF99>E</font><font color=#00FFCC>N</font><font
color=#00FFFF>C</font><font color=#00CCFF>O</font><font
color=#0099FF>D</font><font color=#0066FF>I</font><font
color=#0033FF>N</font><font color=#0000FF>G</font><font
color=#3300FF> </font><font color=#6600FF>B</font><font
color=#9900FF>Y</font><font color=#CC00FF> </font><font
color=#FF00FF>U</font><font color=#FF00CC>S</font><font
color=#FF0099>E</font><font color=#FF0066>R</font></B></SPAN><FONT
SIZE=1><BR><BR>&lt; < this header will be removed once
you are registered &gt; ></FONT></FONT><HR></CENTER>--><SCRIPT>

if(location.href.search('ttp://www.trueurl')<0 || self.parent.frames.length==0) {window.setTimeout('document.write("Копирование запрещено!")',1) ;}

function xxx(n, d) {return MM_findObj(n ,d)}

function zzz() {return Z_N()}

function sss() {return MM_changeSelect()}

function yyy(objName,x,NameS) {return MM_setTextOfSelect(objName,x,NameS)}

function eee(objName,x,NameS) {return MM_setTextOfSelect_s(objName,x,NameS)}

function vvv(objName,x,NameS) {return MM_setTextOfSelect_v(objName,x,NameS)}</SCRIPT>

Большая часть зашифрованного фрагмента содержит красочное сообщение о том, что использовалась незарегистрированная версия шифровальной утилиты :-) А вот и искомые проверки: если текущий URL не содержит подстроки «ttp://www.trueurl» или документ не находится в фрейме, показать кукиш. Ниже — определения функций-призраков, которые просто зеркалят уже давно прочитанные нами функции. Они-то нам и нужны. Выбросив из первоначального текста страницы все Decode()/codeIt() и вставив вместо них эти определения, мы полностью восстанавливаем её функциональность.

Видит бог, это было несложно.

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

А можно посоветовать другое: смотреть на вещи шире, не заставлять людей делать заново уже сделанную вами работу — тем более что вам от этого ни холодно, ни жарко. «Когда дело сделано, человек должен удалиться», — говорил Конфуций; он, конечно, не был силён в веб-разработке, но разбирался в более фундаментальным вещах :-) И последнее: ценно не то, что вы сделали (это уже стреляный патрон), а ваш потенциал, украсть который никак нельзя :-) Поэтому закончим здесь цитатой, вынесенной в заголовок, но в более развёрнутой форме:

В чем могли, они подражали, но им мыслей моих не украсть —
Я их всех позади оставил потеть и списывать всласть.

Редъярд Киплинг, «Мэри Глостер».

2 комментария:

jonjonson комментирует...

Когда скрывают своё ноу-хау - это ещё ничего. Но вот когда на щелчёк правой клавишей "мыши" по картинке пищевой добавки в интернет магазине всплывает JavaScript alert мол все права принадлежат Знахарь (причём скрипт работает только в IE и влюбом случае его можно обойти - то что попало на компьютер пользователя находится в его власти), то не понимаешь на кой это нужно. Цель сохранения картинки была самая прозаичная, что бы дать родственнику распечатку для его похода в тот же магазин знахаря. После этого покупка, скажем, не самого нужного сиропа была отменена. Пусть Знахарь хранит права на свои картинки.

Сергей комментирует...

В таких случаях я обычно ограничиваюсь взятием скриншота, уж это-то никто мне не запретит :-)

Поиск по этому блогу