Skip to content

Commit

Permalink
feat: deobfuscate inlined control flow object
Browse files Browse the repository at this point in the history
  • Loading branch information
j4k0xb committed Jul 19, 2024
1 parent 204c6f2 commit 1caef46
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 3 deletions.
35 changes: 32 additions & 3 deletions packages/webcrack/src/deobfuscate/control-flow-object.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Binding, NodePath } from '@babel/traverse';
import * as t from '@babel/types';
import type { FunctionExpression } from '@babel/types';
import * as t from '@babel/types';
import * as m from '@codemod/matchers';
import type { Transform } from '../ast-utils';
import {
Expand Down Expand Up @@ -101,7 +101,12 @@ export default {
);
const varMatcher = m.variableDeclarator(
varId,
m.capture(m.objectExpression(objectProperties)),
m.objectExpression(objectProperties),
);
// Example: { YhxvC: "default" }.YhxvC
const inlineMatcher = constMemberExpression(
m.objectExpression(objectProperties),
propertyName,
);

function isConstantBinding(binding: Binding) {
Expand All @@ -118,7 +123,10 @@ export default {
if (!binding) return changes;
if (!isConstantBinding(binding)) return changes;
if (!transformObjectKeys(binding)) return changes;
if (!isReadonlyObject(binding, memberAccess)) return changes;
if (!isReadonlyObject(binding, memberAccess)) {
path.addComment('leading', 'webcrack:control_flow_mutable_object');
return changes;
}

const props = new Map(
objectProperties.current!.map((p) => [
Expand Down Expand Up @@ -222,6 +230,27 @@ export default {
this.changes += transform(path);
},
},
MemberExpression: {
exit(path) {
if (!inlineMatcher.match(path.node)) return;

const propName = getPropName(path.node.property)!;
const value = objectProperties.current!.find(
(prop) => getPropName(prop.key) === propName,
)?.value as t.FunctionExpression | t.StringLiteral | undefined;
if (!value) return;

if (t.isStringLiteral(value)) {
path.replaceWith(value);
} else {
inlineFunction(
value,
path.parentPath as NodePath<t.CallExpression>,
);
}
this.changes++;
},
},
};
},
} satisfies Transform;
20 changes: 20 additions & 0 deletions packages/webcrack/src/deobfuscate/test/control-flow-object.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { test } from 'vitest';
import { testTransform } from '../../../test';
import controlFlowObject from '../control-flow-object';

const expectJS = testTransform(controlFlowObject);

// https://github.com/j4k0xb/webcrack/issues/98
test('inlined object', () => {
expectJS(`
({
QuFtJ: function (n, r) {
return n === r;
}
}).QuFtJ(u, undefined);
`).toMatchInlineSnapshot(`u === undefined;`);

expectJS(`
({ YhxvC: "default" }).YhxvC;
`).toMatchInlineSnapshot(`"default";`);
});

0 comments on commit 1caef46

Please sign in to comment.