JavaScriptのコードを自分で簡単に難読化を行う方法
JavaScriptの難読化を行いたいケースはかなり多いのではないでしょうか。
JavaScriptはバックエンドではなくフロントエンドで動作するため常にソースコードは公開されている状態です。
ですが、例えばJavaScriptでクイズを作成した時など、ソースコードに回答が記載されていると厄介なケースが多々あります。
そんな時でも、今回は簡単に難読化を行う方法をご紹介します。
※ 今回は「簡単」であることを前提としてご紹介していきます。単に「なんか読みにくくなる」テクニックだと思って是非試してみたください
難読化ツールはあまり使わない方がいい
難読化ツールはできる限り利用しないことをお勧めします。
なぜなら、
・解読化ツールが存在する場合がある → せっかくの難読化も意味がなくなってしまう
・ファイルサイズが極度に大きくなってしまう → 難読化が不必要な部分も難読化されてしまい、結果ファイルサイズが大きくなってしまうことにつながる
などといった手軽さと引き換えにデメリットもあります。
また、自分の手で難読化を行うメリットとして、
・ケースによって最適化できる → 必要な部分を必要なだけ難読化できる
・ソースコードが理解できる → 難読化したソースコードを直接手を加えることができるので、わざわざ難読化ツールを毎回やる必要もなくなり、作業の効率化につながる
というようなものがあるので、是非自分で難読化にチャレンジしてみてください。
数値の難読化
これはとても簡単なので読み飛ばしてしまっても構いませんが、一応ご紹介しておきます。
例えばクイズを作成する為、JavaScriptを次のように記述しました。
// push_btnにはクリックしたボタンの番号が格納されている。
// ボタン1は正解。2は惜しい。それ以降は違う。と表示する処理
if(push_btn === 1){
console.log("正解!");
}else if(push_btn === 2){
console.log("惜しい!");
}else{
console.log("違います!");
}
この場合の問題点は、
「JavaScriptの知識があれば考えずとも正解が分かる」
という点です。この場合、もはやJavaScriptの知識がなくてもある程度のプログラミングの知識があれば
「ボタン1を押せば正解になる」
ことが導き出せるはずです。
このようなカンニングを防ぐためにどのようにしていったらいいのでしょうか。
ボタンの番号をまず簡単に隠してみましょう。
// push_btnにはクリックしたボタンの番号が格納されている。
// ボタン1は正解。2は惜しい。それ以降は違う。と表示する処理
const x = (((9+14)*(128/2))/4)-1;// 367
if(push_btn === ((((342*76) - 25990)+((x*2)/(3*x-x)))-2)){// 1
console.log("正解!");
}else if(push_btn === ((x*2) / x)){// 2
console.log("惜しい!");
}else{
console.log("違います!");
}
一瞬複雑に見えますが、本当はとても簡単で、かつ見るとかなり面倒くさく感じるので解読する前に諦めさせるのが目的の難読化です。
ですが、仕組みは簡単なので諦めなければ1分足らずで分かってしまうかもしれません。
どのような仕組みかというと、
「ただ数字を分解しているだけ」
になります。
つまり、「100」という数字を「25×4」、それに付け加えて「25×6-70+20」といった具合に、です。
素因数分解のようにやっても構いません。
より複雑になるように変数xを追加しましたが、その変数も同じやり方で、変数xは「367」を表しているので、
const x = (((9+14)*(128/2))/4)-1;
// どちらも全く同じ
const x = 367;
と全く同じ意味になります。
2を隠している部分はあまり崩していないので暗算でも問題なく解けるはずです。
xを1にしたって構わないのですから、
「 (1×2) / 1 」つまり「2/1」であって一分の二、つまり2となるわけです。それをもう少し複雑にしたものが「1」を隠している部分です。
前述もしましたが、この手法はあくまで見掛け倒し的な方法ですので「ソースコードをパッと見られても理解できない」程度のものです。ですが大半の人は「何だこの面倒くさいやつ」と思って諦めてくれますので有効です!
ちなみにもう少し2を複雑にしてみると、
let y = (29_32/(2*6-8))+((4082/2)*(1773/(1+((3*4)-(5^15)))))-(((592/8)/2)*47)+(-50_3*(479*5)) ;// 543
let m = (82*(390+y))*(6_93+(y**2-(252-39)))+(-9_2351*(602_97*(9-5)))-(8*4-16);// 67796
let result=((y*925+(-756_2))*(((17220184/254)/m)-1))+((y*((1+9)/5))/y);
console.log(result);
やり方は同じです。変数や累乗、ビットオペランド的論理和オペランドと呼ばれるものや、それと数値に「_」を追加していますが、数値と数値に「_」を挟んでも数値として認識されます。
そのため、「2493」でも「2_493」でも「2_49_3」でも「2493」として認識されます。
それらを少し入れたことや変数を2つにしたことによってより複雑に見えます。(見えるだけです)
ですが、もちろんこの4行のコードも下記のコードと全く同じ出力結果になります。
console.log(2);
実際コンソールで上記2つのソースコードを比較してみてください。
どちらも「2」と表示されるはずです。
以上が数値の難読化になります。
文字列の難読化
変数による難読化
文字列も数値の場合と同じようなやり方でも十分見にくいコードを作ることができます。
いわゆる「変数」を乱用してしまえばいいわけです。
console.log("おはよう");
とやりたい時に、
var data=["う","お","よ","は"];
console.log(data[1]+data[3]+data[2]+data[0]);
とするだけであっという間に見にくくなりました。
それを分割させて、
var data=["う"];//1
data[]="お";//2
data[]="よ";//3
data[]="は";//4
console.log(data[1]+data[3]+data[2]+data[0]);
書く番号の処理をバラバラに配置する。それだけでもとても見にくいコードの完成です!
ですが、全体のソースコードの量が多くてあまり見つけられそうにない場合は
console.log("お"+'は'+`よ`+"う");
こうするだけでOKです。
「何も隠してないじゃないか!」
と思う方がいるかもしれませんが、大正解です。
ソースコードを見れば一応分かってしまいます。
でも、これは「検索」対策になっています。
このように分割しておけば「おはよう」とソースコードを検索されても引っ掛かりませんよね。
つまり、これは検索しないと見つけにくいほど全体のコード量が多い場合に最適となります。
ですがあくまでも検索対策です。
関数での難読化
変数の他に、関数を利用するという方法もあります。
仕掛けは、「相手に思い込ませる」ということです。
例えば、このようなコードがあったとしたらどのように受け取るでしょうか。
putHTML("content1","正解は2番です!");
「content1というidの要素のHTMLを”正解は二番です!”に変更する」
ように見えるコードです。
ちなみにputHTMLの関数は次のようになっています。
function putHTML(id,html){
html=htmlencoding(html);
document.getElementById(id).innerHTML=html;
}
「htmlencoding()ってHTMLをなんか整形とかして出力するのかな」
と思うはずです。putHTMLの関数の処理はあまり不審なポイントは一見見当たりません。
htmlencodingの関数はこちらです。
function htmlencoding(html){
var encodings=["正解",4];
return encodings[0]+"は"+encodings[1]+"番です!";
}
ここで種明かしです。
まず最初のputHTMLはidとhtmlをきちんと処理しているかのように見えますが、htmlの方はhtmlencodingという正体不明の関数を通して出力されます。
そしてhtmlencodingの方は、引数のことはお構いなしに好きな言葉へ変えてしまっています。
つまり、結果はこのようになります。
putHTML("content1","正解は2番です!");
-> 正解は4番です!
ソースコードを見た人を騙すようなテクニックです。
putHTML、htmlencodingもただの飾りにすぎません。
つまり、「関数の名前には必ず意味がある」と思ってしまうと引っかかってしまいます。
この、htmlencodingの関数とputHTMLをソースコードの分からないような部分に挟んでおけば、ある程度は騙されるはずです!
また、これは「関数の難読化」として紹介しましたが、名前を偽るという部分では変数にも応用することができます。
関数と変数の名前を両方偽ることで、より「リアル」に偽ることができるようになります。
※ちなみにですが、実際に利用するときは、htmlencodingの「正解は4番です!」のテキストを「変数で難読化」にある方法で隠しておくことをお勧めします。
これが「簡単」な難読化です
難読化は、「難読化」の名前の通り、コードの本来の動作を偽ったり隠したりすることです。
ですが、どれほど難読化を行っても元の処理に戻すことは可能であるため、「最高機密の情報」を難読化をして分からなくする目的ではありません。
そのため、「ばれてもしょうがないけど出来れば隠しておきたい情報」に対して、難読化は最高です。
難読化と検索してもツールであったり難しいものばかりで、筆者自身も
「意味わからん」
ような方法ばかりです。(未熟なだけですが)
なので、自分のように「そこまで本格的ではなくていいけど自分が分かるレベルで難読化をしたい」と思っている方にこの記事が届いてれば幸いです。