0

Warning: possibly involves a set of programming bad practices to bypass security features.

We're developing a bundle of scripts that extract public information from some website. I use ViolentMonkey to inject scripts in the website, which uses Google's reCAPTCHA (see example).

To bypass it, I installed Buster: Captcha Solver, a very neat extension which places an icon on reCAPTCHA frames which, upon clicked, switches to audio solving mode and tries to transcribe the audio. It will fail every other attempt, but it's quite helpful.

The thing is: Buster detects reCAPTCHA is loaded - there doesn't seem to be enough a reason for it to require a user click. I wouldn't say it defeats the purpose, but I would rather have it run automatically. I even injected a pre-click which pops open the reCAPTCHA modal (and yes, it works), but I can't force-click Buster's icon because it is enclosed in a closed shadow DOM.

Buster basically uses shadowRoot.appendChild(), so I tried setting @run-at document-start and tampering with HTMLElement.prototype.attachShadow:

HTMLElement.prototype.attachShadow = function(args) {
  return this;
};

This would theoretically make shadowRoot.appendChild() append the child directly to the node itself, but Buster is still able to attach the shadow DOM regardless. I believe overwriting HTMLElement.prototype will only work for the current global scope, and Buster is sandboxed in its own extension's environment. Had it worked, something like this would most likely be possible:

// and yeah, that's really all I'm trying to achieve
document.querySelector('.button-holder.help-button-holder')
    .shadowRoot
    .getElementById('solver-button')
    .click();

I thought of compiling a modified version of Buster's source code in which I simply use .attachShadow({mode: 'open'}) so my scripts can finally access its button, but that'd be too much of a hassle right now. I also can but don't want to use tools outside of Chrome (like AutoHotkey) for this.

TL;DR

How can I programmatically click an element inside a closed shadow DOM with ViolentMonkey/TamperMonkey?

gyohza
  • 736
  • 5
  • 18
  • The only way is to modify Buster's source code because extension's content scripts run in a special isolated world which uses its own JS environment with everything (including the prototypes and variables) isolated. There's no need to compile the extension though: simply edit its content script and replace `closed` with `open`. – wOxxOm Dec 30 '20 at 18:17
  • I only said 'compiling' because I cloned its source code and it's a Vue.js application. If I am to tamper with it, I'll probably have to enable extensions in developer mode and add a .zip file with the modified contents, I'm just not sure how to get the content files from an installed extension. But I will look into it, thanks for the time being. – gyohza Dec 30 '20 at 18:22
  • No, my point is that you don't need the source code. Just download the extension using crxviewer and modify it. You can also copy it from the disk folder if it's installed. – wOxxOm Dec 30 '20 at 18:31
  • Yeah, I got what you meant and I did get the source code, but as I was expecting, it now requires me to provide my own API keys to run the app. Will be back with more info as soon as I grab'em. – gyohza Dec 30 '20 at 18:49
  • Doesn't sound like what I suggested at all. With my suggestion you wouldn't need new keys. – wOxxOm Dec 30 '20 at 19:00
  • Yes, you would. Did you test it? The API keys used by Buster are encoded and when I try to run the modified code, it will ask me to get myself an API key. I already got an API key, but am working on another solution with Puppeteer. I'll post as soon as I get anything. – gyohza Dec 30 '20 at 21:43
  • Indeed I didn't try. Now I see it's an unusually smart self-aware extension which checks its own code. – wOxxOm Dec 30 '20 at 21:58
  • @gyohza did you find the solution? – Nam Vu May 11 '21 at 08:02
  • 1
    @NamVu sorry for the late reply. We did manage to bypass it, but I no longer work for the company so I don't have access to the code. I believe we ended up coding from scratch but based on the same speech recognition API used by Buster - this way we wouldn't need to click the button as we could trigger our own method ourselves. – gyohza Jul 29 '21 at 17:56

0 Answers0