ThaySan
  • 👋Bienvenue
    • Avant-propos
  • 🚩CTF & Writeups
    • 2025 | EC2
      • Let's Crax
    • 2025 | HackDay
      • 🔑Cryptographie
        • Drunk Christmas
        • Find Eve 1
        • Well hidden message - Standard Code Encryption
      • 🔎Forensic
        • Copperwire Extraction
        • Distracted user
        • I believe you can't fly
      • 🧠Misc
        • Hello Steve
      • 💾Programmation
        • Lonely bot
        • Lonely bot #2
        • Lonely bot #3
        • Useless Animals Sorting
        • Who cares about SSI anyway ?
      • ⚙️Reverse
        • Just dig
        • Rusty_rev
        • The Cogs of Blackmail
      • 🎭Steganographie
        • It says a lot when there is no music
        • Mona LSB
        • Well hidden message - Insignificant blue
      • 🌐Web
        • Super Website Verificator 3000
        • The analytical engine leak
        • The Watchful Gears: Uncover the Secrets Within
        • Your region's finest
    • 2024 | Efrei - CyberNight
      • 🔑Cryptographie
        • Clavier spécial
        • Le futur
        • Securechain 30.0
        • Cascade
        • Shared Flag
        • Weird Algorithm
      • 🧊Minecraft
        • Introduction
        • Non aux Bouquins Trafiqués
        • Redstone Gold Block
      • 💾Programmation
        • Captcha 1.0
        • Intro à la prog
        • Captcha 2.0
      • ⚙️Reverse
        • Reverse the Reverse
        • Find me if you can
        • HuGO Decrypt
        • Kitten eXORcism
        • M30W Vault Tech
        • The Ugandan Labyrinth
      • 🎭Stéganographie
        • Le message
        • bon Le ordre
        • COD FORFLAG
        • Mauvaise note
        • Bruit
        • Un (un ?) drôle de QR code
        • Randonnée Guillerette à Bordeaux
      • 💻Système
        • Marche-pied
        • Escabot
        • régulation des Données et des Normes de Sécurité
      • 🌐Web
        • cybernight.zip
        • Mon champion préféré
        • Co(mpressed)okies
        • Gitty Mistake
        • JWT Kiddo
        • Parseur Farceur
      • L'enquête
        • L'enquête 2/6
        • L'Enquête 1/6
        • Bienvenue, enquêteur
    • 2024 | Star-Hack
      • 🔑Cryptographie
        • César, mais pas César
        • Double ennui
        • Langage secret
        • Quadratique Mystérieuse
        • ReSultAt
        • Sup3r S3cr3t
        • Warmup
      • 🔎Forensic
        • Cache-cache
        • Fichier ZIP protégé par mot de passe
        • HEADER
        • Investigation 1
        • Investigation 2
      • 🧠Misc
        • B4l4d3 Urb41n3
        • Bruhh, c'est quoi ça ?
        • Cut13
        • Pika Pika
      • 😈Pwn
        • Pwn0x01
        • Pwn0x02
        • Pwn0x03
      • ⚙️Reverse
        • Assembly
        • Rev0x00
        • Rev0x01
        • Rev0x02
      • 🌐Web
        • Clone Udemy
        • Flask
        • Guess_The_Passcode
        • PHP
        • Tickets
        • Usine de Cookies
    • 2024 | ECW
      • 🔑Cryptographie
        • Course hipPIN
    • 2024 | CTFREI Intro
      • 🔑Cryptographie
        • AES Intro
        • Aléatoire
        • Game of Luck
        • RSA Intro
        • RSA2
        • RSA3
      • 🔎Forensic
        • Mais qui est le photographe ?
        • Mais où est passé mon flag ?
        • Mémoire 1/4
        • Mémoire 2/4
        • Mémoire 3/4
        • Mémoire 4/4
        • My computer is talking
      • 📚OSINT
        • Avion ✈
        • Geoint
        • Google!
        • Googlint
        • Le pivot
        • Le temps commence maintenant
        • Sacré dossier
        • Socint
      • 💾Programmation
        • Try Me
        • Answer Me
        • Eval Me
        • Time Based
      • 😈Pwn
        • BOF Intro
        • Shop
        • BOF 2
        • BOF win()
      • ⚙️Reverse
        • CrackMe1
        • CrackMe2
        • CrackMe3
        • Hidden...
        • Something changed?
        • ZZZ
      • 🎭Stéganographie
        • Cybernight être comme
        • Joli paysage
        • Petit poisson
        • StegHide 'n' Seek
        • Un canard pas comme les autres
      • 💻Système
        • Bash Jail
        • Bash Jail Revenge
        • BrokenBin
        • GTFO Of Here
        • Pyjail
        • Pyjail Revenge
        • Strange input, right?
      • 🌐Web
        • SQLi
        • POST This Money
        • Give me my Flask PIN
        • Access
        • Render
        • RenderV2
        • Touchy
    • 2024 | DefCamp
      • 🔑Cryptographie
        • conv
        • oracle-srl
        • ctr
      • 🔎Forensic
        • i-got-a-virus
        • Alternating
        • call-me-pliz
      • 🧠Misc
        • pyterm
      • 📱Mobile
        • mobisec
      • 📚OSINT
      • 😈Pwn
      • ⚙️Reverse
      • 🕵️Traque
      • 🌐Web
        • noogle
        • production-bay
    • 2024 | 404CTF
      • 🔑Cryptographie
        • Bébé nageur
        • Le petit bain
        • Poor Random Number Generator [1/2]
        • Plongeon Rapide Super Artistique
        • J'éponge donc j'essuie
        • Poor Random Number Generator [2/2]
        • La Seine
        • J'ai glissé chef !
        • SEA - La face cachée de l'Iceberg
      • 🔎Forensic
        • Le tir aux logs
        • Darts Bank
        • Vaut mieux sécuriser que guérir
        • De bons croissants au beurre
        • Poids Raw vs. Cours Jette [1/3]
      • 🔌Hardware
        • Serial killer
        • Le soulevé de GND
        • Comment est votre modulation ? [1/2]
        • Sea side channel [1/4] - Introduction
        • Comment est votre modulation ? [2/2]
        • Sea side channel [2/4] - Reconnaissance
        • Sea side channel [3/4] - Mais où sont les triggers ?
      • 🤖IA
        • Du poison [1/2]
        • Du poison [2/2]
        • Des portes dérobées
      • 🧠Misc
        • Discord
        • De la friture sur la ligne
        • Bienvenue
        • Revers(ibl)e Engineering [0/2]
      • 📚OSINT
        • Légende
        • Not on my watch
        • Secret Training [1/2]
      • 😈Pwn
        • Pseudoverflow
        • Jean Pile
        • Mordu du 100m
        • Antismash
      • 🐈‍⬛Quantique
        • Des trains superposés
        • De l'écoute, pas très discrète
        • De la multiplicité des problèmes
      • ⚙️Reverse
        • ⭐Échauffement
        • ⭐Intronisation du CHAUSSURE
        • ⭐Bugdroid Fight [1/2]
        • ⭐Revers(ibl)e Engineering [1/2]
        • ⭐Bugdroid Fight [2/2]
        • ⭐Nanocombattants
        • ⭐Revers(ibl)e Engineering [2/2]
        • Le Tableau Noir
      • 🎭Stéganographie
        • ⭐L'absence
        • ⭐Regarder en stéréo
        • ⭐La Barre Fixe
        • ⭐Le grand écart
        • ⭐La chute
      • 🌐Web
        • ⭐Vous êtes en RETARD
        • ⭐Le match du siècle [1/2]
        • ⭐Exploit mag
        • ⭐Le match du siècle [2/2]
        • ⭐LE GORFOU 42
        • ⭐La boutique officielle
    • 2024 | CTFREI - Bordeaux
      • 🔑Cryptographie
        • zzz
      • 📚OSINT
        • Alexis Dumas
        • Back to the bureau
        • Dr Octopus
        • Folie et ambition
        • GeoGuessr
        • Hugo Nelots : prélude
        • La fin ?
        • La fuite Dumas
        • Un réseau suspect
      • 💾Programmation
        • Eval me 1
        • Eval me 2
        • Time Based
      • 💻Système
        • Broken Binary 1
        • Broken Binary 2
        • GTFO of here
        • Pyjail 1
        • Pyjail 2
        • Pyjail 3
        • Pyjail 4
      • 🌐Web
        • Au commencement était le verb
        • Becadmin
        • PHP Juggler
    • 2024 | HTB - Cyber Apocalypse Challenges
      • 🔗Blockchain
        • Lucky Faucet
        • Recovery
        • Russian Roulette
      • 🔑Cryptographie
        • Blunt
        • Dynastic
        • Iced TEA
        • Makeshift
        • Primary Knowledge
      • 🔎Forensic
        • An unusual sighting
        • Data Siege
        • Fake Boost
        • Game Invitation
        • It Has Begun
        • Phreaky
        • Pursue The Tracks
        • Urgent
      • 🔌Hardware
        • BunnyPass
        • Flash-ing Logs
        • Maze
        • Rids
        • The PROM
      • 🧠Misc
        • Character
        • Cubicle Riddle
        • Path of Survival
        • Stop Drop and Roll
        • Unbreakable
        • Were Pickle Phreaks
        • Were Pickle Phreaks Revenge
      • 😈Pwn
        • Delulu
        • Pet Companion
        • Tutorial
        • Writing on the Wall
      • ⚙️Reverse
        • BoxCutter
        • Crushing
        • FollowThePath
        • LootStash
        • MazeOfPower
        • Metagaming
        • PackedAway
        • QuickScan
      • 🌐Web
        • Flag Command
        • KORP Terminal
        • Labyrinth Linguist
        • LockTalk
        • Testimonial
        • TimeKORP
    • 2024 | UNbreakable
      • 🔑Cryptographie
        • start-enc
        • traffic-e
      • 🔎Forensic
        • easy-hide
        • password-manager-is-a-must
      • 🧠Misc
        • rfc-meta
      • 📱Mobile
        • flagen
        • improper-configuration
      • 📡Network
        • wifi-basic
        • wifiland
      • 📚OSINT
        • persistent-reccon
        • safe-password
      • 😈Pwn
        • intro-to-assembly
      • ⚙️Reverse
        • fake-add
      • 🎭Stéganographie
        • secrets-of-winter
      • 🌐Web
        • pygment
        • sided-curl
        • you-can-trust-me
    • 2023 | EFREI - CyberNight
      • 📚OSINT
        • Invest Now !
      • 😈Pwn
        • NSA Call Converter
      • ⚙️Reverse
        • CryptoVirus
        • WebChaussettes
      • 🌐Web
        • DoctoLeak
    • 2023 | Flag4All
      • 🔑Cryptographie
        • Aes IV
        • Crypt my loop
        • Kentucky fried chicken
        • RSA primes
        • Xor
    • 2022 | EFREI - CyberNight
      • 🔑Cryptographie
        • Coupé-décalé
        • ExFILEtration
        • Il s'est baissé ou pas
        • J'ai pas roté
        • Les allemands !
        • RSA Strong Prime generator
      • 🔎Forensic
        • Bomberman 1/2
        • Bomberman 2/2
        • Magic
        • Peu importe le chemin
        • Sniff sniff
        • Souvenir
        • Xray
      • 🔌Hardware
        • Class4
        • Find me 2/3
        • Identify 1/3
        • Yo listen 3/3
      • 🧠Misc
        • Et je tombe tombe tombe
        • Des yeux partout
        • RiGOLe
        • Roomba tricheur
        • Survey
        • Tinder
      • 💾Programmation
        • Repeat
        • Startup
        • Timing
      • ⚙️Reverse
        • Auth 1
        • Auth2
        • Auth3
        • Cryptoroomba
        • Tenet
      • 🎭Stéganographie
        • 50 shades of stephane legar
        • Chess master
        • Deviens champion sers toi de tout ce que tu as appris
        • Drifting in the bits
        • Pyramide
        • Spirale
      • 🌐Web
        • Ah bah c'est du propre
        • Cooking roomba
        • Leaderboard
        • vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
