kaliiiiiiiiii / brotector

An advanced antibot for webdrivers
https://kaliiiiiiiiii.github.io/brotector/
MIT License
110 stars 5 forks source link

[feature request] detect hero #9

Open unixfox opened 3 days ago

unixfox commented 3 days ago

Hero: https://github.com/ulixee/hero

Seems to claim that it is better than puppeteer, playwright when it comes to scraping: https://ulixee.org/docs/hero/overview/basic-concepts

For now, it doesn't get detected by brotector:

out


I tried to see if there were some things obvious by using https://deviceandbrowserinfo.com/info_device but couldn't find anything.

But creepjs detects it: https://abrahamjuliot.github.io/creepjs/ as "smart enemy".


Example code:

const Hero = require('@ulixee/hero-playground');

(async () => {
  const hero = new Hero();
  await hero.goto('https://kaliiiiiiiiii.github.io/brotector/');
  await new Promise(resolve => setTimeout(resolve, 5000));
  const tab = hero.activeTab;
  const screenshot = await tab.takeScreenshot();
  require("fs").writeFile("out.png", screenshot, 'base64', function(err) {
    console.log(err);
  });
  await hero.close();
})();
kaliiiiiiiiii commented 2 days ago

Thanks!

kaliiiiiiiiii commented 2 days ago

@unixfox Though, you've forgot to click the button at brotector. Does that cause detection?

unixfox commented 2 days ago

Thank you for your reply!

Indeed I clicked on the button using the documentation: https://ulixee.org/docs/hero/basic-client/interactions

const Hero = require('@ulixee/hero-playground');

(async () => {
  const hero = new Hero();
  await hero.goto('https://kaliiiiiiiiii.github.io/brotector/');
  const tab = hero.activeTab;
  await new Promise(resolve => setTimeout(resolve, 1000));
  const aElem = hero.document.querySelector('button');
  await hero.interact({ click: { element: aElem } })
  await new Promise(resolve => setTimeout(resolve, 3000));
  const screenshot = await tab.takeScreenshot({fullPage: true});
  require("fs").writeFile("out.png", screenshot, 'base64', function(err) {
    console.log(err);
  });
  await hero.close();
})();

And brotector found some interesting things.

out

But maybe we can detect it earlier like creepjs is doing?

kaliiiiiiiiii commented 2 days ago

But maybe we can detect it earlier like creepjs is doing?

Well, hero injects javascript into the main world which patches stuff. Detection of JS patching is a cat-and-mouse game, unfortunately.

Usually smth specific to the framework, and code signature-based detection. Example for reference: https://github.com/kaliiiiiiiiii/brotector/issues/6 https://github.com/kaliiiiiiiiii/brotector/blob/a39efef46b6723f2eaea3932a973acf075ede282/brotector.js#L1-L4 https://github.com/kaliiiiiiiiii/brotector/blob/a39efef46b6723f2eaea3932a973acf075ede282/brotector.js#L370-L389

unixfox commented 2 days ago

Thank you for pointing in the right direction! That's indeed a good idea.

I think creepjs recognize that something is fishy pretty easily thanks to its good prediction mechanism.

Here is a portion of a screenshot taken with hero on creepjs:

image

Hero advertise itself as an Apple device:

image

Hard giveaway when it is ran on a Linux machine.

Lies reported by creepjs: image

kaliiiiiiiiii commented 2 days ago

Lies reported by creepjs: image

Uh yeah could definitely start implementing validation tests for:

  1. Object.defineProperty
  2. Function.prototype.toString
  3. Proxy detection

each on the critical functions and properties