3 points par GN⁺ 2024-08-30 | 1 commentaires | Partager sur WhatsApp
  • En naviguant sur Internet, l’auteur est tombé sur un composant en ASCII art intéressant. Le rendu était impressionnant, mais difficile de comprendre comment il était implémenté
  • En consultant le code source, il a constaté que le code était minifié

Exemple de code minifié

  • Une partie du code ressemblait à ceci :
    const { floor: ra, abs: KE, min: QE } = Math,  
      O5 = ["reactive.network REACTIVE.NETWORK", "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~i!lI;:,^`'. .:â–‘â–’â–“â–ˆ"],  
      G7 = Date.now() % 3 ? O5[1] : O5[0],  
      V5 = G7.length,  
      JE = { fps: 60 };  
    

Demande d’explication du code à ChatGPT

  • L’auteur a demandé à ChatGPT de « décrire le code »
  • Réponse de ChatGPT :

    Le code fourni est assez complexe, mais je vais expliquer clairement chaque partie et sa fonction.

Vue d’ensemble

  • Il définit plusieurs fonctions et composants en JavaScript
  • Il génère du contenu texte dynamique dans une application React
  • Il produit un effet visuel à l’aide d’ASCII art ou d’un jeu de caractères prédéfini

Principaux composants et fonctions

  1. Sélection du jeu de caractères :
const { floor: ra, abs: KE, min: QE } = Math;  
const O5 = ["reactive.network REACTIVE.NETWORK", "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~i!lI;:,^`'. .:â–‘â–’â–“â–ˆ"];  
const G7 = Date.now() % 3 ? O5[1] : O5[0];  
const V5 = G7.length;  
  • Il récupère des fonctions de Math et définit deux jeux de caractères
  • Il choisit un jeu de caractères selon l’heure courante
  • Il stocke la longueur du jeu de caractères sélectionné
  1. Fonction de sélection dynamique des caractères :
function eT(e, t, n, r) {  
  const i = t.time * 8e-5;  
  const s = QE(t.cols, t.rows);  
  const o = t.metrics.aspect * 0.2;  
  const l = { x: ((4 * (e.x - t.cols / 6.25)) / s) * o, y: (5 * (e.y - t.rows / 4)) / s };  
  const u = ra(KE(YE(l) - i) * V5 + (ra(e.x / 1) % 2) * 2) % V5;  
  return G7[u];  
}  
  • La fonction eT génère un caractère en fonction de la position d’entrée et du temps courant
  • Elle ajuste la position puis choisit un caractère dans le jeu sélectionné
  1. Composant React qui affiche le contenu dynamique (tT) :
const tT = () => {  
  const e = j.useRef(null);  
  const [t, n] = j.useState({ height: null, width: null });  
  j.useEffect(() => {  
    function r() {  
      n({ height: window.innerHeight, width: window.innerWidth });  
    }  
    if (typeof window < "u") {  
      n({ height: window.innerHeight, width: window.innerWidth });  
      window.addEventListener("resize", r);  
      return () => window.removeEventListener("resize", r);  
    }  
  }, []);  
  j.useEffect(() => {  
    const r = e.current;  
    if (!r) return;  
    const i = 12;  
    const s = ra(t.width / i) * 1.6;  
    const o = ra(t.height / i);  
    const l = { aspect: s / o };  
    const u = setInterval(() => {  
      let c = "";  
      for (let d = 0; d < o; d++) {  
        for (let f = 0; f < s; f++) c += eT({ x: f, y: d }, { cols: s, rows: o, metrics: l, time: Date.now() });  
        c += `  `;  
      }  
      r.textContent = c;  
    }, 1e3 / JE.fps);  
    return () => clearInterval(u);  
  }, [t]);  
  return a.jsx("div", { style: { position: "absolute", top: 0, left: 0, width: "100%", height: "100%" }, children: a.jsx("div", { ref: e, style: { width: "100%", height: "100%", whiteSpace: "pre", overflow: "hidden" } }) });  
};  
  • Ce composant React met périodiquement à jour le contenu d’un élément div avec des caractères générés dynamiquement
  • Il calcule le nombre de colonnes et de lignes selon la taille de la fenêtre puis remplit le div avec des caractères

Code converti en TypeScript

  • L’auteur a demandé à ChatGPT de convertir le code en TypeScript
  • Réponse de ChatGPT :
    import React, { useEffect, useRef, useState } from 'react';  
    const selectedCharacterSet = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~i!lI;:,^`'. .:â–‘â–’â–“â–ˆ";  
    const characterSetLength = selectedCharacterSet.length;  
    
    const calculateCharacter = (  
      x: number,  
      y: number,  
      cols: number,  
      rows: number,  
      aspect: number,  
      time: number,  
    ): string => {  
      const timeFactor = time * 0.000_08;  
      const size = Math.min(cols, rows);  
      const aspectRatio = aspect * 0.2;  
      const position = {  
        x: ((4 * (x - cols / 6.25)) / size) * aspectRatio,  
        y: (5 * (y - rows / 4)) / size,  
      };  
      const index = Math.floor(  
        Math.abs(  
          Math.cos(position.x * position.x - position.y * position.y) - timeFactor,  
        ) * characterSetLength + (Math.floor(x) % 2) * 2,  
      ) % characterSetLength;  
      return selectedCharacterSet[index];  
    };  
    
    type Size = {  
      height: null | number;  
      width: null | number;  
    };  
    
    const AsciiArtGenerator: React.FC = () => {  
      const textRef = useRef(null);  
      const [size, setSize] = useState({ height: null, width: null });  
    
      useEffect(() => {  
        const handleResize = () => {  
          setSize({ height: window.innerHeight, width: window.innerWidth });  
        };  
        handleResize();  
        window.addEventListener('resize', handleResize);  
        return () => {  
          window.removeEventListener('resize', handleResize);  
        };  
      }, []);  
    
      useEffect(() => {  
        const element = textRef.current;  
        if (!element || !size.width || !size.height) return undefined;  
    
        const cols = Math.floor(size.width / 12) * 1.6;  
        const rows = Math.floor(size.height / 12);  
        const aspectRatio = cols / rows;  
    
        const intervalId = setInterval(() => {  
          let content = '';  
          for (let y = 0; y < rows; y++) {  
            for (let x = 0; x < cols; x++) {  
              content += calculateCharacter(x, y, cols, rows, aspectRatio, Date.now());  
            }  
            content += '\n';  
          }  
          element.textContent = content;  
        }, 1_000 / 60);  
    
        return () => {  
          clearInterval(intervalId);  
        };  
      }, [size]);  
    
      return (  
    
      );  
    };  
    
    export default () => {  
      return ;  
    };  
    

Résumé de GN⁺

  • Cet article explique comment comprendre et restaurer du code minifié
  • Il montre comment utiliser ChatGPT pour expliquer du code complexe et le convertir en TypeScript
  • Il présente une manière d’exploiter des outils d’IA pour aider à la restauration et à la compréhension du code
  • Des projets aux fonctionnalités similaires incluent Prettier et UglifyJS

1 commentaires

 
GN⁺ 2024-08-30
Avis Hacker News
  • L’auteur de HumanifyJS a développé un outil basé sur les LLM. Cet outil utilise un LLM au niveau de l’AST pour garantir que le code continue de fonctionner après la déminification

  • La minification JS est mécanique et relativement simple. C’est fastidieux à faire manuellement, mais la transformation elle-même est limitée, donc on peut la lire en suivant les identifiants avec quelques notes

  • La déminification ou la désobfuscation générale reste un problème non résolu. J’ai déjà écrit par le passé des programmes volontairement obfusqués, et ChatGPT ne les comprenait pas, même à un niveau superficiel

    • Exemple : GPT-4 a tenté d’expliquer un interpréteur Brainfuck de 160 octets, mais le résultat ne ressemblait pas du tout au code d’origine
    • Lien vers le code d’exemple
  • Certains développeurs pourraient être mécontents, car ils utilisent la minification à des fins d’obfuscation. Dans d’anciennes versions de ColdFusion, l’outil de « chiffrement » de code reposait sur un algorithme faible, mais certaines personnes l’utilisaient quand même en pensant qu’il était sûr

  • Il serait peut-être plus approprié d’utiliser ChatGPT ou gpt-4 dans le titre plutôt qu’OpenAI

  • Ce travail est un exemple de performance intellectuelle supérieure à celle de l’humain. Les LLM comprennent la déminification et, sur ce sujet précis, ils sont meilleurs que les humains

  • Les LLM excellent dans la transformation de texte. C’est leur principale force

  • Il y a environ un an, j’ai essayé d’utiliser GPT pour désobfusquer un malware, mais analyser directement le code donnait de meilleurs résultats. En réessayant récemment, il a pu le comprendre dans une certaine mesure

    • Exemple : il a identifié la logique qui détecte le chargement de la page, effectue des calculs et redirige vers un site malveillant
    • Lien vers le rapport
  • Utiliser un LLM pour rendre du code complexe plus lisible est très libérateur. Il manque parfois des détails, mais on peut les vérifier soi-même

    • On peut comprendre l’objectif du code sans saisir pourquoi il a été écrit de cette manière, puis poser la question à un LLM pour obtenir de nouvelles pistes
    • Lien vers un exemple d’utilisation
  • Si le code déminifié ne correspond pas au code minifié, son utilité diminue fortement. Dans de nombreux cas, il est impossible de vérifier les différences après l’exécution du code

  • Quand on veut connaître l’algorithme de calcul d’un site web, il suffit souvent de coller le JS minifié dans ChatGPT pour le comprendre facilement. On peut imaginer un futur où les LLM pourront cloner une application SaaS entière

    • Exemple : pour créer un clone de HubSpot, un LLM pourrait interagir avec le navigateur, analyser l’UI et proposer une architecture backend
    • L’IA sera probablement un puissant facteur déflationniste à l’avenir