forked from veerkun/php-javascript-unpacker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathJavascriptUnpacker.php
92 lines (72 loc) · 2.43 KB
/
JavascriptUnpacker.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<?php
class JavaScriptUnpacker
{
protected $alphabet = array(
52 => '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP',
54 => '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR',
62 => '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
95 => ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'
);
private $base;
private $map;
public function unpack($source, $dynamicHeader = true)
{
if (! $this->isPacked($source, $dynamicHeader)) {
return $source;
}
preg_match("/}\('(.*)',\s*(\d+),\s*(\d+),\s*'(.*?)'\.split\('\|'\)/", $source, $match);
$payload = $match[1];
$this->base = (int) $match[2];
$count = (int) $match[3];
$this->map = explode('|', $match[4]);
if ($count != count($this->map)) {
return $source;
}
$result = preg_replace_callback('#\b\w+\b#', array($this, 'lookup'), $payload);
$result = strtr($result, array('\\' => ''));
return $result;
}
public function isPacked($source, $dynamicHeader = true)
{
$header = $dynamicHeader ? '\w+,\w+,\w+,\w+,\w+,\w+' : 'p,a,c,k,e,[rd]';
$source = strtr($source, array(' ' => ''));
return (bool) preg_match('#^eval\(function\('.$header.'\){#i', trim($source));
}
protected function lookup($match)
{
$word = $match[0];
$unbased = $this->map[$this->unbase($word, $this->base)];
return $unbased ? $unbased : $word;
}
protected function unbase($value, $base)
{
if (2 <= $base && $base <= 36) {
return intval($value, $base);
}
static $dict = array();
$selector = $this->getSelector($base);
if (empty($dict[$selector])) {
$dict[$selector] = array_flip(str_split($this->alphabet[$selector]));
}
$result = 0;
$array = array_reverse(str_split($value));
for ($i = 0, $count = count($array); $i < $count; $i++) {
$cipher = $array[$i];
$result += pow($base, $i) * $dict[$selector][$cipher];
}
return $result;
}
protected function getSelector($base)
{
if ($base > 62) {
return 95;
}
if ($base > 54) {
return 62;
}
if ($base > 52) {
return 54;
}
return 52;
}
}