Пользователь
0,0
рейтинг
26 января 2011 в 04:59

Разработка → Обфускация JavaScript

В статье собраны всем известные методы и предельно извращенные. Эту статью я решил написать после недавнего прочтения поста в блоге Badass JavaScript и решил её дополнить своими находками.

Первый способ


Он всем известен — обфускация минимизаторами такими как JS Packer, JSmin, YUI Compressor, Closure compiler или можно просто пугуглить «JavaScript Obfuscator» и найдется ещё сто штук разных обфускаторов.
Они превращают существующий код
function MyClass(){
    this.foo = function(argument1, argument2){
        var addedArgs = parseInt(argument1)+parseInt(argument2);
        return addedArgs;
    }
    var anonymousInnerFunction = function(){
        // do stuff here!
    }
}

В какой-то такой вид:
function MyClass(){this.foo=function(c,b){var d=parseInt(c)+parseInt(b);return d};var a=function(){}};

Или такой:
var _0xd799=["\x66\x6F\x6F"];function MyClass(){this[_0xd799[0]]=function (_0xefcax2,_0xefcax3){var _0xefcax4=parseInt(_0xefcax2)+parseInt(_0xefcax3);return _0xefcax4;} ;var _0xefcax5=function (){} ;} ;

Или вот такой:
eval(function(p,a,c,k,e,d){e=function(c){return c};if(!''.replace(/^/,String)){while(c--){d[c]=k[c]||c}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('4 0="3 5!";9 2(1){6(1+"\\7"+0)}2("8");',10,10,'a|msg|MsgBox|Hello|var|World|alert|n|OK|function'.split('|'),0,{}))

Но ничего не стоит его восстановить с помощью jsbeautifier.org либо просто убрать eval и получить исходный код, многое потеряем, но смысл кода восстановим. Ну и с первого взгляда мы видим, что перед нами JavaScript.

Все это были цветочки под катом жесткие методы обфускации.

Способ второй


Изменение кода до неузнаваемости, который превратит наш мизерный скрипт:
alert(0)

В такой Braifuck-подобный вид:
([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]])(+[])

Или вот в такой (код может не работать ибо хабрапарсер):
゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ (c^_^o)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');

Тут с первого раза и не скажешь, что перед нами работающий JavaScript.
Тулза делающая код вида один, код вида два. Vladson нашел ещё одну тулзу jjencode

Объяснение некоторых моментов способа два

Пример:
($=[$=[]][(__=!$+$)[_=-~-~-~$]+({}+$)[_/_]+
($$=($_=!''+$)[_/_]+$_[+$])])()[__[_/_]+__
[_+~$]+$_[_]+$$](_/_)

Имеем какое-то месево символов, но на самом деле в нем скрывается alert(1), но ведь там нет ни одной строки и ни одного символа, откуда это?!

Будем разбираться:
$=[] это пустой массив
$=[$=[]] это массив с ссылкой на массив
В переменной $ будет 0.
Теперь у нас есть 0 и мы можем ссылаться. Делаем __ = "false" через (__ = !$ + $ )
Далее _ = -~-~-~$
Оператор ~ в JavaScript означает -(N+1) поэтому -~ = +1
Если $ = 0 тогда -~-~-~$ = 3
Получаем: _ = 3

Таким образом _/_ = 3/3 = 1

(__ = !$ + $ )[ _ = -~-~-~$]
("false")[_]
("false")[3]
"false"[3] = s


({} + $)[_/_]
(" object")[_/_]
(" object")[1]
" object"[1] = o


$$ = ( $_ = !'' + $)[_/_]
$$ = ( "true")[1]
"true"[1] = r

$_[+$] = "true"[0] = t

$_ = "true"null
$$ = rt


($$ = ( $_ = !'' + $)[_/_] + $_[+$] ))

!'' = "true"
$_ = (true)
$_[1] = r
$_[0] = t
$$ = rt


Таким образом первая строка станет ($ = [] ["s" + "o"+ "r"+ "t" ] )()
($=[]["sort"])()

Идем дельше
[__[_/_]+__[_+~$]+$_[_]+$$](_/_)

$ = 0
_ = 3
__ = "false"
$_ = "true"
$$ = "rt"


Строка превращается…
[__[_/_]+__[_+~$]+$_[_]+$$](_/_)

Превращается…
[__[1] + __[3 + -1] + $_[3] + $$)(1);

Превращается…
["false"[1] + "false"[3 + -1 ] + "true"[3] + "rt"] (1)

Превращается в
[ "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


Итог: window["alert"](1)

Это, конечно, искусственный пример и никакой из обфускаторов так не сможет.

Способ третий


Первый способ делал код похожим на JavaScript, второй совершенно не похожим, а третий сделает код вообще невидимым.

Готовых решений не видел, концепт, подсмотренный с одного из видео JS конференций.
Код будет состоять из двух частей: видимая честь — можно использовать что-нибудь описанное выше для её обфускации и невидимая часть.
Если с видимой все ясно, то секрет невидимой вот в чем: Имеющийся «плохой код» (иначе зачем его прятать) мы пропускаем через наш обфускатор-изчезатор, который превращает видимый скрипт в невидимый т.е. в строку состоящую из знаков табуляции (бит 1) и пробелов (бит 0).
В итоге мы получим в 8 раз больше кода чем имели. Видимая часть будет декодировать невидимую часть и её выполнять: декодирует биты в число, а число переделает в символ String.fromCharCode() ну а дальше eval

В конце получается что-то такое (невидимую часть не обязательно скрывать в элементе)
decodeAndEval(document.getElementById("evilCode").innerHTML);
<div id="evilCode">

</div>

deex написал обфускатор-изчезатор

По мотивам: badassjs.com/post/2929065287/obfuscation adamcecc.blogspot.com/2011/01/javascript.html

Буду рад ответить на ваши вопросы и увидеть способы обфускации известные вам.

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

UPD В комментариях ещё несколько раз писали про способ обфускации в png подробнее
Mikhail Davydov @azproduction
карма
448,5
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (85)

  • +5
    Как у этих методов со скоростью работы? И все ли браузеры его правильно поймут?
    Третий способ очень понравился :-)
  • +2
    А следующим шагом будет создание невидимого html6 =)
    • +9
      • 0
        как он хитро через заголовки передал:

          Link <css-without-html.css>;rel=stylesheet
        


        надо запомнить
  • +9
    • 0
      Вы мне напомнили еще один способ обфускации (вернее, второго варианта написания) Expression closure.
      Вот, например, данные выражения идентичны:
      // Обычный синтаксис
      function() { return x * x }

      // Expression closure
      function(x) x * x
      Вот здесь об этом довольно интересно расписано.
      • 0
        Для этого нужен JS 1.8, который мало где есть.
        • 0
          Да, как и написано в статье — работает пока что в FF.
  • +6
    Самый бескомпромисный обфускатор — это Google Closure Compiler в режиме Extreme. Правда для него надо код специально писать и теггировать с нуля. Люблю его.
  • +1
    Эффективность этого метода напрямую зависит от того насколько он неизвестен. Поскольку написать скрипт выдающий исходный код не проблема. И зачем тогда огород городить. Тот кто сможет прочитать логику не шифрованного скрипта, сможет прочитать и шифрованный.
    • 0
      вручную написан — вручную и дешифровать. Другое дело что овчинка выделки может не стоить — в пошаговой отладке все труды шифрующего будут как на ладони.
      • +4
        Извращенная логика — лучший обфускатор!

        НО придумал вариант последнего пункта. Берем в диве текст. Слова разделены пробелами. Нечетное количество пробелов 1, четное 0. Все равно 2 и 1 пробел отображаются как 1 в браузере, так что верстка не плывет. Длинную программу так не написать, но можно так спрятать некую критическую (напр. «аффторскую») функцию. Кстати избыточность кода снижается поскольку пробелы по любому нужны.

        Отмечу что я не очень верю в полезность этого. Большинство авторских функций — просто жуткие велосипеды.
        • 0
          Да, вот только логика, извлекающая код из пробелов, будет слишком уж на виду. Её как прятать? Повторять процесс до бесконечности?
          • 0
            Спрятать в функции делающей нечто полезное. Напр. удаляющей «лишние» пробелы. И ее зашифровать любым из вышеизложенных способов. + похожие имена переменных.

            Я повторяюсь — главное извращенная логика.
        • 0
          Есть в юникоде один символ, U+200B. Вот он: "​". Прямо между кавычками. Zero width space называется, пользуйтесь :)
          Думаю, если поискать — можно еще найти символы такого рода.
          • 0
            Черт, хабрапарсер съел. Ну да в любом случае, его код вы узнали.
  • +1
    Вы взорвали мой мозг! До сих пор не могу поверить что это работает. Я почему-то был уверен, что как минимум «eval» в коде должно быть. А оно воно как…

    >>Буду рад ответить на ваши вопросы

    Вы бы могли привести минимальный JS пример, не содержащий ни одного слова?
    • +1
      Не заметил, в вашей статье уже есть минимальный пример. Почему-то подумал что это фрагмент.

      Спасибо.
  • 0
    jquery код ни один из видимых способов не сделал рабочим
  • +2
    Ради спортивного интереса, какой процент хабравчан желают скрывать написаный ими код в своих проектах, а кому не жалко если кто-то им воспользуется?
    • 0
      Есть просто другая ситуация, не все ведут свои проекты, кто-то просто работает на дядю. Я вот будучи сотрудником одной крупной компании столкнулся с ситуацией, когда начальство дали задание — запретить пользователю копировать текст, вот я песка то поел, т.к. ответ «это не возможно» их не устраивал :-) С JS была похожая ситуация, но благо обфускация помогла отбиться :-)
      • +7
        Позвольте поинтересоваться, как вы заставили начальство считать, что у вас текст копировать нельзя? :)
        • +2
          убрал его с сайта, видимо, это единственный способ
        • 0
          нет, просто привел кучу статей с авторитетных сайтов, где говорится что этого сделать невозможно :-)
      • 0
        А отображать его в виде картинки, сгенерированной на сервере, нельзя? Конечно его и так можно будет распознать, но это гемор.
    • +1
      Проекты разные все-таки бывают… На сайтах — не жалко. А вот у меня, например, интерфейс для встраиваемых устройств на JS, который я продаю. Там килобайт 200 кода, где помимо функционала — еще и UI-фреймворк заточенный для работы на embedded. Без обфускации — никак. Делать OpenSourcе при всей моей любви к нему тоже нельзя, т.к. слишком узкий рынок.
      Но кроме Closure Compiler не вижу смысла что-то рассматривать — он ведь еще и ускоряет код хоть немного. А тут несчастные 300Мгц MIPS'овские железки совсем сдохнут… :-)
  • 0
    3й способ по своей идее напоминает javascript в png.
    • 0
      Особо хорошо в png будут смотреться табуляции и пробелы )
  • 0
    Пишем однострочники на перле яваскрипте?
    • +1
      Превращаем javascript в помесь perl и brainfuck скорее.
  • +2
    > parseInt©
    Парсер — лох.
  • –1
    По последнему способу. Не обязательно в 8 раз, часть символов, например как unicode в js строки надо будет преобразовать например в 2 байта, а тогда уже стремимся к числу в 16 раз больше :)
    • 0
      Все равно в 8 раз больше :) как не крути! И так будет всегда, пока в байте будет 8 бит :) Если, конечно не извращаться и при обфускации не превращать utf8 в utf16.
  • –3
    А меня вот другое интересует.

    Вы занимались обфускацией?
    Зачем вы это делали?

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

    Защищаетесь? От чего?
    • –1
      Вы пишите проект, проект крутится на ваших JS бибилиотеках ( не только JS конечно, но в данном случае ) и Вы не хотите:

      1) Чтобы Ваши библиотеки уплыли куда либо в другие не Ваши проекты

      2) Чтобы в случае чего-либо понадобившегося Вашему клиенту, заказ получили Вы а не фрилансер Вася Пупкин

      Например так, и это далеко не все.
      • 0
        Ну так это ж все расшифровывается так или иначе.
        • 0
          Все расшифровывается так или иначе :-D

          Дело во времени, в ресурсах и целях )
      • +4
        По-моему что обфускация, что защита программ всякими «старфорсами» все это комплексы какие-то. Пишите качественно и количество (денег) не заставит себя долго ждать.
        • 0
          Цели разные бывают. Вот например я сделал игру Алхимия на JS. Суть сводится к тому, чтобы комбинируя имеющиеся элементы получать новые. Все доступные комбинации элементов хранятся в js и доступны любому, кто знает про вошебную комбинацию Ctrl+U. Таким образом, скрыв код, мы сильно сузим множество «читеров». Конечно, комбинации все равно можно будет прочитать, но сделать это будет сложнее.
          Это я к тому, что бывают и непараноидальные поводы скрыть код:)
      • +2
        Превращать свои «хорошие» скрипты в вот в такое месево это зло злейшее.
        Если вы не желаете открывать код — вам не стоит писать на JavaScript. Даже если обработать все GCC, то исходник мы так или иначе получим. А распаковка вот такого добра, которое раз в 20 длиннее кода, может занять несколько секунд и код мы тоже получим.
        Вышеположенные способы представлены исключительно ради спортивного интереса и восновном используются для сокрытия «плохого» JavaScript (XSS скриптов), ворующего ваши куки.
        Мораль: бесполезно бороться с уводом кук регулярками, бьющими по document.cookie. Лучше всего совсем не давать пользователю вводить html разметку (Markdown наше все), если даете вводить, то тщательно фильтруйте источники XSS, а не их код.
        • 0
          Обфускация — вовсе не всегда удлинение кода (компрессия, байт код например), это раз, во вторых что угодно можно декомпилировать, вопрос только во времени и ресурсах.
          В большинстве случаев для неюзанья своих библиотек вполне хватит скомпрессить код, укоротив названия методов и перменных максимально.
          • 0
            За первый способ я двумя руками за, остальные для XSS и извращенцев.
            • 0
              С моей точки зрения способ хорошо если:
              1) увеличивает код не более чем на 5%
              2) уменьшает быстродействие не более чем 5%
              3) степень геморроя по желанию

              :-D
              • 0
                Если отходить от YUI Compressor
                1. Всегда уменьшает
                2. Быстродействие не изменится, даже будет на йоту быстрее из-за коротких переменных.
                3. Прибавит если вы мазохист и отлаживаете сжатые скрипты: Error on line 1 character 5477 // WOW!
                • 0
                  я имел ввиду что каждый сам выбирает уровень геморроя )))
                  но вообще отлаживать компрешенные скрипты — это надо тру дзеном быть )))))
                  • 0
                    для компрешенных, кроме упомянутого бьютифаера, есть reformat/reindent code в различных ide, как например NetBeans и Intellij IDEA )
        • 0
          Что же тогда использовать вместо JavaScript??? Flash не предлагать.
          • –1
            C++
  • +1
    >Представленный код может не работать, ибо хабрапарсер©

    От хабрапарсера отлично помогает тег <pre>
    • 0
      Подскажите как использовать тег <pre> с тегом <source>? Как ни крутил не работает.
      function © {} 
      • 0
        Мой совет с pre скорее относился к случаям, когда source использовать бессмыссленно, например, в коде сразу после фразы «Или вот в такой (код может не работать ибо хабрапарсер)»
  • +10
    Уже так и вижу, как толпа «праграммистаф на Джаве» будет прятать свой уникальный скрипт снежинок или часов в невидимый текст.
  • –1
    А ещё эту статью можно было назвать: «Новая веха в XSS»…
  • 0
    Паковка в png habrahabr.ru/blogs/crazydev/102394/ — наверное тоже разновидность обфускации
  • +1
    спасибо за статью, узнал много нового!
    а также ради интереса сделал обфускатор, который делает яваскрипт невидимым — www.freedomscripts.org/js-invis.html

    только не пойму, почему в опере при декодировании получается такая каша. в ФФ все нормально
    • +2
      Это оперный баг, она корежит/удаляет невидимые символы в textarea
      Добавьте ещё один скрытый элемент:
      <input type="hidden" id='code-2' value="" />

      В функции decode берите код из него
      xcode = document.getElementById('code-2').value.split("\n");

      В функции encode сохраняйте результат в оба элемента
      document.getElementById('code').value = result;
      document.getElementById('code-2').value = result;
      • 0
        спасибо, поправил. а также добавил возможность задания кастомных символов вместо таб и пробел, теперь можно получить более забавную кашу, например js из смайликов
    • 0
      FF 3.6, обфусцированный код не выполняется, при декодировании такая фигня:
      ؁̰̉΄ΐɀ‡̌lj̃ƓЀ̡ΐ‡ġs (это было alert('fuck it'); )
      • 0
        оказывается ff не понимает таб-ы в текстовых полях, оттого не работал декодер
        исправил
  • +2
    Ну, описанное безусловно интересно, но и решается довольно просто. Выделяем код между тегами script, сохраняем в отдельный файл, в начало лепим eval=print; ставим SpiderMonkey, запускаем:
    $ js example_js_eval.txt | indent
    и в итоге получаем расшифрованный код.

    JSUnpack позволяет делать то же и даже большее, например, обходит хитрости с эмуляцией DOM, когда в скрипте принимают участие другие части html-кода, ну как в классическом примере:
    <+html>
    <+head>
    <+title>MyEncrypi0nK3y<+/title>
    <+/head>
    <+script>
    function decrypt(key, input) {
    var output = “”;
    return output;
    }
    eval(decrypt(document.title, “258ff2c006e9bd6”));
    <+/script>
    <+/html><+/code>

    (плюсы добавлены в теги, что отобразить их в комментах, Хабр блокирует).

    Понятно, что суть обфускации - закриптовать код, но надо ведь ещё и скрыть процедуру декрипта.

    Всё вышесказанное касается js в html, но нельзя забывать о js в pdf и swf, где возможности ещё шире и интереснее.
  • 0
    Даешь верблюда на JS: ru.wikipedia.org/wiki/JAPH :)
  • 0
    блин прочитал бы я эту статью пораньше, задумался бы…
  • 0
    Вы можете стать популярным на wtfjs.com/, если закините туда пару цитат из этого кода :)
  • 0
    Теперь ждем, когда на собеседованиях начнут в качестве тестовых заданий на знание js предлагать определить что-же делает «Braifuck-подобный» код. -__-
  • +1
    Для Ample SDK писал обфускатор/минификатор сам (компрессия лучше чем в YUI, Closure). Вот фрагмент кода:

    dg7x5x5656x=_[5];6y Q=8x,kb=0,kc=10;8z hz0w{6y lA=0y cW,kB,kC,kz,ku,kD,kx,kA,kE,kt,kw,ky,kv;7z(6y jt=0,lH,lH,lH;lH=Q[jt];jt0v){kC=lH5x3756x;kz=lH5x3756x*lH5x7216x;if(lH5x7226x7wjw)kz=lH5x7216x4w1?lH5x7226x:db5x5846x(kz,lH5x7226x);ku=kz;kD=lA-lH5x8026x;kx=lH5x7966x>0?kD*lH5x7966x:ku-kD*db5x2006x(lH5x7966x);if((lH5x3946x5x6236x1wkD3vlH5x3946x5x6236x)2w(kD3vku*(lH5x2456x?2:1)/lH5x7966x)){hC(lH);if(lH5x6606x 9z dn){7z(6y o=lH5x6606x5x2886x,je=o5x236x(lH);je<o5x5566x;je0v)if(o[je+1] 9z dp){hB(o[je+1]);0z}}}6z if(lH 9z df1w!(lH 9z _b)){kA=kC*(lH5x2456x?2:1);kE=kx-kA*db5x4256x(kx/kA);if(lH5x2456x1wkE3vkC)kE=2*kC-kE;kB=1/(1-lH5x2026x/2-lH5x3486x/2);kt=kC*lH5x2026x;kw=kC*lH5x3486x;if(kE<kt)ky=kE*(kB*kE/kt)/2;6z if(kE>kC-kw){kv=kE-(kC-kw);ky=kB*(kC-kt/2-kw+kv*(2-kv/kw)/2)}6z ky=kB*(kE-kt/2);hx(lH,ky/kC)}}kb=hM(hz,kc)};gd(dg);ew(lg,_[561],8z0w{kb=hM(hz,kc)},9y);ew(lg,_[866],8z0w{gX(kb)},9y);6y dp=8z0w{dg5x2346x(3x,2x)};dp7x=0y dg(_[7]);8z hD(lM){6y lH=lM5x3406x;lH5x2526x=hE(lH5x2436x5x2526x);lH5x3946x=hE(lH5x2436x5x3946x);lH5x3756x=hF(lH5x2436x5x3756x);lH5x7216x=hG(lH5x2436x5x7216x,1);lH5x7226x=hF(lH5x2436x5x7226x);lH5x2456x=lH5x2436x5x2456x4w_[859];lH5x2026x=hG(lH5x2436x5x2026x,0);lH5x3486x=hG(lH5x2436x5x3486x,0);

    Слайды на тему: Extreme (yet non-intelligent) Minification and Obfuscation of JavaScript
    • 0
      Почему в слайде у GCC вычеркнут Advanced Mode? Код сжимается безопасно (скрипт сам ставит где нужно; {} и т.п.)? Засоряет ли Global Scope?
      • –1
        Вычеркнут, ибо GCC (Advanced Mode) не смог скомпилировать работающий код.
  • 0
    Интересно, что будет, если обфускатору подсунуть обфусцированный код?
    • 0
      Он его обфусцирует?
  • +1
    Тема arguments.callee в виде ключа дешифрации не затронута.
  • +1
    Вот самый простенький энкодер жаваскрипта на жаваскрипте, с примитивной защитой от модификации тела декодера.
    Воткните вместо eval например alert и получите мусор — тело переменной hash изменится, и декодировка сломается.
    Дальше можно опираться на значение eval.toString() и отлавливать подмену тела функции eval, что тоже усложнит декодировку.

    <html>
    <head>
    <style>textarea {width: 100%; height: 50%}</style>
    </head>
    <body>
    <script>

    simpleEncoder = {

      regex : /[^a-z]/g,

      /*
       *
       */
      encode : function(js)
      {
        var hash = this.decode.toString().replace(this.regex, '');
        var s = escape(this.xorStrings(js, hash));

        return "_=" + this.decode.toString() + "('" + s + "', " + this.regex + ")";
      },

      /*
       *
       */
      decode : function(code, regex)
      {
        xorStrings = function (str1, str2)
        {
          var s=new String();  
          for(var i=0; i < str1.length; i++)
          {
            var c1=str1[i].charCodeAt(0);
            var c2=str2[i % str2.length].charCodeAt(0);

            s+=String.fromCharCode((c1 ^ c2 ^ str2.length));            
          }
          return s;
        }

        code = unescape(code);
        hash = arguments.callee.toString().replace(regex, '');

        eval(xorStrings(code, hash));
      },

      /*
       *
       */
      xorChars : function (char1, char2)
      {
        return String.fromCharCode((char1.charCodeAt(0) ^ char2.charCodeAt(0)) % 255);
      },

      /*
       *
       */
      xorStrings : function (str1, str2)
      {
        var s=new String();  
        for(var i=0; i < str1.length; i++)
        {
          var c1=str1[i].charCodeAt(0);
          var c2=str2[i % str2.length].charCodeAt(0);

          s+=String.fromCharCode((c1 ^ c2 ^ str2.length));            
        }
        return s;
      }
    }

    var encoded_js = simpleEncoder.encode("alert('Hello World! Привет, мир!');");
    document.write("<textarea><script>" + encoded_js + "</script></textarea>");

    </script>
    </body>
    </html>

    * This source code was highlighted with Source Code Highlighter.
    • 0
      Надо же, работает.
      arguments.callee.toString() — поручик был такой выдумщик ;)
    • 0
      в вашем случае имея входные данные и сам алгоритм декодирования — все элементарно раскодируется,
      интересно — данный пример где-то юзается — или так — теория?
      • 0
        Это лишь пример ещё одного способа усложнения декодирования.
        • 0
          так а смысл — если раскодировать даже проще чем закодировать (

          hash_decode_fn = you_decode_fn.toString().replace(/[^a-z]/g, '');
          str_js = xorStrings(unescape(you_code), hash_decode_fn);
          
          • 0
            Вы как маленький. Код — proof of concept.
            Добавьте utf8 в имена переменных и функций, не вырезайте их регуляркой, спрячьте декодер, обфусцируйте имена переменных, и получите вполне труднодекодируемый код.
            • 0
              и что — сильно что-то изменится?
              кому не надо — тот и смотреть не будет, а кому надо — «труднодекодируемый» код — это +- 10-15-20 мин, потому что он все равно «декодируемый»
  • 0
    Вы как маленький. Код — proof of concept.
    Добавьте utf8 в имена переменных и функций, не вырезайте их регуляркой, спрячьте декодер, и получите вполне труднодекодируемый код.
  • 0
    Спасибо большое за статью!
  • 0
    Может вопрос будет звучать и глупо, но все же спрошу.
    Можно ли function(p,a,c,k,e,d) как то превратить в нормальный код на сервере, например с помощью PHP?
    • +1
      Насчет PHP не знаю. Можно распарсить код в AST на JS, а потом нарисовать его в читаемом виде.
  • 0
    Ого! Не знал, что в таком коде можно вот так вот детально разобраться. Спасибо большое! Теперь буду знать!
  • +1
    никакой из обфускаторов так не сможет

    Как же? Практически один-в-один происходит в jsfuck.

    Там function выдёргивается через []["filter"], а сами символы f-i-l-t-e-r берутся из true и false, которые в свою очередь !![] и ![].
    • 0
      Поправочка: «i» берётся из undefined, который [][[]]

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