Skip to content

Instantly share code, notes, and snippets.

@MiKhai37
Last active December 6, 2023 17:25
Show Gist options
  • Save MiKhai37/fb44cefedb50b89d9ad3b95ed1734e4e to your computer and use it in GitHub Desktop.
Save MiKhai37/fb44cefedb50b89d9ad3b95ed1734e4e to your computer and use it in GitHub Desktop.
StegCryptoDIY-RNG Solve Script
import imageio.v3 as iio
import numpy as np
from Crypto.Util.number import inverse
ref_path = '/home/bob/CTF/Hackropole-ANSSI/FCSC2019/forensics/StegCryptoDIY/leHACK19_ref.png'
chall_path = '/home/bob/CTF/Hackropole-ANSSI/FCSC2019/forensics/StegCryptoDIY/leHACK19_chall.png'
# Chargement de l'image du challenge et celle de référence
im_ref = iio.imread(ref_path)
im_chall = iio.imread(chall_path)
# Verification de la taille des images
assert im_chall.shape[:2] == im_ref.shape[:2]
# On observe les differente valeurs d'opacité de l'image challenge
opacity_vals = []
for row in im_chall:
for key_pix in row:
opacity_vals.append(key_pix[3])
print("Décompte des valeurs uniques d'opacité")
print(np.asarray(np.unique(opacity_vals, return_counts=True)).T)
# On trace une image avec les pixels dont la valeur d'opacité est de 254
im_hidden = np.zeros(im_ref.shape,dtype='uint8')
for i,row in enumerate(im_chall):
for j,key_pix in enumerate(row):
opacity = key_pix[3]
if opacity == 254:
im_hidden[i][j] = np.array([255,255,255])
else:
im_hidden[i][j] = np.array([0,0,0])
iio.imwrite("./hidden_image.jpg", im_hidden)
# Récupération des pixels composants la clé secrete et de leurs coordonnées
key_pixs = []
for i,row in enumerate(im_chall):
for j,key_pix in enumerate(row):
opacity = key_pix[3]
if opacity == 254 and i >= 75:
key_pixs.append((i, j, key_pix[:-1]))
# Récupération des valeurs composants la clé secrete et de leurs coordonnées dans la bonne base (x,y)
pix_key_vals = []
for key_pix in key_pixs:
y = key_pix[0]
x = key_pix[1]
pix = key_pix[2]
# Recherche du parametres RGB différent
for rgb_ind in range(3):
if pix[rgb_ind]!=im_ref[y][x][rgb_ind]:
pix_key_vals.append((x,y,chr(pix[rgb_ind])))
# On observe les differentes valeurs composants la clé secrete
key_vals = [pix[2] for pix in pix_key_vals]
print("\nValeurs uniques composants la clé secrete: ",''.join(np.unique(key_vals)))
#print("Décompte des valeurs uniques composants la clé secrete")
#print(np.asarray(np.unique(key_vals, return_counts=True)).T)
# On voit dans le compte des valeurs uniques que la clé contient sans doute notre flag
# On recherche donc les coordonnées des pixels correspondant
print("\nPixels possibles contenant le début du flag 'leh'")
for c in 'leh':
for key_val in pix_key_vals:
if key_val[2]==c:
print(key_val)
# Avec les valeurs recuperer on tente de recuperer les composants du LGC ayant permis de générer les x des pixels de la clé
modulus_x = 2**9
# Deux possibilités s'offrent a nous, on teste les deux
possible_xs = [[53,387,375],[53,6,375]]
for known_xs in possible_xs:
try:
multiplier_x = (known_xs[2] - known_xs[1]) * inverse(known_xs[1] - known_xs[0], modulus_x) % modulus_x
increment_x = (known_xs[1] - known_xs[0] * multiplier_x) % modulus_x
print(f"\nSuccess for x_states: {known_xs}, multiplier = {multiplier_x}, increment = {increment_x})")
except ValueError as e:
print(e)
print(f"\nFail for x_states: {known_xs}")
# Seulement une des combinaisons correspond aux nombres générerés par un LCG
# avec les parametres multiplier=417 et incrment=433
class LCG:
def __init__(self, seed, a, c, m):
self.seed = seed
self.a = a
self.c = c
self.m = m
print(f"\nLCG: Valeur Initial={self.seed}, Multiplicateur={self.a}, Incrementeur={self.c}, Modulo={self.m}")
def next(self):
self.seed = (self.a * self.seed + self.c) % self.m
return self.seed
# On génere les coordonnées x de notre clé afin de reconstruire la clé
lcgx = LCG(53,multiplier_x,increment_x,modulus_x)
flag = ['l'] # valeur initiale
for i in range(len(pix_key_vals)-1):
nx = lcgx.next()
for key_val in pix_key_vals:
if(key_val[0]==nx):
#print(nx,val[2])
flag.append(key_val[2])
print(''.join(flag))
print(len(flag))
# La valeur initiale etait celle de la parenthèse
lcgx = LCG(253,multiplier_x,increment_x,modulus_x)
flag = ['('] # valeur initiale
for i in range(len(pix_key_vals)-1):
nx = lcgx.next()
for key_val in pix_key_vals:
if(key_val[0]==nx):
#print(nx,val[2])
flag.append(key_val[2])
print(''.join(flag))
print(len(flag))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment