Skip to content

Commit c4afffa

Browse files
committed
Init commit
0 parents  commit c4afffa

18 files changed

+1449
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
vendor

LICENSE

+674
Large diffs are not rendered by default.

README.md

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# EnPHP Decoder
2+
3+
## Installation & Usage
4+
5+
```bash
6+
git clone https://github.com/ganlvtech/php-enphp-decompiler.git
7+
cd php-enphp-decompiler
8+
composer install
9+
php bin/decode.php tests/assets/admin.php output.php
10+
```
11+
12+
## License
13+
14+
EnPHP Decoder
15+
Copyright (C) 2019 Ganlv
16+
17+
This program is free software: you can redistribute it and/or modify
18+
it under the terms of the GNU General Public License as published by
19+
the Free Software Foundation, either version 3 of the License, or
20+
(at your option) any later version.
21+
22+
This program is distributed in the hope that it will be useful,
23+
but WITHOUT ANY WARRANTY; without even the implied warranty of
24+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25+
GNU General Public License for more details.
26+
27+
You should have received a copy of the GNU General Public License
28+
along with this program. If not, see <https://www.gnu.org/licenses/>.

bin/decode.php

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
/**
3+
* EnPHP Decoder
4+
*
5+
* https://github.com/ganlvtech/php-enphp-decompiler
6+
*
7+
* Copyright (C) 2019 Ganlv
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU General Public License as published by
11+
* the Free Software Foundation, either version 3 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU General Public License
20+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
21+
*/
22+
23+
require __DIR__ . '/../vendor/autoload.php';
24+
25+
$code = file_get_contents($argv[1]);
26+
$decoded = \Ganlv\EnphpDecoder\AutoDecoder::decode($code);
27+
echo $decoded;
28+
file_put_contents($argv[2], $decoded);

composer.json

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "ganlvtech/php-enphp-decoder",
3+
"license": "GPL-3.0",
4+
"authors": [
5+
{
6+
"name": "Ganlv",
7+
"email": "[email protected]"
8+
}
9+
],
10+
"autoload": {
11+
"psr-4": {
12+
"Ganlv\\EnphpDecoder\\": "src"
13+
}
14+
},
15+
"require": {
16+
"ext-zlib": "*",
17+
"nikic/php-parser": "^4.2"
18+
}
19+
}

composer.lock

+69
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/AutoDecoder.php

+168
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
<?php
2+
/**
3+
* EnPHP Decoder
4+
*
5+
* https://github.com/ganlvtech/php-enphp-decompiler
6+
*
7+
* Copyright (C) 2019 Ganlv
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU General Public License as published by
11+
* the Free Software Foundation, either version 3 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU General Public License
20+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
21+
*/
22+
23+
namespace Ganlv\EnphpDecoder;
24+
25+
use Ganlv\EnphpDecoder\NodeVisitors\BeautifyNodeVisitor;
26+
use Ganlv\EnphpDecoder\NodeVisitors\FindAndRemoveGlobalVariableNameNodeVisitor;
27+
use Ganlv\EnphpDecoder\NodeVisitors\FunctionGlobalStringNodeVisitor;
28+
use Ganlv\EnphpDecoder\NodeVisitors\FunctionLikeNodeVisitor;
29+
use Ganlv\EnphpDecoder\NodeVisitors\FunctionLocalVariableRenameNodeVisitor;
30+
use Ganlv\EnphpDecoder\NodeVisitors\GlobalStringNodeVisitor;
31+
use Ganlv\EnphpDecoder\NodeVisitors\RemoveDefineGlobalVariableNameNodeVisitor;
32+
use Ganlv\EnphpDecoder\NodeVisitors\RemoveUnusedConstFetchNodeVisitor;
33+
use PhpParser\Error;
34+
use PhpParser\NodeTraverser;
35+
use PhpParser\ParserFactory;
36+
use PhpParser\PrettyPrinter\Standard;
37+
38+
class AutoDecoder
39+
{
40+
protected $ast;
41+
protected $globalVarName;
42+
protected $delimiter;
43+
protected $data;
44+
protected $start;
45+
protected $length;
46+
protected $stringArray;
47+
48+
public function __construct($ast)
49+
{
50+
$this->ast = $ast;
51+
}
52+
53+
public static function parseFile($code)
54+
{
55+
$parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
56+
$ast = $parser->parse($code);
57+
return $ast;
58+
}
59+
60+
public function findAndRemoveGlobalVariableName()
61+
{
62+
$nodeVisitor = new FindAndRemoveGlobalVariableNameNodeVisitor();
63+
$traverser = new NodeTraverser();
64+
$traverser->addVisitor($nodeVisitor);
65+
$this->ast = $traverser->traverse($this->ast);
66+
$this->globalVarName = $nodeVisitor->globalVarName;
67+
$this->delimiter = $nodeVisitor->delimiter;
68+
$this->data = $nodeVisitor->data;
69+
$this->start = $nodeVisitor->start;
70+
$this->length = $nodeVisitor->length;
71+
return $this->ast;
72+
}
73+
74+
public function removeDefineGlobalVariableName()
75+
{
76+
$nodeVisitor = new RemoveDefineGlobalVariableNameNodeVisitor($this->globalVarName);
77+
$traverser = new NodeTraverser();
78+
$traverser->addVisitor($nodeVisitor);
79+
$this->ast = $traverser->traverse($this->ast);
80+
$this->stringArray = explode($this->delimiter, gzinflate(substr($this->data, $this->start, $this->length)));
81+
return $this->ast;
82+
}
83+
84+
public function removeUnusedConstFetchNodeVisitor()
85+
{
86+
$nodeVisitor = new RemoveUnusedConstFetchNodeVisitor();
87+
$traverser = new NodeTraverser();
88+
$traverser->addVisitor($nodeVisitor);
89+
$this->ast = $traverser->traverse($this->ast);
90+
return $this->ast;
91+
}
92+
93+
public function replaceGlobalString()
94+
{
95+
$nodeVisitor = new GlobalStringNodeVisitor($this->globalVarName, $this->stringArray);
96+
$traverser = new NodeTraverser();
97+
$traverser->addVisitor($nodeVisitor);
98+
$this->ast = $traverser->traverse($this->ast);
99+
return $this->ast;
100+
}
101+
102+
public function replaceFunctionLikeGlobalString()
103+
{
104+
$globalVarName = $this->globalVarName;
105+
$stringArray = $this->stringArray;
106+
$nodeVisitor = new FunctionLikeNodeVisitor(function ($node) use ($globalVarName, $stringArray) {
107+
/** @var $node \PhpParser\Node\Stmt\Function_ */
108+
$nodeVisitor = new FunctionGlobalStringNodeVisitor($globalVarName, $stringArray);
109+
$traverser = new NodeTraverser();
110+
$traverser->addVisitor($nodeVisitor);
111+
$node->stmts = $traverser->traverse($node->stmts);
112+
return null;
113+
});
114+
$traverser = new NodeTraverser();
115+
$traverser->addVisitor($nodeVisitor);
116+
$this->ast = $traverser->traverse($this->ast);
117+
return $this->ast;
118+
}
119+
120+
public function renameFunctionLocalLikeVariable()
121+
{
122+
$nodeVisitor = new FunctionLikeNodeVisitor(function ($node) {
123+
/** @var $node \PhpParser\Node\Stmt\Function_ */
124+
$nodeVisitor = new FunctionLocalVariableRenameNodeVisitor();
125+
$traverser = new NodeTraverser();
126+
$traverser->addVisitor($nodeVisitor);
127+
$ast = $traverser->traverse([$node]);
128+
return $ast[0];
129+
});
130+
$traverser = new NodeTraverser();
131+
$traverser->addVisitor($nodeVisitor);
132+
$this->ast = $traverser->traverse($this->ast);
133+
return $this->ast;
134+
}
135+
136+
public function beautify()
137+
{
138+
$nodeVisitor = new BeautifyNodeVisitor();
139+
$traverser = new NodeTraverser();
140+
$traverser->addVisitor($nodeVisitor);
141+
$this->ast = $traverser->traverse($this->ast);
142+
return $this->ast;
143+
}
144+
145+
public function prettyPrintFile()
146+
{
147+
$prettyPrinter = new Standard();
148+
return $prettyPrinter->prettyPrintFile($this->ast);
149+
}
150+
151+
public static function decode($code)
152+
{
153+
try {
154+
$ast = self::parseFile($code);
155+
} catch (Error $error) {
156+
return '';
157+
}
158+
$decoder = new self($ast);
159+
$decoder->findAndRemoveGlobalVariableName();
160+
$decoder->removeDefineGlobalVariableName();
161+
$decoder->removeUnusedConstFetchNodeVisitor();
162+
$decoder->replaceGlobalString();
163+
$decoder->replaceFunctionLikeGlobalString();
164+
$decoder->renameFunctionLocalLikeVariable();
165+
$decoder->beautify();
166+
return $decoder->prettyPrintFile();
167+
}
168+
}

0 commit comments

Comments
 (0)