0

JavaScript コード ( evalsetTimeoutなど)を動的に解釈するために使用される関数呼び出しの数をカウントしたいと考えています。私の主な目的は、 eval および setTimeout にパラメーターとして渡される文字列を見つけることです。これは、悪意のあるスクリプトが eval 関数を使用して複雑なコードを動的に評価することが一般的であるためです。これを見つける 1 つの方法は、関数をフックして、eval 関数の各呼び出しをトリガーできるようにすることです。しかし、これを行う方法がわかりません。これを例で説明してください。

setTimeout に対して通常どおり試しましたが、正しい結果が得られません。

私のコードは次のとおりです

var sto = setTimeout; setTimeout = function setTimeout(str){
console.log(str);
}

私の実際のユーザースクリプトは次のとおりです。

// ==UserScript==
// @encoding    UTF-8 
// @name        Count_setTimeout
// @run-at      document-start
// ==/UserScript==
addJS_Node("var count=0;");
function Log_StimeoutCreations ()
{
  var sto = setTimeout;
  setTimeout = function(arg, time) 
  {
     if(typeof arg == "string")
        console.log("Insecure setTimeout: ", arg);
     else
        console.log("setTimeout:",arg);   
     count++;
     sto(arg, time);    
  }
}
var waitForDomInterval = setInterval (
function () {
    var domPresentNode;
    if (typeof document.head == "undefined")
        domPresentNode = document.querySelector ("head, body");
    else
        domPresentNode = document.head;
    if (domPresentNode) {
        clearInterval (waitForDomInterval);
        addJS_Node (null, null, Log_StimeoutCreations);           
    }
},
1
);
function addJS_Node (text, s_URL, funcToRun) {
var D                                   = document;
var scriptNode                          = D.createElement ('script');
scriptNode.type                         = "text/javascript";
if (text)       scriptNode.textContent  = text;
if (s_URL)      scriptNode.src          = s_URL;
if (funcToRun)  scriptNode.textContent  = '(' + funcToRun.toString() + ')()';
var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
targ.appendChild (scriptNode);
}
addJS_Node("document.onreadystatechange = function (){if (document.readyState == 'complete'){if(typeof(unsafeWindow)=='undefined') { unsafeWindow=window; } unsafeWindow.console.log('count--'+count);}}");

しかし、ソース コードで表示される setTimeout 関数を取得することすらできません。さらにこれを達成するにはどうすればよいですかこれにより、内部評価関数が得られます。つまり、eval(eval());

4

1 に答える 1

1

あなたは基本的にそれを正しく理解しています。これが私のコードです:

var sto = setTimeout;

setTimeout = function(arg, time) {
    if(typeof arg == "string")
        console.warn("Insecure setTimeout: ", arg);

    // call real setTimeout
    sto(arg, time);
}

// ...now all future setTimeout calls will warn about string use...
setTimeout("alert(1);", 1000);

stoそれについて非常に正確であり、元の へのアクセスを許可するグローバル名前空間に残したくない場合setTimeoutは、クロージャーを使用します。

(function() {
    var sto = setTimeout;
    setTimeout = function(arg, time) {
        if(typeof arg == "string")
            console.warn("Insecure setTimeout!", arg);

        sto(arg, time);
    }
})();

この方法では、新しいラッパー内を除いて、匿名関数が終了するとアクセスできsetTimeoutないため、 real は完全にアクセスできません。stosetTimeout

于 2012-04-23T16:28:31.633 に答える