Alphabet JS obfuscated

Accueil Tags Recherche

18 Août 2021

Alphabet JS obfuscated

Petite excursion amusante dans le JS pour jouer avec les lettres

Là où tout a commencé

Le JavaScript est plein de ces petites surprises sur lesquelles on tombe tous un jour et qui nous font perdre pas mal de temps avant que l’on ne les comprenne. Il y a plusieurs mois, une séance de peer review m’a amené à découvrir un bug, avec à son origine un de ces petites surprises :

0.1 + 0.2
// 0.30000000000000004

Tout en rageant, discutant et râlant là-dessus, je retombe sur le génial et connu repository de WTFJS. N’hésitez pas à aller y faire un tour, c’est instructif et… inspirant…

C’est justement en parcourant cette liste que je tombe sur la perle suivante :

![]+[]
// "false"

Quelques notes avant d’aller plus loin :

  • L’opérande de gauche ![] est interprété comme false (car visiblement !Array() === false)
  • L’opérande de droite [] est un simple array
  • Utiliser l’opérateur + sur un booléen provoque l’appel de toString() sur l’opérande de droite

On a donc pour résumer et expliquer le résultat ces équivalences :

![]+[]
![] + []
!Array() + [].toString()
false + ""
"false"

Il y a une certaine logique derrière (très discutable) mais ce qui me frappe sur le moment, c’est qu’à partir de symboles uniquement (!+[]) on est capable de sortir une chaîne de caractères alphabétiques…

De A à Z

Une idée germe alors : est-on capable de faire un alphabet complet avec un charset restreint à quelques symboles ? Ce serait un excellent moyen d’obfuscate du JavaScript.

Spoiler : Internet. (aka. oui et je ne suis clairement pas le premier à y penser)

Pour commencer, nous aurons besoin de générer deux choses essentielles :

  • Des chaînes de caractères (pour extraire notre alphabet)
  • Des nombres (pour spécifier les indices)

L’idée étant de générer ce genre de code, sans les caractères alphanumériques :

"false"[1]
// a

Les nombres

Avant même de réfléchir au chaînes de caractères disponibles, nous devons être capables de générer des nombres. Il se trouve qu’on peut facilement caster un booléen en entier à l’aide de l’opérateur unaire + :

+false
// 0
+true
// 1

En reprenant le premier opérande de notre exemple (qui valait false je le rappelle) on peut donc avoir :

+![]
// 0
+!![]
// 1

À partir de là, nous allons pouvoir faire deux opérations selon les besoins : l’addition ou la concaténation :

+!![]+!![]
// 2
+!![]+[+!![]]
// 11

Plus de limites, nous pouvons désormais créer n’importe quel nombre grâce à ces deux techniques !

Les booléens

À présent que nous sommes capables d’extraire des caractères d’une chaînes, voyons ce que JavaScript nous propose. Les deux premiers exemples sont évidemment les valeurs booléennes vu précédemment :

![]
// false
!![]
// true

En englobant ces valeurs stringifiée (à l’aide de +[]), nous pouvons ainsi récupérer le énième caractère de chaque chaîne :

(![]+[])[+!![]]
// "a"
(!![]+[])[!![]+!![]+!![]]
(![]+[])[!![]+!![]+!![]+!![]]
// "e"
(![]+[])[+[]]
// "f"
(![]+[])[!![]+!![]]
// "l"
(!![]+[])[+!![]]
// "r"
(![]+[])[!![]+!![]+!![]]
// "s"
(!![]+[])[+[]]
// "t"
(!![]+[])[!![]+!![]]
// "u"

Pour le e nous préférerons l’extraire de la chaîne true car son indice y est plus petit (3) que dans false (4), cela demandera donc un peu moins de symboles.

D’autres chaînes

Avec ce que l’on connaît, on peut déjà facilement trouver deux chaînes supplémentaires. La première est undefined, que JS nous renverra si l’on essaie d’accéder à un indice non défini sur un tableau et qui nous offrirait les lettres d, i et n), or nous savons déjà créer des tableau et des nombres :

[][0]
// undefined
[][+[]]
// undefined
([][+[]]+[])[!![]+!![]]
// "d"
([][+[]]+[])[!![]+!![]+!![]+!![]+!![]]
// "i"
([][+[]]+[])[+!![]]
// "n"

De la même manière que nous avons utilisé toString() sur un tableau, on peut le faire sur un objet et récupérer une nouvelle chaîne avec les lettres b, c, j et o:

({}).toString()
// "[object Object]"
[]+{}
// "[object Object]"
([]+{})[!![]+!![]]
// "b"
([]+{})[!![]+!![]+!![]+!![]+!![]]
// "c"
([]+{})[!![]+!![]+!![]]
// "j"
([]+{})[+!![]]
// "o"

Les constructeurs

La suite de cet article est basé sur le travail de Mr. Papercut, sans lequel je n’aurais pas pu avancer plus loin, fautes de connaissances approfondies sur le JavaScript.

La propriété qui va nous intéresser pour la suite est le constructeur. Cette propriété est disponible sur toutes les variables en JS, et renvoie les résultats suivants :

(1).constructor
// ƒ Number() { [native code] }
"".constructor
// ƒ String() { [native code] }
/a/.constructor
// ƒ RegExp() { [native code] }
[].constructor
// ƒ Array() { [native code] }

On peut là aussi appeler la propriété avec la forme (1)["constructor"], et il se trouve que nous avons déjà toutes les lettres nécessaire !

([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]
// "constructor"

Et ainsi nous pouvons récupérer les lettres g, m, p, v, x et y

/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]
// ƒ RegExp() { [native code] }
[]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]
// "function RegExp() { [native code] }"
([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]
// "g"
([]+(+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]
// "m"
([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+([+!![]]+[+!![]+!![]+!![]+!![]])]
// "p"
([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+([+!![]+!![]]+[+!![]+!![]+!![]+!![]+!![]])]
// "v"
([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+([+!![]]+[+!![]+!![]+!![]])]
// "x"
([]+[][([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]+!![]+!![]]]
// "y"

Les bases

Pour les 5 lettres restantes, n’ayant pas trouvé de moyen de les récupérer via des chaînes, il va falloir ruser avec les bases. La base 36 utilise 36 caractères (les 10 chiffres plus l’alphabet complet), codant les nombres suivants ainsi :

  • 0 : 0
  • 1 : 1
  • 9 : 9
  • 10 : a
  • 35 : z

Le principe serait de transformer un nombre en sa représentation en base 36 :

(10).toString(36)
// "a"
(35).toString(36)
// "z"
(35)["toString"](36)
// "z"

Pour ce faire, nous aurons besoin des nombres et des lettres pour faire le mot toString. Nous avons déjà toutes les lettres sauf une : le S majuscule, mais qui pourra être récupérée à partir du constructeur d’une String :

[]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]
// "function String() { [native code] }"
([]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]
// S
(!![]+[])[+[]]+([]+{})[+!![]]+([]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([![]]+[][[]])[+!![]+[+[]]]+([][+[]]+[])[+!![]]+([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]
// toString
+(!![]+!![]+!![]+[!![]+!![]+!![]+!![]+!![]])
// 35
(+(+!![]+[!![]+!![]+!![]+!![]+!![]+!![]+!![]]))[(!![]+[])[+[]]+([]+{})[+!![]]+([]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([![]]+[][[]])[+!![]+[+[]]]+([][+[]]+[])[+!![]]+([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]](!![]+!![]+!![]+[!![]+!![]+!![]+!![]+!![]+!![]])
// "h"
(+(!![]+!![]+[+[]]))[(!![]+[])[+[]]+([]+{})[+!![]]+([]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([![]]+[][[]])[+!![]+[+[]]]+([][+[]]+[])[+!![]]+([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]](!![]+!![]+!![]+[!![]+!![]+!![]+!![]+!![]+!![]])
// "k"
(+(!![]+!![]+[!![]+!![]+!![]+!![]+!![]+!![]]))[(!![]+[])[+[]]+([]+{})[+!![]]+([]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([![]]+[][[]])[+!![]+[+[]]]+([][+[]]+[])[+!![]]+([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]](!![]+!![]+!![]+[!![]+!![]+!![]+!![]+!![]+!![]])
// "q"
(+(!![]+!![]+!![]+[!![]+!![]]))[(!![]+[])[+[]]+([]+{})[+!![]]+([]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([![]]+[][[]])[+!![]+[+[]]]+([][+[]]+[])[+!![]]+([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]](!![]+!![]+!![]+[!![]+!![]+!![]+!![]+!![]+!![]])
// "w"
(+(!![]+!![]+!![]+[!![]+!![]+!![]+!![]+!![]]))[(!![]+[])[+[]]+([]+{})[+!![]]+([]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([![]]+[][[]])[+!![]+[+[]]]+([][+[]]+[])[+!![]]+([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]](!![]+!![]+!![]+[!![]+!![]+!![]+!![]+!![]+!![]])
// "z"

Optimisations

Bon, c’est bien tout ça mais c’est très verbeux, avec plus de 5000 symboles pour représenter tout l’alphabet ! Quelques optimisations sont possibles ici et là.

La première concerne les lettre h, k et w, qui peuvent aussi s’écrire dans d’autres bases que la base 36. Leurs indices respectifs dans cette base sont 17, 20 et 32 ; il faut prendre en compte que le nombre 36 et ces indices sont assez long à écrire. En jouant avec les différentes bases, les manières les plus courtes d’écrire ces trois lettres sont les suivantes :

(101).toString(21)[1]
(+(+!![]+[+[]]+[+!![]]))[(!![]+[])[+[]]+([]+{})[+!![]]+([]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([![]]+[][[]])[+!![]+[+[]]]+([][+[]]+[])[+!![]]+([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]](!![]+!![]+[+!![]])[+!![]]
// "h"
(20).toString(21)
(+(!![]+!![]+[+[]]))[(!![]+[])[+[]]+([]+{})[+!![]]+([]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([![]]+[][[]])[+!![]+[+[]]]+([][+[]]+[])[+!![]]+([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]](!![]+!![]+[+!![]])
// "k"
(32).toString(33)
(+(!![]+!![]+!![]+[!![]+!![]]))[(!![]+[])[+[]]+([]+{})[+!![]]+([]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([![]]+[][[]])[+!![]+[+[]]]+([][+[]]+[])[+!![]]+([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]](!![]+!![]+!![]+[!![]+!![]+!![]])
// "w"

On gagne ainsi respectivement 45, 29 et 29 symboles pour écrire l’alphabet.

Pour la lettre i (basée sur undefined), le trick est qu’il est beaucoup plus rapide d’écrire 11 que 6 (pour gagner 11 symboles) :

"undefined"[6]
"falseundefined"[11]
// n
!![]+!![]+!![]+!![]+!![]
// 6
+!![]+[+[]]
// 11
[![]]+[][[]]
// "falseundefined"
([![]]+[][[]])[+!![]+[+[]]]
// n

Pour la lettre y, plutôt que de passer par le constructeur Array on peut jouer avec Infinity pour gagner 177 symboles. Là aussi on va aller modifier la chaîne pour chercher l’indice 10 (plus rapide à écrire que l’indice 7)

1e1000
// Infinity
+!![]+(!![]+[])[!![]+!![]+!![]]+[+!![]]+[+[]]+[+[]]+[+[]]
// "1e1000"
+(+!![]+(!![]+[])[!![]+!![]+!![]]+[+!![]]+[+[]]+[+[]]+[+[]])+[]
// "Infinity"
(+(+!![]+(!![]+[])[!![]+!![]+!![]]+[+!![]]+[+[]]+[+[]]+[+[]])+[])[!![]+!![]+!![]+!![]+!![]+!![]+!![]]
// "y"
+[![]]+[+(+!![]+(!![]+[])[!![]+!![]+!![]]+[+!![]]+[+[]]+[+[]]+[+[]])]
// "NaNInfinity
(+[![]]+[+(+!![]+(!![]+[])[!![]+!![]+!![]]+[+!![]]+[+[]]+[+[]]+[+[]])])[+!![]+[+[]]]
// "y"

Avec ces optimisation, on réduit la taille de l’alphabet d’environ 5%. Il doit probablement en exister bien d’autres, toutes aussi intéressantes à découvrir les unes que les autres, n’hésitez pas à m’en faire part si vous en découvrez !

Pour finir

Voici un récapitulatif de l’ensemble de l’alphabet, avec leurs optimisations et l’espace en bonus pour pouvoir écrire ce que vous voulez :

/*   */ ([]+{})[!![]+!![]+!![]+!![]+!![]+!![]+!![]]
/* a */ (![]+[])[+!![]]
/* b */ ([]+{})[!![]+!![]]
/* c */ ([]+{})[!![]+!![]+!![]+!![]+!![]]
/* d */ ([][+[]]+[])[!![]+!![]]
/* e */ ([][+[]]+[])[!![]+!![]+!![]]
/* f */ (![]+[])[+[]]
/* g */ ([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]
/* h */ (+(+!![]+[+[]]+[+!![]]))[(!![]+[])[+[]]+([]+{})[+!![]]+([]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([![]]+[][[]])[+!![]+[+[]]]+([][+[]]+[])[+!![]]+([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]](!![]+!![]+[+!![]])[+!![]]
/* i */ ([![]]+[][[]])[+!![]+[+[]]]
/* j */ ([]+{})[!![]+!![]+!![]]
/* k */ (+(!![]+!![]+[+[]]))[(!![]+[])[+[]]+([]+{})[+!![]]+([]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([![]]+[][[]])[+!![]+[+[]]]+([][+[]]+[])[+!![]]+([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]](!![]+!![]+[+!![]])
/* l */ (![]+[])[!![]+!![]]
/* m */ ([]+(+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]
/* n */ ([][+[]]+[])[+!![]]
/* o */ ([]+{})[+!![]]
/* p */ ([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+([+!![]]+[+!![]+!![]+!![]+!![]])]
/* q */ (+(!![]+!![]+[!![]+!![]+!![]+!![]+!![]+!![]]))[(!![]+[])[+[]]+([]+{})[+!![]]+([]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([![]]+[][[]])[+!![]+[+[]]]+([][+[]]+[])[+!![]]+([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]](!![]+!![]+!![]+[!![]+!![]+!![]+!![]+!![]+!![]])
/* r */ (!![]+[])[+!![]]
/* s */ (![]+[])[!![]+!![]+!![]]
/* t */ (!![]+[])[+[]]
/* u */ (!![]+[])[!![]+!![]]
/* v */ ([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+([+!![]+!![]]+[+!![]+!![]+!![]+!![]+!![]])]
/* w */ (+(!![]+!![]+!![]+[!![]+!![]]))[(!![]+[])[+[]]+([]+{})[+!![]]+([]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([![]]+[][[]])[+!![]+[+[]]]+([][+[]]+[])[+!![]]+([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]](!![]+!![]+!![]+[!![]+!![]+!![]])
/* x */ ([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+([+!![]]+[+!![]+!![]+!![]])]
/* y */ (+[![]]+[+(+!![]+(!![]+[])[!![]+!![]+!![]]+[+!![]]+[+[]]+[+[]]+[+[]])])[+!![]+[+[]]]
/* z */ (+(!![]+!![]+!![]+[!![]+!![]+!![]+!![]+!![]]))[(!![]+[])[+[]]+([]+{})[+!![]]+([]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([![]]+[][[]])[+!![]+[+[]]]+([][+[]]+[])[+!![]]+([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]](!![]+!![]+!![]+[!![]+!![]+!![]+!![]+!![]+!![]])

Avec l’exemple obligatoire ci-dessous :

(+(+!![]+[+[]]+[+!![]]))[(!![]+[])[+[]]+([]+{})[+!![]]+([]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([![]]+[][[]])[+!![]+[+[]]]+([][+[]]+[])[+!![]]+([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]](!![]+!![]+[+!![]])[+!![]]+([][+[]]+[])[!![]+!![]+!![]]+(![]+[])[!![]+!![]]+(![]+[])[!![]+!![]]+([]+{})[+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(+(!![]+!![]+!![]+[!![]+!![]]))[(!![]+[])[+[]]+([]+{})[+!![]]+([]+([]+[])[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([![]]+[][[]])[+!![]+[+[]]]+([][+[]]+[])[+!![]]+([]+/!/[([]+{})[!![]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+(!![]+[])[!![]+!![]]+([]+{})[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]])[+!![]+[+!![]]]](!![]+!![]+!![]+[!![]+!![]+!![]])+([]+{})[+!![]]+(!![]+[])[+!![]]+(![]+[])[!![]+!![]]+([][+[]]+[])[!![]+!![]]
// hello world

Liens :

WTFJS Un article similaire de Mr. Papercut