From 31ce357413df6f483f761cf744866d86b7e3a1e5 Mon Sep 17 00:00:00 2001 From: kaliiiiiiiiii Date: Sun, 22 Sep 2024 21:23:09 +0200 Subject: [PATCH] fix https://github.com/kaliiiiiiiiii/brotector/issues/5 --- .gitignore | 4 +++- README.md | 4 ++++ assets/test.pdf | Bin 0 -> 3156 bytes brotector.js | 30 ++++++++++++++++++++++++++-- package.json | 7 +++++++ tests_nodejs/test_puppeteer.js | 22 +++++++++++++++++++++ tests_nodejs/utils.js | 35 +++++++++++++++++++++++++++++++++ 7 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 assets/test.pdf create mode 100644 package.json create mode 100644 tests_nodejs/test_puppeteer.js create mode 100644 tests_nodejs/utils.js diff --git a/.gitignore b/.gitignore index 4dbb235..aa760e8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ yolov8m-seg.pt downloaded_files/* .idea/* -*/__pycache__/* \ No newline at end of file +*/__pycache__/* +node_modules/* +package-lock.json \ No newline at end of file diff --git a/README.md b/README.md index 7e1a946..720cd48 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,10 @@ see [`Event.isTrusted`](https://developer.mozilla.org/en-US/docs/Web/API/Event/i #### stack.signature detects injected javascript based on the stack trace in hooks +---- +#### pdfStyle +a detection regarding PDF rendering, specific to puppeteer [github issue](https://github.com/kaliiiiiiiiii/brotector/issues/5) + ## Contribution feel free to - open `[feature request]`s for driver detections diff --git a/assets/test.pdf b/assets/test.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8faa3c1c3534318453c87c4f24c69df18c4aa1f4 GIT binary patch literal 3156 zcmcImU2fwx5Ps(=<|Wt!MJ$mLC9*IA#IoHDnuP<$K#K->kZszlK$cR8Zj+vAPq3HS z9;Gv~Tq{-=PKsC$7BwDnW&_Z+1Q%XUoWQXg}RYAag9(qEO{+yj!Q`$3_Jg~up zJgj}FeI;00pq0$|IhmJmN05%8igisGQVjJ*`R_(n!#zYinA3|(Lo0ATn)DB2lUdB1 z+x65|S3(!VnKQ^{`8>&%;QW$gmsy!?1sHx(ls5Vt7vKqmFRnj?lnvv->y4lH@^t?G z9)xf3U^GpW-`ALm?+t@`gA)Y9(HzkS9f`2&5>vcC2As-vTWy=V-%rHa_K`Ay?@H)< zm9TZ-X!vt#X0Hd~cz*19@b|EoBr8*%kMmWW9U&Q-t@po^VPpR|O@SY7iW~D+Hcpe- z5#m4G7&56Uk@wfPK(Z~KjjV;ca{kHh35x@^OzuV{4G*AEM`OS*DDe~E^v2f=g z;{a!3o^ZTft&m>y>UUJXuW(jY)34jDCOIVpvW}qux*1w|K=9DY2MU2!5~zXFDuAk= z(K3Xpv(Qo@f2b8S@M#xzKsUq{miGqZq> z;^%Iz^JXu{z~}3kDd6;>q|ikNImQ`MAEYrh$+LcJ4V?CW6t3`HEd;(jU;W^U53c*+ ztZ}Mncj+j`BFL9S(3VKYYJN6)G}+~h&fc;QWCZpjWa~6VY)SVze$Ll;0i(=BdAeR@ z4LeVTSs+6~wzXqd5J>4sSin~1351Ov$hIy~e3ci#H*Kc7Z zJk|19_+dlO7IBgyDWGDxP5v@;Z_YT+EmZk}sehF%a;Q?0KKgJ6-AG(|QKa<1b7e15 l+#5!+CuQX8!R4T*^~Gyc?kQ(V8yB|97$HN=PEH1+;XmTgZDRlc literal 0 HcmV?d00001 diff --git a/brotector.js b/brotector.js index db7b8c5..52cc975 100644 --- a/brotector.js +++ b/brotector.js @@ -5,7 +5,8 @@ const chromedriverSourceMatches = [ const stackScriptInjectionMatches = { "pyppeteer":" at [\\s\\S]* \\(__pyppeteer_evaluation_script__:[0-9]+:[0-9]+\\)", - "puppeteer":" at [\\s\\S]* \\(__puppeteer_evaluation_script__:[0-9]+:[0-9]+\\)" + "puppeteer":" at [\\s\\S]* \\(__puppeteer_evaluation_script__:[0-9]+:[0-9]+\\)", + "puppeteer":" at pptr:evaluate;file%3A%2F%2F%2F[\\s\\S]*%3A[0-9]+%3A[0-9]+:[0-9]+:[0-9]+" } const hookers = [ @@ -125,6 +126,7 @@ class Brotector { this.hook_mouseEvents() this.hook_canvasVisualize() this.hook_SeleniumScriptInjection() + await this.test_pdfStyle() for (const [obj, func] of hookers){ this.hookFunc(obj, func, ()=>{}) @@ -170,7 +172,7 @@ class Brotector { for (const line of stack.split("\n")){ for (const [type, regex] of Object.entries(stackScriptInjectionMatches)){ if(line.match(regex)){ - this.log({detection:"stack.signature", type:type, score:0.9, data:{stack:stack, hook:hook}}) + this.log({detection:"stack.signature", type:type, score:1, data:{stack:stack, hook:hook}}) } } } @@ -270,6 +272,30 @@ class Brotector { this.log({"detection":"UA_Override", "type":"HighEntropyValues.empty", score:0.9}) } } + async test_pdfStyle(){ + const iframe = document.createElement("iframe") + iframe.style.height = 0 + iframe.style.width = 0 + iframe.style.position = "absolute" + iframe.style.x = 0 + iframe.style.y = 0 + iframe.style.opacity = 0 + iframe.src = "assets/test.pdf"; + document.body.appendChild(iframe); + const style = await new Promise((resolve, reject)=>{ + iframe.onload = ()=>{ + try{ + if(iframe.contentDocument === null) {console.error("Could not load PDF iframe propperly, possibly running on file: url"); resolve(undefined)} + const result = iframe.contentDocument.querySelector('style')?.textContent||false + document.body.removeChild(iframe) + resolve(result) + }catch(e){reject(e)} + } + }) + if(style){ + this.log({detection:"pdfStyle",type:"puppeteer", score:0.9, data:{style:style}}) + } + } hook_mouseEvents() { if (!this._isMouseHooked){ for (let event of ["mousedown", "mouseup", "mousemove", "pointermove", "click", "touchstart", "touchend", "touchmove", "touch", "wheel"]){ diff --git a/package.json b/package.json new file mode 100644 index 0000000..3712abe --- /dev/null +++ b/package.json @@ -0,0 +1,7 @@ +{ + "type": "module", + "dependencies": { + "puppeteer": "^23.4.0", + "static-server": "^3.0.0" + } +} diff --git a/tests_nodejs/test_puppeteer.js b/tests_nodejs/test_puppeteer.js new file mode 100644 index 0000000..2ec9789 --- /dev/null +++ b/tests_nodejs/test_puppeteer.js @@ -0,0 +1,22 @@ +import puppeteer from 'puppeteer'; +import {__server_url__, sleep} from './utils.js' + +const script = async ()=>{ + await brotector.init_done + return brotector.detections +} + +const browser = await puppeteer.launch({ headless: false }); +try{ + const page = await browser.newPage(); + + // Navigate the page to a URL. + await page.goto(__server_url__); + await sleep(500) + await page.click("#clickHere") + const detections = await page.evaluate(script) + if(detections.length == 0){throw Error("Not detected")} + console.log(detections) +}finally{ + await browser.close(); +} diff --git a/tests_nodejs/utils.js b/tests_nodejs/utils.js new file mode 100644 index 0000000..4fd0b15 --- /dev/null +++ b/tests_nodejs/utils.js @@ -0,0 +1,35 @@ +import { dirname } from 'path'; +import { fileURLToPath } from 'url'; +import net from "net"; +import StaticServer from 'static-server' + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const __main_dir__ = dirname(__dirname) + +function sleep (time) { + return new Promise((resolve) => setTimeout(resolve, time)); + } + +const port = await new Promise( res => { + const srv = net.createServer(); + srv.listen(0, () => { + const port = srv.address().port + srv.close((err) => res(port)) + }); +}) + +const __server_url__ = `http://localhost:${port}` + +const server = new StaticServer({ + rootPath: __main_dir__, // required, the root of the server file tree + port: port, // required, the port to listen + host: 'localhost', // optional, defaults to any interface + }); + +await new Promise((resolve, reject)=>{ + try{ + server.start(resolve) + }catch(e){reject(e)} +}) + +export { __main_dir__, __server_url__, sleep} \ No newline at end of file