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

Commit c13ea4d

Browse files
committed
join string literals
1 parent ca900e5 commit c13ea4d

11 files changed

+80
-18
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,5 @@ typings/
7272
!.vscode/launch.json
7373
!.vscode/extensions.json
7474

75-
*.js
75+
*.js
76+
*.map

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"${workspaceFolder}/**/*.js"
1414
],
1515
"args": [
16-
"${workspaceFolder}/test-data/test-obf3.js"
16+
"${workspaceFolder}/test-data/test-obf6.js"
1717
]
1818
}
1919
]

src/deobfuscator.js.map

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/deobfuscator.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import { EspreeFacade } from './EspreeFacade';
55
import { VariableDeclaration } from 'estree';
66
import { StringArrayProtection } from './string-array';
77
import { registerDecoders } from './utils';
8+
import { ProtectionBase } from './protection';
9+
import { StringSplit } from './string-split';
10+
11+
type ProtectionCtor = new (code: string, ast: estree.Program) => ProtectionBase;
812

913
export class Deobfuscator {
1014

@@ -20,6 +24,10 @@ export class Deobfuscator {
2024
};
2125

2226
private ast: estree.Program | null = null;
27+
private protections: ProtectionCtor[] = [
28+
StringSplit,
29+
StringArrayProtection,
30+
];
2331

2432
constructor (public code: string) {
2533

@@ -37,13 +45,15 @@ export class Deobfuscator {
3745
let code = this.code;
3846
let ast = this.ast;
3947

40-
let p = new StringArrayProtection(code, ast);
41-
p.detect();
42-
p.remove();
43-
44-
let result = generate(this.ast);
48+
for (const ctor of this.protections) {
49+
const p = new ctor(code, ast);
50+
if (p.detect()) {
51+
ast = p.remove();
52+
code = generate(ast);
53+
}
54+
}
4555

46-
return result;
56+
return code;
4757
}
4858

4959
}

src/protection.js.map

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/protection.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,21 @@ import * as espree from 'espree';
22
import * as estree from 'estree';
33

44
export abstract class ProtectionBase {
5+
6+
protected active: boolean = false;
7+
58
constructor (
69
protected code: string,
7-
protected ast: estree.Program) {
10+
protected ast: estree.Program)
11+
{
12+
13+
}
14+
15+
abstract detect(): boolean;
16+
abstract remove(): estree.Program;
817

18+
isActive() {
19+
return this.active;
920
}
21+
1022
}

src/string-array.js.map

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/string-array.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ export class StringArrayProtection extends ProtectionBase {
1212
private arrayVar: string = '';
1313
private array: string[] = [];
1414
private astArray: estree.Statement | null = null;
15-
private active: boolean = false;
1615

1716
private hasRotation: boolean = false;
1817
private rotFunc: string = '';
@@ -95,10 +94,6 @@ export class StringArrayProtection extends ProtectionBase {
9594
return this.hasEncoding;
9695
}
9796

98-
isActive() {
99-
return this.active;
100-
}
101-
10297
remove(): estree.Program {
10398
let result = this.ast;
10499
if (!this.active)

src/string-split.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import * as espree from 'espree';
2+
import * as estree from 'estree';
3+
import { ProtectionBase } from "./protection";
4+
import { VisitorOption, traverse, replace } from 'estraverse';
5+
import { isBinaryExpression, isLiteral } from './utils';
6+
7+
export class StringSplit extends ProtectionBase {
8+
9+
constructor(code: string, ast: estree.Program) {
10+
super(code, ast);
11+
this.active = true;
12+
}
13+
14+
detect(): boolean {
15+
return this.active;
16+
}
17+
18+
remove(): estree.Program {
19+
if (!this.active)
20+
return this.ast;
21+
22+
this.ast = <estree.Program> replace(this.ast, {
23+
enter: (node, parent) => {
24+
if (isBinaryExpression(node) && node.operator === '+' &&
25+
isLiteral(node.left) && isLiteral(node.right) &&
26+
typeof node.left.value === 'string' && typeof node.right.value === 'string')
27+
{
28+
return <estree.Literal> {
29+
type: 'Literal',
30+
value: node.left.value + node.right.value
31+
};
32+
}
33+
}
34+
});
35+
36+
return this.ast;
37+
}
38+
39+
}

src/utils.js.map

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/utils.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,12 @@ export function decodeRC4(encoded: string, key: string): string {
3030
throw new Error('Call registerDecoders() first.');
3131
return g.rc4(encoded, key);
3232
}
33+
34+
export function isBinaryExpression(node: estree.Node): node is estree.BinaryExpression {
35+
return node.type === 'BinaryExpression';
36+
}
37+
38+
export function isLiteral(node: estree.Node): node is estree.Literal {
39+
return node.type === 'Literal';
40+
}
41+

0 commit comments

Comments
 (0)