Solution de botanicmagic pour Serial Keyler

reverse linux x86/x64 keygenme

21 janvier 2025

Outil utilisé pour ce challenge : Cutter

Voici les fonctions principales du programme :

undefined8 main(void)
{
    int32_t iVar1;
    int64_t var_98h;
    int64_t var_58h;

    // [+] Username:
    printf(0xa48);
    // lecture stdin username et stockage dans var_98h
    __isoc99_scanf(0xa57, &var_98h);
    // [+] Serial:
    printf(0xa5c);
    // lecture stdin serial et stockage dans var_58h
    __isoc99_scanf(0xa57, &var_58h);
    // appel à la fonction de validation
    iVar1 = fcn.0000083a((char *)&var_98h, (char *)&var_58h);
    if (iVar1 == 0) {
        // [>] Valid serial!
        puts(0xa6b);
        // [>] Now connect to the remote server and generate serials for the given usernames.
        puts(0xa80);
    } else {
        // [!] Incorrect serial.
        puts(0xad3);
    }

    return 0;
}

// validation du serial
void fcn.0000083a(char *arg1, char *arg2)
{
    char *s1;
    char *s;
    int64_t var_68h;
    size_t var_60h;
    char *s2;
    // taille de la chaine username (arg1)
    var_60h = strlen(arg1);
    // initialisation de la chaine s2 sur 0x40 octets
    memset(&s2, 0, 0x40);
    // serial à comparer
    s1 = arg2;
    // username
    s = arg1;
    // tant qu'on n'est pas arrivé à la fin de la chaine username
    for (var_68h = 0; (uint64_t)var_68h < var_60h; var_68h = var_68h + 1) {
        // on effectue un xor sur chaque caractère de la chaine username
        *(uint8_t *)((int64_t)&var_60h + (var_60h - var_68h) + 7) = s[var_68h] ^ 0x1f;
    }
    // comparaison du serial fourni en paramètre avec le serial généré via la boucle ci-dessus
    strcmp(s1, &s2);

    return;
}

Nous avons maintenant une bonne compréhension du fonctionnement, ce qui nous permet de procéder à la création d’un générateur de clés. L’unique exigence est de relever le défi en communiquant avec le conteneur Docker via le port réseau qu’il expose. Toute interaction qui ne respecte pas cette méthode sera invalide. Ainsi, une portion du script doit interagir avec le conteneur. Pour information, j’ai déjà développé ce type d’interaction pour le challenge fifty-shades-of-white.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import subprocess
import re
import logging
import select
import time

def keygen(username: str) -> str:
    """
    Génère un serial basé sur un username donné.
    """
    # Longueur de la chaîne username
    len_username = len(username)

    # Initialise un tableau d'une taille de 0x40 (64 octets)
    key_array = [0] * 0x40

    # Boucle pour transformer chaque caractère de username
    for i in range(len_username):
        # Effectue un XOR entre chaque caractère et 0x1F
        transformed_char = ord(username[i]) ^ 0x1F
        key_array[len_username - i - 1] = transformed_char

    # Convertit key_array en chaîne de caractères (limité à la longueur du username)
    key_serial = ''.join(chr(c) for c in key_array[:len_username])

    return key_serial


