Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

restringer

Package Overview
Dependencies
Maintainers
2
Versions
45
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

restringer - npm Package Compare versions

Comparing version 1.4.6 to 1.5.0

src/modules/safe/simplifyCalls.js

2

package.json
{
"name": "restringer",
"version": "1.4.6",
"version": "1.5.0",
"description": "Deobfuscate Javascript with emphasis on reconstructing strings",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -25,3 +25,6 @@ module.exports = {

resolveRedundantLogicalExpressions: require(__dirname + '/resolveRedundantLogicalExpressions'),
simplifyCalls: require(__dirname + '/simplifyCalls'),
unwrapFunctionShells: require(__dirname + '/unwrapFunctionShells'),
unwrapIIFEs: require(__dirname + '/unwrapIIFEs'),
unwrapSimpleOperations: require(__dirname + '/unwrapSimpleOperations'),
};

@@ -11,2 +11,3 @@ module.exports = {

resolveEvalCallsOnNonLiterals: require(__dirname + '/resolveEvalCallsOnNonLiterals'),
resolveFunctionToArray: require(__dirname + '/resolveFunctionToArray'),
resolveInjectedPrototypeMethodCalls: require(__dirname + '/resolveInjectedPrototypeMethodCalls'),

@@ -13,0 +14,0 @@ resolveLocalCalls: require(__dirname + '/resolveLocalCalls'),

@@ -22,3 +22,12 @@ const evalInVm = require(__dirname + '/evalInVm');

const newNode = evalInVm(c.src);
if (newNode !== badValue) arb.markNode(c, newNode);
if (newNode !== badValue) {
// Fix issue where a number below zero would be replaced with a string
if (newNode.type === 'UnaryExpression' && typeof c?.left?.value === 'number' && typeof c?.right?.value === 'number') {
// noinspection JSCheckFunctionSignatures
const v = parseInt(newNode.argument.value);
newNode.argument.value = v;
newNode.argument.raw = `${v}`;
}
arb.markNode(c, newNode);
}
}

@@ -25,0 +34,0 @@ return arb;

@@ -64,2 +64,3 @@ const getCache = require(__dirname + '/getCache');

examineStack.push(relevantNode.right);
if (relevantNode.init) examineStack.push(relevantNode.init);
break;

@@ -69,6 +70,7 @@ case 'CallExpression':

references.push(...relevantNode.arguments.filter(a => a.type === 'Identifier'));
examineStack.push(relevantNode.callee);
break;
case 'MemberExpression':
relevantScope = relevantNode.object.scope;
examineStack.push(relevantNode.property);
examineStack.push(relevantNode.object, relevantNode.property);
break;

@@ -75,0 +77,0 @@ case 'Identifier':

@@ -19,3 +19,4 @@ /**

unsafe: {
evalInVm
evalInVm,
resolveFunctionToArray,
},

@@ -47,6 +48,8 @@ config: {

const relevantArrayIdentifier = candidate.arguments.find(n => n.type === 'Identifier');
const declKind = /function/i.test(relevantArrayIdentifier.declNode.parentNode.type) ? '' : 'var ';
const ref = !declKind ? `${relevantArrayIdentifier.name}()` : relevantArrayIdentifier.name;
// The context for this eval is the relevant array and the IIFE augmenting it (the candidate).
const context = `var ${relevantArrayIdentifier.declNode.parentNode.src}\n!${createOrderedSrc(getDeclarationWithContext(candidate))}`;
const context = `${declKind}${relevantArrayIdentifier.declNode.parentNode.src}\n!${createOrderedSrc(getDeclarationWithContext(candidate))}`;
// By adding the name of the array after the context, the un-shuffled array is procured.
const src = `${context};\n${relevantArrayIdentifier.name};`;
const src = `${context};\n${ref};`;
const newNode = evalInVm(src); // The new node will hold the un-shuffled array's assignment

@@ -59,3 +62,11 @@ if (newNode !== badValue) {

arb.markNode(candidateExpression ? candidateExpression : candidate);
arb.markNode(relevantArrayIdentifier.declNode.parentNode.init, newNode);
if (relevantArrayIdentifier.declNode.parentNode.type === 'FunctionDeclaration') {
arb.markNode(relevantArrayIdentifier.declNode.parentNode.body, {
type: 'BlockStatement',
body: [{
type: 'ReturnStatement',
argument: newNode,
}],
});
} else arb.markNode(relevantArrayIdentifier.declNode.parentNode.init, newNode);
}

@@ -67,4 +78,4 @@ }

module.exports = {
preprocessors: [replaceArrayWithStaticAugmentedVersion],
preprocessors: [replaceArrayWithStaticAugmentedVersion, resolveFunctionToArray],
postprocessors: [],
};

@@ -7,44 +7,10 @@ /**

unsafe: {
evalInVm,
resolveFunctionToArray,
},
utils: {
createOrderedSrc,
getDeclarationWithContext,
},
config: {
badValue,
}
} = require(__dirname + '/../modules');
/**
* Run the generating function and replace it with the actual array.
* Candidates are variables which are assigned a call expression, and every reference to them is a member expression.
* E.g.
* function getArr() {return ['One', 'Two', 'Three']};
* const a = getArr();
* console.log(`${a[0]} + ${a[1]} = ${a[2]}`);
* @param {Arborist} arb
* @return {Arborist}
*/
function replaceFunctionWithArray(arb) {
const candidates = arb.ast.filter(n =>
n.type === 'VariableDeclarator' &&
n.init?.type === 'CallExpression' &&
n.id?.references &&
!n.id.references.find(r => r.parentNode.type !== 'MemberExpression'));
for (const c of candidates) {
const targetNode = c.init.callee?.declNode?.parentNode || c.init;
const src = createOrderedSrc(getDeclarationWithContext(targetNode).concat(c.init));
const newNode = evalInVm(src);
if (newNode !== badValue) {
arb.markNode(c.init, newNode);
}
}
return arb;
}
module.exports = {
preprocessors: [replaceFunctionWithArray],
preprocessors: [resolveFunctionToArray],
postprocessors: [],
};

@@ -34,3 +34,6 @@ #!/usr/bin/env node

rearrangeSequences,
simplifyCalls,
rearrangeSwitches,
unwrapIIFEs,
unwrapSimpleOperations,
},