Propulsé par GitBook
Sur cette page
  • Challenge
  • Solution

Cet article vous a-t-il été utile ?

  1. CTF & Writeups
  2. 2024 | Efrei - CyberNight
  3. Cryptographie

Weird Algorithm

Flag: CYBN{N0t_v3ry_3ff1c1ent_4lg0r1thm}

Challenge

Description


Nous avons intercepté un fichier contenant des informations top secrètes. Cependant, ce fichier semble totalement vide. Nous pensons que ses auteurs ont utilisé un algorithme dont nous avons réussi à obtenir une partie de la documentation.

Votre mission est simple : rendre ces informations lisibles.

Solution

Le fichier chiffré ne contient que 2 caractères différents et en contient 1190 :

with open('flag.enc', 'r') as f:
  encrypted = f.read()

print(f'Size: {len(encrypted)}')
print(f'Caracters: {len(set(encrypted))}')
print(f'Divisors: {divisors(len(encrypted))}')

# Size: 1190
# Caracters: 2
# Divisors: [1, 2, 5, 7, 10, 14, 17, 34, 35, 70, 85, 119, 170, 238, 595, 1190]

Il faut partir sur l'hypothèse que tous les nombres dans la matrice finale montrée dans le PDF sont écrit en binaire où l'on a remplacé 0 et 1 par 2 caractères random.

De là, il faut forcément que les paramètres bits et depth soient des diviseurs de 1190, puisqu'ils représentent la largeur et la hauteur de la matrice.

On sait qu'on a chiffré de l'ASCII (la valeur max est 127), on en déduit que bits = 7

Concernant depth, 5 est la seule valeur plausible, car pour toutes les valeurs ASCII possibles, le maximum de nombres de facteurs premiers est 6 (et il est n'est pas diviseur de 1190).

from sympy import factorint

print(max([len(factorint(n, multiple=True)) for n in range(128)]))
# 6

Maintenant, on va réassembler tous les bits ensemble pour former des nombres. Le caractère qui correspond à 0 ou 1 n'a pas d'importance.

with open('flag.enc', 'r') as f:
  encrypted = f.read()

bits = 7
depth = 5
encrypted = ''.join(['1' if c == ' ' else '0' for c in encrypted])

numbers = [int(encrypted[i:i+bits], 2) for i in range(0, len(encrypted), bits)]
print(f'\nNumbers:\n{numbers}')

# Numbers:
# [41, 113, 41, 41, 41, 42, 42, 41, 41, 41, 57, 43, 41, 41, 41, 43, 41, 41, 41, 41, 41, 45, 42, 41, 41, 42, 41, 42, 41, 47, 42, 37, 69, 45, 41, 41, 42, 41, 41, 41, 42, 42, 45, 41, 41, 42, 35, 59, 41, 41, 57, 41, 35, 41, 77, 41, 42, 41, 41, 43, 41, 43, 59, 41, 41, 42, 41, 45, 41, 41, 35, 37, 41, 37, 42, 41, 41, 41, 41, 41, 41, 41, 41, 57, 43, 41, 41, 47, 41, 41, 41, 45, 42, 42, 79, 42, 42, 41, 42, 41, 41, 41, 41, 41, 43, 42, 43, 41, 42, 53, 59, 42, 43, 59, 35, 45, 43, 41, 42, 47, 43, 41, 41, 42, 41, 41, 37, 43, 41, 42, 41, 47, 41, 42, 41, 45, 107, 41, 41, 43, 1, 43, 43, 42, 41, 19, 41, 41, 41, 41, 57, 42, 41, 47, 43, 47, 41, 35, 53, 59, 42, 43, 41, 42, 43, 41, 53, 42, 41, 41]

On voit que 41, 42 et 43 reviennent énormément. C'est normal, ils correspondent aux facteurs 1, 2 et 3 comme on peut le déduire du tableau montré dans l'exemple :

Maintenant, il faut déterminer la clé du XOR. Pour ça on va faire l'hypothèse que le nombre le plus présent est le facteur 1, de là, on pourra déterminé avec quoi il a été XOR et donc la clé :

stats = sorted([(n, numbers.count(n)) for n in set(numbers)], key=lambda o: o[1], reverse=True)
print(f'\nStats:\n{stats}')

# On prend le nombre le plus présent
xored_one = stats[0][0]
key = 1 ^ xored_one
print(f'\nKey: {key}')

# Stats:
# [(41, 82), (42, 30), (43, 17), (45, 7), (47, 6), (35, 5), (59, 5), (37, 4), (57, 4), (53, 3), (1, 1), (69, 1), (107, 1), (77, 1), (79, 1), (113, 1), (19, 1)]
# 
# Key: 40

On peut désormais XOR tous les nombres avec cette clé :

numbers = [n ^ key for n in numbers]
print(f'\nNumbers:\n{numbers}')

# Numbers:
# [1, 89, 1, 1, 1, 2, 2, 1, 1, 1, 17, 3, 1, 1, 1, 3, 1, 1, 1, 1, 1, 5, 2, 1, 1, 2, 1, 2, 1, 7, 2, 13, 109, 5, 1, 1, 2, 1, 1, 1, 2, 2, 5, 1, 1, 2, 11, 19, 1, 1, 17, 1, 11, 1, 101, 1, 2, 1, 1, 3, 1, 3, 19, 1, 1, 2, 1, 5, 1, 1, 11, 13, 1, 13, 2, 1, 1, 1, 1, 1, 1, 1, 1, 17, 3, 1, 1, 7, 1, 1, 1, 5, 2, 2, 103, 2, 2, 1, 2, 1, 1, 1, 1, 1, 3, 2, 3, 1, 2, 29, 19, 2, 3, 19, 11, 5, 3, 1, 2, 7, 3, 1, 1, 2, 1, 1, 13, 3, 1, 2, 1, 7, 1, 2, 1, 5, 67, 1, 1, 3, 41, 3, 3, 2, 1, 59, 1, 1, 1, 1, 17, 2, 1, 7, 3, 7, 1, 11, 29, 19, 2, 3, 1, 2, 3, 1, 29, 2, 1, 1]

Il n'y a que des nombres premiers, notre hypothèse se confirme et nous sommes sur la bonne voie.

Dans le PDF, on sait que tous les caractères ASCII sont décomposés en depth facteurs premiers, donc ici en 5 facteurs chacun. La question est de savoir comment ils sont disposés dans notre tableau :

On peut tester les deux, mais c'est bien la seconde façon de faire qui est la bonne :

def mul(values: list[int]) -> int:
  acc = 1
  for n in values:
    acc *= n
  return acc 


# Donne des valeurs qui ne sont pas ASCII
groups = [numbers[i:i+depth] for i in range(0, len(numbers), depth)]
print(f'Groups:\n{groups}')
caracters = [mul(group) for group in groups]
print(f'Caracters:\n{caracters}')

# Groups:
# [[1, 89, 1, 1, 1], [2, 2, 1, 1, 1], [17, 3, 1, 1, 1], [3, 1, 1, 1, 1], [1, 5, 2, 1, 1], [2, 1, 2, 1, 7], [2, 13, 109, 5, 1], [1, 2, 1, 1, 1], [2, 2, 5, 1, 1], [2, 11, 19, 1, 1], [17, 1, 11, 1, 101], [1, 2, 1, 1, 3], [1, 3, 19, 1, 1], [2, 1, 5, 1, 1], [11, 13, 1, 13, 2], [1, 1, 1, 1, 1], [1, 1, 1, 17, 3], [1, 1, 7, 1, 1], [1, 5, 2, 2, 103], [2, 2, 1, 2, 1], [1, 1, 1, 1, 3], [2, 3, 1, 2, 29], [19, 2, 3, 19, 11], [5, 3, 1, 2, 7], [3, 1, 1, 2, 1], [1, 13, 3, 1, 2], [1, 7, 1, 2, 1], [5, 67, 1, 1, 3], [41, 3, 3, 2, 1], [59, 1, 1, 1, 1], [17, 2, 1, 7, 3], [7, 1, 11, 29, 19], [2, 3, 1, 2, 3], [1, 29, 2, 1, 1]]
# Caracters:
# [89, 4, 51, 3, 10, 28, 14170, 2, 20, 418, 18887, 6, 57, 10, 3718, 1, 51, 7, 2060, 8, 3, 348, 23826, 210, 6, 78, 14, 1005, 738, 59, 714, 42427, 36, 58]


# Fonctionne
width = len(numbers) // depth
groups = [[numbers[width * x + w] for x in range(depth)] for w in range(width)]
print(f'Groups 2:\n{groups}')
caracters = [mul(group) for group in groups]
print(f'Caracters 2:\n{caracters}')

# Groups 2:
# [[1, 1, 1, 1, 67], [89, 1, 1, 1, 1], [1, 2, 11, 3, 1], [1, 1, 13, 2, 3], [1, 1, 1, 3, 41], [2, 1, 13, 1, 3], [2, 2, 2, 2, 3], [1, 2, 1, 29, 2], [1, 5, 1, 19, 1], [1, 1, 1, 2, 59], [17, 1, 1, 3, 1], [3, 2, 1, 19, 1], [1, 11, 1, 11, 1], [1, 19, 1, 5, 1], [1, 1, 1, 3, 17], [3, 1, 17, 1, 2], [1, 17, 3, 2, 1], [1, 1, 1, 7, 7], [1, 11, 1, 3, 3], [1, 1, 7, 1, 7], [1, 101, 1, 1, 1], [5, 1, 1, 2, 11], [2, 2, 1, 1, 29], [1, 1, 5, 1, 19], [1, 1, 2, 13, 2], [2, 3, 2, 3, 3], [1, 1, 103, 1, 1], [2, 3, 2, 2, 2], [1, 19, 2, 1, 3], [7, 1, 1, 7, 1], [2, 1, 2, 1, 29], [13, 2, 1, 2, 2], [109, 1, 1, 1, 1], [5, 5, 1, 5, 1]]
# Caracters 2:
# [67, 89, 66, 78, 123, 78, 48, 116, 95, 118, 51, 114, 121, 95, 51, 102, 102, 49, 99, 49, 101, 110, 116, 95, 52, 108, 103, 48, 114, 49, 116, 104, 109, 125]

Le script complet :

with open('flag.enc', 'r') as f:
  encrypted = f.read()

bits = 7
depth = 5
encrypted = ''.join(['1' if c == ' ' else '0' for c in encrypted])

numbers = [int(encrypted[i:i+bits], 2) for i in range(0, len(encrypted), bits)]
stats = sorted([(n, numbers.count(n)) for n in set(numbers)], key=lambda o: o[1], reverse=True)
xored_one = stats[0][0]
key = 1 ^ xored_one

numbers = [n ^ key for n in numbers]


def mul(values: list[int]) -> int:
  acc = 1
  for n in values:
    acc *= n
  return acc 

# Fonctionne
width = len(numbers) // depth
groups = [[numbers[width * x + w] for x in range(depth)] for w in range(width)]
caracters = [mul(group) for group in groups]

flag = bytes([mul(group) for group in groups]).decode()
print(flag)

# CYBN{N0t_v3ry_3ff1c1ent_4lg0r1thm}
PrécédentShared FlagSuivantMinecraft

Dernière mise à jour il y a 5 mois

Cet article vous a-t-il été utile ?

🚩
🔑