jsCrypter/js/jsUnCrypt.js
2020-05-29 21:19:56 +02:00

163 lines
5.4 KiB
JavaScript

function packify( input ) {
var script = input,
len,
i,
chunk,
chunk_size,
re,
matches,
savings,
potential,
potentials = {},
potentials_arr = [],
map = '',
char_code,
char,
output;
// Single quotes need to be escaped, so use double-quotes in your input
// source whenever possible.
script = script.replace( /'/g, "\\'" );
// Replace any non-space whitespace with spaces (shouldn't be necessary).
script = script.replace( /\s+/g, ' ' );
// Return number of chars saved by replacing `count` occurences of `string`.
function get_savings( string, count ) {
return ( string.length - 1 ) * ( count - 1 ) - 2;
};
// Just trying to keep things DRY here... Let's match some patterns!
function get_re_match( pattern, text ) {
var re = RegExp( pattern.replace( /(\W)/g, '\\$1' ), 'g' );
return [
text.match( re ) || [],
re
];
};
// Look for recurring patterns between 2 and 20 characters in length (could
// have been between 2 and len / 2, but that gets REALLY slow).
for ( chunk_size = 2, len = script.length; chunk_size <= 20; chunk_size++ ) {
// Start at the beginning of the input string, go to the end.
for ( i = 0; i < len - chunk_size; i++ ) {
// Grab the "chunk" at the current position.
chunk = script.substr( i, chunk_size );
if ( !potentials[ chunk ] ) {
// Find the number of chunk matches in the input script.
matches = get_re_match( chunk, script )[0];
// If any matches, save this chunk as a potential pattern. By using an
// object instead of an array, we don't have to worry about uniquing
// the array as new potentials will just overwrite previous potentials.
if ( get_savings( chunk, matches.length ) >= 0 ) {
potentials[ chunk ] = matches.length;
}
}
}
}
// Since we'll need to sort the potentials, create an array from the object.
for ( i in potentials ) {
potentials.hasOwnProperty( i )
&& potentials_arr.push({ pattern: i, count: potentials[ i ] });
}
// Potentials get sorted first by byte savings, then by # of occurrences
// (favoring smaller count, longer patterns), then lexicographically.
function sort_potentials( a, b ) {
return get_savings( b.pattern, b.count ) - get_savings( a.pattern, a.count )
|| a.count - b.count
|| ( a.pattern < b.pattern ? -1 : a.pattern > b.pattern ? 1 : 0 );
};
// Loop over all the potential patterns, unless we run out of replacement
// chars first. Dealing with 7-bit ASCII, valid replacement chars are 1-31
// & 127 (excluding ASCII 10 & 13).
for ( char_code = 0; potentials_arr.length && char_code < 127; ) {
// Re-calculate match counts.
for ( i = 0, len = potentials_arr.length; i < len; i++ ) {
potential = potentials_arr[i];
matches = get_re_match( potential.pattern, script )[0];
potential.count = matches.length;
}
// Sort the array of potentials such that replacements that will yield the
// highest byte savings come first.
potentials_arr.sort( sort_potentials );
// Get the current best potential replacement.
potential = potentials_arr.shift();
// Find all chunk matches in the input string.
chunk = potential.pattern;
matches = get_re_match( chunk, script );
re = matches[1];
matches = matches[0];
// Ensure that replacing this potential pattern still actually saves bytes.
savings = get_savings( chunk, matches.length );
if ( savings >= 0 ) {
// Increment the current replacement character.
char_code = ++char_code == 10 ? 11
: char_code == 13 ? 14
: char_code == 32 ? 127
: char_code;
// Get the replacement char.
char = String.fromCharCode( char_code );
//console.log( char_code, char, matches.length, chunk, savings );
// Replace the pattern with the replacement character.
script = script.replace( re, char );
// Add the char + pattern combo into the map of replacements.
map += char + chunk;
}
}
// For each group of 1 low ASCII char / 1+ regular ASCII chars combo in the
// map string, replace the low ASCII char in the script string with the
// remaining regular ASCII chars, then eval the script string. Using with in
// this manner ensures that the temporary _ var won't be leaked.
output = ""
+ "with({_:'" + script + "'})"
+ "'" + map + "'.replace(/.([ -~]+)/g,function(x,y){"
+ "_=_.replace(RegExp(x[0],'g'),y)"
+ "}),"
+ "eval(_)";
if ( eval( output.replace( 'eval(_)', '_' ) ) === input ) {
// If the output *actually* evals to the input string, packing was
// successful. Log some useful stats and return the output.
return output;
} else {
// Otherwise, exit with an error.
console.log( 'Error!' );
return input;
}
};
function jsUnCrypt(code) {
while(code.search("eval")||code.search("document.write")) {
if (code.search("eval") {
code = code.replace("eval","code=");
} else if (code.search("document.write")) {
code = code.replace("eval","code=");
}
code = eval("code");
}
alert("code");
}