From 3d68105b2cac175a917f6c235e33e52e510e47da Mon Sep 17 00:00:00 2001 From: Alex Zaytsev Date: Wed, 2 Sep 2020 14:29:31 +1200 Subject: [PATCH] Optimize wrapper --- jsfuck.js | 31 ++++++++++++++++++++++++++++--- test/jsfuck_test.js | 5 +++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/jsfuck.js b/jsfuck.js index 8f5f2336..ef5147d0 100644 --- a/jsfuck.js +++ b/jsfuck.js @@ -239,6 +239,10 @@ } } + function escapeSequenceForReplace(c) { + return escapeSequence(c).replace('\\', 't'); + } + function encode(input, wrapWithEval, runInParentScope){ var output = []; @@ -254,8 +258,24 @@ } unmappped = unmappped.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); unmappped = new RegExp('[^' + unmappped + ']','g'); - var hasUnmappedCharacters = unmappped.test(input); - if (hasUnmappedCharacters) { + var unmappedCharactersCount = (input.match(unmappped) || []).length; + if (unmappedCharactersCount > 1) { + // Without this optimization one unmapped caracter has encoded length + // of about 3600 characters. Every additional unmapped character adds + // 2000 to the total length. For example, the lenght of `~` is 3605, + // `~~` is 5600, and `~~~` is 7595. + // + // The loader with replace has encoded length of about 5300 characters + // and every additional character adds 100 to the total length. + // In the same example the length of `~~` becomes 5371 and `~~~` -- 5463. + // + // So, when we have more than one unmapped character we want to encode whole input + // except select characters (that have encoded length less than about 70) + // into an escape sequence. + // + // NOTE: `t` should be escaped! + input = input.replace(/[^0123456789.adefilnrsuN]/g, escapeSequenceForReplace); + } else if (unmappedCharactersCount > 0) { //Because we will wrap the input into a string we need to escape Backslash // and Double quote characters (we do not need to worry about other characters // because they are not mapped explicitly). @@ -295,7 +315,12 @@ output += "+[]"; } - if (hasUnmappedCharacters) { + if (unmappedCharactersCount > 1) { + // replace `t` with `\\` + output = "(" + output + ")[" + encode("split") + "](" + encode ("t") + ")[" + encode("join") +"](" + encode("\\") + ")"; + } + + if (unmappedCharactersCount > 0) { output = "[][" + encode("flat") + "]"+ "[" + encode("constructor") + "]" + "(" + encode("return\"") + "+" + output + "+" + encode("\"") + ")()"; diff --git a/test/jsfuck_test.js b/test/jsfuck_test.js index 2bf6dfca..0c0cbfc8 100644 --- a/test/jsfuck_test.js +++ b/test/jsfuck_test.js @@ -63,6 +63,11 @@ createTest('NaNtrue'); createTest('trueNaN'); createTest('undefinedNaN'); createTest('~\\"'); +createTest('t~'); +createTest('~t'); +createTest('[(~t~)]'); +createTest('~0123456789 abcdefghijklmnopqrstuvwxyz()+.~'); +createTest('~0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ()+.~'); for(var i=MIN; i