Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new scriptlet that prevents some anti-debugging #3378

Closed
9 tasks done
D4niloMR opened this issue Sep 16, 2024 · 28 comments
Closed
9 tasks done

Add new scriptlet that prevents some anti-debugging #3378

D4niloMR opened this issue Sep 16, 2024 · 28 comments
Labels
enhancement New feature or request fixed issue has been addressed

Comments

@D4niloMR
Copy link

D4niloMR commented Sep 16, 2024

Prerequisites

  • I verified that this is not a filter list issue. Report any issues with filter lists or broken website functionality in the uAssets issue tracker.
  • This is NOT a YouTube, Facebook or Twitch report. These sites MUST be reported by clicking their respective links.
  • This is not a support issue or a question. For support, questions, or help, visit /r/uBlockOrigin.
  • I performed a cursory search of the issue tracker to avoid opening a duplicate issue.
  • The issue is not present after disabling uBO in the browser.
  • I checked the documentation to understand that the issue I am reporting is not normal behavior.

I tried to reproduce the issue when...

  • uBO is the only extension.
  • uBO uses default lists and settings.
  • using a new, unmodified browser profile.

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
Copy link
Contributor

uBlock-user commented Sep 16, 2024

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

@D4niloMR
Copy link
Author

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

@uBlock-user
Copy link
Contributor

uBlock-user commented Sep 16, 2024

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
Copy link
Member

gorhill commented Sep 16, 2024

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
Copy link
Author

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
Copy link
Member

gorhill commented Sep 16, 2024

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
Copy link
Contributor

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

@gorhill
Copy link
Member

gorhill commented Sep 16, 2024

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

gorhill added a commit to gorhill/uBlock that referenced this issue Sep 17, 2024
@gorhill
Copy link
Member

gorhill commented Sep 17, 2024

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

@uBlock-user
Copy link
Contributor

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

@gorhill
Copy link
Member

gorhill commented Sep 17, 2024

Why not try it?

@D4niloMR
Copy link
Author

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

Screenshots

image

image

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

@gorhill
Copy link
Member

gorhill commented Sep 17, 2024

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
Copy link
Author

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
Copy link
Member

gorhill commented Sep 17, 2024

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
Copy link

I can reproduce, whole browser begun freezing:

screenshoot

ss

gorhill added a commit to gorhill/uBlock that referenced this issue Sep 17, 2024
@D4niloMR
Copy link
Author

D4niloMR commented Sep 18, 2024

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

@gorhill
Copy link
Member

gorhill commented Sep 18, 2024

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
Copy link
Author

D4niloMR commented Sep 18, 2024

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
Copy link
Member

gorhill commented Sep 18, 2024

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
Copy link
Author

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

@garry-ut99
Copy link

garry-ut99 commented Sep 18, 2024

I suffer from the issue above.

Yes, same for me:

  • when using noopFunc in the scriptlet:
    • dev tools work fine: are responsive and switching between dev tools tabs is responsive as well
    • and logger says: Replaced argument: Before: "debugger" After: function(){}
  • when using /* debugger */ or any other random string value:
    • dev tools are unresponsive / laggy (like without the scriptlet)
    • and logger says: Replaced argument: Before: "debugger" After: undefined

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
Copy link
Member

stephenhawk8054 commented Sep 18, 2024

How about this:

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

@uBlock-user
Copy link
Contributor

Why not try it?

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

@gwarser gwarser added the enhancement New feature or request label Sep 19, 2024
@garry-ut99
Copy link

garry-ut99 commented Sep 19, 2024

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
Copy link
Member

gorhill commented Sep 19, 2024

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
Copy link

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

@D4niloMR
Copy link
Author

Also works fine for me.

@uBlock-user uBlock-user added the fixed issue has been addressed label Sep 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request fixed issue has been addressed
Projects
None yet
Development

No branches or pull requests

6 participants