js-confuser 1.5.9 → 1.7.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/.github/workflows/node.js.yml +2 -2
- package/CHANGELOG.md +55 -0
- package/README.md +346 -165
- package/dist/constants.js +6 -2
- package/dist/index.js +9 -21
- package/dist/obfuscator.js +19 -31
- package/dist/options.js +5 -5
- package/dist/order.js +1 -3
- package/dist/presets.js +6 -7
- package/dist/probability.js +2 -4
- package/dist/templates/bufferToString.js +13 -0
- package/dist/templates/crash.js +3 -3
- package/dist/templates/es5.js +18 -0
- package/dist/templates/functionLength.js +16 -0
- package/dist/transforms/calculator.js +77 -21
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
- package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -1
- package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
- package/dist/transforms/deadCode.js +33 -25
- package/dist/transforms/dispatcher.js +8 -4
- package/dist/transforms/es5/antiDestructuring.js +2 -0
- package/dist/transforms/es5/es5.js +31 -34
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +92 -58
- package/dist/transforms/finalizer.js +82 -0
- package/dist/transforms/flatten.js +229 -148
- package/dist/transforms/identifier/globalAnalysis.js +88 -0
- package/dist/transforms/identifier/globalConcealing.js +10 -83
- package/dist/transforms/identifier/movedDeclarations.js +35 -88
- package/dist/transforms/identifier/renameVariables.js +124 -59
- package/dist/transforms/identifier/variableAnalysis.js +58 -62
- package/dist/transforms/lock/lock.js +0 -37
- package/dist/transforms/minify.js +60 -57
- package/dist/transforms/opaquePredicates.js +1 -1
- package/dist/transforms/preparation/preparation.js +2 -2
- package/dist/transforms/preparation.js +231 -0
- package/dist/transforms/renameLabels.js +1 -1
- package/dist/transforms/rgf.js +139 -247
- package/dist/transforms/stack.js +128 -26
- package/dist/transforms/string/encoding.js +150 -179
- package/dist/transforms/string/stringCompression.js +14 -15
- package/dist/transforms/string/stringConcealing.js +25 -8
- package/dist/transforms/string/stringEncoding.js +13 -24
- package/dist/transforms/transform.js +12 -19
- package/dist/traverse.js +24 -10
- package/dist/util/gen.js +17 -1
- package/dist/util/identifiers.js +37 -3
- package/dist/util/insert.js +35 -4
- package/dist/util/random.js +15 -0
- package/docs/ControlFlowFlattening.md +595 -0
- package/{Countermeasures.md → docs/Countermeasures.md} +1 -15
- package/{Integrity.md → docs/Integrity.md} +2 -2
- package/docs/RGF.md +419 -0
- package/package.json +5 -5
- package/src/constants.ts +3 -0
- package/src/index.ts +2 -2
- package/src/obfuscator.ts +19 -31
- package/src/options.ts +14 -103
- package/src/order.ts +1 -5
- package/src/presets.ts +6 -7
- package/src/probability.ts +2 -3
- package/src/templates/bufferToString.ts +68 -0
- package/src/templates/crash.ts +15 -19
- package/src/templates/es5.ts +131 -0
- package/src/templates/functionLength.ts +14 -0
- package/src/transforms/calculator.ts +122 -59
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
- package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +4 -1
- package/src/transforms/deadCode.ts +383 -26
- package/src/transforms/dispatcher.ts +9 -4
- package/src/transforms/es5/antiDestructuring.ts +2 -0
- package/src/transforms/es5/es5.ts +32 -77
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +133 -129
- package/src/transforms/{hexadecimalNumbers.ts → finalizer.ts} +29 -13
- package/src/transforms/flatten.ts +357 -300
- package/src/transforms/identifier/globalAnalysis.ts +85 -0
- package/src/transforms/identifier/globalConcealing.ts +14 -103
- package/src/transforms/identifier/movedDeclarations.ts +49 -102
- package/src/transforms/identifier/renameVariables.ts +149 -78
- package/src/transforms/identifier/variableAnalysis.ts +66 -73
- package/src/transforms/lock/lock.ts +1 -42
- package/src/transforms/minify.ts +91 -75
- package/src/transforms/opaquePredicates.ts +2 -2
- package/src/transforms/preparation.ts +238 -0
- package/src/transforms/renameLabels.ts +2 -2
- package/src/transforms/rgf.ts +213 -405
- package/src/transforms/stack.ts +156 -36
- package/src/transforms/string/encoding.ts +115 -212
- package/src/transforms/string/stringCompression.ts +27 -18
- package/src/transforms/string/stringConcealing.ts +39 -9
- package/src/transforms/string/stringEncoding.ts +18 -18
- package/src/transforms/transform.ts +21 -23
- package/src/traverse.ts +23 -4
- package/src/types.ts +2 -1
- package/src/util/gen.ts +28 -3
- package/src/util/identifiers.ts +43 -2
- package/src/util/insert.ts +38 -3
- package/src/util/random.ts +13 -0
- package/test/code/Cash.test.ts +1 -1
- package/test/code/Dynamic.test.ts +12 -10
- package/test/code/ES6.src.js +146 -0
- package/test/code/ES6.test.ts +28 -2
- package/test/index.test.ts +2 -1
- package/test/probability.test.ts +44 -0
- package/test/templates/template.test.ts +1 -1
- package/test/transforms/antiTooling.test.ts +22 -0
- package/test/transforms/calculator.test.ts +40 -0
- package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +702 -160
- package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
- package/test/transforms/deadCode.test.ts +66 -15
- package/test/transforms/dispatcher.test.ts +20 -1
- package/test/transforms/es5/antiDestructuring.test.ts +16 -0
- package/test/transforms/flatten.test.ts +399 -86
- package/test/transforms/identifier/movedDeclarations.test.ts +63 -8
- package/test/transforms/identifier/renameVariables.test.ts +119 -0
- package/test/transforms/lock/antiDebug.test.ts +2 -2
- package/test/transforms/lock/lock.test.ts +1 -48
- package/test/transforms/minify.test.ts +104 -0
- package/test/transforms/preparation.test.ts +157 -0
- package/test/transforms/rgf.test.ts +261 -381
- package/test/transforms/stack.test.ts +143 -21
- package/test/transforms/string/stringCompression.test.ts +39 -0
- package/test/transforms/string/stringConcealing.test.ts +82 -0
- package/test/transforms/string/stringEncoding.test.ts +53 -2
- package/test/transforms/transform.test.ts +66 -0
- package/test/traverse.test.ts +139 -0
- package/test/util/identifiers.test.ts +113 -1
- package/test/util/insert.test.ts +57 -3
- package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
- package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
- package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
- package/src/transforms/eval.ts +0 -89
- package/src/transforms/hideInitializingCode.ts +0 -432
- package/src/transforms/identifier/nameRecycling.ts +0 -280
- package/src/transforms/label.ts +0 -64
- package/src/transforms/preparation/nameConflicts.ts +0 -102
- package/src/transforms/preparation/preparation.ts +0 -176
- package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
- package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
- package/test/transforms/eval.test.ts +0 -131
- package/test/transforms/hideInitializingCode.test.ts +0 -336
- package/test/transforms/identifier/nameRecycling.test.ts +0 -205
- package/test/transforms/preparation/nameConflicts.test.ts +0 -52
- package/test/transforms/preparation/preparation.test.ts +0 -62
|
@@ -2,6 +2,9 @@ import { isBlock } from "../../traverse";
|
|
|
2
2
|
import { Identifier, SequenceExpression } from "../../util/gen";
|
|
3
3
|
import Transform from "../transform";
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Expression Obfuscation runs before Control Flow Flattening
|
|
7
|
+
*/
|
|
5
8
|
export default class ExpressionObfuscation extends Transform {
|
|
6
9
|
constructor(o) {
|
|
7
10
|
super(o);
|
|
@@ -17,7 +20,7 @@ export default class ExpressionObfuscation extends Transform {
|
|
|
17
20
|
var deleteExprs = [];
|
|
18
21
|
|
|
19
22
|
object.body.forEach((stmt, i) => {
|
|
20
|
-
if (stmt.type == "ExpressionStatement") {
|
|
23
|
+
if (stmt.type == "ExpressionStatement" && !stmt.directive) {
|
|
21
24
|
var expr = stmt.expression;
|
|
22
25
|
|
|
23
26
|
if (
|
|
@@ -226,6 +226,356 @@ function setCookie(cname, cvalue, exdays) {
|
|
|
226
226
|
getHeightBalanced,
|
|
227
227
|
};
|
|
228
228
|
`),
|
|
229
|
+
Template(`
|
|
230
|
+
function ListNode(){}
|
|
231
|
+
var addTwoNumbers = function(l1, l2) {
|
|
232
|
+
var carry = 0;
|
|
233
|
+
var sum = 0;
|
|
234
|
+
var head = new ListNode(0);
|
|
235
|
+
var now = head;
|
|
236
|
+
var a = l1;
|
|
237
|
+
var b = l2;
|
|
238
|
+
while (a !== null || b !== null) {
|
|
239
|
+
sum = (a ? a.val : 0) + (b ? b.val : 0) + carry;
|
|
240
|
+
carry = Math.floor(sum / 10);
|
|
241
|
+
now.next = new ListNode(sum % 10);
|
|
242
|
+
now = now.next;
|
|
243
|
+
a = a ? a.next : null;
|
|
244
|
+
b = b ? b.next : null;
|
|
245
|
+
}
|
|
246
|
+
if (carry) now.next = new ListNode(carry);
|
|
247
|
+
return head.next;
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
console.log(addTwoNumbers)
|
|
251
|
+
`),
|
|
252
|
+
Template(`
|
|
253
|
+
var threeSum = function(nums) {
|
|
254
|
+
var len = nums.length;
|
|
255
|
+
var res = [];
|
|
256
|
+
var l = 0;
|
|
257
|
+
var r = 0;
|
|
258
|
+
nums.sort((a, b) => (a - b));
|
|
259
|
+
for (var i = 0; i < len; i++) {
|
|
260
|
+
if (i > 0 && nums[i] === nums[i - 1]) continue;
|
|
261
|
+
l = i + 1;
|
|
262
|
+
r = len - 1;
|
|
263
|
+
while (l < r) {
|
|
264
|
+
if (nums[i] + nums[l] + nums[r] < 0) {
|
|
265
|
+
l++;
|
|
266
|
+
} else if (nums[i] + nums[l] + nums[r] > 0) {
|
|
267
|
+
r--;
|
|
268
|
+
} else {
|
|
269
|
+
res.push([nums[i], nums[l], nums[r]]);
|
|
270
|
+
while (l < r && nums[l] === nums[l + 1]) l++;
|
|
271
|
+
while (l < r && nums[r] === nums[r - 1]) r--;
|
|
272
|
+
l++;
|
|
273
|
+
r--;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return res;
|
|
278
|
+
};
|
|
279
|
+
console.log(threeSum)
|
|
280
|
+
`),
|
|
281
|
+
Template(`
|
|
282
|
+
var combinationSum2 = function(candidates, target) {
|
|
283
|
+
var res = [];
|
|
284
|
+
var len = candidates.length;
|
|
285
|
+
candidates.sort((a, b) => (a - b));
|
|
286
|
+
dfs(res, [], 0, len, candidates, target);
|
|
287
|
+
return res;
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
var dfs = function (res, stack, index, len, candidates, target) {
|
|
291
|
+
var tmp = null;
|
|
292
|
+
if (target < 0) return;
|
|
293
|
+
if (target === 0) return res.push(stack);
|
|
294
|
+
for (var i = index; i < len; i++) {
|
|
295
|
+
if (candidates[i] > target) break;
|
|
296
|
+
if (i > index && candidates[i] === candidates[i - 1]) continue;
|
|
297
|
+
tmp = Array.from(stack);
|
|
298
|
+
tmp.push(candidates[i]);
|
|
299
|
+
dfs(res, tmp, i + 1, len, candidates, target - candidates[i]);
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
console.log(combinationSum2);
|
|
304
|
+
`),
|
|
305
|
+
Template(`
|
|
306
|
+
var isScramble = function(s1, s2) {
|
|
307
|
+
return helper({}, s1, s2);
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
var helper = function (dp, s1, s2) {
|
|
311
|
+
var map = {};
|
|
312
|
+
|
|
313
|
+
if (dp[s1 + s2] !== undefined) return dp[s1 + s2];
|
|
314
|
+
if (s1 === s2) return true;
|
|
315
|
+
|
|
316
|
+
for (var j = 0; j < s1.length; j++) {
|
|
317
|
+
if (map[s1[j]] === undefined) map[s1[j]] = 0;
|
|
318
|
+
if (map[s2[j]] === undefined) map[s2[j]] = 0;
|
|
319
|
+
map[s1[j]]++;
|
|
320
|
+
map[s2[j]]--;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
for (var key in map) {
|
|
324
|
+
if (map[key] !== 0) {
|
|
325
|
+
dp[s1 + s2] = false;
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
for (var i = 1; i < s1.length; i++) {
|
|
331
|
+
if ((helper(dp, s1.substr(0, i), s2.substr(0, i))
|
|
332
|
+
&& helper(dp, s1.substr(i), s2.substr(i))) ||
|
|
333
|
+
(helper(dp, s1.substr(0, i), s2.substr(s2.length - i))
|
|
334
|
+
&& helper(dp, s1.substr(i), s2.substr(0, s2.length - i)))) {
|
|
335
|
+
dp[s1 + s2] = true;
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
dp[s1 + s2] = false;
|
|
341
|
+
return false;
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
console.log(isScramble);
|
|
345
|
+
`),
|
|
346
|
+
Template(`
|
|
347
|
+
var candy = function(ratings) {
|
|
348
|
+
var len = ratings.length;
|
|
349
|
+
var res = [];
|
|
350
|
+
var sum = 0;
|
|
351
|
+
for (var i = 0; i < len; i++) {
|
|
352
|
+
res.push((i !== 0 && ratings[i] > ratings[i - 1]) ? (res[i - 1] + 1) : 1);
|
|
353
|
+
}
|
|
354
|
+
for (var j = len - 1; j >= 0; j--) {
|
|
355
|
+
if (j !== len - 1 && ratings[j] > ratings[j + 1]) res[j] = Math.max(res[j], res[j + 1] + 1);
|
|
356
|
+
sum += res[j];
|
|
357
|
+
}
|
|
358
|
+
return sum;
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
console.log(candy)
|
|
362
|
+
`),
|
|
363
|
+
Template(`
|
|
364
|
+
var maxPoints = function(points) {
|
|
365
|
+
var max = 0;
|
|
366
|
+
var map = {};
|
|
367
|
+
var localMax = 0;
|
|
368
|
+
var samePoint = 0;
|
|
369
|
+
var k = 0;
|
|
370
|
+
var len = points.length;
|
|
371
|
+
for (var i = 0; i < len; i++) {
|
|
372
|
+
map = {};
|
|
373
|
+
localMax = 0;
|
|
374
|
+
samePoint = 1;
|
|
375
|
+
for (var j = i + 1; j < len; j++) {
|
|
376
|
+
if (points[i].x === points[j].x && points[i].y === points[j].y) {
|
|
377
|
+
samePoint++;
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
if (points[i].y === points[j].y) k = Number.MAX_SAFE_INTEGER;
|
|
381
|
+
else k = (points[i].x - points[j].x) / (points[i].y - points[j].y);
|
|
382
|
+
if (!map[k]) map[k] = 0;
|
|
383
|
+
map[k]++;
|
|
384
|
+
localMax = Math.max(localMax, map[k]);
|
|
385
|
+
}
|
|
386
|
+
localMax += samePoint;
|
|
387
|
+
max = Math.max(max, localMax);
|
|
388
|
+
}
|
|
389
|
+
return max;
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
console.log(maxPoints)
|
|
393
|
+
`),
|
|
394
|
+
Template(`
|
|
395
|
+
var maximumGap = function(nums) {
|
|
396
|
+
var len = nums.length;
|
|
397
|
+
if (len < 2) return 0;
|
|
398
|
+
|
|
399
|
+
var max = Math.max(...nums);
|
|
400
|
+
var min = Math.min(...nums);
|
|
401
|
+
if (max === min) return 0;
|
|
402
|
+
|
|
403
|
+
var minBuckets = Array(len - 1).fill(Number.MAX_SAFE_INTEGER);
|
|
404
|
+
var maxBuckets = Array(len - 1).fill(Number.MIN_SAFE_INTEGER);
|
|
405
|
+
var gap = Math.ceil((max - min) / (len - 1));
|
|
406
|
+
var index = 0;
|
|
407
|
+
for (var i = 0; i < len; i++) {
|
|
408
|
+
if (nums[i] === min || nums[i] === max) continue;
|
|
409
|
+
index = Math.floor((nums[i] - min) / gap);
|
|
410
|
+
minBuckets[index] = Math.min(minBuckets[index], nums[i]);
|
|
411
|
+
maxBuckets[index] = Math.max(maxBuckets[index], nums[i]);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
var maxGap = Number.MIN_SAFE_INTEGER;
|
|
415
|
+
var preVal = min;
|
|
416
|
+
for (var j = 0; j < len - 1; j++) {
|
|
417
|
+
if (minBuckets[j] === Number.MAX_SAFE_INTEGER && maxBuckets[j] === Number.MIN_SAFE_INTEGER) continue;
|
|
418
|
+
maxGap = Math.max(maxGap, minBuckets[j] - preVal);
|
|
419
|
+
preVal = maxBuckets[j];
|
|
420
|
+
}
|
|
421
|
+
maxGap = Math.max(maxGap, max - preVal);
|
|
422
|
+
|
|
423
|
+
return maxGap;
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
console.log(maximumGap);
|
|
427
|
+
`),
|
|
428
|
+
Template(`
|
|
429
|
+
/**
|
|
430
|
+
* @param {number} capacity
|
|
431
|
+
*/
|
|
432
|
+
var LRUCache = function(capacity) {
|
|
433
|
+
this.capacity = capacity;
|
|
434
|
+
this.length = 0;
|
|
435
|
+
this.map = {};
|
|
436
|
+
this.head = null;
|
|
437
|
+
this.tail = null;
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* @param {number} key
|
|
442
|
+
* @return {number}
|
|
443
|
+
*/
|
|
444
|
+
LRUCache.prototype.get = function(key) {
|
|
445
|
+
var node = this.map[key];
|
|
446
|
+
if (node) {
|
|
447
|
+
this.remove(node);
|
|
448
|
+
this.insert(node.key, node.val);
|
|
449
|
+
return node.val;
|
|
450
|
+
} else {
|
|
451
|
+
return -1;
|
|
452
|
+
}
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* @param {number} key
|
|
457
|
+
* @param {number} value
|
|
458
|
+
* @return {void}
|
|
459
|
+
*/
|
|
460
|
+
LRUCache.prototype.put = function(key, value) {
|
|
461
|
+
if (this.map[key]) {
|
|
462
|
+
this.remove(this.map[key]);
|
|
463
|
+
this.insert(key, value);
|
|
464
|
+
} else {
|
|
465
|
+
if (this.length === this.capacity) {
|
|
466
|
+
this.remove(this.head);
|
|
467
|
+
this.insert(key, value);
|
|
468
|
+
} else {
|
|
469
|
+
this.insert(key, value);
|
|
470
|
+
this.length++;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Your LRUCache object will be instantiated and called as such:
|
|
477
|
+
* var obj = Object.create(LRUCache).createNew(capacity)
|
|
478
|
+
* var param_1 = obj.get(key)
|
|
479
|
+
* obj.put(key,value)
|
|
480
|
+
*/
|
|
481
|
+
|
|
482
|
+
LRUCache.prototype.remove = function (node) {
|
|
483
|
+
var prev = node.prev;
|
|
484
|
+
var next = node.next;
|
|
485
|
+
if (next) next.prev = prev;
|
|
486
|
+
if (prev) prev.next = next;
|
|
487
|
+
if (this.head === node) this.head = next;
|
|
488
|
+
if (this.tail === node) this.tail = prev;
|
|
489
|
+
delete this.map[node.key];
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
LRUCache.prototype.insert = function (key, val) {
|
|
493
|
+
var node = new List(key, val);
|
|
494
|
+
if (!this.tail) {
|
|
495
|
+
this.tail = node;
|
|
496
|
+
this.head = node;
|
|
497
|
+
} else {
|
|
498
|
+
this.tail.next = node;
|
|
499
|
+
node.prev = this.tail;
|
|
500
|
+
this.tail = node;
|
|
501
|
+
}
|
|
502
|
+
this.map[key] = node;
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
console.log(LRUCache);
|
|
506
|
+
`),
|
|
507
|
+
Template(`
|
|
508
|
+
var isInterleave = function(s1, s2, s3) {
|
|
509
|
+
var dp = {};
|
|
510
|
+
if (s3.length !== s1.length + s2.length) return false;
|
|
511
|
+
return helper(s1, s2, s3, 0, 0, 0, dp);
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
var helper = function (s1, s2, s3, i, j, k, dp) {
|
|
515
|
+
var res = false;
|
|
516
|
+
|
|
517
|
+
if (k >= s3.length) return true;
|
|
518
|
+
if (dp['' + i + j + k] !== undefined) return dp['' + i + j + k];
|
|
519
|
+
|
|
520
|
+
if (s3[k] === s1[i] && s3[k] === s2[j]) {
|
|
521
|
+
res = helper(s1, s2, s3, i + 1, j, k + 1, dp) || helper(s1, s2, s3, i, j + 1, k + 1, dp);
|
|
522
|
+
} else if (s3[k] === s1[i]) {
|
|
523
|
+
res = helper(s1, s2, s3, i + 1, j, k + 1, dp);
|
|
524
|
+
} else if (s3[k] === s2[j]) {
|
|
525
|
+
res = helper(s1, s2, s3, i, j + 1, k + 1, dp);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
dp['' + i + j + k] = res;
|
|
529
|
+
|
|
530
|
+
return res;
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
console.log(isInterleave);
|
|
534
|
+
`),
|
|
535
|
+
Template(`
|
|
536
|
+
var solveNQueens = function(n) {
|
|
537
|
+
var res = [];
|
|
538
|
+
if (n === 1 || n >= 4) dfs(res, [], n, 0);
|
|
539
|
+
return res;
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
var dfs = function (res, points, n, index) {
|
|
543
|
+
for (var i = index; i < n; i++) {
|
|
544
|
+
if (points.length !== i) return;
|
|
545
|
+
for (var j = 0; j < n; j++) {
|
|
546
|
+
if (isValid(points, [i, j])) {
|
|
547
|
+
points.push([i, j]);
|
|
548
|
+
dfs(res, points, n, i + 1);
|
|
549
|
+
if (points.length === n) res.push(buildRes(points));
|
|
550
|
+
points.pop();
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
|
|
556
|
+
var buildRes = function (points) {
|
|
557
|
+
var res = [];
|
|
558
|
+
var n = points.length;
|
|
559
|
+
for (var i = 0; i < n; i++) {
|
|
560
|
+
res[i] = '';
|
|
561
|
+
for (var j = 0; j < n; j++) {
|
|
562
|
+
res[i] += (points[i][1] === j ? 'Q' : '.');
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return res;
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
var isValid = function (oldPoints, newPoint) {
|
|
569
|
+
var len = oldPoints.length;
|
|
570
|
+
for (var i = 0; i < len; i++) {
|
|
571
|
+
if (oldPoints[i][0] === newPoint[0] || oldPoints[i][1] === newPoint[1]) return false;
|
|
572
|
+
if (Math.abs((oldPoints[i][0] - newPoint[0]) / (oldPoints[i][1] - newPoint[1])) === 1) return false;
|
|
573
|
+
}
|
|
574
|
+
return true;
|
|
575
|
+
};
|
|
576
|
+
|
|
577
|
+
console.log(solveNQueens);
|
|
578
|
+
`),
|
|
229
579
|
];
|
|
230
580
|
|
|
231
581
|
/**
|
|
@@ -235,7 +585,6 @@ function setCookie(cname, cvalue, exdays) {
|
|
|
235
585
|
* - Adds fake code from various samples.
|
|
236
586
|
*/
|
|
237
587
|
export default class DeadCode extends Transform {
|
|
238
|
-
usedNames: Set<string>;
|
|
239
588
|
made: number;
|
|
240
589
|
|
|
241
590
|
constructor(o) {
|
|
@@ -253,35 +602,43 @@ export default class DeadCode extends Transform {
|
|
|
253
602
|
}
|
|
254
603
|
|
|
255
604
|
transform(object: Node, parents: Node[]) {
|
|
256
|
-
if (ComputeProbabilityMap(this.options.deadCode)) {
|
|
257
|
-
return
|
|
258
|
-
|
|
259
|
-
if (this.made > 100) {
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
605
|
+
if (!ComputeProbabilityMap(this.options.deadCode)) {
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
262
608
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
609
|
+
// Hard-coded limit of 100 Dead Code insertions
|
|
610
|
+
this.made++;
|
|
611
|
+
if (this.made > 100) {
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
return () => {
|
|
616
|
+
var body = getBlockBody(object);
|
|
267
617
|
|
|
268
|
-
|
|
269
|
-
|
|
618
|
+
// Do not place code before Import statements or 'use strict' directives
|
|
619
|
+
var safeOffset = 0;
|
|
620
|
+
for (var node of body) {
|
|
621
|
+
if (node.type === "ImportDeclaration" || node.directive) safeOffset++;
|
|
622
|
+
else break;
|
|
623
|
+
}
|
|
270
624
|
|
|
271
|
-
|
|
272
|
-
do {
|
|
273
|
-
template = choice(templates);
|
|
274
|
-
} while (this.options.es5 && template.source.includes("async"));
|
|
625
|
+
var index = getRandomInteger(safeOffset, body.length);
|
|
275
626
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
);
|
|
627
|
+
var name = this.getPlaceholder();
|
|
628
|
+
var variableDeclaration = VariableDeclaration(
|
|
629
|
+
VariableDeclarator(name, Literal(false))
|
|
630
|
+
);
|
|
281
631
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
632
|
+
var template;
|
|
633
|
+
do {
|
|
634
|
+
template = choice(templates);
|
|
635
|
+
} while (this.options.es5 && template.source.includes("async"));
|
|
636
|
+
|
|
637
|
+
var ifStatement = IfStatement(Identifier(name), template.compile(), null);
|
|
638
|
+
|
|
639
|
+
body.splice(index, 0, ifStatement);
|
|
640
|
+
|
|
641
|
+
prepend(object, variableDeclaration);
|
|
642
|
+
};
|
|
286
643
|
}
|
|
287
644
|
}
|
|
@@ -68,6 +68,8 @@ import Template from "../templates/template";
|
|
|
68
68
|
* 3. using `this`
|
|
69
69
|
*/
|
|
70
70
|
export default class Dispatcher extends Transform {
|
|
71
|
+
// Debug mode preserves function names
|
|
72
|
+
isDebug = false;
|
|
71
73
|
count: number;
|
|
72
74
|
|
|
73
75
|
constructor(o) {
|
|
@@ -124,6 +126,8 @@ export default class Dispatcher extends Transform {
|
|
|
124
126
|
|
|
125
127
|
if (context === c) {
|
|
126
128
|
if (o.type == "FunctionDeclaration" && o.id.name) {
|
|
129
|
+
var name = o.id.name;
|
|
130
|
+
|
|
127
131
|
if (
|
|
128
132
|
o.$requiresEval ||
|
|
129
133
|
o.async ||
|
|
@@ -136,8 +140,6 @@ export default class Dispatcher extends Transform {
|
|
|
136
140
|
illegalFnNames.add(name);
|
|
137
141
|
}
|
|
138
142
|
|
|
139
|
-
var name = o.id.name;
|
|
140
|
-
|
|
141
143
|
// If dupe, no routing
|
|
142
144
|
if (functionDeclarations[name]) {
|
|
143
145
|
illegalFnNames.add(name);
|
|
@@ -196,14 +198,17 @@ export default class Dispatcher extends Transform {
|
|
|
196
198
|
// map original name->new game
|
|
197
199
|
var gen = this.getGenerator();
|
|
198
200
|
Object.keys(functionDeclarations).forEach((name) => {
|
|
199
|
-
newFnNames[name] =
|
|
201
|
+
newFnNames[name] = this.isDebug
|
|
202
|
+
? "_dispatcher_" + this.count + "_" + name
|
|
203
|
+
: gen.generate();
|
|
200
204
|
});
|
|
201
205
|
// set containing new name
|
|
202
206
|
var set = new Set(Object.keys(newFnNames));
|
|
203
207
|
|
|
204
208
|
// Only make a dispatcher function if it caught any functions
|
|
205
209
|
if (set.size > 0) {
|
|
206
|
-
var payloadArg =
|
|
210
|
+
var payloadArg =
|
|
211
|
+
this.getPlaceholder() + "_dispatcher_" + this.count + "_payload";
|
|
207
212
|
|
|
208
213
|
var dispatcherFnName =
|
|
209
214
|
this.getPlaceholder() + "_dispatcher_" + this.count;
|
|
@@ -211,6 +211,8 @@ export default class AntiDestructuring extends Transform {
|
|
|
211
211
|
exprs.push(AssignmentExpression(operator, clone(x), realm));
|
|
212
212
|
|
|
213
213
|
names.add(x.name);
|
|
214
|
+
} else if (x.type == "MemberExpression") {
|
|
215
|
+
exprs.push(AssignmentExpression(operator, clone(x), realm));
|
|
214
216
|
} else if (x.type == "ObjectPattern") {
|
|
215
217
|
x.properties.forEach((property) => {
|
|
216
218
|
recursive(
|
|
@@ -7,14 +7,10 @@ import {
|
|
|
7
7
|
BlockStatement,
|
|
8
8
|
ReturnStatement,
|
|
9
9
|
CallExpression,
|
|
10
|
-
ObjectExpression,
|
|
11
|
-
ArrayExpression,
|
|
12
10
|
ThisExpression,
|
|
13
|
-
Property,
|
|
14
11
|
} from "../../util/gen";
|
|
15
|
-
import { clone,
|
|
16
|
-
import { isBlock,
|
|
17
|
-
import Template from "../../templates/template";
|
|
12
|
+
import { clone, prepend } from "../../util/insert";
|
|
13
|
+
import { isBlock, walk } from "../../traverse";
|
|
18
14
|
import { ObfuscateOrder } from "../../order";
|
|
19
15
|
import { ok } from "assert";
|
|
20
16
|
import { reservedKeywords } from "../../constants";
|
|
@@ -23,6 +19,7 @@ import AntiTemplate from "./antiTemplate";
|
|
|
23
19
|
import AntiClass from "./antiClass";
|
|
24
20
|
import AntiES6Object from "./antiES6Object";
|
|
25
21
|
import AntiSpreadOperator from "./antiSpreadOperator";
|
|
22
|
+
import { ES5Template } from "../../templates/es5";
|
|
26
23
|
|
|
27
24
|
/**
|
|
28
25
|
* `Const` and `Let` are not allowed in ES5.
|
|
@@ -96,24 +93,40 @@ export class AntiArrowFunction extends Transform {
|
|
|
96
93
|
}
|
|
97
94
|
}
|
|
98
95
|
|
|
99
|
-
|
|
96
|
+
/**
|
|
97
|
+
* The ES5 options aims to convert ES6 and up features down to ES5-compatible code.
|
|
98
|
+
*
|
|
99
|
+
* The obfuscator regularly adds ES6 code (variable destructuring, spread element, etc.)
|
|
100
|
+
* This transformations goal is undo only these things.
|
|
101
|
+
*/
|
|
102
|
+
export default class ES5 extends Transform {
|
|
100
103
|
constructor(o) {
|
|
101
|
-
super(o);
|
|
104
|
+
super(o, ObfuscateOrder.ES5);
|
|
105
|
+
|
|
106
|
+
this.before.push(new AntiClass(o));
|
|
107
|
+
this.before.push(new AntiTemplate(o));
|
|
108
|
+
this.before.push(new AntiSpreadOperator(o));
|
|
109
|
+
this.before.push(new AntiES6Object(o));
|
|
110
|
+
this.before.push(new AntiArrowFunction(o));
|
|
111
|
+
this.before.push(new AntiDestructuring(o));
|
|
112
|
+
this.before.push(new AntiConstLet(o));
|
|
102
113
|
}
|
|
103
114
|
|
|
104
|
-
|
|
105
|
-
|
|
115
|
+
apply(tree: Node) {
|
|
116
|
+
super.apply(tree);
|
|
117
|
+
|
|
118
|
+
var nodesToAdd = ES5Template.compile();
|
|
119
|
+
prepend(tree, ...nodesToAdd);
|
|
106
120
|
}
|
|
107
121
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
object.init.type == "ExpressionStatement"
|
|
113
|
-
) {
|
|
114
|
-
object.init = object.init.expression;
|
|
115
|
-
}
|
|
122
|
+
// FixedExpressions
|
|
123
|
+
match(object: Node, parents: Node[]) {
|
|
124
|
+
return !!object.type;
|
|
125
|
+
}
|
|
116
126
|
|
|
127
|
+
transform(object: Node, parents: Node[]) {
|
|
128
|
+
return () => {
|
|
129
|
+
// Object.keyword -> Object["keyword"]
|
|
117
130
|
if (object.type == "MemberExpression") {
|
|
118
131
|
if (!object.computed && object.property.type == "Identifier") {
|
|
119
132
|
if (reservedKeywords.has(object.property.name)) {
|
|
@@ -123,6 +136,7 @@ class FixedExpressions extends Transform {
|
|
|
123
136
|
}
|
|
124
137
|
}
|
|
125
138
|
|
|
139
|
+
// { keyword: ... } -> { "keyword": ... }
|
|
126
140
|
if (object.type == "Property") {
|
|
127
141
|
if (!object.computed && object.key.type == "Identifier") {
|
|
128
142
|
if (reservedKeywords.has(object.key.name)) {
|
|
@@ -133,62 +147,3 @@ class FixedExpressions extends Transform {
|
|
|
133
147
|
};
|
|
134
148
|
}
|
|
135
149
|
}
|
|
136
|
-
|
|
137
|
-
export default class ES5 extends Transform {
|
|
138
|
-
constructor(o) {
|
|
139
|
-
super(o, ObfuscateOrder.ES5);
|
|
140
|
-
|
|
141
|
-
this.before.push(new AntiClass(o));
|
|
142
|
-
this.before.push(new AntiTemplate(o));
|
|
143
|
-
this.before.push(new AntiSpreadOperator(o));
|
|
144
|
-
this.before.push(new AntiES6Object(o));
|
|
145
|
-
this.before.push(new AntiArrowFunction(o));
|
|
146
|
-
this.before.push(new AntiDestructuring(o));
|
|
147
|
-
this.before.push(new AntiConstLet(o));
|
|
148
|
-
|
|
149
|
-
this.concurrent.push(new FixedExpressions(o));
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
match(object: Node, parents: Node[]) {
|
|
153
|
-
return object.type == "Program";
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
transform(object: Node, parents: Node[]) {
|
|
157
|
-
var block = getBlock(object, parents);
|
|
158
|
-
|
|
159
|
-
getBlockBody(block).splice(
|
|
160
|
-
0,
|
|
161
|
-
0,
|
|
162
|
-
...Template(`
|
|
163
|
-
!Array.prototype.forEach ? Array.prototype.forEach = function (callback, thisArg) {
|
|
164
|
-
thisArg = thisArg;
|
|
165
|
-
for (var i = 0; i < this.length; i++) {
|
|
166
|
-
callback.call(thisArg, this[i], i, this);
|
|
167
|
-
}
|
|
168
|
-
} : 0;
|
|
169
|
-
|
|
170
|
-
!Array.prototype.map ? Array.prototype.map = function (callback, thisArg) {
|
|
171
|
-
thisArg = thisArg;
|
|
172
|
-
var array=[];
|
|
173
|
-
for (var i = 0; i < this.length; i++) {
|
|
174
|
-
array.push( callback.call(thisArg, this[i], i, this) );
|
|
175
|
-
}
|
|
176
|
-
return array;
|
|
177
|
-
} : 0;
|
|
178
|
-
|
|
179
|
-
!Array.prototype.reduce ? Array.prototype.reduce = function(fn, initial) {
|
|
180
|
-
var values = this;
|
|
181
|
-
if ( typeof initial === "undefined" ) {
|
|
182
|
-
initial = 0;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
values.forEach(function(item, index){
|
|
186
|
-
initial = fn(initial, item, index, this);
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
return initial;
|
|
190
|
-
} : 0;
|
|
191
|
-
`).compile()
|
|
192
|
-
);
|
|
193
|
-
}
|
|
194
|
-
}
|