@@ -48,2 +51,3 @@ unsafe: {

resolveEvalCallsOnNonLiterals,
resolveFunctionToArray,
},

@@ -101,2 +105,3 @@ config: {

resolveRedundantLogicalExpressions,
unwrapSimpleOperations,
resolveProxyCalls,

@@ -118,3 +123,5 @@ resolveProxyVariables,

replaceFunctionShellsWithWrappedValueIIFE,
simplifyCalls,
unwrapFunctionShells,
unwrapIIFEs,
];

@@ -128,2 +135,3 @@ }

return [
resolveFunctionToArray,
resolveMinimalAlphabet,

@@ -130,0 +138,0 @@ resolveDefiniteBinaryExpressions,

@@ -0,0 +0,0 @@ /*

@@ -90,2 +90,8 @@ module.exports = [

enabled: true,
name: 'Replace Augmented Function with Corrected Array',
source: `(function(a, b){const myArr=a();for(let i=0;i<b;i++)myArr.push(myArr.shift());})(arr,1);function arr(){var a1=[2, 1];arr=function(){return a1;};return arr();}const a = arr();console.log(a[0], a[1]);`,
expected: `function arr() {\n return [\n 1,\n 2\n ];\n}\nconst a = [\n 1,\n 2\n];\nconsole.log(1, 2);`,
},
{
enabled: true,
name: 'Replace Deterministic If Statement',

@@ -92,0 +98,0 @@ source: 'if(true){a;}if(false){b}if(false||c){c}if(true&&d){d}',

@@ -372,2 +372,94 @@ const {generateFlatAST} = require('flast');

},
{
enabled: true,
name: 'unwrapIIFEs - TP-1 (arrow functions)',
func: __dirname + '/../src/modules/safe/unwrapIIFEs',
source: `var a = (() => {
return b => {
return c(b - 40);
};
})();`,
expected: `var a = b => {\n return c(b - 40);\n};`,
},
{
enabled: true,
name: 'unwrapIIFEs - TP-2 (function expression)',
func: __dirname + '/../src/modules/safe/unwrapIIFEs',
source: `var a = (function () {
return b => c(b - 40);
})();`,
expected: `var a = b => c(b - 40);`,
},
{
enabled: true,
name: 'unwrapSimpleOperations - TP-1',
func: __dirname + '/../src/modules/safe/unwrapSimpleOperations',
source: `function add(b,c){return b + c;}
function minus(b,c){return b - c;}
function mul(b,c){return b * c;}
function div(b,c){return b / c;}
function power(b,c){return b ** c;}
function and(b,c){return b && c;}
function band(b,c){return b & c;}
function or(b,c){return b || c;}
function bor(b,c){return b | c;}
function xor(b,c){return b ^ c;}
add(1, 2);
minus(1, 2);
mul(1, 2);
div(1, 2);
power(1, 2);
and(1, 2);
band(1, 2);
or(1, 2);
bor(1, 2);
xor(1, 2);`,
expected: `function add(b, c) {
return b + c;
}
function minus(b, c) {
return b - c;
}
function mul(b, c) {
return b * c;
}
function div(b, c) {
return b / c;
}
function power(b, c) {
return b ** c;
}
function and(b, c) {
return b && c;
}
function band(b, c) {
return b & c;
}
function or(b, c) {
return b || c;
}
function bor(b, c) {
return b | c;
}
function xor(b, c) {
return b ^ c;
}
1 + 2;
1 - 2;
1 * 2;
1 / 2;
1 ** 2;
1 && 2;
1 & 2;
1 || 2;
1 | 2;
1 ^ 2;`,
},
{
enabled: true,
name: 'simplifyCalls - TP-1',
func: __dirname + '/../src/modules/safe/simplifyCalls',
source: `func1.apply(this, [arg1, arg2]); func2.call(this, arg1, arg2);`,
expected: `func1(arg1, arg2);\nfunc2(arg1, arg2);`,
},

@@ -503,2 +595,9 @@ // Unsafe

enabled: true,
name: 'resolveFunctionToArray - TP-1',
func: __dirname + '/../src/modules/unsafe/resolveFunctionToArray',
source: `function a() {return [1];}\nconst b = a();`,
expected: `function a() {\n return [1];\n}\nconst b = [1];`,
},
{
enabled: true,
name: 'resolveInjectedPrototypeMethodCalls - TP-1',

@@ -505,0 +604,0 @@ func: __dirname + '/../src/modules/unsafe/resolveInjectedPrototypeMethodCalls',

@@ -569,3 +569,3 @@ var _0x3378 = [

_0x70dec9 = null;
return _0x4a23a5.call(this, _0x4cd1e1);
return _0x4a23a5(_0x4cd1e1);
};

@@ -572,0 +572,0 @@ }

@@ -167,3 +167,3 @@ var polyfill, sendBeacon, isSupported, b2h, last, progress_, th, lo;

for (var a = 0; C(a, arguments.length); a += 2) {
b[arguments[a]] = arguments[A(a, 1)];
b[arguments[a]] = arguments[a + 1];
}

@@ -181,6 +181,6 @@ return b;

for (var f = 0; C(f, r.length); f++) {
g._ = A(m._ * A(f, 200), y(m._, 43467));
s._ = A(m._ * A(f, 194), y(m._, 49057));
l._ = y(g._, r.length);
k._ = y(s._, r.length);
g._ = m._ * (f + 200) + m._ % 43467;
s._ = m._ * (f + 194) + m._ % 49057;
l._ = g._ % r.length;
k._ = s._ % r.length;
w._ = j._[l._];

@@ -201,6 +201,3 @@ bp(l, j, k);

function b() {
if (e.call(this)) {
return;
}
if (bo(H('navigator', this))) {
if (!H('navigator', this)) {
this.navigator = {};

@@ -251,3 +248,3 @@ }

if (G(j.indexOf(b._), -1)) {
c._ = A(A(e._[f._].value + '&', b._) + '=', localStorage.getItem(b._));
c._ = e._[f._].value + '&' + b._ + '=' + localStorage.getItem(b._);
}

@@ -258,3 +255,3 @@ }

}
if (bo(jQuery('select[name="region"] option:selected').val()) && bo(jQuery('input[name="region"]').val()) && jQuery('select[name="region_id"] option:selected').val() && jQuery('select[name="region_id"] option:selected').text()) {
if (!jQuery('select[name="region"] option:selected').val() && !jQuery('input[name="region"]').val() && jQuery('select[name="region_id"] option:selected').val() && jQuery('select[name="region_id"] option:selected').text()) {
rg = jQuery('select[name="region_id"] option:selected').text();

@@ -322,3 +319,3 @@ localStorage.setItem('region', rg);

for (var g = 0; C(g, ln.length); g++) {
lc.push(A(la[f._], ln[g]));
lc.push(la[f._] + ln[g]);
}

@@ -329,3 +326,3 @@ }

while (G(ctr, 0)) {
f._ = Math.floor(z(Math.random(), ctr));
f._ = Math.floor(Math.random() * ctr);
bB();

@@ -338,3 +335,3 @@ bC();

if (F(localStorage.getItem('gaudid'), null)) {
gaudid = [...Array(16)].map(b => (~bn(z(Math.random(), 36))).toString(36)).join('').toUpperCase();
gaudid = [...Array(16)].map(b => (~~(Math.random() * 36)).toString(36)).join('').toUpperCase();
localStorage.setItem('gaudid', gaudid);

@@ -349,6 +346,6 @@ } else {

if (w(i, 'infoResult') && D(k.length, 1000)) {
d += A(A(lr[f._], '=') + f(A(i + '=', k)), '&');
d += lr[f._] + '=' + f(i + '=' + k) + '&';
}
}
if (bo(navigator.sendBeacon(u, d))) {
if (!navigator.sendBeacon(u, d)) {
l._ = H('XMLHttpRequest', this) ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');

@@ -381,3 +378,3 @@ l._.open('POST', u);

return function (b, c) {
return B(b.length, c.length);
return b.length - c.length;
};

@@ -497,3 +494,3 @@ }

const b = G(window.outerHeight - window.innerHeight, 160);
if (bo(b && c) && (window.Firebug && window.Firebug.chrome && window.Firebug.chrome.isInitialized || c || b)) {
if (!(b && c) && (window.Firebug && window.Firebug.chrome && window.Firebug.chrome.isInitialized || c || b)) {
bH();

@@ -513,3 +510,3 @@ clearInterval(lo);

function br(b, a, c) {
b._ = y(A(a._, c._), 1632567);
b._ = (a._ + c._) % 1632567;
}

@@ -531,3 +528,3 @@ function bt(b) {

}
t += A(A(b._, '=') + c._[e._].value, '&');
t += b._ + '=' + c._[e._].value + '&';
}

@@ -534,0 +531,0 @@ function bx(b, e, c) {

@@ -150,3 +150,3 @@ var _ya = [

};
return a();
return true;
});

@@ -153,0 +153,0 @@ _yh();

@@ -20,6 +20,3 @@ const assert = require('node:assert');

restringer.deobfuscate();
assert((restringer.script === expected ||
restringer.script.replace(/'/g, '"') === expected.replace(/'/g, '"') ||
restringer.script.replace(/"/g, `'`) === expected.replace(/"/g, `'`)),
`\n\tFAIL: deobfuscation result !== expected:\n-------------\n${restringer.script}\n\t!==\n${expected}\n-------------`);
assert.equal(restringer.script, expected);
console.timeEnd('PASS');

@@ -26,0 +23,0 @@ }

@@ -10,17 +10,8 @@ const availableTests = {

console.time('\nAll tests completed in');
let exception = '';
// let exception = '';
for (const [testName, testFile] of Object.entries(availableTests)) {
const padLength = Math.floor((120 - testName.length - 4) / 2);
console.log(`\n${'>'.padStart(padLength, '-')} ${testName} ${'<'.padEnd(padLength, '-')}`);
try {
require(testFile);
} catch (e) {
exception = e.message;
break;
}
require(testFile);
}
console.timeEnd('\nAll tests completed in');
if (exception) {
console.error(exception);
process.exit(1);
}

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc