uBlockOrigin / uBlock-issues

This is the community-maintained issue tracker for uBlock Origin
https://github.com/gorhill/uBlock
944 stars 80 forks source link

Add new scriptlet that prevents some anti-debugging #3378

Closed D4niloMR closed 1 month ago

D4niloMR commented 1 month ago

Prerequisites

I tried to reproduce the issue when...

Description

Mostly for websites that has obfuscated code with anti-debugging. Maybe in the future it will be possible to replace the snippet below with trusted-replace-argument .

Only the proxy is necessary.

window.Function.prototype.constructor = new Proxy(window.Function.prototype.constructor, {
  apply: function(target, thisArg, args) {
    if (typeof args[0] === "string" && args[0].includes("debugger")) {
      return;
    }
    return Reflect.apply(target, thisArg, args);
    }
  });
window.console.clear = function () {};
Object.defineProperties(Object.prototype, { devtoolsDetector:{}, Debugger:{} });

A specific URL where the issue occurs.

https://veev.to/d/4vz566d3awg0
https://www.japscan.lol/
https://animet2.net/
https://binged.to/watch/movie/365177

Steps to Reproduce

  1. Disable annoyances lists.
  2. Choose one of the URLs above.
  3. Navigate to the site and open devtools.
  4. Boom, debugger statement

Expected behavior

Visiting site with obfuscated code the debugger statement is not executed.

Actual behavior

Visiting site with obfuscated code and anti debugger, the debugger statement is executed.

uBO version

1.59.1b22

Browser name and version

Firefox Developer Edition 131.0b6

Operating System and version

Windows 10

uBlock-user commented 1 month ago

@D4niloMR ##+js(trusted-replace-argument, Function.prototype.constructor, 0, undefined, condition, debugger) ?

D4niloMR commented 1 month ago

Doesn't work, I don't see nothing logged with ##+js(trusted-replace-argument, Function.prototype.constructor) either.

uBlock-user commented 1 month ago

Well it's based on

window.Function.prototype.constructor = new Proxy(window.Function.prototype.constructor, {
  apply: function(target, thisArg, args) {
    if (typeof args[0] === "string" && args[0].includes("debugger")) {
      return;
    }
    return Reflect.apply(target, thisArg, args);
    }
  });

If that works, then this should also work...

Maybe trusted-suppress-native-method is needed

gorhill commented 1 month ago

There is this extension specialized in defusing anti-devtools: https://github.com/Andrews54757/Anti-Anti-Debug

AMO: https://addons.mozilla.org/en-US/firefox/addon/anti-anti-debug/ CWS: https://chromewebstore.google.com/detail/anti-anti-debug/mnmnmcmdkigakhlfkcdimghndnmomfeo

D4niloMR commented 1 month ago

That extension seems good. Still it would be handy to have a scriptlet to trap Function.prototype.constructor, or better, using trusted-replace-argument on it.

gorhill commented 1 month ago

trusted-replace-argument should work but doesn't because the trapped target ends up being construct, which is problematic for Function since it can be called either through new Function(...) or directly through Function(...). Also, if I end up fixing this somehow, the function argument can be a different position than 0, so the scriptlet might need a way to provide argument position relative to the end, and/or a way to scan all arguments.

uBlock-user commented 1 month ago

same reason for trusted-suppress-native-method not working ?

gorhill commented 1 month ago

trusted-suppress-native-method uses the same internal helper to trap, so probably the same issue.

gorhill commented 1 month ago

##+js(trusted-replace-argument, Function.prototype.constructor, 0, , condition, debugger) works in 1.59.1rc0.

uBlock-user commented 1 month ago

what about ##+js(trusted-replace-argument, Function.prototype.constructor, 0, undefined, condition, debugger) ?

gorhill commented 1 month ago

Why not try it?

D4niloMR commented 1 month ago

It works, but seems to take a lot of resources, especially on Firefox.

