JavaScript Advent Calendar 2016 14日目の記事です。
任意サイトにおいて window 配下に紐づいている全オブジェクト (つまりグローバル変数と、それにぶらさがっている全変数) を再帰的に列挙してみようと思います。
これはウェブサイトの内部構造(のとっかかり)を外部の人間が解析したいときに役立つであろうテクニックです。
スクリプト
Chrome Developer Tools Console にて以下を実行します。
(function(){ var f = document.body.appendChild(document.createElement('iframe')); f.style.display = 'none'; window.console = f.contentWindow.console; })(); (function(){ var g_objs = {}; var ACCESS_MARK = 4; function join(left, right){ if(!isNaN(right)){ return left + '[' + right + ']'; } else if(right.match(/[\/\-]/)){ return left + "['" + right + "']"; } else{ return left + '.' + right; } } function enumObj(parent, name, depth){ if(depth > 30){ debugger; } // 子オブジェクト取得 for(var key in parent){ if(key === '__accessed__')continue; if(key === '$'){ // debugger; } // オブジェクト取得 var obj = null; var type = 'error'; try{ obj = parent[key]; type = typeof obj; } catch(e){ } // 既にアクセスしたオブジェクトは無視 try{ if(obj !== null){ if(obj.__accessed__ === ACCESS_MARK)continue; obj.__accessed__ = ACCESS_MARK; var unique = obj + JSON.stringify(obj); if(g_objs[unique])continue; g_objs[unique] = ACCESS_MARK; } } catch(e){ } // オブジェクト情報出力 console.log(join(name, key) + ' : ' + type); // さらに掘る if(obj === null)continue; if(typeof obj === 'string')continue; if(typeof obj === 'number')continue; enumObj(obj, join(name, key), depth + 1); } } enumObj(window, 'window', 0); })();
結果
たとえば twitter.com で上記スクリプトを実行してみた例です。
twitter.com からひっぱってきたオブジェクト群 · GitHub
window.speechSynthesis : object window.speechSynthesis.pending : boolean window.speechSynthesis.onvoiceschanged : object .... window.$.Tween : function window.$.Tween.propHooks : object .... window.loadrunner.Module.exports['bower_components/flight/lib/registry'].components[0].attachedTo[0]['tweet-post-iframe'] : object window.loadrunner.Module.exports['bower_components/flight/lib/registry'].components[0].attachedTo[0]['tweet-post-iframe'].ondeviceorientationabsolute : object window.loadrunner.Module.exports['bower_components/flight/lib/registry'].components[0].attachedTo[0]['tweet-post-iframe'].ondeviceorientation : object window.loadrunner.Module.exports['bower_components/flight/lib/registry'].components[0].attachedTo[0]['tweet-post-iframe'].ondevicemotion : object window.loadrunner.Module.exports['bower_components/flight/lib/registry'].components[0].attachedTo[0]['tweet-post-iframe'].ontouchstart : object .... window.loadrunner.Module.exports['bower_components/flight/lib/registry'].components[0].attachedTo[0].jQuery22401681574395691191.events.dataDidUserUnpinTweet : object window.loadrunner.Module.exports['bower_components/flight/lib/registry'].components[0].attachedTo[0].jQuery22401681574395691191.events.dataDidUserUnpinTweet[0] : object ....
おしまい
あくまでもグローバルなツリーに乗っている変数しか検出できない(スコープに隠れてしまっている変数や関数等は検出できない)のですが、解析のとっかかりの一つにはなるかと思います。