js-confuser-vm 0.0.6 → 0.0.7
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/CHANGELOG.md +55 -0
- package/README.MD +101 -37
- package/dist/build-runtime.js +15 -2
- package/dist/compiler.js +98 -51
- package/dist/runtime.js +5 -1
- package/dist/transforms/bytecode/aliasedOpcodes.js +2 -8
- package/dist/transforms/bytecode/macroOpcodes.js +21 -19
- package/dist/transforms/bytecode/microOpcodes.js +236 -0
- package/dist/transforms/bytecode/resolveContants.js +5 -11
- package/dist/transforms/bytecode/resolveLabels.js +5 -3
- package/dist/transforms/bytecode/specializedOpcodes.js +21 -16
- package/dist/transforms/runtime/internalVariables.js +202 -0
- package/dist/transforms/runtime/macroOpcodes.js +30 -18
- package/dist/transforms/runtime/microOpcodes.js +76 -0
- package/dist/transforms/runtime/specializedOpcodes.js +20 -18
- package/dist/utils/op-utils.js +15 -8
- package/index.ts +3 -2
- package/jest.config.js +2 -0
- package/package.json +1 -1
- package/src/build-runtime.ts +18 -3
- package/src/compiler.ts +152 -65
- package/src/options.ts +1 -0
- package/src/runtime.ts +5 -1
- package/src/transforms/bytecode/aliasedOpcodes.ts +2 -12
- package/src/transforms/bytecode/macroOpcodes.ts +28 -29
- package/src/transforms/bytecode/microOpcodes.ts +291 -0
- package/src/transforms/bytecode/resolveContants.ts +6 -13
- package/src/transforms/bytecode/resolveLabels.ts +5 -4
- package/src/transforms/bytecode/specializedOpcodes.ts +38 -28
- package/src/transforms/runtime/internalVariables.ts +270 -0
- package/src/transforms/runtime/macroOpcodes.ts +47 -20
- package/src/transforms/runtime/microOpcodes.ts +93 -0
- package/src/transforms/runtime/specializedOpcodes.ts +27 -32
- package/src/types.ts +1 -1
- package/src/utils/op-utils.ts +21 -8
- package/src/utilts.ts +0 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,58 @@
|
|
|
1
|
+
## `0.0.7` Micro Opcodes
|
|
2
|
+
|
|
3
|
+
- Added new option `microOpcodes` which breaks opcodes into multiple sub-opcodes.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
// Input Code
|
|
7
|
+
console.log("Hello world!");
|
|
8
|
+
|
|
9
|
+
// Before
|
|
10
|
+
// [2, 1, 0, 0], LOAD_GLOBAL reg[1] = console 1:0-1:7
|
|
11
|
+
// [0, 2, 1, 0], LOAD_CONST reg[2] = "log" 1:0-1:27
|
|
12
|
+
// [8, 3, 1, 2], GET_PROP reg[3] = reg[1][reg[2]] 1:0-1:27
|
|
13
|
+
// [0, 4, 2, 0], LOAD_CONST reg[4] = "Hello world!" 1:12-1:26
|
|
14
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = reg[3](recv=reg[1], 1 args) 1:0-1:27
|
|
15
|
+
|
|
16
|
+
// What the opcode "LOAD_CONST" looks like:
|
|
17
|
+
case OP.LOAD_CONST:
|
|
18
|
+
var dst = this._operand();
|
|
19
|
+
frame.regs[dst] = this._constant();
|
|
20
|
+
break;
|
|
21
|
+
|
|
22
|
+
// After
|
|
23
|
+
// [60, 1], MICRO_LOAD_GLOBAL_0 1 1:0-1:7
|
|
24
|
+
// [61, 0, 0], MICRO_LOAD_GLOBAL_1 [0, 0]
|
|
25
|
+
// [62], MICRO_LOAD_GLOBAL_2
|
|
26
|
+
// [63], MICRO_LOAD_GLOBAL_3
|
|
27
|
+
// [58, 2], MICRO_LOAD_CONST_0 2 1:0-1:27
|
|
28
|
+
// [59, 1, 0], MICRO_LOAD_CONST_1 [1, 0]
|
|
29
|
+
// [64, 3], MICRO_GET_PROP_0 3 1:0-1:27
|
|
30
|
+
// [65, 1], MICRO_GET_PROP_1 1
|
|
31
|
+
// [66, 2], MICRO_GET_PROP_2 2
|
|
32
|
+
// [67], MICRO_GET_PROP_3
|
|
33
|
+
// [58, 4], MICRO_LOAD_CONST_0 4 1:12-1:26
|
|
34
|
+
// [59, 2, 0], MICRO_LOAD_CONST_1 [2, 0]
|
|
35
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = reg[3](recv=reg[1], 1 args) 1:0-1:27
|
|
36
|
+
|
|
37
|
+
// What the opcodes "MICRO_LOAD_CONST_0" (58) and "MICRO_LOAD_CONST_1" (59) looks like:
|
|
38
|
+
case 58:
|
|
39
|
+
// MICRO_LOAD_CONST_0
|
|
40
|
+
this._internals[0] = this._operand();
|
|
41
|
+
break;
|
|
42
|
+
case 59:
|
|
43
|
+
// MICRO_LOAD_CONST_1
|
|
44
|
+
frame.regs[this._internals[0]] = this._constant();
|
|
45
|
+
break;
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- Fixed `Macro Opcodes` possibly clashing variables when merging opcode handlers.
|
|
49
|
+
|
|
50
|
+
- Added support for update expressions on member expressions (`object.prop++`, `object.prop--`)
|
|
51
|
+
|
|
52
|
+
- Added support for Template literals (ES6 feature added for convenience)
|
|
53
|
+
|
|
54
|
+
- Added programs [cash.min.js](https://github.com/fabiospampinato/cash/blob/master/dist/cash.min.js) and [sha256.js](https://gist.github.com/bryanchow/1649353) to the test suite
|
|
55
|
+
|
|
1
56
|
## `0.0.6` Register based
|
|
2
57
|
|
|
3
58
|
- Switched from stack-based to register-based VM.
|
package/README.MD
CHANGED
|
@@ -41,6 +41,7 @@ JsConfuserVM.obfuscate(`
|
|
|
41
41
|
concealConstants: true, // conceal strings and integers in the constant pool?
|
|
42
42
|
selfModifying: true, // do self-modifying bytecode for function bodies?
|
|
43
43
|
macroOpcodes: true, // create combined opcodes for repeated instruction sequences?
|
|
44
|
+
microOpcodes: true, // break opcodes into sub-opcodes?
|
|
44
45
|
specializedOpcodes: true, // create specialized opcodes for commonly used opcode+operand pairs?
|
|
45
46
|
aliasedOpcodes: true, // create duplicate opcodes for commonly used opcodes?
|
|
46
47
|
timingChecks: true, // add timing checks to detect debuggers?
|
|
@@ -50,25 +51,35 @@ JsConfuserVM.obfuscate(`
|
|
|
50
51
|
})
|
|
51
52
|
|
|
52
53
|
/*
|
|
53
|
-
var c=Symbol();function
|
|
54
|
-
function
|
|
55
|
-
function
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
a.g[
|
|
62
|
-
a
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
case
|
|
67
|
-
a.g[
|
|
68
|
-
|
|
69
|
-
for(
|
|
70
|
-
|
|
71
|
-
0,
|
|
54
|
+
var c=Symbol();function f(a,e){this.A=a;this.H=e;this.I=!1;this.J=void 0}function h(a){return a.I?a.J:a.A.h[a.H]}function k(a,e){a.I?a.J=e:a.A.h[a.H]=e}function m(a){this.v=a;this.D=[];this.prototype={}}function n(a,e,b){this.K=a;this.h=Array(a.v.L).fill(void 0);this.l=a.v.R;this.W=e!==void 0?e:void 0;this.G=b!==void 0?b:0;this.o=null;this.F=[]}function p(a,e,b,d){this.u=a;this.O=b;this.m=d;this.j=[];this.B=[];this.i=new n(new m({C:0,L:e,R:0}),void 0,0);this.g={}}
|
|
55
|
+
function v(a){return a.u[a.i.l++]}function w(a,e,b){for(var d=0;d<a.B.length;d++){var g=a.B[d];if(g.A===e&&g.H===b)return g}g=new f(e,b);a.B.push(g);return g}function x(a,e,b){e=e??v(a);b=b??v(a);a=a.O[e];if(!b)return a;if(typeof a==="number")return a^b;a=typeof Buffer!=="undefined"?Buffer.from(a,"base64"):Uint8Array.from(atob(a),function(g){return g.charCodeAt(0)});e="";for(var d=0;d<a.length/2;d++)e+=String.fromCharCode((a[d*2]|a[d*2+1]<<8)^b+d&65535);return e}
|
|
56
|
+
function z(a,e){a.B=a.B.filter(function(b){return b.A===e?(b.J=b.A.h[b.H],b.I=!0,!1):!0})}
|
|
57
|
+
function A(a){for(var e=performance.now();;){var b=a.i;if(b.l>=a.u.length)break;var d=b.l++;d=a.u[d];var g=performance.now(),D=g-e>1E3;e=g;if(D){for(d=0;d<a.u.length;d++)a.u[d]=0;b.h.fill(void 0);d=51142;b.l=a.u.length}try{switch(d){case 48376:a.g[16541]=v(a);a.g[36877]=b.h[v(a)];b.h[a.g[16541]]=a.g[36877]^b.h[v(a)];break;case 24807:a.g[32755]=v(a);a.g[30211]=b.h[v(a)];b.h[a.g[32755]]=a.g[30211]>>>b.h[v(a)];break;case 25812:a.g[11979]=3;b.h[a.g[11979]]=b.h[4];break;case 21199:a.g[16541]=4;b.h[a.g[16541]]=
|
|
58
|
+
x(a,0,19941);break;case 48511:a.g[38915]=b.h[5];z(a,b);if(a.j.length===0)return a.g[38915];b.o===null||typeof a.g[38915]==="object"&&a.g[38915]!==null||(a.g[38915]=b.o);a.g[25255]=a.j.pop();a.g[25255].h[b.G]=a.g[38915];a.i=a.g[25255];break;case 26119:a.g[16541]=v(a);a.g[3839]=b.h[v(a)];b.h[a.g[16541]]=a.g[3839]>b.h[v(a)];break;case 7802:a.g[16541]=v(a);a.g[62634]=b.h[v(a)];b.h[a.g[16541]]=a.g[62634]!==b.h[v(a)];break;case 29164:a.g[16541]=3;b.h[a.g[16541]]=x(a,0,19941);break;case 45474:a.g[19089]=
|
|
59
|
+
v(a);a.g[25428]=b.h[v(a)];a.g[7422]=b.h[v(a)];a.g[40522]=v(a);a.g[28705]=Array(a.g[40522]);for(a.g[12462]=0;a.g[12462]<a.g[40522];a.g[12462]++)a.g[28705][a.g[12462]]=b.h[v(a)];if(a.g[7422]&&a.g[7422][c]){a.g[7358]=a.g[7422][c];a.g[58907]=new n(a.g[7358],a.g[25428],a.g[19089]);for(a.g[12462]=0;a.g[12462]<a.g[28705].length;a.g[12462]++)a.g[58907].h[a.g[12462]]=a.g[28705][a.g[12462]];a.g[58907].h[a.g[7358].v.C]=a.g[28705];a.j.push(a.i);a.i=a.g[58907]}else b.h[a.g[19089]]=a.g[7422].apply(a.g[25428],a.g[28705]);
|
|
60
|
+
break;case 47786:a.g[3766]=v(a);a.g[62634]=b.h[v(a)];b.h[a.g[3766]]=a.g[62634]!=b.h[v(a)];break;case 45528:a.g[16541]=2;b.h[a.g[16541]]=b.h[5];break;case 37324:a.g[38915]=b.h[v(a)];z(a,b);if(a.j.length===0)return a.g[38915];b.o===null||typeof a.g[38915]==="object"&&a.g[38915]!==null||(a.g[38915]=b.o);a.g[23776]=a.j.pop();a.g[23776].h[b.G]=a.g[38915];a.i=a.g[23776];break;case 37593:a.g[21276]=0;b.h[a.g[21276]]=b.h[7];break;case 16492:a.g[16541]=v(a);a.g[62634]=b.h[v(a)];b.h[a.g[16541]]=a.g[62634]<=
|
|
61
|
+
b.h[v(a)];break;case 1900:b.l=13;break;case 42013:a.m[x(a)]=b.h[v(a)];break;case 63795:a.g[28560]=v(a);b.h[a.g[28560]]=v(a);break;case 54788:a.g[2920]=b.h[v(a)];a.g[37378]=b.h[v(a)];a.g[35839]=b.h[v(a)];a.g[27080]=Object.getOwnPropertyDescriptor(a.g[2920],a.g[37378]);a.g[39506]={set:a.g[35839],configurable:!0,enumerable:!0};a.g[27080]&&typeof a.g[27080].get==="function"&&(a.g[39506].get=a.g[27080].get);Object.defineProperty(a.g[2920],a.g[37378],a.g[39506]);break;case 12182:a.g[29248]=v(a);a.g[52124]=
|
|
62
|
+
b.h[v(a)];a.g[47986]=b.h[v(a)];b.h[a.g[29248]]=delete a.g[52124][a.g[47986]];break;case 3376:a.g[16541]=5;a.g[62634]=b.h[2];b.h[a.g[16541]]=a.g[62634]+b.h[3];break;case 4123:a.g[63658]=5;a.g[40080]=b.h[3];a.g[37378]=b.h[4];b.h[a.g[63658]]=a.g[40080][a.g[37378]];break;case 27100:a.g[16541]=v(a);b.h[a.g[16541]]=-b.h[v(a)];break;case 35987:a.g[16541]=3;b.h[a.g[16541]]=b.h[6];break;case 59134:a.g[11440]=5;b.h[a.g[11440]]=x(a,4,0);break;case 47879:a.g[59573]=v(a);v(a);b.h[a.g[59573]]=void 0;break;case 59967:a.g[16541]=
|
|
63
|
+
7;a.g[54385]=b.h[0];b.h[a.g[16541]]=a.g[54385]-b.h[6];break;case 37122:a.g[16541]=v(a);a.g[62634]=b.h[v(a)];b.h[a.g[16541]]=a.g[62634]>=b.h[v(a)];break;case 18522:a.g[1489]=v(a);a.g[38065]=b.h[v(a)];b.h[a.g[1489]]=a.g[38065]===b.h[v(a)];break;case 60376:a.g[19925]=b.h[3];z(a,b);if(a.j.length===0)return a.g[19925];b.o===null||typeof a.g[19925]==="object"&&a.g[19925]!==null||(a.g[19925]=b.o);a.g[53519]=a.j.pop();a.g[53519].h[b.G]=a.g[19925];a.i=a.g[53519];break;case 28102:a.g[16541]=v(a);a.g[10179]=
|
|
64
|
+
v(a);a.g[38805]=Array(a.g[10179]);for(a.g[37753]=0;a.g[37753]<a.g[10179];a.g[37753]++)a.g[38805][a.g[37753]]=b.h[v(a)];b.h[a.g[16541]]=a.g[38805];break;case 55907:a.g[249]=v(a);a.g[13793]=v(a);a.g[7488]=v(a);a.g[33443]=v(a);a.g[59975]=v(a);a.g[44466]=Array(a.g[59975]);for(a.g[33125]=0;a.g[33125]<a.g[59975];a.g[33125]++)a.g[5413]=v(a),a.g[61217]=v(a),a.g[44466][a.g[33125]]={V:a.g[5413],M:a.g[61217]};a.g[29776]={C:a.g[7488],L:a.g[33443],R:a.g[13793],X:a.g[44466]};a.g[32226]=new m(a.g[29776]);for(a.g[33125]=
|
|
65
|
+
0;a.g[33125]<a.g[44466].length;a.g[33125]++)a.g[49053]=a.g[44466][a.g[33125]],a.g[49053].V?a.g[32226].D.push(w(a,b,a.g[49053].M)):a.g[32226].D.push(b.K.D[a.g[49053].M]);var q=a;a.g[31999]=function(l){return function(){for(var t=Array.prototype.slice.call(arguments),y=new p(q.u,l.v.L,q.O,q.m),u=new n(l,this==null?q.m:this,0),r=0;r<t.length;r++)u.h[r]=t[r];u.h[l.v.C]=t;y.i=u;return A(y)}}(a.g[32226]);a.g[31999][c]=a.g[32226];a.g[31999].prototype=a.g[32226].prototype;b.h[a.g[249]]=a.g[31999];break;case 138:a.g[16541]=
|
|
66
|
+
5;b.h[a.g[16541]]=x(a,5,58082);break;case 48909:a.g[16541]=v(a);a.g[41461]=b.h[v(a)];b.h[a.g[16541]]=a.g[41461]%b.h[v(a)];break;case 13149:a.g[14138]=v(a);a.g[52124]=b.h[v(a)];a.g[37378]=b.h[v(a)];b.h[a.g[14138]]=a.g[52124][a.g[37378]];break;case 63724:a.g[55552]=4;a.g[21339]=44;b.h[a.g[55552]]||(b.l=a.g[21339]);break;case 25433:a.g[16541]=4;b.h[a.g[16541]]=b.h[5];break;case 5005:a.g[52124]=b.h[v(a)];a.g[37378]=b.h[v(a)];a.g[3547]=b.h[v(a)];Reflect.set(a.g[52124],a.g[37378],a.g[3547]);break;case 44357:b.F.push({U:v(a),
|
|
67
|
+
S:v(a),T:a.j.length});break;case 52184:a.g[16541]=v(a);b.h[a.g[16541]]=~b.h[v(a)];break;case 17926:b.F.pop();break;case 17061:a.g[16541]=v(a);b.h[a.g[16541]]=+b.h[v(a)];break;case 739:a.g[22118]=v(a);a.g[36985]=b.h[v(a)];a.g[41836]=v(a);a.g[59944]=Array(a.g[41836]);for(a.g[33125]=0;a.g[33125]<a.g[41836];a.g[33125]++)a.g[59944][a.g[33125]]=b.h[v(a)];if(a.g[36985]&&a.g[36985][c]){a.g[6850]=a.g[36985][c];a.g[30557]=Object.create(a.g[6850].prototype||null);a.g[58907]=new n(a.g[6850],a.g[30557],a.g[22118]);
|
|
68
|
+
a.g[58907].o=a.g[30557];for(a.g[33125]=0;a.g[33125]<a.g[59944].length;a.g[33125]++)a.g[58907].h[a.g[33125]]=a.g[59944][a.g[33125]];a.g[58907].h[a.g[6850].v.C]=a.g[59944];a.j.push(a.i);a.i=a.g[58907]}else b.h[a.g[22118]]=Reflect.construct(a.g[36985],a.g[59944]);break;case 16825:a.g[16541]=v(a);a.g[3993]=b.h[v(a)];b.h[a.g[16541]]=a.g[3993]in b.h[v(a)];break;case 62846:a.g[16541]=6;b.h[a.g[16541]]=x(a,0,19941);break;case 41878:a.g[16541]=v(a);a.g[35268]=b.h[v(a)];b.h[a.g[16541]]=a.g[35268]==b.h[v(a)];
|
|
69
|
+
break;case 46432:a.g[29035]=4;a.g[62634]=b.h[2];b.h[a.g[29035]]=a.g[62634]<=b.h[3];break;case 51142:b.l=v(a);break;case 29761:a.g[44199]=v(a);a.g[7487]=b.h[v(a)];b.h[a.g[44199]]=a.g[7487]>>b.h[v(a)];break;case 47732:a.g[16541]=v(a);b.h[a.g[16541]]=b.W;break;case 21541:a.g[16076]=9;a.g[21339]=75;b.h[a.g[16076]]||(b.l=a.g[21339]);break;case 14784:a.g[16541]=3;b.h[a.g[16541]]=x(a,1,30115);break;case 51607:a.g[16541]=v(a);a.g[65339]=b.h[v(a)];a.g[47106]=b.h[v(a)];if(typeof a.g[47106]==="function")b.h[a.g[16541]]=
|
|
70
|
+
a.g[65339]instanceof a.g[47106];else{a.g[5038]=a.g[47106].prototype;a.g[21339]=Object.getPrototypeOf(a.g[65339]);for(a.g[25853]=!1;a.g[21339]!==null;){if(a.g[21339]===a.g[5038]){a.g[25853]=!0;break}a.g[21339]=Object.getPrototypeOf(a.g[21339])}b.h[a.g[16541]]=a.g[25853]}break;case 55835:a.g[16541]=v(a);b.h[a.g[16541]]=h(b.K.D[v(a)]);break;case 29844:a.g[42713]=v(a);a.g[1817]=x(a);if(!(a.g[1817]in a.m))throw new ReferenceError(`${a.g[1817]} is not defined`);b.h[a.g[42713]]=a.m[a.g[1817]];break;case 24699:a.g[16541]=
|
|
71
|
+
5;a.g[62634]=b.h[2];b.h[a.g[16541]]=a.g[62634]+b.h[4];break;case 44361:a.g[16541]=v(a);a.g[52124]=b.h[v(a)];a.g[15140]=[];if(a.g[52124]!==null&&a.g[52124]!==void 0)for(a.g[23643]=Object.create(null),a.g[61494]=Object(a.g[52124]);a.g[61494]!==null;){a.g[46538]=Object.getOwnPropertyNames(a.g[61494]);for(a.g[33125]=0;a.g[33125]<a.g[46538].length;a.g[33125]++)a.g[7176]=a.g[46538][a.g[33125]],a.g[7176]in a.g[23643]||(a.g[23643][a.g[7176]]=!0,a.g[34638]=Object.getOwnPropertyDescriptor(a.g[61494],a.g[7176]),
|
|
72
|
+
a.g[34638]&&a.g[34638].enumerable&&a.g[15140].push(a.g[7176]));a.g[61494]=Object.getPrototypeOf(a.g[61494])}b.h[a.g[16541]]={N:a.g[15140],P:0};break;case 49820:a.g[16541]=v(a);b.h[a.g[16541]]=x(a);break;case 51817:a.g[38915]=b.h[4];z(a,b);if(a.j.length===0)return a.g[38915];b.o===null||typeof a.g[38915]==="object"&&a.g[38915]!==null||(a.g[38915]=b.o);a.g[23776]=a.j.pop();a.g[23776].h[b.G]=a.g[38915];a.i=a.g[23776];break;case 64967:a.g[52124]=b.h[v(a)];a.g[37378]=b.h[v(a)];a.g[11470]=b.h[v(a)];a.g[12672]=
|
|
73
|
+
Object.getOwnPropertyDescriptor(a.g[52124],a.g[37378]);a.g[60061]={get:a.g[11470],configurable:!0,enumerable:!0};a.g[12672]&&typeof a.g[12672].set==="function"&&(a.g[60061].set=a.g[12672].set);Object.defineProperty(a.g[52124],a.g[37378],a.g[60061]);break;case 45309:a.g[7138]=v(a);a.g[18365]=v(a);a.g[49429]=v(a);for(a.g[9236]=a.g[18365];a.g[9236]<a.g[49429];a.g[9236]++)a.u[a.g[7138]+(a.g[9236]-a.g[18365])]=a.u[a.g[9236]];break;case 49746:a.g[12540]=v(a);k(b.K.D[a.g[12540]],b.h[v(a)]);break;case 7780:a.g[16541]=
|
|
74
|
+
3;a.g[1817]=x(a,2,31810);if(!(a.g[1817]in a.m))throw new ReferenceError(`${a.g[1817]} is not defined`);b.h[a.g[16541]]=a.m[a.g[1817]];break;case 20641:a.g[16541]=v(a);a.g[7422]=b.h[v(a)];a.g[11407]=v(a);a.g[59944]=Array(a.g[11407]);for(a.g[33125]=0;a.g[33125]<a.g[11407];a.g[33125]++)a.g[59944][a.g[33125]]=b.h[v(a)];if(a.g[7422]&&a.g[7422][c]){a.g[7358]=a.g[7422][c];a.g[58907]=new n(a.g[7358],a.m,a.g[16541]);for(a.g[33125]=0;a.g[33125]<a.g[59944].length;a.g[33125]++)a.g[58907].h[a.g[33125]]=a.g[59944][a.g[33125]];
|
|
75
|
+
a.g[58907].h[a.g[7358].v.C]=a.g[59944];a.j.push(a.i);a.i=a.g[58907]}else b.h[a.g[16541]]=a.g[7422].apply(null,a.g[59944]);break;case 5381:a.g[16541]=v(a);a.g[14415]=b.h[v(a)];b.h[a.g[16541]]=a.g[14415]-b.h[v(a)];break;case 60964:a.g[1E3]=9;a.g[62634]=b.h[5];b.h[a.g[1E3]]=a.g[62634]>b.h[8];break;case 19072:a.g[12158]=v(a);a.g[21339]=v(a);b.h[a.g[12158]]&&(b.l=a.g[21339]);break;case 51960:a.g[16541]=3;b.h[a.g[16541]]=b.h[2];break;case 30357:a.g[16541]=v(a);a.g[63497]=b.h[v(a)];a.g[57844]=v(a);a.g[63497].P>=
|
|
76
|
+
a.g[63497].N.length?b.l=a.g[57844]:b.h[a.g[16541]]=a.g[63497].N[a.g[63497].P++];break;case 20745:a.g[16541]=v(a);a.g[62634]=b.h[v(a)];b.h[a.g[16541]]=a.g[62634]/b.h[v(a)];break;case 11726:a.g[9620]=v(a);a.g[62634]=b.h[v(a)];b.h[a.g[9620]]=a.g[62634]&b.h[v(a)];break;case 48568:a.g[5190]=3;b.h[a.g[5190]]=x(a,4,0);break;case 3645:a.g[22553]=v(a);a.g[807]=x(a);a.g[645]=Object.prototype.hasOwnProperty.call(a.m,a.g[807])?a.m[a.g[807]]:void 0;b.h[a.g[22553]]=typeof a.g[645];break;case 46061:a.g[34726]=v(a);
|
|
77
|
+
a.g[59851]=v(a);a.g[62133]={};for(a.g[33125]=0;a.g[33125]<a.g[59851];a.g[33125]++)a.g[37378]=b.h[v(a)],a.g[3547]=b.h[v(a)],a.g[62133][a.g[37378]]=a.g[3547];b.h[a.g[34726]]=a.g[62133];break;case 20491:debugger;break;case 24674:a.g[51590]=1;b.h[a.g[51590]]=b.h[3];break;case 60658:a.g[16541]=v(a);a.g[62634]=b.h[v(a)];b.h[a.g[16541]]=a.g[62634]<<b.h[v(a)];break;case 8845:a.g[16541]=2;b.h[a.g[16541]]=b.h[3];break;default:throw Error("Unknown opcode: "+d+" at pc "+(b.l-1));case 59199:a.g[16541]=v(a);a.g[62634]=
|
|
78
|
+
b.h[v(a)];b.h[a.g[16541]]=a.g[62634]+b.h[v(a)];break;case 5385:a.g[39284]=4;b.h[a.g[39284]]=x(a,3,32194);break;case 20918:a.g[16541]=v(a);a.g[16160]=b.h[v(a)];b.h[a.g[16541]]=a.g[16160]|b.h[v(a)];break;case 25652:a.g[16541]=8;b.h[a.g[16541]]=x(a,0,19941);break;case 51993:a.g[14091]=v(a);a.g[20393]=b.h[v(a)];b.h[a.g[14091]]=a.g[20393]*b.h[v(a)];break;case 29458:a.g[27021]=4;b.h[a.g[27021]]=b.h[0];break;case 38570:throw b.h[v(a)];case 21903:a.g[16541]=v(a);a.g[46842]=b.h[v(a)];b.h[a.g[16541]]=a.g[46842]<
|
|
79
|
+
b.h[v(a)];break;case 17068:a.g[16541]=5;b.h[a.g[16541]]=b.h[0];break;case 26163:a.g[55552]=v(a);a.g[16422]=v(a);b.h[a.g[55552]]||(b.l=a.g[16422]);break;case 28425:a.g[16541]=v(a);b.h[a.g[16541]]=typeof b.h[v(a)];break;case 63202:a.g[60330]=v(a);b.h[a.g[60330]]=b.h[v(a)];break;case 31805:a.g[53668]=v(a);b.h[a.g[53668]]=!b.h[v(a)];break;case 57225:b.l=59}}catch(l){b=null;for(d=a.i;;){if(d.F.length>0){b=d;break}z(a,d);if(a.j.length===0)break;d=a.j.pop();a.i=d}if(!b)throw l;d=b.F.pop();a.j.length=d.T;
|
|
80
|
+
b.h[d.S]=l;b.l=d.U;a.i=b}}}var B={},C;for(C of Object.getOwnPropertyNames(globalThis))B[C]=globalThis[C];if(typeof window!=="undefined"){B.window=window;for(C of Object.getOwnPropertyNames(window))B[C]=window[C]}B.undefined=void 0;B.Infinity=Infinity;B.NaN=NaN;
|
|
81
|
+
A(new p(function(a){a=typeof Buffer!=="undefined"?Buffer.from(a,"base64"):Uint8Array.from(atob(a),function(d){return d.charCodeAt(0)});for(var e=new Uint16Array(a.length/2),b=0;b<e.length;b++)e[b]=a[b*2]|a[b*2+1]<<8;return e}("/bAEAFIAWwCNE5aj8uz9sA2/zi2qlqqWY9r9sBEAWwBtAKFQ52DnYD0OPQ5FrTNmCVGPVRnLbEC2UZV2+Lz4vMyRB7sJb/2wJwBtAHIAtlE/58Zt/bDMkf2wMAByAHQAzJF6Hv2wNgB0AHkA3GnOLT18B2Y/5/2wPwB5AIUAB7v4vKKxBNYNv6KxPXxFrQTWY9o9fO2z/bBPAIUAiABJrVLCPXxj2gMAMgABAAoAAABiYOxxjSLAOWC17PhkHgkVGxChUAYAAQABAAIAorEHAAMABQACAAIABgD4ys9Se2DYsWwHuL3Y64oA2LF+9ZOMEnOsQn71P+rZkjRkJO4lVDANWWONItRkid9pyv7mf70="),0,
|
|
82
|
+
[19940,30138,"IXwsfCp8NnwpfCt8LXw=","rn2sfaN9",void 0,58082],B));
|
|
72
83
|
*/
|
|
73
84
|
```
|
|
74
85
|
|
|
@@ -103,6 +114,7 @@ S(new C(function(b){b=typeof Buffer!=="undefined"?Buffer.from(b,"base64"):Uint8A
|
|
|
103
114
|
- [x] try..catch
|
|
104
115
|
- [x] getter/setters
|
|
105
116
|
- [x] debugger;
|
|
117
|
+
- [x] template literals (**ES6**)
|
|
106
118
|
|
|
107
119
|
### Missing
|
|
108
120
|
|
|
@@ -119,8 +131,9 @@ S(new C(function(b){b=typeof Buffer!=="undefined"?Buffer.from(b,"base64"):Uint8A
|
|
|
119
131
|
- [ ] dead handlers
|
|
120
132
|
- [ ] dead bytecode insertion
|
|
121
133
|
- [x] macro opcodes (Combine multiple opcodes into a "macro opcode")
|
|
134
|
+
- [x] micro opcodes (Break opcodes into sub-opcodes)
|
|
122
135
|
- [x] specialized opcodes (Create specific opcodes for opcode+operand pairs)
|
|
123
|
-
- [x] aliased opcodes (
|
|
136
|
+
- [x] aliased opcodes (Create duplicate opcodes, including variants with shuffled operand order)
|
|
124
137
|
- [x] encoded bytecode array
|
|
125
138
|
- [x] self-modifying bytecode
|
|
126
139
|
- [x] timing checks
|
|
@@ -176,16 +189,16 @@ console.log("Hello world!");
|
|
|
176
189
|
console.log("Hello world!");
|
|
177
190
|
|
|
178
191
|
// Before
|
|
192
|
+
// [2, 1, 0], LOAD_GLOBAL reg[1] = console 1:0-1:7
|
|
193
|
+
// [0, 2, 1], LOAD_CONST reg[2] = "log" 1:0-1:27
|
|
194
|
+
// [8, 3, 1, 2], GET_PROP [3, 1, 2] 1:0-1:27
|
|
195
|
+
// [0, 4, 2], LOAD_CONST reg[4] = "Hello world!" 1:12-1:26
|
|
196
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = method(recv=reg[1], fn=reg[3], 1 args)1:0-1:27
|
|
179
197
|
// [2, 1, 0], LOAD_GLOBAL reg[1] = console 2:0-2:7
|
|
180
198
|
// [0, 2, 1], LOAD_CONST reg[2] = "log" 2:0-2:27
|
|
181
199
|
// [8, 3, 1, 2], GET_PROP [3, 1, 2] 2:0-2:27
|
|
182
200
|
// [0, 4, 2], LOAD_CONST reg[4] = "Hello world!" 2:12-2:26
|
|
183
201
|
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = method(recv=reg[1], fn=reg[3], 1 args)2:0-2:27
|
|
184
|
-
// [2, 1, 0], LOAD_GLOBAL reg[1] = console 3:0-3:7
|
|
185
|
-
// [0, 2, 1], LOAD_CONST reg[2] = "log" 3:0-3:27
|
|
186
|
-
// [8, 3, 1, 2], GET_PROP [3, 1, 2] 3:0-3:27
|
|
187
|
-
// [0, 4, 2], LOAD_CONST reg[4] = "Hello world!" 3:12-3:26
|
|
188
|
-
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = method(recv=reg[1], fn=reg[3], 1 args)3:0-3:27
|
|
189
202
|
|
|
190
203
|
// After
|
|
191
204
|
// [5074, 1, 0, 2, 1, 3, 1, 2, 4, 2, 5, 1, 3, 1, 4], LOAD_GLOBAL,LOAD_CONST,GET_PROP,LOAD_CONST,CALL_METHOD [1, 0, 2, 1, 3, 1, 2, 4, 2, 5, 1, 3, 1, 4]2:0-2:7
|
|
@@ -195,22 +208,26 @@ console.log("Hello world!");
|
|
|
195
208
|
case 5074:
|
|
196
209
|
// LOAD_GLOBAL
|
|
197
210
|
var dst = this._operand();
|
|
198
|
-
|
|
211
|
+
var globalName = this._constant();
|
|
212
|
+
if (!(globalName in this.globals)) {
|
|
213
|
+
throw new ReferenceError(`${globalName} is not defined`);
|
|
214
|
+
}
|
|
215
|
+
frame.regs[dst] = this.globals[globalName];
|
|
199
216
|
// LOAD_CONST
|
|
200
|
-
var
|
|
201
|
-
frame.regs[
|
|
217
|
+
var dst_1 = this._operand();
|
|
218
|
+
frame.regs[dst_1] = this._constant();
|
|
202
219
|
// GET_PROP
|
|
203
220
|
// dst = regs[obj][regs[key]]
|
|
204
|
-
var
|
|
221
|
+
var dst_2 = this._operand();
|
|
205
222
|
var obj = frame.regs[this._operand()];
|
|
206
223
|
var key = frame.regs[this._operand()];
|
|
207
|
-
frame.regs[
|
|
224
|
+
frame.regs[dst_2] = obj[key];
|
|
208
225
|
// LOAD_CONST
|
|
209
|
-
var
|
|
210
|
-
frame.regs[
|
|
226
|
+
var dst_3 = this._operand();
|
|
227
|
+
frame.regs[dst_3] = this._constant();
|
|
211
228
|
// CALL_METHOD
|
|
212
229
|
// dst, receiverReg, calleeReg, argc, [argReg...]
|
|
213
|
-
var
|
|
230
|
+
var dst_4 = this._operand();
|
|
214
231
|
var receiver = frame.regs[this._operand()];
|
|
215
232
|
var callee = frame.regs[this._operand()];
|
|
216
233
|
var argc = this._operand();
|
|
@@ -218,17 +235,64 @@ case 5074:
|
|
|
218
235
|
for (var i = 0; i < argc; i++) args[i] = frame.regs[this._operand()];
|
|
219
236
|
if (callee && callee[CLOSURE_SYM]) {
|
|
220
237
|
var c = callee[CLOSURE_SYM];
|
|
221
|
-
var f = new Frame(c, frame._pc, frame, receiver,
|
|
238
|
+
var f = new Frame(c, frame._pc, frame, receiver, dst_4);
|
|
222
239
|
for (var i = 0; i < args.length; i++) f.regs[i] = args[i];
|
|
223
240
|
f.regs[c.fn.paramCount] = args;
|
|
224
241
|
this._frameStack.push(this._currentFrame);
|
|
225
242
|
this._currentFrame = f;
|
|
226
243
|
} else {
|
|
227
|
-
frame.regs[
|
|
244
|
+
frame.regs[dst_4] = callee.apply(receiver, args);
|
|
228
245
|
}
|
|
229
246
|
break;
|
|
230
247
|
```
|
|
231
248
|
|
|
249
|
+
#### `microOpcodes` (true/false)
|
|
250
|
+
|
|
251
|
+
Breaks opcodes into mulitple sub-opcodes.
|
|
252
|
+
|
|
253
|
+
```js
|
|
254
|
+
// Input Code
|
|
255
|
+
console.log("Hello world!");
|
|
256
|
+
|
|
257
|
+
// Before
|
|
258
|
+
// [2, 1, 0, 0], LOAD_GLOBAL reg[1] = console 1:0-1:7
|
|
259
|
+
// [0, 2, 1, 0], LOAD_CONST reg[2] = "log" 1:0-1:27
|
|
260
|
+
// [8, 3, 1, 2], GET_PROP reg[3] = reg[1][reg[2]] 1:0-1:27
|
|
261
|
+
// [0, 4, 2, 0], LOAD_CONST reg[4] = "Hello world!" 1:12-1:26
|
|
262
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = reg[3](recv=reg[1], 1 args) 1:0-1:27
|
|
263
|
+
|
|
264
|
+
// What the opcode "LOAD_CONST" looks like:
|
|
265
|
+
case OP.LOAD_CONST:
|
|
266
|
+
var dst = this._operand();
|
|
267
|
+
frame.regs[dst] = this._constant();
|
|
268
|
+
break;
|
|
269
|
+
|
|
270
|
+
// After
|
|
271
|
+
// [60, 1], MICRO_LOAD_GLOBAL_0 1 1:0-1:7
|
|
272
|
+
// [61, 0, 0], MICRO_LOAD_GLOBAL_1 [0, 0]
|
|
273
|
+
// [62], MICRO_LOAD_GLOBAL_2
|
|
274
|
+
// [63], MICRO_LOAD_GLOBAL_3
|
|
275
|
+
// [58, 2], MICRO_LOAD_CONST_0 2 1:0-1:27
|
|
276
|
+
// [59, 1, 0], MICRO_LOAD_CONST_1 [1, 0]
|
|
277
|
+
// [64, 3], MICRO_GET_PROP_0 3 1:0-1:27
|
|
278
|
+
// [65, 1], MICRO_GET_PROP_1 1
|
|
279
|
+
// [66, 2], MICRO_GET_PROP_2 2
|
|
280
|
+
// [67], MICRO_GET_PROP_3
|
|
281
|
+
// [58, 4], MICRO_LOAD_CONST_0 4 1:12-1:26
|
|
282
|
+
// [59, 2, 0], MICRO_LOAD_CONST_1 [2, 0]
|
|
283
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = reg[3](recv=reg[1], 1 args) 1:0-1:27
|
|
284
|
+
|
|
285
|
+
// What the opcodes "MICRO_LOAD_CONST_0" (58) and "MICRO_LOAD_CONST_1" (59) looks like:
|
|
286
|
+
case 58:
|
|
287
|
+
// MICRO_LOAD_CONST_0
|
|
288
|
+
this._internals[0] = this._operand();
|
|
289
|
+
break;
|
|
290
|
+
case 59:
|
|
291
|
+
// MICRO_LOAD_CONST_1
|
|
292
|
+
frame.regs[this._internals[0]] = this._constant();
|
|
293
|
+
break;
|
|
294
|
+
```
|
|
295
|
+
|
|
232
296
|
#### `specializedOpcodes` (true/false)
|
|
233
297
|
|
|
234
298
|
Creates specialized opcodes for commonly used opcode+operand pairs.
|
|
@@ -298,7 +362,7 @@ case OP.LOAD_GLOBAL:
|
|
|
298
362
|
// [51807, 1], ALIAS_RETURN_0 1
|
|
299
363
|
|
|
300
364
|
// What the opcode "ALIAS_LOAD_GLOBAL_1_0" (52040) looks like:
|
|
301
|
-
|
|
365
|
+
case 52040:
|
|
302
366
|
// ALIAS_LOAD_GLOBAL_1_0 (order: [1,0])
|
|
303
367
|
let _unsortedOperands = [this._operand(), this._operand()];
|
|
304
368
|
let _operands = [_unsortedOperands[1], _unsortedOperands[0]];
|
|
@@ -390,7 +454,7 @@ Please transpile your code down first using [Babel](https://github.com/babel/bab
|
|
|
390
454
|
|
|
391
455
|
### Project
|
|
392
456
|
|
|
393
|
-
- Register
|
|
457
|
+
- Register based VM
|
|
394
458
|
- Lua-style closure and upvalue model
|
|
395
459
|
- CPython-style opcodes and codegen
|
|
396
460
|
- Compiler is in src/compiler.ts
|
package/dist/build-runtime.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { generate } from "@babel/generator";
|
|
2
2
|
import { parse } from "@babel/parser";
|
|
3
3
|
import { applyMacroOpcodes } from "./transforms/runtime/macroOpcodes.js";
|
|
4
|
+
import { applyMicroOpcodes } from "./transforms/runtime/microOpcodes.js";
|
|
5
|
+
import { applyInteralVariablesToRuntime } from "./transforms/runtime/internalVariables.js";
|
|
4
6
|
import { applyShuffleOpcodes } from "./transforms/runtime/shuffleOpcodes.js";
|
|
5
7
|
import { applyMinify } from "./transforms/runtime/minify.js";
|
|
6
8
|
import { applySpecializedOpcodes } from "./transforms/runtime/specializedOpcodes.js";
|
|
7
9
|
import { applyAliasedOpcodes } from "./transforms/runtime/aliasedOpcodes.js";
|
|
8
|
-
export async function obfuscateRuntime(runtime, bytecode, options, compiler) {
|
|
10
|
+
export async function obfuscateRuntime(runtime, bytecode, options, compiler, generateBytecodeComment) {
|
|
9
11
|
let ast;
|
|
10
12
|
try {
|
|
11
13
|
ast = parse(runtime, {
|
|
@@ -19,7 +21,15 @@ export async function obfuscateRuntime(runtime, bytecode, options, compiler) {
|
|
|
19
21
|
|
|
20
22
|
// Specialized opcode cases must be applied BEFORE shuffleOpcodes
|
|
21
23
|
if (options.specializedOpcodes) {
|
|
22
|
-
applySpecializedOpcodes(ast,
|
|
24
|
+
applySpecializedOpcodes(ast, compiler);
|
|
25
|
+
}
|
|
26
|
+
if (options.microOpcodes) {
|
|
27
|
+
applyInteralVariablesToRuntime(ast, compiler);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Micro opcode cases must be applied BEFORE shuffleOpcodes
|
|
31
|
+
if (options.microOpcodes && Object.keys(compiler.MICRO_OPS).length > 0) {
|
|
32
|
+
applyMicroOpcodes(ast, compiler);
|
|
23
33
|
}
|
|
24
34
|
|
|
25
35
|
// Macro opcode cases must be applied BEFORE shuffleOpcodes
|
|
@@ -45,6 +55,9 @@ export async function obfuscateRuntime(runtime, bytecode, options, compiler) {
|
|
|
45
55
|
});
|
|
46
56
|
}
|
|
47
57
|
|
|
58
|
+
// Add comment here for more accurate opcode names
|
|
59
|
+
generated = generateBytecodeComment() + "\n" + generated;
|
|
60
|
+
|
|
48
61
|
// Minify code?
|
|
49
62
|
if (options.minify) {
|
|
50
63
|
try {
|