Screenshots ![image](https://github.com/user-attachments/assets/49b366ea-5c3e-4782-95e2-109f0d73e8f9) ![image](https://github.com/user-attachments/assets/646e2214-afbf-43a9-b5f5-5ec12040c20b)

https://share.firefox.dev/3ZoT6tD

gorhill commented 1 month ago

seems to take a lot of resources, especially on Firefox

At https://veev.to/d/4vz566d3awg0, this happens without the filter too, just opening the dev console?

D4niloMR commented 1 month ago

Yes, but I wasn't with devtools opened while profiling and it still used a lot of resources.

I can't reproduce this issue anymore on that site though. I can on japscan.lol.

gorhill commented 1 month ago

Looks like it's related to the scriptlet sending logging information to uBO's background process -- might be an issue when a site does something very fast non-stop which is being trapped by uBO.

garry-ut99 commented 1 month ago

I can reproduce, whole browser begun freezing:

screenshoot ![ss](https://github.com/user-attachments/assets/62fe91cf-5245-438b-91f0-de695e96fa15)
D4niloMR commented 1 month ago

Now it becomes unresponsive, more noticeable when the logger/devtools is open. Firefox still freezes if wait long enough.

gorhill commented 1 month ago

I am going to need all the details of what I need to do to reproduce.

I could reproduce performance issue only when the logger was opened when navigating to https://veev.to/d/4vz566d3awg0 while using the filter veev.to##+js(trusted-replace-argument, Function.prototype.constructor, 0, , condition, debugger), and this was squarely a issue with sending too much logging information to the logger from the page context -- as the page probably keep creating debugger functions non-stop in a tight loop. Once I added the throttling code to prevent repeatedly reporting thesame information to the logger, the issue went away. The profiling data you shared also show the issue was the logging overhead.

Now if you have another scenario causing issue, I will need all the details on how to reproduce on my side, and profiling data is welcome.

D4niloMR commented 1 month ago

The issue of the resources is fixed. Now I'm reporting that on my end, navigating through the devtools tabs is unresponsive, like network tab, sources/debugger and expanding nodes in inspector.

But this is probably the site's own issue, I didn't notice that the snippet in the description and the Anti Anti Debug extension was throwing error and stopping the debugger call. Once I added veev.to##+js(trusted-replace-argument, Function.prototype.constructor, 0, noopFunc, condition, debugger) the issue went away.

gorhill commented 1 month ago

veev.to##+js(trusted-replace-argument, Function.prototype.constructor, 0, noopFunc, condition, debugger)

You shouldn't be using noopFunc, the argument is supposed to be a string representing the body of the function to create and using noopFunc causes an exception -- try Function.prototype.constructor(function(){}) in dev console of https://example.com/).

This doesn't throw:

veev.to##+js(trusted-replace-argument, Function.prototype.constructor, 0, /* debugger */, condition, debugger)

You can try at https://example.com/ console: Function.prototype.constructor('/* debugger */')

D4niloMR commented 1 month ago

Yes, but on my end if it doesn't throw I suffer from the issue above.

garry-ut99 commented 1 month ago

I suffer from the issue above.

Yes, same for me:


You shouldn't be using noopFunc, the argument is supposed to be a string representing the body of the function to create

Description says: "-- the value is interpreted the same way the value for set-constant is interpreted." - I guess D4niloMR interpreted it that it should be fed with the same values like from set-constant scriptlet, hence that's why he used noopFunc, and it actually does work (for him and for me)...

and using noopFunc causes an exception -- try Function.prototype.constructor(function(){}) in dev console of https://example.com/).

For me it throws after pasted manually in dev console, but not when used in the scriptlet on the site, maybe that's why it works for me and for D4niloMR.

(I tested on Firefox).

stephenhawk8054 commented 1 month ago

How about this:

veev.to##+js(trusted-replace-argument, Function.prototype.constructor, 0, {"value": "/* debugger */"}, condition, debugger)
uBlock-user commented 1 month ago

Why not try it?

I cannot reproduce debugger statement, so need someone to test.

garry-ut99 commented 1 month ago

Logger says: Replaced argument: Before: "debugger" After: ("works in") Logger says: Replaced argument: Before: "debugger" After: /* debugger */ ("How about this") Logger says: Replaced argument: Before: "debugger" After: undefined ("so need someone to test")

In all cases, dev tools are still unresponsive / laggy / freezing (like without the scriptlet) every time dev tools are opened or closed. The only filter which works and fixes dev tools for me, is the one with noopFunc. (Tested on Firefox).

gorhill commented 1 month ago

Yes, but on my end if it doesn't throw I suffer from the issue above.

Right, I didn't realize an exception worked better. In that case, this filter might be a better match:

veev.to##+js(trusted-suppress-native-method, Function.prototype.constructor, '"debugger"', abort)
garry-ut99 commented 1 month ago

The above filter works fine as well for me (on both Firefox and Chromium).

D4niloMR commented 1 month ago

Also works fine for me.