3v3ntl0g - forensics - webtopia

import struct
import sys
from pathlib import Path

def lire_evenements(fichier_bin: str):
    buf = Path(fichier_bin).read_bytes()
    nb_entrees = len(buf) // 24
    evenements = []
    offset = 0

    for _ in range(nb_entrees):
        tv_sec, tv_usec, ev_type, code, value = struct.unpack_from('<qqHHI', buf, offset)
        evenements.append((tv_sec, tv_usec, ev_type, code, value))
        offset += 24

    return evenements

def reconstruction_texte(evenements):
    code_to_char = {
        19: ('r', 'R', None),
        20: ('t', 'T', None),
        21: ('y', 'Y', None),
        22: ('u', 'U', None),
        25: ('p', 'P', None),
        31: ('s', 'S', None),
        32: ('d', 'D', None),
        35: ('h', 'H', None),
        46: ('c', 'C', None),
        49: ('n', 'N', None),
        50: (',', '?', None),
        2:  ('&', '1', None),
        3:  ('é', '2', None),
        4:  ('"', '3', None),
        5:  ("'", '4', '{'),
        6:  ('(', '5', '['),
        7:  ('-', '6', None),
        8:  ('è', '7', None),
        9:  ('_', '8', None),
        10: ('ç', '9', None),
        11: ('à', '0', None),
        12: (')', '-', None),
        13: ('=', '+', '}'),
    }

    CODE_SHIFT_GAUCHE  = 42   
    CODE_SHIFT_DROIT   = 54   
    CODE_ALTGR         = 100 
    CODE_CTRL_GAUCHE   = 29   
    evenements_sorted = sorted(evenements, key=lambda e: (e[0], e[1]))

    shift_active = False
    altgr_active = False
    texte = ""

    for tv_sec, tv_usec, ev_type, code, value in evenements_sorted:
        if ev_type != 1:
            continue
        if code in (CODE_SHIFT_GAUCHE, CODE_SHIFT_DROIT):
            if   value == 1: 
                shift_active = True
            elif value == 0:  
                shift_active = False
            continue

        if code == CODE_ALTGR:
            if   value == 1:
                altgr_active = True
            elif value == 0:
                altgr_active = False
            continue

        if code == CODE_CTRL_GAUCHE:
            if value == 1:
                break
            else:
                continue

        if value != 1:
            continue

        if code in code_to_char:
            sans_shift, avec_shift, avec_altgr = code_to_char[code]
            if altgr_active and (avec_altgr is not None):
                ch = avec_altgr
            elif shift_active:
                ch = avec_shift
            else:
                ch = sans_shift
            texte += ch

    return texte


if __name__ == '__main__':
    if len(sys.argv) > 1:
        fichier = sys.argv[1]
    else:
        fichier = 'shuffled.bin'

    if not Path(fichier).is_file():
        print(f"Erreur : le fichier '{fichier}' n'existe pas.")
        sys.exit(1)

    evenements = lire_evenements(fichier)
    flag = reconstruction_texte(evenements)

    print("=== FLAG ===")
    print(flag)
 

Which prints out our flag:

N0PS{c4n_y0U_R34d_Th15??}