Skip to content

Instantly share code, notes, and snippets.

@meredian
Last active March 20, 2020 05:45
Show Gist options
  • Save meredian/4876493b4e19947a3fb3ec3659a73090 to your computer and use it in GitHub Desktop.
Save meredian/4876493b4e19947a3fb3ec3659a73090 to your computer and use it in GitHub Desktop.
First approach to sniffing detector
'use strict';
// Prerequisites: node 8+
// Install: npm install puppeteer
const puppeteer = require('puppeteer');
// const Membrane = require('es7-membrane');
function sniffDetector() {
const DEBUG = false
window.watched = [];
window.sniffed = {};
window.nonConfigurable = {};
const log = function(...args) {
console.log(JSON.stringify(args, null, 4));
};
const debug = function(...args) {
if (DEBUG) {
log(...args)
}
}
const setRecursiveSniffer = (obj, objectPath) => {
debug("Running recursive sniffer for path: " + objectPath, obj);
let propertyNames = new Set(); // new Set(Object.getOwnPropertyNames(obj));
for (const propertyName in obj) {
propertyNames.add(propertyName);
}
Array.from(propertyNames).forEach((propertyName) => {
const childPath = objectPath + '.' + propertyName;
const child = obj[propertyName];
debug("Inspecting node", {childPath, child});
const childType = Object.prototype.toString.call(child);
window.watched.push(childPath);
if (childType === '[object Object]' || childType === '[object Array]') {
setRecursiveSniffer(child, childPath);
} else {
let descriptor = Reflect.getOwnPropertyDescriptor(obj, propertyName) || {};
if (descriptor.configurable != false) {
['value', 'writable'].forEach((descriptorProp) => {
if (Reflect.has(descriptor, descriptorProp)) {
Reflect.deleteProperty(descriptor, descriptorProp);
}
});
descriptor.get = () => {
window.sniffed[childPath] = child;
return child;
}
const updated = Reflect.defineProperty(obj, propertyName, descriptor);
if (!updated) {
throw new Error(`Can't update ${childPath} descriptor`);
}
} else {
console.log(`Non-configurable descriptor for ${childPath}`);
window.nonConfigurable[childPath] = child;
}
}
});
debug("Done setting recursive sniffer for path: " + objectPath);
};
setRecursiveSniffer(window.navigator, 'window.navigator');
// setRecursiveSniffer(window.document, 'window.document');
}
(async () => {
const browser = await puppeteer.launch({
args: ['--javascript-harmony']
});
const page = await browser.newPage();
page.on('pageerror', err => console.error('PAGE EXCEPTION OCCURED:', err));
page.on('console', msg => console.log('PAGE LOG:', msg.text()));
page.on('error', err => console.error('PAGE ERROR LOG:', err));
try {
await page.evaluateOnNewDocument(sniffDetector);
// await page.goto('http://example.com', {waitUntil: 'networkidle2'})
await page.goto('https://www.google.com', {waitUntil: 'networkidle2'});
const sniffedData = await page.evaluate(async function () {
return {
sniffed: this.sniffed,
blind: this.nonConfigurable,
watched: window.watched,
}
});
console.log('All watched handlers: ', sniffedData.watched);
console.log('Sniffed: ', sniffedData.sniffed);
console.log('Failed to set handler (may also be sniffed): ', sniffedData.blind);
await browser.close();
} catch (e) {
console.log(e);
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment