On a vu que tu avais quelques prédispositions au hacking. On t’as donc fait une reproduction quasi-conforme du captcha de notre cible pour que tu puisses t’entraîner.
Résous-le ou l’on trouvera quelqu’un d’autre pour le faire !
Ce challenge tourne sur un docker et n'est pas disponible
Solution
Lorsque l'on recharge plusieurs fois la page, on voit que le fond du captcha ne change jamais. On peut donc collecter plusieurs images avec le texte à différents endroits pour reconstituer le fond sans texte :
De là, on va pouvoir faire une différence entre notre image de fond et les nouveaux captchas pour ne garder que les pixels qui changent. Voici un exemple avec le captcha :
Maintenant on va normaliser pour que tout ce qui est noir devienne blanc, et le reste devienne noir :
diff = diff.point(lambda x: 0 if x < 20 else 0xff)
Maintenant, avec un OCR comme tesseract, on peut lire automatiquement le texte :
from PIL import Image, ImageChops
import pytesseract
background = Image.open('background.png').convert('RGB')
captcha = Image.open('captcha.png')
diff = ImageChops.difference(background, captcha).convert('L')
diff = diff.point(lambda x: 0xff if x < 20 else 0x0)
# Le charset permet de limiter les erreurs, ON PEUT FAIRE SANS
# On peut le déduire en regardant plusieurs captcha
CHARSET = '23456789ACDFGHJKMNPRUWYacdfghjkmnpruwy'
# le paramètre config est là pour le charset, donc optionnel
code = pytesseract.image_to_string(diff, config=f'-c tessedit_char_whitelist={CHARSET}').strip()
print(code)
# FDGym5Wg
Maintenant, on automatise le processus pour le faire 5 fois à la suite. L'OCR peut se tromper donc il faut faire sûrement plus que 5 essais :
from requests import Session
from PIL import Image, ImageChops
from io import BytesIO
from base64 import b64decode
import pytesseract
URL = f'https://d9a72c483447cadd.challenge1.cybernight-c.tf'
CHARSET = '23456789ACDFGHJKMNPRUWYacdfghjkmnpruwy'
def get_captcha(session: Session) -> Image.Image:
response = session.get(f'{URL}/api/captcha')
return Image.open(BytesIO(b64decode(response.content)))
def solve_captcha(session: Session, captcha: Image):
diff = ImageChops.difference(background, captcha).convert('L')
diff = diff.point(lambda x: 0 if x < 20 else 0xff)
code = pytesseract.image_to_string(diff, config=f'-c tessedit_char_whitelist={CHARSET}').strip()
return session.post(f'{URL}/api/captcha', json={'code': code}).json()
background = Image.open('background.png').convert('RGB')
session = Session()
session.get(URL)
while True:
captcha = get_captcha(session)
response = solve_captcha(session, captcha)
if 'flag' in response and response['flag']:
break
print(session.get(URL).text)
print(f'Cookie à mettre dans son navigateur : {session.cookies.get("session")}')
Comme pour Captcha 1, on peut soit afficher le contenu de la page dans le terminal, soit copié-collé le cookie utilisé vers son navigateur pour profiter d'un magnifique GIF.