← Retour aux projets

🐍​ Python Capture The Flag

Cybersecurity Hacking Réseau Encoding Regex Cryptographie CTF

Capture The Flag avec plusieurs challenges à résoudre et envoyer vers un serveur distant. Projet validant à l'ESGI pour la matière scripting python.

Code Source

'''
 # @ Author: Enzo Juillard
 # @ Description: Python exam (CTF) file
 '''

import socket
import datetime as date
import re
import base64
import base58
import webcolors

ip = ""
#port = 

# Functions

def caesar_decode(text, key):

    result = ''
    
    for char in text:
        if char.isalpha():
            if char.isupper():
                # DEBUG : inversion du sens
                result += chr((ord(char) - ord('A') + key) % 26 + ord('A'))
            else:
                result += chr((ord(char) - ord('a') + key) % 26 + ord('a'))
        else:
            result += char
    return result

def send_answer(client_socket, answer):
    
    client_socket.send(answer.encode("utf-8"))
    response = client_socket.recv(1024)
    return response.decode()

def ascii_to_char(ascii_codes_string):
    
    return ''.join(chr(int(code) + 64) for code in ascii_codes_string.split())


# Connect to server
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSocket.connect((ip,port))

# Receive first response
firstResponse = clientSocket.recv(1024)
print(firstResponse.decode())

# 1er FLAG - Send name, class

txt = "enzo/juillard/3SI3"
response = send_answer(clientSocket, txt)
print(response)

# 2ème FLAG - Send today's date
todayDate = date.datetime.now().strftime("%d/%m")
dateResponse = send_answer(clientSocket, todayDate)
print(dateResponse)

# 3ème FLAG - Send the result of calculation
regexCalculation = r"(d+)s*([+-*/])s*(d+)"
calculationQuestion = dateResponse
findNumbers = re.search(regexCalculation, calculationQuestion)
num1 = int(findNumbers.group(1))
operator = findNumbers.group(2)
num2 = int(findNumbers.group(3))

match operator:
    case "*":
        result = num1 * num2
    case "-":
        result = num1 - num2
    case "+":
        result = num1 + num2
        
calculationResponse = send_answer(clientSocket, str(result))
print(calculationResponse)

# 4ème FLAG - Message Decode
regexDecode = r"message:s*(.+)$"
decodeResponse = calculationResponse
code = re.search(regexDecode, decodeResponse)

codeString = code.group(1)
print(codeString)

decodedString = None

# Check base64
base64_pattern = r"^[A-Za-z0-9+/]*={0,2}$"
if re.match(base64_pattern, codeString) and len(codeString) % 4 == 0:
    try:
        decodedBytes = base64.b64decode(codeString)
        decodedString = decodedBytes.decode("utf-8")
        print(f"Decoded from base64: {decodedString}")
    except Exception as e:
        print(f"Base64 failed: {e}")
        decodedString = None

# Check base32
if decodedString is None:
    base32_pattern = r"^[A-Z2-7=]*$"
    if re.match(base32_pattern, codeString):
        try:
            decodedBytes = base64.b32decode(codeString)
            decodedString = decodedBytes.decode("utf-8")
            print(f"Decoded from base32: {decodedString}")
        except Exception as e:
            print(f"Base32 failed: {e}")
            decodedString = None

# Check base58
if decodedString is None:
    base58_pattern = r"^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]*$"
    if re.match(base58_pattern, codeString):
        try:
            decodedBytes = base58.b58decode(codeString)
            decodedString = decodedBytes.decode("utf-8")
            print(f"Decoded from base58: {decodedString}")
        except Exception as e:
            print(f"Base58 failed: {e}")
            decodedString = None
            
# Check base85
if decodedString is None:
    base85_pattern = r"^[!-u]+$"
    if re.match(base85_pattern, codeString):
        
        # Try first base85
        try:
            decodedBytes = base64.b85decode(codeString)
            decodedString = decodedBytes.decode("utf-8")
            print(f"Decoded from base85: {decodedString}")
        except Exception:
            
            # Try second base85
            try:
                decodedBytes = base64.a85decode(codeString)
                decodedString = decodedBytes.decode("utf-8")
                print(f"Decoded from base85: {decodedString}")
            except Exception as e:
                print(f"Base85 failed: {e}")
                decodedString = None

