obscura-js 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +156 -0
- package/dist/bin/haze.d.ts +3 -0
- package/dist/bin/haze.d.ts.map +1 -0
- package/dist/bin/haze.js +54 -0
- package/dist/bin/haze.js.map +1 -0
- package/dist/src/antiDebug/index.d.ts +11 -0
- package/dist/src/antiDebug/index.d.ts.map +1 -0
- package/dist/src/antiDebug/index.js +23 -0
- package/dist/src/antiDebug/index.js.map +1 -0
- package/dist/src/antiDebug/integrityTag.d.ts +21 -0
- package/dist/src/antiDebug/integrityTag.d.ts.map +1 -0
- package/dist/src/antiDebug/integrityTag.js +100 -0
- package/dist/src/antiDebug/integrityTag.js.map +1 -0
- package/dist/src/antiDebug/nativeBinding.d.ts +15 -0
- package/dist/src/antiDebug/nativeBinding.d.ts.map +1 -0
- package/dist/src/antiDebug/nativeBinding.js +89 -0
- package/dist/src/antiDebug/nativeBinding.js.map +1 -0
- package/dist/src/index.d.ts +12 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +35 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/obfuscation/cff.d.ts +26 -0
- package/dist/src/obfuscation/cff.d.ts.map +1 -0
- package/dist/src/obfuscation/cff.js +129 -0
- package/dist/src/obfuscation/cff.js.map +1 -0
- package/dist/src/obfuscation/deadCode.d.ts +10 -0
- package/dist/src/obfuscation/deadCode.d.ts.map +1 -0
- package/dist/src/obfuscation/deadCode.js +70 -0
- package/dist/src/obfuscation/deadCode.js.map +1 -0
- package/dist/src/obfuscation/functionTable.d.ts +18 -0
- package/dist/src/obfuscation/functionTable.d.ts.map +1 -0
- package/dist/src/obfuscation/functionTable.js +105 -0
- package/dist/src/obfuscation/functionTable.js.map +1 -0
- package/dist/src/obfuscation/index.d.ts +15 -0
- package/dist/src/obfuscation/index.d.ts.map +1 -0
- package/dist/src/obfuscation/index.js +47 -0
- package/dist/src/obfuscation/index.js.map +1 -0
- package/dist/src/obfuscation/mba.d.ts +12 -0
- package/dist/src/obfuscation/mba.d.ts.map +1 -0
- package/dist/src/obfuscation/mba.js +91 -0
- package/dist/src/obfuscation/mba.js.map +1 -0
- package/dist/src/obfuscation/sequenceExpression.d.ts +16 -0
- package/dist/src/obfuscation/sequenceExpression.d.ts.map +1 -0
- package/dist/src/obfuscation/sequenceExpression.js +85 -0
- package/dist/src/obfuscation/sequenceExpression.js.map +1 -0
- package/dist/src/obfuscation/stringPool.d.ts +14 -0
- package/dist/src/obfuscation/stringPool.d.ts.map +1 -0
- package/dist/src/obfuscation/stringPool.js +142 -0
- package/dist/src/obfuscation/stringPool.js.map +1 -0
- package/dist/src/types.d.ts +65 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +3 -0
- package/dist/src/types.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.applyControlFlowFlattening = applyControlFlowFlattening;
|
|
40
|
+
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
41
|
+
const t = __importStar(require("@babel/types"));
|
|
42
|
+
/**
|
|
43
|
+
* Pass: Control Flow Flattening (CFF)
|
|
44
|
+
*
|
|
45
|
+
* Transforms a function body into a flat state machine with a central
|
|
46
|
+
* dispatcher loop, hiding the original execution order.
|
|
47
|
+
*
|
|
48
|
+
* Before:
|
|
49
|
+
* function f() { stmt0; stmt1; stmt2; }
|
|
50
|
+
*
|
|
51
|
+
* After:
|
|
52
|
+
* function f() {
|
|
53
|
+
* let __s = 0;
|
|
54
|
+
* while (true) {
|
|
55
|
+
* switch (__s) {
|
|
56
|
+
* case 0: stmt0; __s = 1; break;
|
|
57
|
+
* case 1: stmt1; __s = 2; break;
|
|
58
|
+
* case 2: stmt2; __s = -1; break;
|
|
59
|
+
* default: return;
|
|
60
|
+
* }
|
|
61
|
+
* }
|
|
62
|
+
* }
|
|
63
|
+
*/
|
|
64
|
+
function applyControlFlowFlattening(ast, options = {}) {
|
|
65
|
+
const passes = options.passes ?? 1;
|
|
66
|
+
const stateVar = "__haze_s";
|
|
67
|
+
/**
|
|
68
|
+
* If `stmt` is a let/const VariableDeclaration, extract the declarators into
|
|
69
|
+
* `hoisted` (as var-declared names only) and return ExpressionStatements for
|
|
70
|
+
* the assignments, so variables are function-scoped and accessible across cases.
|
|
71
|
+
* Returns null for declarators that have no initializer.
|
|
72
|
+
*/
|
|
73
|
+
function extractHoisted(stmt, hoisted) {
|
|
74
|
+
if (!t.isVariableDeclaration(stmt) || (stmt.kind !== "let" && stmt.kind !== "const")) {
|
|
75
|
+
return t.cloneNode(stmt, true);
|
|
76
|
+
}
|
|
77
|
+
const assignments = [];
|
|
78
|
+
for (const decl of stmt.declarations) {
|
|
79
|
+
// Hoist: var name; (or var { a, b };)
|
|
80
|
+
hoisted.push(t.variableDeclarator(t.cloneNode(decl.id, true)));
|
|
81
|
+
if (decl.init) {
|
|
82
|
+
assignments.push(t.assignmentExpression("=", t.cloneNode(decl.id, true), t.cloneNode(decl.init, true)));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (assignments.length === 0)
|
|
86
|
+
return t.emptyStatement();
|
|
87
|
+
if (assignments.length === 1)
|
|
88
|
+
return t.expressionStatement(assignments[0]);
|
|
89
|
+
return t.expressionStatement(t.sequenceExpression(assignments));
|
|
90
|
+
}
|
|
91
|
+
for (let pass = 0; pass < passes; pass++) {
|
|
92
|
+
(0, traverse_1.default)(ast, {
|
|
93
|
+
Function(path) {
|
|
94
|
+
if (!t.isBlockStatement(path.node.body))
|
|
95
|
+
return;
|
|
96
|
+
const body = path.node.body.body;
|
|
97
|
+
// Skip trivial or already-flattened bodies
|
|
98
|
+
if (body.length <= 1)
|
|
99
|
+
return;
|
|
100
|
+
if (body.some((s) => t.isSwitchStatement(s)))
|
|
101
|
+
return;
|
|
102
|
+
const hoisted = [];
|
|
103
|
+
const cases = body.map((stmt, idx) => {
|
|
104
|
+
const nextState = idx === body.length - 1 ? t.numericLiteral(-1) : t.numericLiteral(idx + 1);
|
|
105
|
+
const converted = extractHoisted(stmt, hoisted);
|
|
106
|
+
const caseBody = [];
|
|
107
|
+
if (!t.isEmptyStatement(converted))
|
|
108
|
+
caseBody.push(converted);
|
|
109
|
+
caseBody.push(t.expressionStatement(t.assignmentExpression("=", t.identifier(stateVar), nextState)), t.breakStatement());
|
|
110
|
+
return t.switchCase(t.numericLiteral(idx), caseBody);
|
|
111
|
+
});
|
|
112
|
+
// default: return;
|
|
113
|
+
cases.push(t.switchCase(null, [t.returnStatement()]));
|
|
114
|
+
const dispatcher = t.whileStatement(t.booleanLiteral(true), t.blockStatement([t.switchStatement(t.identifier(stateVar), cases)]));
|
|
115
|
+
const prelude = [
|
|
116
|
+
t.variableDeclaration("let", [
|
|
117
|
+
t.variableDeclarator(t.identifier(stateVar), t.numericLiteral(0)),
|
|
118
|
+
]),
|
|
119
|
+
];
|
|
120
|
+
if (hoisted.length > 0) {
|
|
121
|
+
prelude.push(t.variableDeclaration("var", hoisted));
|
|
122
|
+
}
|
|
123
|
+
path.node.body = t.blockStatement([...prelude, dispatcher]);
|
|
124
|
+
path.skip();
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=cff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cff.js","sourceRoot":"","sources":["../../../src/obfuscation/cff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as t from "@babel/types";
|
|
2
|
+
import type { DeadCodeOptions } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* Pass: Dead Code Injection
|
|
5
|
+
*
|
|
6
|
+
* Inserts unreachable/useless code blocks throughout the program body to
|
|
7
|
+
* inflate file size and confuse static analysis tools.
|
|
8
|
+
*/
|
|
9
|
+
export declare function applyDeadCode(ast: t.File, options?: DeadCodeOptions): void;
|
|
10
|
+
//# sourceMappingURL=deadCode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deadCode.d.ts","sourceRoot":"","sources":["../../../src/obfuscation/deadCode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,cAAc,CAAC;AAClC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAmChD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,GAAE,eAAoB,GAAG,IAAI,CAa9E"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.applyDeadCode = applyDeadCode;
|
|
37
|
+
const t = __importStar(require("@babel/types"));
|
|
38
|
+
/** Dead code expression templates */
|
|
39
|
+
const DEAD_TEMPLATES = [
|
|
40
|
+
() => t.ifStatement(t.binaryExpression("===", t.numericLiteral(0), t.numericLiteral(1)), t.blockStatement([
|
|
41
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier("console"), t.identifier("log")), [
|
|
42
|
+
t.stringLiteral("unreachable"),
|
|
43
|
+
])),
|
|
44
|
+
])),
|
|
45
|
+
() => t.whileStatement(t.booleanLiteral(false), t.blockStatement([
|
|
46
|
+
t.expressionStatement(t.numericLiteral(Math.floor(Math.random() * 0xffff))),
|
|
47
|
+
])),
|
|
48
|
+
() => t.variableDeclaration("var", [
|
|
49
|
+
t.variableDeclarator(t.identifier(`__dead_${Math.floor(Math.random() * 0xffff).toString(16)}`), t.binaryExpression("&", t.numericLiteral(Math.floor(Math.random() * 0xff)), t.numericLiteral(0))),
|
|
50
|
+
]),
|
|
51
|
+
];
|
|
52
|
+
/**
|
|
53
|
+
* Pass: Dead Code Injection
|
|
54
|
+
*
|
|
55
|
+
* Inserts unreachable/useless code blocks throughout the program body to
|
|
56
|
+
* inflate file size and confuse static analysis tools.
|
|
57
|
+
*/
|
|
58
|
+
function applyDeadCode(ast, options = {}) {
|
|
59
|
+
const targetLines = options.targetLines ?? 50;
|
|
60
|
+
const body = ast.program.body;
|
|
61
|
+
let injected = 0;
|
|
62
|
+
let insertAt = 0;
|
|
63
|
+
while (injected < targetLines && insertAt <= body.length) {
|
|
64
|
+
const template = DEAD_TEMPLATES[injected % DEAD_TEMPLATES.length];
|
|
65
|
+
body.splice(insertAt, 0, template());
|
|
66
|
+
injected++;
|
|
67
|
+
insertAt += 2; // skip one real statement between injections
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=deadCode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deadCode.js","sourceRoot":"","sources":["../../../src/obfuscation/deadCode.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,sCAaC;AAvDD,gDAAkC;AAGlC,qCAAqC;AACrC,MAAM,cAAc,GAA0B;IAC5C,GAAG,EAAE,CACH,CAAC,CAAC,WAAW,CACX,CAAC,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EACnE,CAAC,CAAC,cAAc,CAAC;QACf,CAAC,CAAC,mBAAmB,CACnB,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE;YACjF,CAAC,CAAC,aAAa,CAAC,aAAa,CAAC;SAC/B,CAAC,CACH;KACF,CAAC,CACH;IACH,GAAG,EAAE,CACH,CAAC,CAAC,cAAc,CACd,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,EACvB,CAAC,CAAC,cAAc,CAAC;QACf,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;KAC5E,CAAC,CACH;IACH,GAAG,EAAE,CACH,CAAC,CAAC,mBAAmB,CAAC,KAAK,EAAE;QAC3B,CAAC,CAAC,kBAAkB,CAClB,CAAC,CAAC,UAAU,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,EACzE,CAAC,CAAC,gBAAgB,CAChB,GAAG,EACH,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,EAClD,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CACpB,CACF;KACF,CAAC;CACL,CAAC;AAEF;;;;;GAKG;AACH,SAAgB,aAAa,CAAC,GAAW,EAAE,UAA2B,EAAE;IACtE,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC;IAC9C,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,IAAqB,CAAC;IAE/C,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,OAAO,QAAQ,GAAG,WAAW,IAAI,QAAQ,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QACzD,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QAClE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrC,QAAQ,EAAE,CAAC;QACX,QAAQ,IAAI,CAAC,CAAC,CAAC,6CAA6C;IAC9D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as t from "@babel/types";
|
|
2
|
+
import type { FunctionTableOptions } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* Pass: Indirect Function Table
|
|
5
|
+
*
|
|
6
|
+
* Collects named function declarations, moves them into a single array, and
|
|
7
|
+
* replaces each call site with a dynamic index lookup.
|
|
8
|
+
*
|
|
9
|
+
* Before:
|
|
10
|
+
* function foo(x) { return x; }
|
|
11
|
+
* foo(1);
|
|
12
|
+
*
|
|
13
|
+
* After:
|
|
14
|
+
* const __haze_ft = [function foo(x) { return x; }];
|
|
15
|
+
* __haze_ft[0](1);
|
|
16
|
+
*/
|
|
17
|
+
export declare function applyFunctionTable(ast: t.File, options?: FunctionTableOptions): void;
|
|
18
|
+
//# sourceMappingURL=functionTable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"functionTable.d.ts","sourceRoot":"","sources":["../../../src/obfuscation/functionTable.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,cAAc,CAAC;AAClC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAErD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,GAAE,oBAAyB,GAAG,IAAI,CA6DxF"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.applyFunctionTable = applyFunctionTable;
|
|
40
|
+
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
41
|
+
const t = __importStar(require("@babel/types"));
|
|
42
|
+
/**
|
|
43
|
+
* Pass: Indirect Function Table
|
|
44
|
+
*
|
|
45
|
+
* Collects named function declarations, moves them into a single array, and
|
|
46
|
+
* replaces each call site with a dynamic index lookup.
|
|
47
|
+
*
|
|
48
|
+
* Before:
|
|
49
|
+
* function foo(x) { return x; }
|
|
50
|
+
* foo(1);
|
|
51
|
+
*
|
|
52
|
+
* After:
|
|
53
|
+
* const __haze_ft = [function foo(x) { return x; }];
|
|
54
|
+
* __haze_ft[0](1);
|
|
55
|
+
*/
|
|
56
|
+
function applyFunctionTable(ast, options = {}) {
|
|
57
|
+
const minFunctions = options.minFunctions ?? 2;
|
|
58
|
+
const tableId = "__haze_ft";
|
|
59
|
+
// Collect top-level named function declarations first, then remove only if threshold is met
|
|
60
|
+
const functions = [];
|
|
61
|
+
const nameToIndex = new Map();
|
|
62
|
+
const functionPaths = [];
|
|
63
|
+
(0, traverse_1.default)(ast, {
|
|
64
|
+
FunctionDeclaration(path) {
|
|
65
|
+
if (!path.node.id)
|
|
66
|
+
return;
|
|
67
|
+
if (!t.isProgram(path.parent) && !t.isBlockStatement(path.parent))
|
|
68
|
+
return;
|
|
69
|
+
functionPaths.push(path);
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
if (functionPaths.length < minFunctions)
|
|
73
|
+
return;
|
|
74
|
+
// Build the index map before touching the AST
|
|
75
|
+
for (let i = 0; i < functionPaths.length; i++) {
|
|
76
|
+
nameToIndex.set(functionPaths[i].node.id.name, i);
|
|
77
|
+
}
|
|
78
|
+
// Replace call sites FIRST (while function bodies are still in the AST)
|
|
79
|
+
// so calls inside one function to another are also rewritten.
|
|
80
|
+
(0, traverse_1.default)(ast, {
|
|
81
|
+
CallExpression(path) {
|
|
82
|
+
if (!t.isIdentifier(path.node.callee))
|
|
83
|
+
return;
|
|
84
|
+
const idx = nameToIndex.get(path.node.callee.name);
|
|
85
|
+
if (idx === undefined)
|
|
86
|
+
return;
|
|
87
|
+
path.node.callee = t.memberExpression(t.identifier(tableId), t.numericLiteral(idx), true // computed
|
|
88
|
+
);
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
// Now extract function expressions and remove declarations from the AST
|
|
92
|
+
for (const path of functionPaths) {
|
|
93
|
+
functions.push({
|
|
94
|
+
id: path.node.id.name,
|
|
95
|
+
fn: t.functionExpression(null, path.node.params, path.node.body, path.node.generator, path.node.async),
|
|
96
|
+
});
|
|
97
|
+
path.remove();
|
|
98
|
+
}
|
|
99
|
+
// Prepend: const __haze_ft = [fn0, fn1, ...]
|
|
100
|
+
const tableDeclaration = t.variableDeclaration("const", [
|
|
101
|
+
t.variableDeclarator(t.identifier(tableId), t.arrayExpression(functions.map((f) => f.fn))),
|
|
102
|
+
]);
|
|
103
|
+
ast.program.body.unshift(tableDeclaration);
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=functionTable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"functionTable.js","sourceRoot":"","sources":["../../../src/obfuscation/functionTable.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type * as t from "@babel/types";
|
|
2
|
+
import type { ObfuscationOptions } from "../types";
|
|
3
|
+
import { applySequenceExpression } from "./sequenceExpression";
|
|
4
|
+
import { applyMba } from "./mba";
|
|
5
|
+
import { applyFunctionTable } from "./functionTable";
|
|
6
|
+
import { applyStringPool } from "./stringPool";
|
|
7
|
+
import { applyControlFlowFlattening } from "./cff";
|
|
8
|
+
import { applyDeadCode } from "./deadCode";
|
|
9
|
+
export { applySequenceExpression, applyMba, applyFunctionTable, applyStringPool, applyControlFlowFlattening, applyDeadCode, };
|
|
10
|
+
/**
|
|
11
|
+
* Run all enabled obfuscation passes in order.
|
|
12
|
+
* Each pass is opt-in: pass `false` to skip it entirely.
|
|
13
|
+
*/
|
|
14
|
+
export declare function applyObfuscation(ast: t.File, options: ObfuscationOptions | undefined, appliedPasses: string[]): void;
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/obfuscation/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,CAAC,MAAM,cAAc,CAAC;AACvC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,OAAO,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EACL,uBAAuB,EACvB,QAAQ,EACR,kBAAkB,EAClB,eAAe,EACf,0BAA0B,EAC1B,aAAa,GACd,CAAC;AAEF;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,CAAC,CAAC,IAAI,EACX,OAAO,EAAE,kBAAkB,YAAK,EAChC,aAAa,EAAE,MAAM,EAAE,GACtB,IAAI,CAyBN"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.applyDeadCode = exports.applyControlFlowFlattening = exports.applyStringPool = exports.applyFunctionTable = exports.applyMba = exports.applySequenceExpression = void 0;
|
|
4
|
+
exports.applyObfuscation = applyObfuscation;
|
|
5
|
+
const sequenceExpression_1 = require("./sequenceExpression");
|
|
6
|
+
Object.defineProperty(exports, "applySequenceExpression", { enumerable: true, get: function () { return sequenceExpression_1.applySequenceExpression; } });
|
|
7
|
+
const mba_1 = require("./mba");
|
|
8
|
+
Object.defineProperty(exports, "applyMba", { enumerable: true, get: function () { return mba_1.applyMba; } });
|
|
9
|
+
const functionTable_1 = require("./functionTable");
|
|
10
|
+
Object.defineProperty(exports, "applyFunctionTable", { enumerable: true, get: function () { return functionTable_1.applyFunctionTable; } });
|
|
11
|
+
const stringPool_1 = require("./stringPool");
|
|
12
|
+
Object.defineProperty(exports, "applyStringPool", { enumerable: true, get: function () { return stringPool_1.applyStringPool; } });
|
|
13
|
+
const cff_1 = require("./cff");
|
|
14
|
+
Object.defineProperty(exports, "applyControlFlowFlattening", { enumerable: true, get: function () { return cff_1.applyControlFlowFlattening; } });
|
|
15
|
+
const deadCode_1 = require("./deadCode");
|
|
16
|
+
Object.defineProperty(exports, "applyDeadCode", { enumerable: true, get: function () { return deadCode_1.applyDeadCode; } });
|
|
17
|
+
/**
|
|
18
|
+
* Run all enabled obfuscation passes in order.
|
|
19
|
+
* Each pass is opt-in: pass `false` to skip it entirely.
|
|
20
|
+
*/
|
|
21
|
+
function applyObfuscation(ast, options = {}, appliedPasses) {
|
|
22
|
+
if (options.sequenceExpression !== false) {
|
|
23
|
+
(0, sequenceExpression_1.applySequenceExpression)(ast, options.sequenceExpression ?? {});
|
|
24
|
+
appliedPasses.push("sequenceExpression");
|
|
25
|
+
}
|
|
26
|
+
if (options.mba !== false) {
|
|
27
|
+
(0, mba_1.applyMba)(ast, options.mba ?? {});
|
|
28
|
+
appliedPasses.push("mba");
|
|
29
|
+
}
|
|
30
|
+
if (options.functionTable !== false) {
|
|
31
|
+
(0, functionTable_1.applyFunctionTable)(ast, options.functionTable ?? {});
|
|
32
|
+
appliedPasses.push("functionTable");
|
|
33
|
+
}
|
|
34
|
+
if (options.stringPool !== false) {
|
|
35
|
+
(0, stringPool_1.applyStringPool)(ast, options.stringPool ?? {});
|
|
36
|
+
appliedPasses.push("stringPool");
|
|
37
|
+
}
|
|
38
|
+
if (options.controlFlowFlattening !== false) {
|
|
39
|
+
(0, cff_1.applyControlFlowFlattening)(ast, options.controlFlowFlattening ?? {});
|
|
40
|
+
appliedPasses.push("controlFlowFlattening");
|
|
41
|
+
}
|
|
42
|
+
if (options.deadCode !== false) {
|
|
43
|
+
(0, deadCode_1.applyDeadCode)(ast, options.deadCode ?? {});
|
|
44
|
+
appliedPasses.push("deadCode");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/obfuscation/index.ts"],"names":[],"mappings":";;;AAsBA,4CA6BC;AAjDD,6DAA+D;AAQ7D,wGARO,4CAAuB,OAQP;AAPzB,+BAAiC;AAQ/B,yFARO,cAAQ,OAQP;AAPV,mDAAqD;AAQnD,mGARO,kCAAkB,OAQP;AAPpB,6CAA+C;AAQ7C,gGARO,4BAAe,OAQP;AAPjB,+BAAmD;AAQjD,2GARO,gCAA0B,OAQP;AAP5B,yCAA2C;AAQzC,8FARO,wBAAa,OAQP;AAGf;;;GAGG;AACH,SAAgB,gBAAgB,CAC9B,GAAW,EACX,UAA8B,EAAE,EAChC,aAAuB;IAEvB,IAAI,OAAO,CAAC,kBAAkB,KAAK,KAAK,EAAE,CAAC;QACzC,IAAA,4CAAuB,EAAC,GAAG,EAAE,OAAO,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC;QAC/D,aAAa,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,KAAK,KAAK,EAAE,CAAC;QAC1B,IAAA,cAAQ,EAAC,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;QACjC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IACD,IAAI,OAAO,CAAC,aAAa,KAAK,KAAK,EAAE,CAAC;QACpC,IAAA,kCAAkB,EAAC,GAAG,EAAE,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;QACrD,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACtC,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,KAAK,KAAK,EAAE,CAAC;QACjC,IAAA,4BAAe,EAAC,GAAG,EAAE,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;QAC/C,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,OAAO,CAAC,qBAAqB,KAAK,KAAK,EAAE,CAAC;QAC5C,IAAA,gCAA0B,EAAC,GAAG,EAAE,OAAO,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC;QACrE,aAAa,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;QAC/B,IAAA,wBAAa,EAAC,GAAG,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;QAC3C,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACjC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as t from "@babel/types";
|
|
2
|
+
import type { MbaOptions } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* Pass: Mixed Boolean Arithmetic (MBA)
|
|
5
|
+
*
|
|
6
|
+
* Replaces simple numeric literals and binary expressions with equivalent
|
|
7
|
+
* MBA expressions, making static analysis significantly harder.
|
|
8
|
+
*
|
|
9
|
+
* Example: `x + y` → `(x ^ y) + 2 * (x & y)`
|
|
10
|
+
*/
|
|
11
|
+
export declare function applyMba(ast: t.File, options?: MbaOptions): void;
|
|
12
|
+
//# sourceMappingURL=mba.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mba.d.ts","sourceRoot":"","sources":["../../../src/obfuscation/mba.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,cAAc,CAAC;AAClC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,GAAE,UAAe,GAAG,IAAI,CAiEpE"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.applyMba = applyMba;
|
|
40
|
+
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
41
|
+
const t = __importStar(require("@babel/types"));
|
|
42
|
+
/**
|
|
43
|
+
* Pass: Mixed Boolean Arithmetic (MBA)
|
|
44
|
+
*
|
|
45
|
+
* Replaces simple numeric literals and binary expressions with equivalent
|
|
46
|
+
* MBA expressions, making static analysis significantly harder.
|
|
47
|
+
*
|
|
48
|
+
* Example: `x + y` → `(x ^ y) + 2 * (x & y)`
|
|
49
|
+
*/
|
|
50
|
+
function applyMba(ast, options = {}) {
|
|
51
|
+
const rounds = options.rounds ?? 1;
|
|
52
|
+
for (let r = 0; r < rounds; r++) {
|
|
53
|
+
(0, traverse_1.default)(ast, {
|
|
54
|
+
BinaryExpression: {
|
|
55
|
+
exit(path) {
|
|
56
|
+
const { operator, left, right } = path.node;
|
|
57
|
+
if (!t.isExpression(left) || !t.isExpression(right))
|
|
58
|
+
return;
|
|
59
|
+
// Skip non-numeric-context operators
|
|
60
|
+
if (operator !== "+" && operator !== "-")
|
|
61
|
+
return;
|
|
62
|
+
// Skip string concatenation — MBA identities only hold for integers
|
|
63
|
+
if (operator === "+" &&
|
|
64
|
+
(t.isStringLiteral(left) ||
|
|
65
|
+
t.isStringLiteral(right) ||
|
|
66
|
+
t.isTemplateLiteral(left) ||
|
|
67
|
+
t.isTemplateLiteral(right)))
|
|
68
|
+
return;
|
|
69
|
+
// Prevent infinite expansion
|
|
70
|
+
if (path.node.extra?.["mbaExpanded"])
|
|
71
|
+
return;
|
|
72
|
+
let replacement;
|
|
73
|
+
if (operator === "+") {
|
|
74
|
+
// x + y ≡ (x ^ y) + 2 * (x & y)
|
|
75
|
+
replacement = t.binaryExpression("+", t.binaryExpression("^", t.cloneNode(left), t.cloneNode(right)), t.binaryExpression("*", t.numericLiteral(2), t.binaryExpression("&", t.cloneNode(left), t.cloneNode(right))));
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// x - y ≡ (x ^ y) - 2 * (~x & y)
|
|
79
|
+
replacement = t.binaryExpression("-", t.binaryExpression("^", t.cloneNode(left), t.cloneNode(right)), t.binaryExpression("*", t.numericLiteral(2), t.binaryExpression("&", t.unaryExpression("~", t.cloneNode(left)), t.cloneNode(right))));
|
|
80
|
+
}
|
|
81
|
+
if (!replacement.extra)
|
|
82
|
+
replacement.extra = {};
|
|
83
|
+
replacement.extra["mbaExpanded"] = true;
|
|
84
|
+
path.replaceWith(replacement);
|
|
85
|
+
path.skip();
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=mba.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mba.js","sourceRoot":"","sources":["../../../src/obfuscation/mba.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,4BAiEC;AA7ED,+DAAuC;AACvC,gDAAkC;AAGlC;;;;;;;GAOG;AACH,SAAgB,QAAQ,CAAC,GAAW,EAAE,UAAsB,EAAE;IAC5D,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;IAEnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,IAAA,kBAAQ,EAAC,GAAG,EAAE;YACZ,gBAAgB,EAAE;gBAChB,IAAI,CAAC,IAAI;oBACP,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;oBAE5C,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC;wBAAE,OAAO;oBAC5D,qCAAqC;oBACrC,IAAI,QAAQ,KAAK,GAAG,IAAI,QAAQ,KAAK,GAAG;wBAAE,OAAO;oBAEjD,oEAAoE;oBACpE,IACE,QAAQ,KAAK,GAAG;wBAChB,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC;4BACtB,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC;4BACxB,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC;4BACzB,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;wBAE7B,OAAO;oBAET,6BAA6B;oBAC7B,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,aAAa,CAAC;wBAAE,OAAO;oBAE7C,IAAI,WAAyB,CAAC;oBAE9B,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;wBACrB,kCAAkC;wBAClC,WAAW,GAAG,CAAC,CAAC,gBAAgB,CAC9B,GAAG,EACH,CAAC,CAAC,gBAAgB,CAAC,GAAG,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAC9D,CAAC,CAAC,gBAAgB,CAChB,GAAG,EACH,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EACnB,CAAC,CAAC,gBAAgB,CAAC,GAAG,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAC/D,CACF,CAAC;oBACJ,CAAC;yBAAM,CAAC;wBACN,mCAAmC;wBACnC,WAAW,GAAG,CAAC,CAAC,gBAAgB,CAC9B,GAAG,EACH,CAAC,CAAC,gBAAgB,CAAC,GAAG,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAC9D,CAAC,CAAC,gBAAgB,CAChB,GAAG,EACH,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EACnB,CAAC,CAAC,gBAAgB,CAChB,GAAG,EACH,CAAC,CAAC,eAAe,CAAC,GAAG,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,EACzC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CACnB,CACF,CACF,CAAC;oBACJ,CAAC;oBAED,IAAI,CAAC,WAAW,CAAC,KAAK;wBAAE,WAAW,CAAC,KAAK,GAAG,EAAE,CAAC;oBAC/C,WAAW,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;oBAExC,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;oBAC9B,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,CAAC;aACF;SACF,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as t from "@babel/types";
|
|
2
|
+
import type { SequenceExpressionOptions } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* Pass: Sequence Expression Flattening
|
|
5
|
+
*
|
|
6
|
+
* Converts block statements inside `if` / `else` branches into comma-separated
|
|
7
|
+
* sequence expressions, mirroring reCAPTCHA's code-flattening technique.
|
|
8
|
+
*
|
|
9
|
+
* Before:
|
|
10
|
+
* if (cond) { a = 1; b = 2; }
|
|
11
|
+
*
|
|
12
|
+
* After:
|
|
13
|
+
* cond && ((a = 1), (b = 2));
|
|
14
|
+
*/
|
|
15
|
+
export declare function applySequenceExpression(ast: t.File, options?: SequenceExpressionOptions): void;
|
|
16
|
+
//# sourceMappingURL=sequenceExpression.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sequenceExpression.d.ts","sourceRoot":"","sources":["../../../src/obfuscation/sequenceExpression.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,cAAc,CAAC;AAClC,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAE1D;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,CAAC,CAAC,IAAI,EACX,OAAO,GAAE,yBAA8B,GACtC,IAAI,CAsCN"}
|