def interact_with_docker():
    """
    Interagit avec un container Docker via netcat pour obtenir des noms, générer des licences valides, et les soumettre.
    """
    # Configuration du logging
    logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(message)s")

    try:
        # Ouvre une connexion netcat avec le container Docker
        with subprocess.Popen(['nc', 'localhost', '4000'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, bufsize=1) as proc:
            timeout = 60  # Temps maximum d'exécution en secondes
            start_time = time.time()
            # Tant que la connexion est ouverte
            while True:
                    # Si le timeout est atteint, on sort de la boucle
                    if time.time() - start_time > timeout:
                        logging.error("Timeout reached. Exiting.")
                        break
                    # Utilise select pour vérifier si des données sont disponibles
                    ready, _, _ = select.select([proc.stdout], [], [], 1.0)
                    if ready:
                        # Lit les données reçues
                        output = proc.stdout.readline()
                        # Si la chaîne est vide, cela signifie que le flux est fermé ou que le processus est terminé
                        if not output :
                            print("No more output from the Docker container. Exiting.")
                            break

                        # Affiche les données reçues
                        logging.info(f"Received: {output.strip()}")
                        # Vérifie si le flag est donné
                        if ">>> Well done! Here is the flag:" in output:
                            logging.info("Flag received! Exiting.")
                            print(output.strip())  # Affiche la ligne contenant le flag
                            break

                        # Vérifie si une demande de licence est faite
                        match = re.search(r"What is a valid serial for username: (.+)", output)
                        # Si une demande de licence est faite
                        if match:
                            # Récupère le nom de l'utilisateur
                            username = match.group(1)
                            # Génère une licence admin (1337) pour l'utilisateur
                            logging.info(f"Generating key for {username}")
                            thekey = keygen(username)
                            logging.info(f"Generated key: \n{thekey}")
                            # Soumet la licence générée
                            proc.stdin.write(thekey + '\n')
                            # Vide le buffer
                            proc.stdin.flush()
    except Exception as e:
        logging.error(f"Error during Docker interaction: {e}")
    finally:
        if proc:
            proc.stdin.close()
            proc.stdout.close()
            logging.info("Netcat connection closed")

if __name__ == "__main__":
    interact_with_docker()
chmod +x serial-keyler.py

Maintenant, exécutons le programme (le flag est à la fin):

$ ./serial-keyler.py
2025-01-21 11:18:37,731 - Received: What is a valid serial for username: ecsc
2025-01-21 11:18:37,731 - Generating key for ecsc
2025-01-21 11:18:37,731 - Generated key:
|l|z
2025-01-21 11:18:37,733 - Received: >>> What is a valid serial for username: ANSSI
2025-01-21 11:18:37,733 - Generating key for ANSSI
2025-01-21 11:18:37,733 - Generated key:
VLLQ^
2025-01-21 11:18:37,735 - Received: >>> What is a valid serial for username: HelloWorld
2025-01-21 11:18:37,735 - Generating key for HelloWorld
2025-01-21 11:18:37,735 - Generated key:
{smpHpsszW
2025-01-21 11:18:37,737 - Received: >>> What is a valid serial for username: TeamFrance
2025-01-21 11:18:37,737 - Generating key for TeamFrance
2025-01-21 11:18:37,737 - Generated key:
z|q~mYr~zK
2025-01-21 11:18:37,739 - Received: >>> What is a valid serial for username: XwUYfyUypGrSDCDJIaveDodN
2025-01-21 11:18:37,739 - Generating key for XwUYfyUypGrSDCDJIaveDodN
2025-01-21 11:18:37,739 - Generated key:
Q{p[zi~VU[\[LmXofJfyFJhG
2025-01-21 11:18:37,742 - Received: >>> What is a valid serial for username: VDTPrNFzDig0BRpArHg7E
2025-01-21 11:18:37,742 - Generating key for VDTPrNFzDig0BRpArHg7E
2025-01-21 11:18:37,743 - Generated key:
Z(xWm^oM]/xv[eYQmOK[I
2025-01-21 11:18:37,746 - Received: >>> What is a valid serial for username: LovPuwmfm9MsRLc0iNZD
2025-01-21 11:18:37,746 - Generating key for LovPuwmfm9MsRLc0iNZD
2025-01-21 11:18:37,747 - Generated key:
[EQv/|SMlR&ryrhjOipS
2025-01-21 11:18:37,749 - Received: >>> What is a valid serial for username: QEDjL7O4TSazow4
2025-01-21 11:18:37,749 - Generating key for QEDjL7O4TSazow4
2025-01-21 11:18:37,749 - Generated key:
+hpe~LK+P(Su[ZN
2025-01-21 11:18:37,751 - Received: >>> What is a valid serial for username: BKYnVmN1hd3bd4fTvLbPrW
2025-01-21 11:18:37,751 - Generating key for BKYnVmN1hd3bd4fTvLbPrW
2025-01-21 11:18:37,751 - Generated key:
HmO}SiKy+{},{w.QrIqFT]
2025-01-21 11:18:37,753 - Received: >>> What is a valid serial for username: Xq4iI52IHDg9pINta982O
2025-01-21 11:18:37,754 - Generating key for Xq4iI52IHDg9pINta982O
2025-01-21 11:18:37,754 - Generated key:
P-'&~kQVo&x[WV-*Vv+nG
2025-01-21 11:18:37,756 - Received: >>> What is a valid serial for username: 0M1XrNqehtUvjJboUgC
2025-01-21 11:18:37,756 - Generating key for 0M1XrNqehtUvjJboUgC
2025-01-21 11:18:37,756 - Generated key:
\xJp}UuiJkwznQmG.R/
2025-01-21 11:18:37,759 - Received: >>> What is a valid serial for username: L9yjX09lmhDokOd0DsY4e
2025-01-21 11:18:37,759 - Generating key for L9yjX09lmhDokOd0DsY4e
2025-01-21 11:18:37,759 - Generated key:
z+Fl[/{Ptp[wrs&/Guf&S
2025-01-21 11:18:37,763 - Received: >>> What is a valid serial for username: 43O4pAgFIksYQY7FSfKQ
2025-01-21 11:18:37,763 - Generating key for 43O4pAgFIksYQY7FSfKQ
2025-01-21 11:18:37,763 - Generated key:
NTyLY(FNFltVYx^o+P,+
2025-01-21 11:18:37,765 - Received: >>> What is a valid serial for username: rUN9B3ZBSOcs
2025-01-21 11:18:37,765 - Generating key for rUN9B3ZBSOcs
2025-01-21 11:18:37,765 - Generated key:
l|PL]E,]&QJm
2025-01-21 11:18:37,767 - Received: >>> What is a valid serial for username: EnMBnnzBWx9btLJPTw
2025-01-21 11:18:37,767 - Generating key for EnMBnnzBWx9btLJPTw
2025-01-21 11:18:37,768 - Generated key:
hKOUSk}&gH]eqq]RqZ
2025-01-21 11:18:37,770 - Received: >>> What is a valid serial for username: 95ckfJtbHH62m
2025-01-21 11:18:37,770 - Generating key for 95ckfJtbHH62m
2025-01-21 11:18:37,770 - Generated key:
r-)WW}kUyt|*&
2025-01-21 11:18:37,772 - Received: >>> What is a valid serial for username: kT5cH5NSlSZraq6
2025-01-21 11:18:37,772 - Generating key for kT5cH5NSlSZraq6
2025-01-21 11:18:37,773 - Generated key:
)n~mELsLQ*W|*Kt
2025-01-21 11:18:37,775 - Received: >>> What is a valid serial for username: 42ZQ01zYAwg3jvSJtKxCw
2025-01-21 11:18:37,775 - Generating key for 42ZQ01zYAwg3jvSJtKxCw
2025-01-21 11:18:37,775 - Generated key:
h\gTkULiu,xh^Fe./NE-+
2025-01-21 11:18:37,778 - Received: >>> What is a valid serial for username: HcmBtMXglbQFniOkyynFm
2025-01-21 11:18:37,779 - Generating key for HcmBtMXglbQFniOkyynFm
2025-01-21 11:18:37,779 - Generated key:
rYqfftPvqYN}sxGRk]r|W
2025-01-21 11:18:37,781 - Received: >>> What is a valid serial for username: obmo7Y1VNWaNXtpY
2025-01-21 11:18:37,781 - Generating key for obmo7Y1VNWaNXtpY
2025-01-21 11:18:37,781 - Generated key:
FokGQ~HQI.F(pr}p
2025-01-21 11:18:37,783 - Received: >>> What is a valid serial for username: CFI3OLrc5HZZX6zqhf52ZygL
2025-01-21 11:18:37,783 - Generating key for CFI3OLrc5HZZX6zqhf52ZygL
2025-01-21 11:18:37,783 - Generated key:
SxfE-*ywne)GEEW*|mSP,VY\
2025-01-21 11:18:37,785 - Received: >>> What is a valid serial for username: 2U4nfXuEgEgjduFH
2025-01-21 11:18:37,785 - Generating key for 2U4nfXuEgEgjduFH
2025-01-21 11:18:37,786 - Generated key:
WYj{uxZxZjGyq+J-
2025-01-21 11:18:37,788 - Received: >>> What is a valid serial for username: EecGNDRluX2Dbs
2025-01-21 11:18:37,788 - Generating key for EecGNDRluX2Dbs
2025-01-21 11:18:37,788 - Generated key:
l}[-GjsM[QX|zZ
2025-01-21 11:18:37,791 - Received: >>> What is a valid serial for username: ybWSqeHQ45nC0FBQp91KHjaH
2025-01-21 11:18:37,791 - Generating key for ybWSqeHQ45nC0FBQp91KHjaH
2025-01-21 11:18:37,791 - Generated key:
W~uWT.&oN]Y/\q*+NWznLH}f
2025-01-21 11:18:37,794 - Received: >>> What is a valid serial for username: DrCo2oqyS3t5mQlAoeb
2025-01-21 11:18:37,794 - Generating key for DrCo2oqyS3t5mQlAoeb
2025-01-21 11:18:37,794 - Generated key:
}zp^sNr*k,Lfnp-p\m[
2025-01-21 11:18:37,796 - Received: >>> What is a valid serial for username: REoWLpWJPWkLF2yZha
2025-01-21 11:18:37,796 - Generating key for REoWLpWJPWkLF2yZha
2025-01-21 11:18:37,796 - Generated key:
~wEf-YStHOUHoSHpZM
2025-01-21 11:18:37,799 - Received: >>> What is a valid serial for username: wpeE2xUVRIOGo4PfDvU81
2025-01-21 11:18:37,799 - Generating key for wpeE2xUVRIOGo4PfDvU81
2025-01-21 11:18:37,799 - Generated key:
.'Ji[yO+pXPVMIJg-Zzoh
2025-01-21 11:18:37,801 - Received: >>> What is a valid serial for username: udxPlav4fJITLGLITxB
2025-01-21 11:18:37,801 - Generating key for udxPlav4fJITLGLITxB
2025-01-21 11:18:37,801 - Generated key:
]gKVSXSKVUy+i~sOg{j
2025-01-21 11:18:37,803 - Received: >>> What is a valid serial for username: v4b6NT5Nysi7psreOZHlwe
2025-01-21 11:18:37,804 - Generating key for v4b6NT5Nysi7psreOZHlwe
2025-01-21 11:18:37,804 - Generated key:
zhsWEPzmlo(vlfQ*KQ)}+i
2025-01-21 11:18:37,806 - Received: >>> What is a valid serial for username: kMXFkKM2cVvzPX1Y68cK
2025-01-21 11:18:37,806 - Generating key for kMXFkKM2cVvzPX1Y68cK
2025-01-21 11:18:37,806 - Generated key:
T|')F.GOeiI|-RTtYGRt
2025-01-21 11:18:37,809 - Received: >>> What is a valid serial for username: 2UE0C2oXalEtvznriPlp
2025-01-21 11:18:37,809 - Generating key for 2UE0C2oXalEtvznriPlp
2025-01-21 11:18:37,809 - Generated key:
osOvmqeikZs~Gp-\/ZJ-
2025-01-21 11:18:37,812 - Received: >>> What is a valid serial for username: j85Y1qFuy5VUGBglIE
2025-01-21 11:18:37,812 - Generating key for j85Y1qFuy5VUGBglIE
2025-01-21 11:18:37,812 - Generated key:
ZVsx]XJI*fjYn.F*'u
2025-01-21 11:18:37,815 - Received: >>> What is a valid serial for username: 7R7HgQ9nANyW5Dl
2025-01-21 11:18:37,815 - Generating key for 7R7HgQ9nANyW5Dl
2025-01-21 11:18:37,815 - Generated key:
s[*HfQ^q&NxW(M(
2025-01-21 11:18:37,817 - Received: >>> What is a valid serial for username: ykYJjLPo3OpP
2025-01-21 11:18:37,817 - Generating key for ykYJjLPo3OpP
2025-01-21 11:18:37,817 - Generated key:
OoP,pOSuUFtf
2025-01-21 11:18:37,819 - Received: >>> What is a valid serial for username: RBKxv9VcpOfKOq
2025-01-21 11:18:37,819 - Generating key for RBKxv9VcpOfKOq
2025-01-21 11:18:37,819 - Generated key:
nPTyPo|I&igT]M
2025-01-21 11:18:37,822 - Received: >>> What is a valid serial for username: hkZ2W4GnQJxxIA5s
2025-01-21 11:18:37,822 - Generating key for hkZ2W4GnQJxxIA5s
2025-01-21 11:18:37,822 - Generated key:
l*^VggUNqX+H-Etw
2025-01-21 11:18:37,825 - Received: >>> What is a valid serial for username: BICmaMTemglFDMZ3PfLB
2025-01-21 11:18:37,825 - Generating key for BICmaMTemglFDMZ3PfLB
2025-01-21 11:18:37,825 - Generated key:
]SyO,ER[YsxrzKR~r\V]
2025-01-21 11:18:37,828 - Received: >>> What is a valid serial for username: HqvTIfFvLzRAz
2025-01-21 11:18:37,828 - Generating key for HqvTIfFvLzRAz
2025-01-21 11:18:37,829 - Generated key:
e^MeSiYyVKinW
2025-01-21 11:18:37,831 - Received: >>> What is a valid serial for username: 70xYeo0GEfIple43kToj
2025-01-21 11:18:37,831 - Generating key for 70xYeo0GEfIple43kToj
2025-01-21 11:18:37,831 - Generated key:
upKt,+zsoVyZX/pzFg/(
2025-01-21 11:18:37,833 - Received: >>> What is a valid serial for username: 0rfJsFbDpS3Twg6T
2025-01-21 11:18:37,833 - Generating key for 0rfJsFbDpS3Twg6T
2025-01-21 11:18:37,833 - Generated key:
K)xhK,Lo[}YlUym/
2025-01-21 11:18:37,835 - Received: >>> What is a valid serial for username: e0T9UVHYqqJe3m5z2D6D61
2025-01-21 11:18:37,835 - Generating key for e0T9UVHYqqJe3m5z2D6D61
2025-01-21 11:18:37,835 - Generated key:
.)[)[-e*r,zUnnFWIJ&K/z
2025-01-21 11:18:37,838 - Received: >>> What is a valid serial for username: CQflXhZeIIUnCyk9ahiBx3yr
2025-01-21 11:18:37,838 - Generating key for CQflXhZeIIUnCyk9ahiBx3yr
2025-01-21 11:18:37,838 - Generated key:
mf,g]vw~&tf\qJVVzEwGsyN\
2025-01-21 11:18:37,840 - Received: >>> What is a valid serial for username: VuTypY3R0690TYiNTi
2025-01-21 11:18:37,840 - Generating key for VuTypY3R0690TYiNTi
2025-01-21 11:18:37,840 - Generated key:
vKQvFK/&)/M,FofKjI
2025-01-21 11:18:37,843 - Received: >>> What is a valid serial for username: qmaQ0DqLK0ZZOI
2025-01-21 11:18:37,843 - Generating key for qmaQ0DqLK0ZZOI
2025-01-21 11:18:37,843 - Generated key:
VPEE/TSn[/N~rn
2025-01-21 11:18:37,845 - Received: >>> What is a valid serial for username: RPi6KPPfjGU5lGj4dwO
2025-01-21 11:18:37,845 - Generating key for RPi6KPPfjGU5lGj4dwO
2025-01-21 11:18:37,845 - Generated key:
Ph{+uXs*JXuyOOT)vOM
2025-01-21 11:18:37,848 - Received: >>> What is a valid serial for username: 2xsBC7LpwEfaA3CP
2025-01-21 11:18:37,848 - Generating key for 2xsBC7LpwEfaA3CP
2025-01-21 11:18:37,848 - Generated key:
O\,^~yZhoS(\]lg-
2025-01-21 11:18:37,850 - Received: >>> What is a valid serial for username: NeRlyiKu3VPCG4LY60vuMu
2025-01-21 11:18:37,850 - Generating key for NeRlyiKu3VPCG4LY60vuMu
2025-01-21 11:18:37,850 - Generated key:
jRji/)FS+X\OI,jTvfsMzQ
2025-01-21 11:18:37,852 - Received: >>> What is a valid serial for username: BtAocjzlDwnrLOmFBBGiDFI
2025-01-21 11:18:37,852 - Generating key for BtAocjzlDwnrLOmFBBGiDFI
2025-01-21 11:18:37,852 - Generated key:
VY[vX]]YrPSmqh[seu|p^k]
2025-01-21 11:18:37,855 - Received: >>> What is a valid serial for username: 8p7LZ1K77ZwAlqF4fmUi9i
2025-01-21 11:18:37,855 - Generating key for 8p7LZ1K77ZwAlqF4fmUi9i
2025-01-21 11:18:37,855 - Generated key:
v&vJry+Yns^hE((T.ES(o'
2025-01-21 11:18:37,857 - Received: >>> What is a valid serial for username: nZkvFxEuj7OS
2025-01-21 11:18:37,857 - Generating key for nZkvFxEuj7OS
2025-01-21 11:18:37,857 - Generated key:
LP(ujZgYitEq
2025-01-21 11:18:37,860 - Received: >>> What is a valid serial for username: FydHq4uJlgTJK3yCAP5G
2025-01-21 11:18:37,861 - Generating key for FydHq4uJlgTJK3yCAP5G
2025-01-21 11:18:37,861 - Generated key:
X*O^\f,TUKxsUj+nW{fY
2025-01-21 11:18:37,863 - Received: >>> What is a valid serial for username: Do1k4gpxYekMjPUn66sl0g
2025-01-21 11:18:37,863 - Generating key for Do1k4gpxYekMjPUn66sl0g
2025-01-21 11:18:37,864 - Generated key:
x/sl))qJOuRtzFgox+t.p[
2025-01-21 11:18:37,866 - Received: >>> What is a valid serial for username: UOXhNfNkRb7nbhaGCAzc
2025-01-21 11:18:37,866 - Generating key for UOXhNfNkRb7nbhaGCAzc
2025-01-21 11:18:37,866 - Generated key:
|e^\X~w}q(}MtQyQwGPJ
2025-01-21 11:18:37,908 - Received: >>> What is a valid serial for username: HwKSlIJNyLztw8KoySag1TL9
2025-01-21 11:18:37,908 - Generating key for HwKSlIJNyLztw8KoySag1TL9
2025-01-21 11:18:37,908 - Generated key:
&SK.x~LfpT'hkeSfQUVsLThW
2025-01-21 11:18:37,912 - Received: >>> Well done! Here is the flag: FCSC{8f1018d0cfe395018a1c90dbff352e2ba4a6261336fb7c32454cdae4974d4333}
2025-01-21 11:18:37,912 - Flag received! Exiting.
>>> Well done! Here is the flag: FCSC{8f1018d0cfe395018a1c90dbff352e2ba4a6261336fb7c32454cdae4974d4333}
2025-01-21 11:18:37,912 - Netcat connection closed

Voici une version plus légère du script :

#!/usr/bin/env python3
import subprocess, re, select, time

def keygen(username: str) -> str:
    return ''.join(chr(ord(c) ^ 0x1F) for c in username[::-1])

def interact_with_docker():
    try:
        with subprocess.Popen(['nc', 'localhost', '4000'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True, bufsize=1) as proc:
            start_time = time.time()
            while True:
                if time.time() - start_time > 60: break
                ready, _, _ = select.select([proc.stdout], [], [], 1.0)
                if ready:
                    output = proc.stdout.readline()
                    if not output: break
                    print(output.strip())
                    if ">>> Well done! Here is the flag:" in output: break
                    match = re.search(r"What is a valid serial for username: (.+)", output)
                    if match:
                        thekey = keygen(match.group(1))
                        proc.stdin.write(thekey + '\n')
                        proc.stdin.flush()
    except Exception as e:
        print(f"Error during Docker interaction: {e}")
    finally:
        proc.stdin.close()
        proc.stdout.close()

if __name__ == "__main__":
    interact_with_docker()