#JavaScriptを全角文字で書いて更に難読化させる
JavaScriptの一部の文字列、もしくは、命令全体を全角文字で書くことによって、更に難読化させることができます。
セキュリティー上、少しでも見られたくないURLや文字列、命令文を記述したりするのに有効です。
ソースコード上では、ただ全角コードで記述してあるため、可読性が良く、かつ、難読化させる時は、全角文字を強制的に \uxxxxのような文字列にするために、更に難読化させる効果があります。
現代のブラウザは、JavaScriptはUTF-16で実行されていますが、ツールによって変換を行ないます。
ソースはUTF-8で記述するようにしてください。
##必要なツール
- 各種packerソフト jsPacker.plがお勧め http://dean.edwards.name/download/#packer
- yuicompressor
- 以下のソースのツール
#!/usr/bin/perl
# Usage perl utf16.pl inputfile outputfile
use utf8;
use Encode;
$in=$ARGV[0];
$out=$ARGV[1];
$buf="";
open(R,"<:utf8",$in)||die "$in not found\n";
#binmode(R,":utf8");
open(W, ">$out")||die "$out can't write\n";
foreach(<R>) {
for($i=0; $i<length($_); $i++) {
$c=substr($_, $i, 1);
if(utf8::is_utf8($c) && (ord($c) > 0x7f)) {
utf8::encode($c);
Encode::from_to($c, "utf8", "utf16");
$c=~s/(.)/unpack('H2',$1)/eg;
$c=~s/(feff)/\\u/g;
$buf.=$c;
$c=substr($_, $i+1, 1);
} else {
$buf.=$c;
}
}
# print W "\n";
}
$buf=~s/\\u([0-9A-Fa-f][0-9A-Fa-f])(\n)/"\\u$1" . unpack("H2",$2)/ge;
print W $buf;
close(W);
close(R);
##難読化方法
Makefile等で
perl utf16.pl script.js script.min.js.tmp1
yuicompressor --type js script.min.js.tmp1 > script.min.js.tmp2
perl jsPacker.pl -e62 -q -f -i script.min.js.tmp2 > script.min.js
rm -f script.min.js.tmp1 script.min.js.tmp2
##実例として、まず、行ないたいソースです。
###ソース
var GLOBAL = (this || 0).self || global;
(function (G, D, W){
W.onload = function() {
alert("test");
}
})(GLOBAL, document, window);
###難読化します
eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36);};;if(!''.replace(/^/,String)){while(c--)d[c.toString(a)]=k[c]||c.toString(a);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;}('e 1=(d||0).9||8;(2(b,c,a){a.7=2(){6("5")}})(1,4,3);',15,15,'|GLOBAL|function|window|document|test|alert|onload|global|self||||this|var'.split('|'),0,{}))
alert、test共に文字列がソースに存在します。
##次に、「test」の文字だけ、更に難読化します
###ソース
var GLOBAL = (this || 0).self || global;
(function (G, D, W){
W.onload = function() {
alert(zenhan("test"));
};
var zenhan=function(str) {
var h = '';
str.split('').forEach(function (s) {
h += String.fromCharCode(s.charCodeAt(0) - 0xFEE0);
});
return h;
};
})(GLOBAL, document, window);
###難読化します
eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36);};;if(!''.replace(/^/,String)){while(c--)d[c.toString(a)]=k[c]||c.toString(a);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;}('2 3=(r||0).q||p;(1(b,c,a){a.o=1(){n(d("\\4\\m\\l\\4"))};2 d=1(f){2 e="";f.k("").j(1(g){e+=i.h(g.9(0)-8)});7 e}})(3,6,5);',28,28,'|function|var|GLOBAL|uff54|window|document|return|65248|charCodeAt||||||||fromCharCode|String|forEach|split|uff53|uff45|alert|onload|global|self|this'.split('|'),0,{}))
testの文字列がわかりづらくなりました。
##alert("test")自体をすべて難読化する
evalを使うことで、すべて全角文字でJavaScriptを書くことができます。
var GLOBAL = (this || 0).self || global;
(function (G, D, W){
W.onload = function() {
eval(zenhan("alert(’test’);"));
};
var zenhan=function(str) {
var h = '';
str.split('').forEach(function (s) {
h += String.fromCharCode(s.charCodeAt(0) - 0xFEE0);
});
return h;
};
})(GLOBAL, document, window);
eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36);};;if(!''.replace(/^/,String)){while(c--)d[c.toString(a)]=k[c]||c.toString(a);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;}('2 4=(y||0).x||w;(1(v,u,9){9.t=1(){r(6("\\q\\p\\8\\o\\3\\n\\7\\3\\8\\m\\3\\7\\l\\k"))};2 6=1(5){2 h="";5.j("").i(1(s){h+=g.f(s.e(0)-d)});c h}})(4,b,a);',35,35,'|function|var|uff54|GLOBAL|str|zenhan|u2019|uff45|W|window|document|return|65248|charCodeAt|fromCharCode|String||forEach|split|uff1b|uff09|uff53|uff08|uff52|uff4c|uff41|eval||onload|D|G|global|self|this'.split('|'),0,{}))
alert、testともにわかりづらくなりました。
##function zenhanの注意
- 強制的にコードを引き算するため、半角文字が含んでいるとうまく動作しません。
- 全角文字に存在して、半角文字に存在する文字列を含めることはできません。例:「あいうえお」
##最後に
- あくまで難読化であって、何らかの方法で復号することはできます。(筆者は既に確認済です)
- 難読化を行うことによって、パフォーマンスが落ちたり、動作しなくなったりする可能性があります。よくデバッグを行ないながら行いましょう。