if decodedString is not None:
    finalResponse = send_answer(clientSocket, decodedString)
    print(finalResponse)


# 5ème FLAG - Message Majuscle Decode
regexMajDecode = r"majuscule:s*(.+)$"
decodeMajResponse = finalResponse
majCode = re.search(regexMajDecode, decodeMajResponse)

majCodeString = majCode.group(1)
print(majCodeString)
majDecoded = (bytes.fromhex(majCodeString).decode("utf-8").upper())
word = ''
word += majDecoded[0]

for i in range(len(majDecoded)):
    if majDecoded[i] == " " and i+1 < len(majDecoded):
        word += majDecoded[i+1].upper()

print(f"Decoded: {word}")
majDecodeResponse = send_answer(clientSocket, word)
print(majDecodeResponse)

# 6ème FLAG - Message majuscle Decode 2

regexCaesarDecode = r"majuscule:s*(.+)$"
decodeCaesarResponse = majDecodeResponse
hexCaesarCode = re.search(regexCaesarDecode, decodeCaesarResponse)
hexCaesarCodeString = hexCaesarCode.group(1)
print(hexCaesarCodeString)

# Convertion HEXA vers ASCII
asciiCodesString = bytes.fromhex(hexCaesarCodeString).decode("utf-8")
print(f"HEXA decode: {asciiCodesString}")

# Convertion ASCII vers char
asciiCharacters = ascii_to_char(asciiCodesString)
print(f"ASCII decode: {asciiCharacters}")

# Caesar decode
caesarPlaintext = caesar_decode(asciiCharacters, 5).upper()
print(f"Ceasar decoded: {caesarPlaintext}")

caesarDecodeResponse = send_answer(clientSocket, caesarPlaintext)
print(caesarDecodeResponse)

# 7ème FLAG - RGB
regexRGB = r"RGBs*[:=]?s*(?(d+),s*(d+),s*(d+))?"
rgbResponse = caesarDecodeResponse
rgbCode = re.search(regexRGB, rgbResponse)

rgbRed = int(rgbCode.group(1))
rgbGreen = int(rgbCode.group(2))
rgbBlue = int(rgbCode.group(3))
print(rgbRed, rgbGreen, rgbBlue)

rgbColor = webcolors.rgb_to_name((rgbRed, rgbGreen, rgbBlue)).upper()
print(f"RGB Name: {rgbColor}")

rgbResponse = send_answer(clientSocket, rgbColor)
print(rgbResponse)

#  8ème FLAG - Previous question answer (Build function that detect numero of question and return the answer)
regexPreviousQuestion = r"questions+(d+)"
previousQuestionResponse = rgbResponse
previousNumber = re.search(regexPreviousQuestion, previousQuestionResponse)
questionNumber = int(previousNumber.group(1))
print(f"Question number: {questionNumber}")

tabAnswers = [txt, todayDate, str(result), decodedString, word, caesarPlaintext, rgbColor]

previousAnswer = tabAnswers[questionNumber - 1]
previousQuestionAnswer = send_answer(clientSocket, previousAnswer)
print(previousQuestionAnswer)

#  9ème FLAG - Last letter of the Xth word
regexNumberWord = r"dernière lettre du (d+)ème mot"
regexWordsList = r"liste:s*(.+)$"
lastLetterResponse = previousQuestionAnswer
numberWordMatch = re.search(regexNumberWord, lastLetterResponse)
wordsListMatch = re.search(regexWordsList, lastLetterResponse)

wordIndex = int(numberWordMatch.group(1)) - 1
wordsList = wordsListMatch.group(1).split()
lastLetter = wordsList[wordIndex][-1]

lastLetterResponse = send_answer(clientSocket, lastLetter)
print(lastLetterResponse)

# 10ème FLAG - All previous answers with underscore
tabAnswers.append(previousAnswer)
tabAnswers.append(lastLetter)
underscoreAnswers = '_'.join(tabAnswers)
print(tabAnswers)
print(underscoreAnswers)

underscoreResponse = send_answer(clientSocket, underscoreAnswers)
print(underscoreResponse)

# Close the connection
clientSocket.close()