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

Scriptlet to spoof CSS property value #2618

Closed
8 tasks done
MasterKia opened this issue Apr 28, 2023 · 26 comments
Closed
8 tasks done

Scriptlet to spoof CSS property value #2618

MasterKia opened this issue Apr 28, 2023 · 26 comments
Labels
enhancement New feature or request fixed issue has been addressed

Comments

@MasterKia
Copy link
Member

MasterKia commented Apr 28, 2023

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

What about a scriptlet that will return a different CSS property value to counter getComputedStyle() (maybe by proxying CSSStyleDeclaration.prototype.getPropertyValue) to foil sophisticated anti-blockers that check all CSS properties of an element (like megaup, aternos, ylilauta.org)?

example.com##+js(spoof-css, a[href*="ads/redirect/"] > img, clip-path, none)
example.com##a[href*="ads/redirect/"] > img:style(clip-path: circle(0) !important;)

A specific URL where the issue occurs.

.

Steps to Reproduce

.

Expected behavior

.

Actual behavior

.

uBO version

.

Browser name and version

.

Operating System and version

.

@krystian3w
Copy link

Why not:

example.com##a[href*="ads/redirect/"] > img:spoof(clip-path: none !important;)
example.com##a[href*="ads/redirect/"] > img:style(clip-path: circle(0) !important;)

Based on migration ra, rc to pseudo-classes syntax.

@MasterKia
Copy link
Member Author

MasterKia commented Apr 28, 2023

Nice idea. My only concern is that we might experience the same problem with ##body:remove-attr(oncontextmenu) sometimes not working on Chromium.

@krystian3w
Copy link

krystian3w commented Apr 28, 2023

I suppose this trouble can only apply to javascript written with html attributes:

https://www.w3schools.com/tags/ref_eventattributes.asp

