Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.

Commit 9c76827

Browse files
committed
fix decoders
1 parent d6e1019 commit 9c76827

File tree

2 files changed

+70
-21
lines changed

2 files changed

+70
-21
lines changed

src/string-array.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as estree from 'estree';
33
import { assert } from 'console';
44
import { VisitorOption, traverse, replace } from 'estraverse';
55
import { ProtectionBase } from "./protection";
6-
import { cutCode, decodeBase64, decodeRC4, isVariableDeclaration, isIdentifier, isFunctionExpression, isLiteral, isCallExpression, isExpressionStatement, isArrayExpression } from './utils';
6+
import * as Utils from './utils';
77

88
type EncodingType = 'none' | 'base64' | 'rc4';
99

@@ -29,15 +29,15 @@ export class StringArrayProtection extends ProtectionBase {
2929

3030
detect(): boolean {
3131
this.active = false;
32-
if (this.ast.body && this.ast.body.length > 0 && isVariableDeclaration(this.ast.body[0])) {
32+
if (this.ast.body && this.ast.body.length > 0 && Utils.isVariableDeclaration(this.ast.body[0])) {
3333
const strArrayDef = <estree.VariableDeclaration> this.ast.body[0];
3434
if (strArrayDef.declarations && strArrayDef.declarations.length > 0) {
3535
const strArrayDecl = strArrayDef.declarations[0];
36-
if (strArrayDecl.init && isArrayExpression(strArrayDecl.init) && isIdentifier(strArrayDecl.id)) {
36+
if (strArrayDecl.init && Utils.isArrayExpression(strArrayDecl.init) && Utils.isIdentifier(strArrayDecl.id)) {
3737
this.arrayVar = strArrayDecl.id.name;
3838
this.astArray = this.ast.body[0] as estree.Statement;
3939
this.array = strArrayDecl.init.elements.map(e => {
40-
assert(isLiteral(e));
40+
assert(Utils.isLiteral(e));
4141
assert(typeof (<estree.Literal> e).value === 'string');
4242
return (<estree.Literal> e).value as string;
4343
});
@@ -52,15 +52,15 @@ export class StringArrayProtection extends ProtectionBase {
5252

5353
private detectRotation(): boolean {
5454
this.hasRotation = false;
55-
if (this.ast.body.length > 1 && isExpressionStatement(this.ast.body[1])) {
55+
if (this.ast.body.length > 1 && Utils.isExpressionStatement(this.ast.body[1])) {
5656
const expr = <estree.ExpressionStatement> this.ast.body[1];
57-
if (isCallExpression(expr.expression)) {
57+
if (Utils.isCallExpression(expr.expression)) {
5858
if (expr.expression.arguments.length === 2) {
59-
const id = <estree.Identifier> expr.expression.arguments.find(isIdentifier);
60-
const cnt = <estree.Literal> expr.expression.arguments.find(isLiteral);
59+
const id = <estree.Identifier> expr.expression.arguments.find(Utils.isIdentifier);
60+
const cnt = <estree.Literal> expr.expression.arguments.find(Utils.isLiteral);
6161
if (id && id.name === this.arrayVar && cnt && typeof cnt.value === 'number') {
6262
this.hasRotation = true;
63-
this.rotFunc = cutCode(this.code, expr);
63+
this.rotFunc = Utils.cutCode(this.code, expr);
6464
this.astRot = this.ast.body[1] as estree.Statement;
6565
}
6666
}
@@ -72,13 +72,13 @@ export class StringArrayProtection extends ProtectionBase {
7272
private detectEncoding(): boolean {
7373
this.hasEncoding = false;
7474
let index = this.hasRotation ? 2 : 1;
75-
if (this.ast.body.length > index && isVariableDeclaration(this.ast.body[index])) {
75+
if (this.ast.body.length > index && Utils.isVariableDeclaration(this.ast.body[index])) {
7676
const decVar = <estree.VariableDeclaration> this.ast.body[index];
7777
if (decVar.declarations && decVar.declarations.length > 0) {
7878
const decDecl = <estree.VariableDeclarator> decVar.declarations[0];
79-
if (isIdentifier(decDecl.id) && decDecl.init && isFunctionExpression(decDecl.init)) {
79+
if (Utils.isIdentifier(decDecl.id) && decDecl.init && Utils.isFunctionExpression(decDecl.init)) {
8080
if (decDecl.init.params.length === 2) {
81-
const decFuncCode = cutCode(this.code, decDecl.init);
81+
const decFuncCode = Utils.cutCode(this.code, decDecl.init);
8282
this.encoding = /\batob\b/.test(decFuncCode)
8383
? (/%(?:0x100|256)\D/.test(decFuncCode) ? 'rc4' : 'base64')
8484
: 'none';
@@ -105,11 +105,11 @@ export class StringArrayProtection extends ProtectionBase {
105105
if (this.hasEncoding && this.astDecoder) {
106106
if (this.encoding === 'base64') {
107107
for (let i = 0; i < this.array.length; ++i)
108-
this.array[i] = decodeBase64(this.array[i]);
108+
this.array[i] = Utils.decodeBase64(this.array[i]);
109109
} else if (this.encoding === 'rc4') {
110110
this.fillKeys();
111111
for (let i = 0; i < this.array.length; ++i)
112-
this.array[i] = decodeRC4(this.array[i], this.rc4Keys[i]);
112+
this.array[i] = Utils.decodeRC4(this.array[i], this.rc4Keys[i]);
113113
}
114114
this.removeDecoderCalls();
115115
}
@@ -161,10 +161,10 @@ export class StringArrayProtection extends ProtectionBase {
161161
}
162162

163163
private checkDecoderCall(node: estree.Node): estree.CallExpression | null {
164-
if (isCallExpression(node) && isIdentifier(node.callee)) {
164+
if (Utils.isCallExpression(node) && Utils.isIdentifier(node.callee)) {
165165
if (node.callee.name === this.decFuncName) {
166166
assert(node.arguments.length === 2);
167-
assert(node.arguments.every(isLiteral));
167+
assert(node.arguments.every(Utils.isLiteral));
168168
return node;
169169
}
170170
}

src/utils.ts

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,61 @@ export function cutCode(code: string, node: estree.BaseNodeWithoutComments): str
88
}
99

1010
export function registerDecoders(): void {
11-
(function (g: any) {
12-
var j='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
13-
g.atob || (g.atob = function(k:any){var l=String(k)['replace'](/=+$/,'');for(var m=0x0,n=0,o,p=0x0,q='';o=l['charAt'](p++);~o&&(n=m%0x4?n*0x40+o:o,m++%0x4)?q+=String['fromCharCode'](0xff&n>>(-0x2*m&0x6)):0x0){o=j['indexOf'](o);}return q;});
11+
(function (that: any) {
12+
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
13+
that.atob || (
14+
that.atob = function(input: any) {
15+
var str = String(input).replace(/=+$/, '');
16+
for (
17+
var bc = 0, bs = 0, buffer, idx = 0, output = '';
18+
buffer = str.charAt(idx++);
19+
~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
20+
bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
21+
) {
22+
buffer = chars.indexOf(buffer);
23+
}
24+
return output;
25+
});
1426
})(global);
15-
(function (g: any) {
16-
g.rc4 || (g.rc4 = function(s:any,t:any){var u=[],v=0x0,w,x='',y='';s=g.atob(s);for(var z=0x0,A=s['length'];z<A;z++){y+='%'+('00'+s['charCodeAt'](z)['toString'](0x10))['slice'](-0x2);}s=decodeURIComponent(y);for(var B=0x0;B<0x100;B++){u[B]=B;}for(B=0x0;B<0x100;B++){v=(v+u[B]+t['charCodeAt'](B%t['length']))%0x100;w=u[B];u[B]=u[v];u[v]=w;}B=0x0;v=0x0;for(var C=0x0;C<s['length'];C++){B=(B+0x1)%0x100;v=(v+u[B])%0x100;w=u[B];u[B]=u[v];u[v]=w;x+=String['fromCharCode'](s['charCodeAt'](C)^u[(u[B]+u[v])%0x100]);}return x;});
27+
28+
(function (that: any) {
29+
that.rc4 || (
30+
that.rc4 = function (str: any, key: any) {
31+
var s = [], j = 0, x, res = '', newStr = '';
32+
33+
str = that.atob(str);
34+
35+
for (var k = 0, length = str.length; k < length; k++) {
36+
newStr += '%' + ('00' + str.charCodeAt(k).toString(16)).slice(-2);
37+
}
38+
39+
str = decodeURIComponent(newStr);
40+
41+
for (var i = 0; i < 256; i++) {
42+
s[i] = i;
43+
}
44+
45+
for (i = 0; i < 256; i++) {
46+
j = (j + s[i] + key.charCodeAt(i % key.length)) % 256;
47+
x = s[i];
48+
s[i] = s[j];
49+
s[j] = x;
50+
}
51+
52+
i = 0;
53+
j = 0;
54+
55+
for (var y = 0; y < str.length; y++) {
56+
i = (i + 1) % 256;
57+
j = (j + s[i]) % 256;
58+
x = s[i];
59+
s[i] = s[j];
60+
s[j] = x;
61+
res += String.fromCharCode(str.charCodeAt(y) ^ s[(s[i] + s[j]) % 256]);
62+
}
63+
64+
return res;
65+
});
1766
})(global);
1867
}
1968

0 commit comments

Comments
 (0)