Created
April 17, 2023 08:28
-
-
Save SakiiR/700d2c5ca2eddb28123493498c584189 to your computer and use it in GitHub Desktop.
PlaidCTF - CSS bruteforce write up
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const puppeteer = require('puppeteer'); | |
const Jimp = require("jimp"); | |
const DEBUG = false; | |
const URL = "https://plaidctf.com/files/css.74486b61b22e49b3d8c5afebee1269e37b50071afbf1608b8b4563bf8d09ef92.html" | |
const minimal_args = [ | |
'--autoplay-policy=user-gesture-required', | |
'--disable-background-networking', | |
'--disable-background-timer-throttling', | |
'--disable-backgrounding-occluded-windows', | |
'--disable-breakpad', | |
'--disable-client-side-phishing-detection', | |
'--disable-component-update', | |
'--disable-default-apps', | |
'--disable-dev-shm-usage', | |
'--disable-domain-reliability', | |
'--disable-extensions', | |
'--disable-features=AudioServiceOutOfProcess', | |
'--disable-hang-monitor', | |
'--disable-ipc-flooding-protection', | |
'--disable-notifications', | |
'--disable-offer-store-unmasked-wallet-cards', | |
'--disable-popup-blocking', | |
'--disable-print-preview', | |
'--disable-prompt-on-repost', | |
'--disable-renderer-backgrounding', | |
'--disable-setuid-sandbox', | |
'--disable-speech-api', | |
'--disable-sync', | |
'--hide-scrollbars', | |
'--ignore-gpu-blacklist', | |
'--metrics-recording-only', | |
'--mute-audio', | |
'--no-default-browser-check', | |
'--no-first-run', | |
'--no-pings', | |
'--no-sandbox', | |
'--no-zygote', | |
'--password-store=basic', | |
'--use-gl=swiftshader', | |
'--use-mock-keychain', | |
]; | |
const blocked_domains = [ | |
'googlesyndication.com', | |
'adservice.google.com', | |
]; | |
class Exploit { | |
async init() { | |
this.i = 0; | |
const browser = await puppeteer.launch({ | |
headless: true, | |
args: minimal_args | |
}); | |
// Create a new page | |
this.page = await browser.newPage(); | |
await this.page.setRequestInterception(true); | |
this.page.on('request', request => { | |
const url = request.url() | |
if (blocked_domains.some(domain => url.includes(domain))) { | |
request.abort(); | |
} else { | |
request.continue(); | |
} | |
}); | |
await this.page.goto(URL, { waitUntil: 'domcontentloaded' }); | |
await this.page.setViewport({ width: 1920, height: 1050 }); | |
await this.page.evaluate(() => { | |
window.$ = (s) => document.querySelector(s); | |
window.$$ = (s) => document.querySelectorAll(s); | |
window.sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); | |
}) | |
if (DEBUG) { | |
await this.page.evaluate(() => { | |
$('body > div > div:nth-child(2)').style.zIndex = "999" // Set congrats displayed | |
}) | |
} | |
await this.page.evaluate(() => { | |
Array.from($$("body>div>div:nth-child(n+10)")).map(el => el.style.display = 'none') | |
// Array.from($$("body>div>div:nth-child(n+10)")).map(el => el.remove()) | |
}) | |
} | |
async setOpen(offset, open) { | |
await this.page.evaluate(({ offset, open }) => { | |
$$("body>div>div:nth-child(9) details")[offset].open = open | |
}, { offset, open }) | |
} | |
async test(offset, pos) { | |
const path = DEBUG ? "test.png" : void 0; | |
const quality = 0; | |
const type = 'jpeg'; | |
const clipGreen = { width: 200, height: 25, x: 7, y: 66 } | |
offset = offset * 26 | |
for (let c = 0; c < 26; ++c) { | |
const i = offset + c | |
await this.setOpen(i, c < pos); | |
} | |
const buffer = await this.page.screenshot({ type, quality, path, clip: clipGreen }); | |
const image = await Jimp.read(buffer); | |
for (let y = 0; y < image.getHeight(); ++y) { | |
for (let x = 0; x < image.getHeight(); ++x) { | |
const color = image.getPixelColour(x, y); | |
if ([0x16fc2eff, 0x19ff00ff, 0x00ff00ff].includes(color)) { | |
console.log("found"); | |
await this.page.screenshot({ type, quality: 100, path: `founds/found-${this.i}.png`, fullPage: true }); | |
image.write(`founds/found-${this.i}-clipped.jpeg`); | |
} | |
} | |
} | |
console.log(`Tries: ${this.i++}`) | |
} | |
async bf() { | |
const alphLength = 26 | |
for (let a = 0; a <= alphLength; ++a) { | |
await this.test(0, a) | |
for (let b = 0; b <= alphLength; ++b) { | |
await this.test(1, b) | |
for (let c = 0; c <= alphLength; ++c) { | |
await this.test(2, c) | |
} | |
} | |
} | |
} | |
} | |
async function main() { | |
const exploit = new Exploit(); | |
await exploit.init(); | |
exploit.bf() | |
} | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment