Actuellement jsfuck utilise le code suivant pour obtenir le caractère "C"

console.log(
    Function("return escape")()(("")["italics"]())[2],
)
   
console.log(  // after expansion
    []["flat"]["constructor"]("return escape")()(([]+[])["italics"]())[!![]+!![]]
)

console.log(  // after final strings expansion we get pure jsfuck code
    [][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]][[]+([]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[!![]+!![]+!![]]+(!![]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[[]+(+!![])+(+[])]+([]+[][[]])[+!![]]+([]+![])[!![]+!![]+!![]]+([]+!![])[+![]]+([]+!![])[+!![]]+([]+!![])[!![]+!![]]+([]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[!![]+!![]+!![]]+([]+!![])[+![]]+(!![]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[[]+(+!![])+(+[])]+([]+!![])[+!![]]]([]+([]+!![])[+!![]]+([]+!![])[!![]+!![]+!![]]+([]+!![])[+![]]+([]+!![])[!![]+!![]]+([]+!![])[+!![]]+([]+[][[]])[+!![]]+(+[![]]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[+([]+(+!![])+(+!![]))]+([]+!![])[!![]+!![]+!![]]+([]+![])[!![]+!![]+!![]]+([]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[!![]+!![]+!![]]+([]+![])[+!![]]+(+([]+(!![]+!![])+(!![]+!![]+!![]+!![]+!![])))[[]+([]+!![])[+![]]+(!![]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[[]+(+!![])+(+[])]+([]+[])[[]+([]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[!![]+!![]+!![]]+(!![]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[[]+(+!![])+(+[])]+([]+[][[]])[+!![]]+([]+![])[!![]+!![]+!![]]+([]+!![])[+![]]+([]+!![])[+!![]]+([]+!![])[!![]+!![]]+([]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[!![]+!![]+!![]]+([]+!![])[+![]]+(!![]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[[]+(+!![])+(+[])]+([]+!![])[+!![]]][[]+([]+[][[]])[+!![]]+([]+![])[+!![]]+((+[])[[]+([]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[!![]+!![]+!![]]+(!![]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[[]+(+!![])+(+[])]+([]+[][[]])[+!![]]+([]+![])[!![]+!![]+!![]]+([]+!![])[+![]]+([]+!![])[+!![]]+([]+!![])[!![]+!![]]+([]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[!![]+!![]+!![]]+([]+!![])[+![]]+(!![]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[[]+(+!![])+(+[])]+([]+!![])[+!![]]]+[])[[]+(+!![])+(+!![])]+([]+!![])[!![]+!![]+!![]]]](+([]+(!![]+!![]+!![])+(+[])))+([]+!![])[!![]+!![]+!![]])()(([]+[])[[]+([]+[][[]])[!![]+!![]+!![]+!![]+!![]]+([]+!![])[+![]]+([]+![])[+!![]]+([]+![])[!![]+!![]]+([]+[][[]])[!![]+!![]+!![]+!![]+!![]]+([]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[!![]+!![]+!![]]+([]+![])[!![]+!![]+!![]]]())[!![]+!![]]
)

Mais cette méthode utilise une fonction obsolète "".italics (info ici). Je développe un petit outil et j'essaie de trouver une alternative basée sur btoa mais j'ai découvert avec tristesse que cela n'est pas pris en charge par node.js (en ligne)

console.log(
  Function("return btoa")()("t.")[1]
)

console.log( // after expansion
  []["flat"]["constructor"]("return btoa")()("t.")[+!![]]
)

console.log( // after full expansion
  [][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]][[]+([]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[!![]+!![]+!![]]+(!![]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[[]+(+!![])+(+[])]+([]+[][[]])[+!![]]+([]+![])[!![]+!![]+!![]]+([]+!![])[+![]]+([]+!![])[+!![]]+([]+!![])[!![]+!![]]+([]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[!![]+!![]+!![]]+([]+!![])[+![]]+(!![]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[[]+(+!![])+(+[])]+([]+!![])[+!![]]]([]+([]+!![])[+!![]]+([]+!![])[!![]+!![]+!![]]+([]+!![])[+![]]+([]+!![])[!![]+!![]]+([]+!![])[+!![]]+([]+[][[]])[+!![]]+(+[![]]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[+([]+(+!![])+(+!![]))]+([][[]+([]+!![])[!![]+!![]+!![]]+([]+[][[]])[+!![]]+([]+!![])[+![]]+([]+!![])[+!![]]+([]+[][[]])[!![]+!![]+!![]+!![]+!![]]+([]+!![])[!![]+!![]+!![]]+([]+![])[!![]+!![]+!![]]]()+[])[!![]+!![]]+([]+!![])[+![]]+(!![]+[][[]+([]+![])[+[]]+([]+![])[!![]+!![]]+([]+![])[+!![]]+([]+!![])[+![]]])[[]+(+!![])+(+[])]+([]+![])[+!![]])()([]+([]+!![])[+![]]+(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]])[+!![]]
)

Existe-t-il un moyen (en travaillant sur les versions actuelles de chrome, safari, firefox et node.js) pour obtenir le caractère "C" en utilisant jsfuck mais sans utiliser de méthodes obsolètes?

6
Kamil Kiełczewski 31 août 2020 à 18:22

5 réponses

Meilleure réponse

Le fait que escape soit semi-obsolète ne cessait de me déranger, alors j'ai tenté une autre tentative. Reconstruisons JSFuck à partir de zéro.

Niveau 0

Vous pouvez obtenir les valeurs suivantes en tant que primitives:

false           ![]
true            !![]
undefined       [][[]]
NaN             +[![]]
""              []+[]
0               +[]
1               +!+[]
2               +!+[]+!+[]
3               +!+[]+!+[]+!+[]
4               +!+[]+!+[]+!+[]+!+[]
5               +!+[]+!+[]+!+[]+!+[]+!+[]
6               +!+[]+!+[]+!+[]+!+[]+!+[]+!+[]
7               +!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]
8               +!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]
9               +!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]

Niveau 1

Avec les valeurs ci-dessus et le fait que value+[] se convertit en chaîne, nous pouvons définir les règles de substitution de caractères suivantes:

"0"             0+[]
"1"             1+[]
"2"             2+[]
"3"             3+[]
"4"             4+[]
"5"             5+[]
"6"             6+[]
"7"             7+[]
"8"             8+[]
"9"             9+[]
"a"             (false+[])[1]
"d"             (undefined+[])[2]
"e"             (true+[])[3]
"f"             (false+[])[0]
"i"             ([false]+undefined)[1+[0]]
"l"             (false+[])[2]
"n"             (undefined+[])[1]
"r"             (true+[])[1]
"s"             (false+[])[3]
"t"             (true+[])[0]
"u"             (undefined+[])[0]
"N"             (NaN+[])[0]

Niveau 2

Avec les caractères ci-dessus, nous pouvons construire ces quatre chaînes:

"11e100"        +!+[]+[+!+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]]
"1e1000"        +!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]]+[+[]]
"flat"          (![]+[])[+[]]+(![]+[])[+!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]
"entries"       (true+[])[3]+(undefined+[])[1]+(true+[])[0]+(true+[])[1]+([false]+undefined)[1+[0]]+(true+[])[3]+(false+[])[3]

Avec lequel nous pouvons obtenir trois valeurs supplémentaires:

1.1e+101                +("11e100")
Infinity                +("1e1000")
Array Iterator          []["entries"]()
Array.prototype.flat    []["flat"]

Le dernier est particulièrement utile, car lorsqu'il est converti en chaîne, il donne ceci:

"function flat() {\n    [native code]\n}"

Ou ca:

"function flat() { [native code] }"

C'est un peu bizarre de travailler avec, mais les caractères jusqu'à et y compris le { sont toujours les mêmes, tout comme le dernier caractère.

Array Iterator se convertira en quelque chose de plus stable:

"[object Array Iterator]"

Cela nous donne plus de personnages avec lesquels travailler:

" "             ([false]+[]["flat"])[2+[0]]
"("             ([]+[]["flat"])[1+[3]]
")"             ([]+[]["flat"])[1+[4]]
"+"             (+("11e100")+[])[4]
"."             (+("11e100")+[])[1]
"["             ([]+[]["entries"]())[0]
"]"             ([]+[]["entries"]())[2+[2]]
"{"             ([true]+[]["flat"])[2+[0]]
"c"             ([]["flat"]+[])[3]
"j"             ([]+[]["entries"]())[3]
"o"             ([true]+[]["flat"])[1+[0]]
"y"             (true+[Infinity])[1+[1]]
"A"             ([NaN]+([]+[]["entries"]()))[1+[1]]
"I"             (Infinity+[])[0]

Niveau 3

En combinant des caractères et des valeurs de niveau 1 et 2, nous pouvons désormais créer trois nouvelles chaînes:

".0000001"      (+("11e100")+[])[1]+[0]+[0]+[0]+[0]+[0]+[0]+[1]
"constructor"   ([]["flat"]+[])[3]+([true]+[]["flat"])[1+[0]]+(undefined+[])[1]+(false+[])[3]+(true+[])[0]+(true+[])[1]+(undefined+[])[0]+([]["flat"]+[])[3]+(true+[])[0]+([true]+[]["flat"])[1+[0]]+(true+[])[1]

Et cela nous donne accès à un tas d'autres valeurs:

1e-7            +(".0000001")
Boolean         (![])["constructor"]
Number          (+[])["constructor"]
String          ([]+[])["constructor"]
Function        []["flat"]["constructor"]

En convertissant en chaînes, nous obtenons encore plus de caractères:

"-"             (+(".0000001")+[])[2]
"b"             ([]+(+[])["constructor"])[1+[2]]
"g"             (false+[0]+([]+[])["constructor"])[2+[0]]
"m"             ([]+(+[])["constructor"])[1+[1]]
"B"             ([NaN]+(![])["constructor"])[1+[2]]
"F"             ([NaN]+[]["flat"]["constructor"])[1+[2]]
"S"             ([NaN]+([]+[])["constructor"])[1+[2]]

Niveau 4

Étant donné la majuscule S, nous pourrions maintenant construire la chaîne "toString manuellement. Cependant, si nous construisons d'abord la chaîne "name", nous pouvons obtenir un code global plus court:

"name"         (undefined+[])[1]+(false+[])[1]+([]+(+[])["constructor"])[1+[1]]+(true+[])[3]
"toString"     (true+[])[0]+([true]+[]["flat"])[1+[0]]+([]+[])["constructor"]["name"]

Et avec cela, nous pouvons appeler Number.toString(), en nous donnant toutes les lettres minuscules restantes:

"h"             (+(1+[0]+[1]))["toString"](2+[1])[1]
"k"             (+(2+[0]))["toString"](2+[1])
"p"             (+(2+[1]+[1]))["toString"](3+[1])[1]
"q"             (+(2+[1]+[2]))["toString"](3+[1])[1]
"v"             (+(3+[1]))["toString"](3+[2])
"w"             (+(3+[2]))["toString"](3+[3])
"x"             (+(1+[0]+[1]))["toString"](3+[4])[1]
"z"             (+(3+[5]))["toString"](3+[6])

En même temps, nous pouvons construire deux autres chaînes:

"slice"         (false+[])[3]+(false+[])[2]+([false]+undefined)[1+[0]]+([]["flat"]+[])[3]+(true+[])[3]
"-1"            (+(".0000001")+[])[2]+[+!+[]]

Et cela nous donne un dernier personnage dont nous avons besoin pour le niveau suivant:

"}"             ([true]+[]["flat"])["slice"]("-1")

Niveau 5

À ce stade, il y a une primitive que nous avons obtenue que nous n'avons pas encore utilisée: en utilisant Function comme primitive eval:

[]["flat"]["constructor"](...)()

Puisque nous avons maintenant toutes les lettres minuscules ainsi que l'espace, +, ., [, ], { et }, nous pouvons construire:

"try{String().normalize(false)}catch(f){return f}"

Au moyen de:

(true+[])[0]+(true+[])[1]+(true+[Infinity])[1+[1]]+([true]+[]["flat"])[2+[0]]+([]+[])["constructor"]["name"]+([]+[]["flat"])[1+[3]]+([]+[]["flat"])[1+[4]]+(+("11e100")+[])[1]+(undefined+[])[1]+([true]+[]["flat"])[1+[0]]+(true+[])[1]+([]+(+[])["constructor"])[1+[1]]+(false+[])[1]+(false+[])[2]+([false]+undefined)[1+[0]]+(+(3+[5]))["toString"](3+[6])+(true+[])[3]+([]+[]["flat"])[1+[3]]+![]+([]+[]["flat"])[1+[4]]+([true]+[]["flat"])["slice"]("-1")+([]["flat"]+[])[3]+(false+[])[1]+(true+[])[0]+([]["flat"]+[])[3]+(+(1+[0]+[1]))["toString"](2+[1])[1]+([]+[]["flat"])[1+[3]]+(false+[])[0]+([]+[]["flat"])[1+[4]]+([true]+[]["flat"])[2+[0]]+(true+[])[1]+(true+[])[3]+(true+[])[0]+(undefined+[])[0]+(true+[])[1]+(undefined+[])[1]+([false]+[]["flat"])[2+[0]]+(false+[])[0]+([true]+[]["flat"])["slice"]("-1")

Appeler String.prototype.normalize() avec une valeur qui n'est pas un formulaire de normalisation Unicode valide lèvera un RangeError, que nous attrapons et renvoyons à l'appelant. On a ainsi:

RangeError      []["flat"]["constructor"]("try{String().normalize(false)}catch(f){return f}")()

Notez que ce qui précède est une instance - nous devrions utiliser ["constructor"] pour obtenir la fonction / constructeur, mais nous pouvons simplement le convertir en chaîne tel quel, en nous donnant deux lettres majuscules supplémentaires:

"E"             ([false]+[]["flat"]["constructor"]("try{String().normalize(false)}catch(f){return f}")())[1+[0]]
"R"             ([]+[]["flat"]["constructor"]("try{String().normalize(false)}catch(f){return f}")())[0]

Niveau 6

Avec deux autres personnages déverrouillés, nous pouvons maintenant construire cette chaîne:

"return RegExp" (true+[])[1]+(true+[])[3]+(true+[])[0]+(undefined+[])[0]+(true+[])[1]+(undefined+[])[1]+([false]+[]["flat"])[2+[0]]+([]+[]["flat"]["constructor"]("try{String().normalize(false)}catch(f){return f}")())[0]+(true+[])[3]+(false+[0]+([]+[])["constructor"])[2+[0]]+([false]+[]["flat"]["constructor"]("try{String().normalize(false)}catch(f){return f}")())[1+[0]]+(+(1+[0]+[1]))["toString"](3+[4])[1]+(+(2+[1]+[1]))["toString"](3+[1])[1]

Et cela nous donne une nouvelle valeur / fonction:

RegExp          []["flat"]["constructor"]("return RegExp")()

Lorsqu'il est invoqué sans argument et en convertissant le RegExp résultant en chaîne, nous obtenons:

"/(?:)/"        []+[]["flat"]["constructor"]("return RegExp")()()

Nous avons donc un tas de nouveaux caractères spéciaux:

"/"             ([]+[]["flat"]["constructor"]("return RegExp")()())[0]
":"             ([]+[]["flat"]["constructor"]("return RegExp")()())[3]
"?"             ([]+[]["flat"]["constructor"]("return RegExp")()())[2]

Niveau 7

Maintenant, nous renvoyons l'un de ces caractères dans l'expression régulière pour obtenir une nouvelle chaîne:

"/\\//"         []+RegExp("/")

Cela nous donne accès à un seul nouveau personnage:

"\\"            ([]+RegExp("/"))[1]

Niveau 8

Construisons une nouvelle chaîne:

"try{Function([]+[[]].concat([[]]))()}catch(f){return f}"

Par:

(true+[])[0]+(true+[])[1]+(true+[Infinity])[1+[1]]+([true]+[]["flat"])[2+[0]]+[]["flat"]["constructor"]["name"]+([]+[]["flat"])[1+[3]]+([]+[]["entries"]())[0]+([]+[]["entries"]())[2+[2]]+(+("11e100")+[])[4]+([]+[]["entries"]())[0]+([]+[]["entries"]())[0]+([]+[]["entries"]())[2+[2]]+([]+[]["entries"]())[2+[2]]+(+("11e100")+[])[1]+([]["flat"]+[])[3]+([true]+[]["flat"])[1+[0]]+(undefined+[])[1]+([]["flat"]+[])[3]+(false+[])[1]+(true+[])[0]+([]+[]["flat"])[1+[3]]+([]+[]["entries"]())[0]+([]+[]["entries"]())[0]+([]+[]["entries"]())[2+[2]]+([]+[]["entries"]())[2+[2]]+([]+[]["flat"])[1+[4]]+([]+[]["flat"])[1+[4]]+([]+[]["flat"])[1+[3]]+([]+[]["flat"])[1+[4]]+([true]+[]["flat"])["slice"]("-1")+([]["flat"]+[])[3]+(false+[])[1]+(true+[])[0]+([]["flat"]+[])[3]+(+(1+[0]+[1]))["toString"](2+[1])[1]+([]+[]["flat"])[1+[3]]+(false+[])[0]+([]+[]["flat"])[1+[4]]+([true]+[]["flat"])[2+[0]]+(true+[])[1]+(true+[])[3]+(true+[])[0]+(undefined+[])[0]+(true+[])[1]+(undefined+[])[1]+([false]+[]["flat"])[2+[0]]+(false+[])[0]+([true]+[]["flat"])["slice"]("-1")

Cela équivaut à:

"try{Function(',')()}catch(f){return f}"

Sauf que nous ne pouvons pas (encore) écrire ','. L'évaluation qui renverra un objet SyntaxError, qui, une fois converti en chaîne, produira:

"SyntaxError: Unexpected token ','"

Nous pouvons ensuite insérer cette chaîne dans RegExp("[\u0027]").exec(...)[0] pour extraire le guillemet simple.
Alors on veut courir:

RegExp("[\u0027]").exec(Function("try{Function([]+[[]].concat([[]]))()}catch(f){return f}")())[0]

En appliquant tout un tas de substitutions d'en haut, nous obtenons un dernier caractère:

"'"             RegExp(([]+[]["entries"]())[0]+([]+RegExp("/"))[1]+(undefined+[])[0]+[+[]]+[+[]]+[+!+[]+!+[]]+[+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([]+[]["entries"]())[2+[2]])[(true+[])[3]+(+(1+[0]+[1]))["toString"](3+[4])[1]+(true+[])[3]+([]["flat"]+[])[3]]([]["flat"]["constructor"]((true+[])[0]+(true+[])[1]+(true+[Infinity])[1+[1]]+([true]+[]["flat"])[2+[0]]+[]["flat"]["constructor"]["name"]+([]+[]["flat"])[1+[3]]+([]+[]["entries"]())[0]+([]+[]["entries"]())[2+[2]]+(+("11e100")+[])[4]+([]+[]["entries"]())[0]+([]+[]["entries"]())[0]+([]+[]["entries"]())[2+[2]]+([]+[]["entries"]())[2+[2]]+(+("11e100")+[])[1]+([]["flat"]+[])[3]+([true]+[]["flat"])[1+[0]]+(undefined+[])[1]+([]["flat"]+[])[3]+(false+[])[1]+(true+[])[0]+([]+[]["flat"])[1+[3]]+([]+[]["entries"]())[0]+([]+[]["entries"]())[0]+([]+[]["entries"]())[2+[2]]+([]+[]["entries"]())[2+[2]]+([]+[]["flat"])[1+[4]]+([]+[]["flat"])[1+[4]]+([]+[]["flat"])[1+[3]]+([]+[]["flat"])[1+[4]]+([true]+[]["flat"])["slice"]("-1")+([]["flat"]+[])[3]+(false+[])[1]+(true+[])[0]+([]["flat"]+[])[3]+(+(1+[0]+[1]))["toString"](2+[1])[1]+([]+[]["flat"])[1+[3]]+(false+[])[0]+([]+[]["flat"])[1+[4]]+([true]+[]["flat"])[2+[0]]+(true+[])[1]+(true+[])[3]+(true+[])[0]+(undefined+[])[0]+(true+[])[1]+(undefined+[])[1]+([false]+[]["flat"])[2+[0]]+(false+[])[0]+([true]+[]["flat"])["slice"]("-1"))())[0]

Niveau 9

À ce stade, nous pouvons renvoyer chaque caractère que nous voulons simplement en faisant:

Function("return '\uXXXX'")()

Démo

Prenons le caractère "C" de votre question:

Function("return '\u0043'")()

L'exécution de toutes les substitutions ci-dessus produit un cauchemar absolu de 167'060 octets. Cela dépasse la longueur maximale du message sur SO,

Siguza 2 sept. 2020 à 21:49

Ici, je développe réponse Siguza si nous utilisons de / encodeURI non obsolète (niveau 5) que nous avons

console.log(
  decodeURI(encodeURI(" ")[0]+"43"),
  (NaN+[]["entries"]()["to"+String["name"]]["call"]())[11] // here is for U came from
)
2
Kamil Kiełczewski 11 sept. 2020 à 11:40

L'approche entière dépend de escape("<"), ce qui donne "%3C". Nous pouvons facilement remplacer cela par escape(","), ce qui nous donne "%2C". JSFuck a déjà un moyen d'obtenir ",": [[]]["concat"]([[]])+[]

escape(",")[2]

Devient

Function("return escape")()(",")[2]

Devient

[]["flat"]["constructor"]("return escape")()([[]]["concat"]([[]])+[])[2]

Devient

[]["f"+"l"+"a"+"t"]["c"+"o"+"n"+"s"+"t"+"r"+"u"+"c"+"t"+"o"+"r"]("r"+"e"+"t"+"u"+"r"+"n"+" "+"e"+"s"+"c"+"a"+"p"+"e")()([[]]["c"+"o"+"n"+"c"+"a"+"t"]([[]])+[])[2]

Devient

[][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]][([][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]]+[])[!+[]+!+[]+!+[]]+([][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]]+[])[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([]+[][[]])[+!+[]]+([]+![])[!+[]+!+[]+!+[]]+([]+!![])[+[]]+([]+!![])[+!+[]]+([]+[][[]])[+[]]+([][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]]+[])[!+[]+!+[]+!+[]]+([]+!![])[+[]]+([][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]]+[])[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([]+!![])[+!+[]]](([]+!![])[+!+[]]+([]+!![])[!+[]+!+[]+!+[]]+([]+!![])[+[]]+([]+[][[]])[+[]]+([]+!![])[+!+[]]+([]+[][[]])[+!+[]]+([]+[][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]])[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([]+!![])[!+[]+!+[]+!+[]]+([]+![])[!+[]+!+[]+!+[]]+([][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]]+[])[!+[]+!+[]+!+[]]+([]+![])[+!+[]]+(+([]+(+!+[]+!+[])+(+!+[])+(+!+[])))[([]+!+[])[+[]]+([]+[][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]])[+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([]+([]+[])[([][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]]+[])[!+[]+!+[]+!+[]]+([][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]]+[])[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([]+[][[]])[+!+[]]+([]+![])[!+[]+!+[]+!+[]]+([]+!![])[+[]]+([]+!![])[+!+[]]+([]+[][[]])[+[]]+([][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]]+[])[!+[]+!+[]+!+[]]+([]+!![])[+[]]+([][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]]+[])[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([]+!![])[+!+[]]])[+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([]+!+[])[+[]]+([]+!+[])[+!+[]]+([]+[][[]])[+!+[]+!+[]+!+[]+!+[]+!+[]]+([]+[][[]])[+!+[]]+([]+([]+[])[([][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]]+[])[!+[]+!+[]+!+[]]+([][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]]+[])[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([]+[][[]])[+!+[]]+([]+![])[!+[]+!+[]+!+[]]+([]+!![])[+[]]+([]+!![])[+!+[]]+([]+[][[]])[+[]]+([][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]]+[])[!+[]+!+[]+!+[]]+([]+!![])[+[]]+([][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]]+[])[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([]+!![])[+!+[]]])[[]+(+!+[])+(+!+[]+!+[]+!+[]+!+[])]]([]+(+!+[]+!+[]+!+[])+(+!+[]))[+!+[]]+([]+!![])[!+[]+!+[]+!+[]])()([[]][([][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]]+[])[!+[]+!+[]+!+[]]+([][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]]+[])[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([]+[][[]])[+!+[]]+([][([]+![])[+[]]+([]+![])[!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]]+[])[!+[]+!+[]+!+[]]+([]+![])[+!+[]]+([]+!![])[+[]]]([[]])+[])[!+[]+!+[]]

Je l'ai fait manuellement, donc ce n'est peut-être pas la représentation optimale / la plus courte.

1
Siguza 31 août 2020 à 17:06

Solution JS de bas niveau

C'est une alternative à cette réponse (j'utilise l'idée matchAll à partir de là à l'étape intermédiaire). Idée principale pour générer le caractère C (et plus) en utilisant du code char mais sans utiliser de guillemets - c'est possible lorsque nous définissons le champ objet:

console.log(
  Function("return Object.entries({\\u0043:false})")()[0][0]
)

Pour transformer cette solution proche de jsf j'utilise les "helpers" suivants

console.log(
  // "(" left parenthesis: 
  ([]["flat"]+"")[13], 
  
  // ")" right parenthesis:
  ([0]+false+[]["flat"])[20],
  
  // "{" left brace:
  (true+[]["flat"])[20],
  
  // "}" right brace:
  ([]["flat"]+"")["slice"]("-1"),
  
  // "+" plus
  (+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]])+[])[2],
  
  // "-" minus:
  (+((+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+[+[]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+!+[]]])+[])[!+[]+!+[]],
  
  // " " space:
  (NaN+[]["flat"])[11],
  
  // "." dot:
  (+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]],
  
  // "RegExp" string: (""+"".matchAll()).split(" ")[1]
  ([]+("")["matchAll"]())["split"](" ")[1],

  // ":" - colon: (Function("return RegExp")()()+"")[3]
  ([]["flat"]["constructor"]("return "+([]+("")["matchAll"]())["split"](" ")[1])()()+[])[3],

  // "/" - slash: (Function("return RegExp")()()+"")[0]
  ([]["flat"]["constructor"]("return "+([]+("")["matchAll"]())["split"](" ")[1])()()+[])[0], 
    
  // "\" - backslash: (Function("return RegExp(RegExp()+[])")()+[])[1]
  // (Function(("return "+false+"("+false+"()+[])").split(false).join("RegExp"))()+[])[1]
  ([]["flat"]["constructor"](("return "+false+"("+false+"()+[])")["split"](false)["join"](([]+("")["matchAll"]())["split"](" ")[1]))()+[])[1],
)

Enfin, nous avons (après le décodage complet, il aura ~ 16k caractères jsf)

// step 1
console.log(
  []["flat"]["constructor"]("return"+" "+"Object"+"."+"entries"+"("+"{"+"\\"+"u0043"+":"+false+"}"+")")()[0][0]
)

// step 2
console.log(
  []["flat"]["constructor"]("return"+" "+"Object"+"."+"entries"+([]["flat"]+"")[13]+(true+[]["flat"])[20]+([]["flat"]["constructor"](("return "+false+"("+false+"()+[])")["split"](false)["join"](([]+("")["matchAll"]())["split"](" ")[1]))()+[])[1]+"u0043"+":"+false+([]["flat"]+"")["slice"]("-1")+([0]+false+[]["flat"])[20])()[0][0]
)

Pour ce faire, nous restons au niveau 3 selon la réponse Siguza

1
Kamil Kiełczewski 13 sept. 2020 à 21:03

Ceci est le développement de ma précédente réponse - voici l'astuce qui permet d'obtenir la chaîne RegExp (mais nous utilisons lettre R ici) sans lever d'exception (!) - (nous sommes donc au niveau 4 selon Siguza noation)

// TRICK:
console.log(
  (""+"".matchAll(""))   // 1. this gives "...RegExp..."
)


// encode/decode URI strings
console.log(
  "encode"+(NaN+[]["entries"]()["to"+String["name"]]["call"]())[11]+(NaN+""["matchAll"](""))[11]+([]+(+"1e1000"))[0],
  
  "decode"+(NaN+[]["entries"]()["to"+String["name"]]["call"]())[11]+(NaN+""["matchAll"](""))[11]+([]+(+"1e1000"))[0]
)



// Final formula
console.log(
  decodeURI(encodeURI(" ")[0]+"43")
)

Et formule finale élargie

// JSF (with allowed strings and numbers and NaN)
console.log(
  []["flat"]["constructor"]("return "+"decode"+(NaN+[]["entries"]()["to"+([]+[])["constructor"]["name"]]["call"]())[11]+(NaN+""["matchAll"](""))[11]+([]+(+"1e1000"))[0])()([]["flat"]["constructor"]("return "+"encode"+(NaN+[]["entries"]()["to"+([]+[])["constructor"]["name"]]["call"]())[11]+(NaN+""["matchAll"](""))[11]+([]+(+"1e1000"))[0])()((NaN+[]["flat"])[11])[0]+43)
)
0
Kamil Kiełczewski 11 sept. 2020 à 19:15