which is not recommended - actions should be created in the file or "<script> </script>" section (https://kornel-ski.translate.goog/pl/onclick?_x_tr_sl=pl&_x_tr_tl=en&_x_tr_hl=pl&_x_tr_pto=wapp).

@uBlock-user
Copy link
Contributor

##body:remove-attr(oncontextmenu)

Use ##body:remove-attr(oncontextmenu):watch-attr(oncontextmenu) then.

@krystian3w
Copy link

krystian3w commented Apr 28, 2023

#2618 (comment) - This solve trouble with blocked right click on 99% of pages?

#2403 (comment)

@gorhill
Copy link
Member

gorhill commented May 20, 2023

Based on migration ra, rc to pseudo-classes syntax.

Spoofing requires to patch JavaScript calls, which can only be done in the page world. Code for procedural cosmetic filters execute in content script world.

@krystian3w
Copy link

krystian3w commented May 20, 2023

And are there any plans to e.g. on musixmatch.com replace +js(ra, oncontextmenu, body, complete) to +js(nowoif, something)?

https://github.com/uBlockOrigin/uAssets/blob/ee4ce452e50fccf8253a6014db44122f4faf5e38/filters/annoyances.txt#L2007

@gorhill
Copy link
Member

gorhill commented May 20, 2023

Can I get real world examples (preferably not requiring account) for which I can test such scriptlet?

@peace2000
Copy link
Member

peace2000 commented May 20, 2023

Can I get real world examples (preferably not requiring account) for which I can test such scriptlet?

https://ylilauta.org/jorma/131700539

To spoof that ##iframe.a has value display: block even if it's truly hidden?

@gorhill
Copy link
Member

gorhill commented May 20, 2023

When I use ##iframe.a, the frame is not hidden, is there an exception filter? If so I am not seeing it in the logger.


Ok never mind, code stepping I see an exception filter, not reported in logger. It works if I use ##iframe.a.a.

gorhill added a commit to gorhill/uBlock that referenced this issue May 20, 2023
Related issue:
- uBlockOrigin/uBlock-issues#2618

Usage:

    example.com##+js(spoof-css, selector, property-name, property-value, ...)

- selector: a valid CSS selector which matches the elements for which
  the spoofing must apply.
- property-name: a CSS property name (can be dashed- or camel-cased)
- property-value: the value to return regardless of the currently
  computed value.

There can be any number of property-name/property-value pairs, all
separated by commas.

A special property-name/property-value pair `debug/1` can be used
to force the browser to break when `getComputedStyle()` or
`getBoundingClientrect()` is called, useful to help pinpoint usage
of those calls in the page's source code:

    example.com##+js(spoof-css, .ad, debug, 1)
@MasterKia
Copy link
Member Author

MasterKia commented May 24, 2023

On soft98.ir when I only add:
soft98.ir##+js(spoof-css, a[href*="s0ft98.ir"], clip-path, none) or
soft98.ir##+js(spoof-css, a[href*="s0ft98.ir"], nonsense, none)

I get detection after a few seconds.

But if I use this userscript:

// @run-at      document-start

(function () {
'use strict';
const handler = {
  apply(target, thisArg, args) {
    let response = Reflect.apply(target, thisArg, args);
    if (args == "clip-path" || args == "clipPath") {
      response = "none";
    }
    return response;
  }
}

const myProxy = new Proxy(CSSStyleDeclaration.prototype.getPropertyValue, handler);
CSSStyleDeclaration.prototype.getPropertyValue = myProxy;

}) ();

and then use this filter:
soft98.ir##a[href*="s0ft98.ir"]:style(clip-path: circle(0) !important;)

Then I get no detection.

Edit: added @run-at.

@gorhill
Copy link
Member

gorhill commented May 24, 2023

But if I use this userscript:

I tried with ViolentMonkey and I still get detection with your script.


Ok, seems to work when using // @run-at document-start.

@gorhill
Copy link
Member

gorhill commented May 24, 2023

Note that your code has an issue but it accidentally works because of truthiness. Should be:

if (args[0] === "clip-path" || args[0] === "clipPath") {

@gorhill
Copy link
Member

gorhill commented May 24, 2023

Ok the page is doing something else than just checking the properties. For spoof-css to work on that site, I had to wholly remove the proxying of getComputedStyle(), so it does something with that call that triggers the detection.

@MasterKia

This comment was marked as resolved.

@Yuki2718
Copy link

Yuki2718 commented Sep 10, 2023

Is it possible to specify not a static value but value obtainable from elements or scripts?
On https://github.com/uBlockOrigin/uAssets/discussions/17361#discussioncomment-6960192 an excerpt of detection code https://www.btcbitco.in/myassets/aOW9dugd31nhaaOW9dugd31nhd.js?ver= (direct access forbidden even with parameter)

Code
function aOW9dugd31nhests() {
            
                var done = 20;
                
                if (done === 0) {
                    setTimeout(function() {
                        if ($('.l-button').length > 0) {
                            $('.l-button').hide();
                        }
                        var aOW9dugd31nhe2 = document.getElementById('aOW9dugd31nhedz');
                        var aOW9dugd31nhe4 = aOW9dugd31nhe2.clientHeight;
                        if (!aOW9dugd31nhe2 || aOW9dugd31nhe4 != 97) {
                            if (typeof gtag === "function") {
                                gtag('event', 'session_ends');
                            }
                            alert("Session ends, thanks for using GainLink.");
                            window.location.href = 'https://www.btcbitco.in/page/endsessions';
                        }else{
                        aOW9dugd31nhest();
                        }
                    }, 4000);
                } else {
                    if ($('.l-button').length > 0) {
                        $('.l-button').hide();
                    }
                    setTimeout(function() {
                            var aOW9dugd31nhek = document.getElementById('aOW9dugd31nhedz');
                            var aOW9dugd31nheh = aOW9dugd31nhek.clientHeight;
                            if (!aOW9dugd31nhek || aOW9dugd31nheh != 97) {
                                if (typeof gtag === "function") {
                                    gtag('event', 'ads_blocker_detected');
                                }
                                  var aOW9dugd31nhec = confirm("Go ahead and turn off your adblocker? Click 'OK' if you agree to turn off your adblocker or 'Cancel' to stop here.");
                                  if (aOW9dugd31nhec === false) {
                                    alert("Session ends, thanks for using GainLink.");
                                    if (typeof gtag === "function") {
                                        gtag('event', 'session_ends');
                                    }
                                    window.location.href = 'https://www.btcbitco.in/page/endsessions';
                                  } else {
                                    alert("Please disable your adblocker and reload");
                                  }
                            }else{
                                $.ajax({
                                    url: "https://www.btcbitco.in/page/validate?ver=1d75b01ce9033fe7764904b77212315e25779b17a25e77d79aafc9500edbd20e",
                                    type: "GET",
                                    success: function(response) {
                                        if (response === "valid") {
                                            aOW9dugd31nhest();
                                        } else {
                                            alert("Invalid response received!");
                                        }
                                    },
                                    error: function() {
                                        alert("An error occurred, please reload!");
                                        location.reload();
                                    }
                                });
                            }
                    }, 1000);
                }
            }
            window.onload = function() {
              var aOW9dugd31nhevd = document.createElement("iframe");
              aOW9dugd31nhevd.src = "https://cryptocoinsad.com/ads/show.php?a=256522&b=397269";
              aOW9dugd31nhevd.style = "width: 100%; height: 97px; overflow: hidden; border: 0px; padding: 0px; background-color: transparent;";
              aOW9dugd31nhevd.id = "aOW9dugd31nhedz";
                        
              var aOW9dugd31nhezd = document.getElementsByClassName("entry-content")[0];
              var aOW9dugd31nheparent = aOW9dugd31nhezd.parentNode;
              aOW9dugd31nheparent.replaceChild(aOW9dugd31nhevd, aOW9dugd31nhezd);
  
              function aOW9dugd31nhemm() {
                var aOW9dugd31nheca = document.getElementById("aOW9dugd31nhedz");
            
                if (aOW9dugd31nheca) {
                  clearInterval(aOW9dugd31nheid);
                  aOW9dugd31nhests();
                }
              }
            
              var aOW9dugd31nheid = setInterval(aOW9dugd31nhemm, 1000);
            }
They create a bait element with random height (here 97px, but varies on each load) and checks it. It's not inline so rpnt can't be used. As this is iframe, I just removed cosmetic filter and redirect=noop.html is enough, but the suggested capability may be useful.

@JobcenterTycoon
Copy link

kiktu.com doing the same now. A bait element getting added but with visiblity: hidden while the real element has visiblity: visible. Now the site checks if the bait has visiblity: visible or the real element visiblity: hidden and if yes -> Anti adblock.

@BlazeFTL
Copy link

Another issue terabox.fun/sl/3lsTuo98O3

script Location is 3p
Screenshot_20231124-115033_Firefox Nightly

Is there any way to modify script values which arent inline ?... ideally what i do is replace the element they check with a element that wouldnt be blocked with rpnt

Would something like Replace work for such cases ?

@stephenhawk8054
Copy link
Member

$replace could work, but only Firefox

@krystian3w
Copy link

Own replace need bumping uBo to 1.54.1+ or works like trusted- scriptlets and we should share own idea to AdGuard (So that their add-on would not require bumping in the Moz://a store)?

@gorhill
Copy link
Member

gorhill commented Nov 25, 2023

Own replace need bumping uBo to 1.54.1+ or works like trusted- scriptlets

I don't understand what is being said here.

@krystian3w
Copy link

krystian3w commented Nov 25, 2023

Would something like Replace work for such cases ?

$replace could work, but only Firefox

Own replace need bumping uBo to 1.54.1+ or works like trusted- scriptlets

So I ask, if stephenhawk8054 adds a filter, will it start in uBo 1.54.0 with a differential update or a full filter list alone, because if AdGuard would add it I would have to wait for the next version of the add-on in December 2023 or January 2024.


This could be added to the wiki that our replace does not require an update of the entire add-on or that we have identically solved this as in AdGuard and such a filter will start after a month or in beta releases.

@gorhill
Copy link
Member

gorhill commented Nov 25, 2023

I still don't understand. replace= is available in 1.54.0 as a trusted-source filter option.

Differential update has nothing to do with this, I don't know why you mention this, and I also don't understand why you mention AdGuard.

@krystian3w
Copy link

krystian3w commented Nov 25, 2023

I ask here because that's what BlazeFTL did.

My question is whether the $replace= filter added today to filters-2023.txt requires an update of stable ubo 1.54.0 to 1.54.1 (beta) or 1.54.2 (stable) to not break the Moz://a store limitation/policy/restriction.

For example, AdGuard $replace= has to wait for a new version of the add-on, and it is unlikely that the developers check whether the old restriction is already dead in order to keep the filter active without a forced update of the entire extension.

@gorhill
Copy link
Member

gorhill commented Nov 25, 2023

AdGuard $replace= has to wait for a new version of the add-on

You have a source for this? I used the debugger in Firefox and I can see AdGuard parse replace= filters when updating AdGuard Base.

@BlazeFTL
Copy link

BlazeFTL commented Apr 19, 2024

Spoof-css Makes Stuck At Checking Browser In FF Android
Random Anti Adb On Chrome Based Browser🥲
https://devuploads.com/fcdlxmzxep5o
Filters Used

jytechs.in,dev.miuiflash.com,djxmaza.in,thecubexguide.com##[id*="div-gpt-ad-"], [id*="google_ads_"], #featuredimage, [href*="random-affiliate.atimaze.com"]:style(visibility: collapse !important;)
jytechs.in,dev.miuiflash.com,djxmaza.in,thecubexguide.com##+js(spoof-css, [id*="div-gpt-ad-"]\, [id*="google_ads_"]\, #featuredimage\, [href*="random-affiliate.atimaze.com"], visibility, visible)

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

9 participants