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 ....
おしまい
あくまでもグローバルなツリーに乗っている変数しか検出できない(スコープに隠れてしまっている変数や関数等は検出できない)のですが、解析のとっかかりの一つにはなるかと思います。