|
| 1 | +import type * as t from '@babel/types'; |
1 | 2 | import debug from 'debug';
|
2 | 3 | import type { AsyncTransform } from '../ast-utils';
|
3 | 4 | import {
|
@@ -30,46 +31,52 @@ export default {
|
30 | 31 | if (!sandbox) return;
|
31 | 32 |
|
32 | 33 | const logger = debug('webcrack:deobfuscate');
|
33 |
| - const stringArray = findStringArray(ast); |
34 |
| - logger( |
35 |
| - stringArray |
36 |
| - ? `String Array: ${stringArray.length} strings` |
37 |
| - : 'String Array: no', |
38 |
| - ); |
39 |
| - if (!stringArray) return; |
| 34 | + const visitedStringArrays = new Set<t.Node>(); |
40 | 35 |
|
41 |
| - const rotator = findArrayRotator(stringArray); |
42 |
| - logger(`String Array Rotate: ${rotator ? 'yes' : 'no'}`); |
| 36 | + while (true) { |
| 37 | + const stringArray = findStringArray(ast); |
| 38 | + logger( |
| 39 | + stringArray |
| 40 | + ? `String Array: ${stringArray.length} strings` |
| 41 | + : 'String Array: no', |
| 42 | + ); |
| 43 | + if (!stringArray) break; |
| 44 | + if (visitedStringArrays.has(stringArray.path.node)) break; |
| 45 | + visitedStringArrays.add(stringArray.path.node); |
43 | 46 |
|
44 |
| - const decoders = findDecoders(stringArray); |
45 |
| - logger(`String Array Encodings: ${decoders.length}`); |
| 47 | + const rotator = findArrayRotator(stringArray); |
| 48 | + logger(`String Array Rotate: ${rotator ? 'yes' : 'no'}`); |
46 | 49 |
|
47 |
| - state.changes += applyTransform(ast, inlineObjectProps).changes; |
| 50 | + const decoders = findDecoders(stringArray); |
| 51 | + logger(`String Array Encodings: ${decoders.length}`); |
48 | 52 |
|
49 |
| - for (const decoder of decoders) { |
50 |
| - state.changes += applyTransform( |
51 |
| - ast, |
52 |
| - inlineDecoderWrappers, |
53 |
| - decoder.path, |
| 53 | + state.changes += applyTransform(ast, inlineObjectProps).changes; |
| 54 | + |
| 55 | + for (const decoder of decoders) { |
| 56 | + state.changes += applyTransform( |
| 57 | + ast, |
| 58 | + inlineDecoderWrappers, |
| 59 | + decoder.path, |
| 60 | + ).changes; |
| 61 | + } |
| 62 | + |
| 63 | + const vm = new VMDecoder(sandbox, stringArray, decoders, rotator); |
| 64 | + state.changes += ( |
| 65 | + await applyTransformAsync(ast, inlineDecodedStrings, { vm }) |
54 | 66 | ).changes;
|
55 |
| - } |
56 | 67 |
|
57 |
| - const vm = new VMDecoder(sandbox, stringArray, decoders, rotator); |
58 |
| - state.changes += ( |
59 |
| - await applyTransformAsync(ast, inlineDecodedStrings, { vm }) |
60 |
| - ).changes; |
| 68 | + if (decoders.length > 0) { |
| 69 | + stringArray.path.remove(); |
| 70 | + rotator?.remove(); |
| 71 | + decoders.forEach((decoder) => decoder.path.remove()); |
| 72 | + state.changes += 2 + decoders.length; |
| 73 | + } |
61 | 74 |
|
62 |
| - if (decoders.length > 0) { |
63 |
| - stringArray.path.remove(); |
64 |
| - rotator?.remove(); |
65 |
| - decoders.forEach((decoder) => decoder.path.remove()); |
66 |
| - state.changes += 2 + decoders.length; |
| 75 | + state.changes += applyTransforms( |
| 76 | + ast, |
| 77 | + [mergeStrings, deadCode, controlFlowObject, controlFlowSwitch], |
| 78 | + { noScope: true }, |
| 79 | + ).changes; |
67 | 80 | }
|
68 |
| - |
69 |
| - state.changes += applyTransforms( |
70 |
| - ast, |
71 |
| - [mergeStrings, deadCode, controlFlowObject, controlFlowSwitch], |
72 |
| - { noScope: true }, |
73 |
| - ).changes; |
74 | 81 | },
|
75 | 82 | } satisfies AsyncTransform<Sandbox>;
|
0 commit comments