Skip to content

Commit

Permalink
Merge pull request #36 from j4k0xb/inline-var-assignments
Browse files Browse the repository at this point in the history
  • Loading branch information
j4k0xb authored Dec 22, 2023
2 parents e1aff38 + f76ffc3 commit ccda000
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 13 deletions.
31 changes: 27 additions & 4 deletions packages/webcrack/src/ast-utils/inline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,47 @@ import { findParent } from './matcher';

/**
* Replace all references of a variable with the initializer.
* Make sure the binding is immutable before using!
* Example:
* `const a = 1; console.log(a);` -> `console.log(1);`
*
* Example with `unsafeAssignments` being `true`:
* `let a; a = 2; console.log(a);` -> `console.log(2);`
*
* @param unsafeAssignments Also inline assignments to the variable (not guaranteed to be the final value)
*/
export function inlineVariable(
binding: Binding,
init?: m.Matcher<t.Expression>,
value = m.anyExpression(),
unsafeAssignments = false,
) {
const varDeclarator = binding.path.node;
const varMatcher = m.variableDeclarator(
m.identifier(binding.identifier.name),
init,
value,
);
const assignmentMatcher = m.assignmentExpression(
'=',
m.identifier(binding.identifier.name),
value,
);
if (varMatcher.match(varDeclarator)) {

if (binding.constant && varMatcher.match(varDeclarator)) {
binding.referencePaths.forEach((ref) => {
ref.replaceWith(varDeclarator.init!);
});
binding.path.remove();
} else if (
unsafeAssignments &&
binding.constantViolations.length === 1 &&
assignmentMatcher.match(binding.constantViolations[0]?.node)
) {
const assignment = binding
.constantViolations[0] as NodePath<t.AssignmentExpression>;
binding.referencePaths.forEach((ref) => {
ref.replaceWith(assignment.node.right);
});
assignment.remove();
binding.path.remove();
}
}

Expand Down
11 changes: 11 additions & 0 deletions packages/webcrack/src/ast-utils/test/inline.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ test('inline variable', () => {
expect(ast).toMatchInlineSnapshot(`let b = 1;`);
});

test('inline variable with assignment', () => {
const ast = parse('let a; a = 1; let b = a;');
traverse(ast, {
Program(path) {
const binding = path.scope.getBinding('a')!;
inlineVariable(binding, undefined, true);
},
});
expect(ast).toMatchInlineSnapshot(`let b = 1;`);
});

test('inline array elements', () => {
const ast = parse('const arr = ["foo", "bar"]; console.log(arr[0]);');
traverse(ast, {
Expand Down
11 changes: 3 additions & 8 deletions packages/webcrack/src/deobfuscate/decoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@ import { expression } from '@babel/template';
import { NodePath } from '@babel/traverse';
import * as t from '@babel/types';
import * as m from '@codemod/matchers';
import {
anyLiteral,
findParent,
inlineVariable,
renameFast,
} from '../ast-utils';
import { findParent, inlineVariable, renameFast } from '../ast-utils';
import { StringArray } from './string-array';

/**
Expand Down Expand Up @@ -78,8 +73,8 @@ export class Decoder {
ref.parentPath!.traverse({
ReferencedIdentifier(path) {
const varBinding = path.scope.getBinding(path.node.name)!;
if (!varBinding || !varBinding.constant) return;
inlineVariable(varBinding, anyLiteral);
if (!varBinding) return;
inlineVariable(varBinding, literalArgument, true);
},
});
if (literalCall.match(ref.parent)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ function b(c, d) {
}, b(c, d);
}
function hi() {
const x = 0xd6;
let x;
const y = 0xd3;
x = 0xd6;
console[b(x)](b(y));
console[b(x)](b(y));
}
Expand Down

0 comments on commit ccda000

Please sign in to comment.