Skip to content

Use safe Function.prototype.toString() in scriptlets #2907

Description

@MasterKia

Some sites (or libraries) tamper with Function.prototype.toString which is used in these scriptlets to match against the handler function:
addEventListener-defuser, no-setInterval-if, no-setTimeout-if, adjustSetInterval, adjustSetTimeout, noeval-if

Example 1

Add:

noorlib.ir##+js(aeld, copy, dontMatch, log, 2)

Visit:
https://noorlib.ir/book/view/30999?pageNumber=10&viewType=pdf
See in console:

[uBO] addEventListener('copy', function() {
    [native code]
})

Use this userscript:

(function() {
  const safe = {
    'toString': self.Function.prototype.toString,
    'log': console.log.bind(console)
  }

  self.EventTarget.prototype.addEventListener = new Proxy(self.EventTarget.prototype.addEventListener, {
    apply(target, thisArg, args) {
      const originalToString = String(args[1]);
      const safeToString = safe.toString.call(args[1]);
      if (originalToString !== safeToString && args[0] === 'copy') {
        safe.log(`${args[0]}\n\n[Original toString] ${originalToString}\n\n[Safe toString] ${safeToString}`)
      };
      return Reflect.apply(target, thisArg, args);
    }
  });
}) ();

See in console:

function(){var r=Array.prototype.slice.call(arguments);try{n&&"function"==typeof n&&n.apply(this,arguments);var o=r.map((function(t){return _e(t,e)}));return t.apply(this,o)}catch(t){throw ye+=1,setTimeout((function(){ye-=1})),H((function(n){n.addEventProcessor((function(t){return e.mechanism&&(Object(y.b)(t,void 0,void 0),Object(y.a)(t,e.mechanism)),t.extra=Object(a.a)(Object(a.a)({},t.extra),{arguments:r}),t})),D(t)})),t}}

The tampered toString():

function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=Object(O.f)(this)||this;return He.apply(n,t)}

Example 2

On soft98.ir, enter in console:

(() => {}).toString()

See "function() { [native code] }" instead of "() => {}".

The tampered toString():

"function(){return en()}"

Example 3

On extremereportbot.com, enter in console:

iframe = document.createElement('iframe'); document.body.appendChild(iframe); safeToString = iframe.contentWindow.Function.prototype.toString; console.log(safeToString.call(Function.prototype.toString))

See function toString(){return"function"==typeof this&&this[a]||e.call(this)} instead of "function toString() { [native code] }"

https://github.com/gorhill/uBlock/pull/3901

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions