0

I want to count the number of function calls that are used to dynamically interpret JavaScript code (e.g., eval and setTimeout). My main intention is to find the strings passed as parameters to eval and setTimeout . This is because it is common for malicious scripts to dynamically evaluate complex code using the eval function. One way to find this is to hook the function so that each call to eval function can be triggered. But i am not sure how to do this. Please Explain this with an example.

I tried it normally for setTimeout but I am not getting the correct result.

My code is as follows

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

My actual userscript is:

// ==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);}}");

But I am not even getting the setTimeout functions viewed in Source code. How do I achieve this moreover By this will I get inner eval functions i.e, eval(eval());

2
  • I would add github.com/jterrace/js.js to the list Commented Apr 23, 2012 at 12:57
  • So calling setTimeout when you've set setTimeout = function(str) { console.log(str) } doesn't output something to the console? If so, it sounds like you're never calling it (or calling setTimeout before you redefine it). Commented Apr 23, 2012 at 16:14

1 Answer 1

1

You've basically got it right. Here's my code:

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);

If you want to be super-correct about it and not leave sto in the global namespace allowing access to the original setTimeout, use a closure:

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

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

This way, the real setTimeout is completely inaccessible, since sto is inaccessible once the anonymous function ends, except within the new setTimeout wrapper.

Sign up to request clarification or add additional context in comments.

2 Comments

I want to add this function to my userscript i included it but i am not getting the output because the function is not ending. I pasted my userscript please go through that and suggest any changes.
I tried this userscript on google.co.in but i am getting a never ending result.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.