Skip to content

Commit 76cd4c7

Browse files
committed
Add decodeRecursive. Add ExplodeDelimiterWithApostropheException.
1 parent 349b5a3 commit 76cd4c7

File tree

8 files changed

+132
-72
lines changed

8 files changed

+132
-72
lines changed

README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,25 @@ Download the `zip` file and unzip them into a folder. All dependencies have been
2020

2121
## Usage
2222

23+
### Decode One File
24+
2325
```bash
2426
php bin/decode.php input.php output.php
2527
```
2628

2729
Call `bin/decode.php` decode `input.php` and save it to `output.php`.
2830

29-
## About EnPHP Bugs
31+
### Decode All Files in A Directory
32+
33+
```bash
34+
php bin/decodeRecursive.php dir/
35+
```
36+
37+
Call `bin/decodeRecursive.php` decode all php files in `dir/` recursively and save it to its original path.
3038

31-
**EnPHP is for php 5. There may be some problem is you use the obfuscated files on php 7.**
39+
**CAUTION: This will OVERWRITE all php files! If any error happened with the decoder, your files MAY NOT BE RECOVERED! Please backup your files!**
40+
41+
## About EnPHP Bugs
3242

3343
See <docs/enphp_bugs.md>.
3444

bin/decodeRecursive.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
/**
3+
* EnPHP Decoder
4+
*
5+
* https://github.com/ganlvtech/php-enphp-decoder
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+
use Ganlv\EnphpDecoder\AutoDecoder;
24+
use Ganlv\EnphpDecoder\KnownEnphpBugs\KnownEnphpBugsException;
25+
26+
error_reporting(E_ALL);
27+
28+
require __DIR__ . '/../vendor/autoload.php';
29+
30+
function endsWith($haystack, $needle)
31+
{
32+
$length = strlen($needle);
33+
if ($length == 0) {
34+
return true;
35+
}
36+
return (substr($haystack, -$length) === $needle);
37+
}
38+
39+
function decodeRecursive($dir)
40+
{
41+
$files = scandir($dir);
42+
foreach ($files as $key => $value) {
43+
$path = realpath($dir . DIRECTORY_SEPARATOR . $value);
44+
if (!is_dir($path)) {
45+
if (endsWith($path, '.php')) {
46+
echo $path;
47+
$modified = false;
48+
try {
49+
$code = file_get_contents($path);
50+
$ast = AutoDecoder::parseFile($code);
51+
$decoder = new AutoDecoder($ast);
52+
$modified = $decoder->autoDecode();
53+
if ($modified) {
54+
file_put_contents($path, $decoder->prettyPrintFile());
55+
echo ' Decoded.';
56+
}
57+
} catch (KnownEnphpBugsException $e) {
58+
echo ' Known EnPHP Bugs: ', $e->getMessage();
59+
} catch (Throwable $e) {
60+
echo ' Decode error.', PHP_EOL;
61+
echo $e->getTraceAsString();
62+
}
63+
if (!$modified) {
64+
echo ' Unchanged.';
65+
}
66+
echo PHP_EOL;
67+
}
68+
} else {
69+
if ($value != '.' && $value != '..') {
70+
decodeRecursive($path);
71+
}
72+
}
73+
}
74+
}
75+
76+
decodeRecursive($argv[1]);

docs/enphp_bugs.md

Lines changed: 4 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,11 @@
11
# About EnPHP Bugs
22

3-
**EnPHP is for php 5. There may be some problem is you use the obfuscated files on php 7.**
3+
## explode delimiter with apostrophe
44

5-
**php 5.5 5.6 7.0 is no longer supported.** See [PHP: Supported Versions](http://php.net/supported-versions.php).
6-
7-
EnPHP has bugs. The obfuscated files cannot even run properly on php 7. You shouldn't ask a decoder to recover a broken file to a normal file.
8-
9-
See [PHP 5.x to 7.x: Changes to the handling of indirect variables, properties, and methods](http://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.variable-handling.indirect).
10-
11-
Here are some known EnPHP bugs running on php 7. They **WON'T** be fixed.
12-
13-
## Class Static Call
14-
15-
```php
16-
class Foo
17-
{
18-
public static function baz()
19-
{
20-
echo 'baz';
21-
}
22-
}
23-
24-
class Bar extends Foo
25-
{
26-
public function __construct()
27-
{
28-
parent::baz();
29-
}
30-
}
31-
```
32-
33-
class Bar will be obfuscated like this
34-
35-
```php
36-
class Bar extends Foo
37-
{
38-
public function __construct()
39-
{
40-
parent::$GLOBALS[GLOBAL_VAR_KEY][0x0]();
41-
}
42-
}
43-
```
44-
45-
This means `(parent::$GLOBALS)[GLOBAL_VAR_KEY][0x0]();` instead of what we expected `parent::{$GLOBALS[GLOBAL_VAR_KEY][0x0]}();`.
46-
47-
## Class Method Call
48-
49-
```php
50-
class Foo
51-
{
52-
public function bar()
53-
{
54-
echo 'bar';
55-
}
56-
57-
public function __construct()
58-
{
59-
$this->bar();
60-
}
61-
}
62-
```
63-
64-
The constructor will be encoded like this
5+
tests/bug_samples/Rush.php
656

667
```php
67-
class Foo
68-
{
69-
public function __construct()
70-
{
71-
$v0 = &$GLOBALS[GLOBAL_VAR_KEY];
72-
$this->$v0[0x0]();
73-
}
74-
}
8+
explode('|\'|%|\'', 'post.|\\\'|%|\\\'site_config|\\\'|%|\\\'设置成功|\\\'|%|\\\'API|\\\'|%|\\\'api_config|\\\'|%|\\\'taobao|\\\'|%|\\\'key|\\\'|%|\\\'taobaoAppkey|\\\'|%|\\\'site');
759
```
7610

77-
This means `($this->$v0)[0x0]()` instead of what we expected `$this->{$v0[0x0]}()`.
11+
This is EnPHP's bug. Won't Fix!
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace Ganlv\EnphpDecoder\KnownEnphpBugs;
4+
5+
class ExplodeDelimiterWithApostropheException extends KnownEnphpBugsException
6+
{
7+
public $stringArray;
8+
public $dim;
9+
10+
public function __construct($stringArray, $dim)
11+
{
12+
$this->stringArray = $stringArray;
13+
$this->dim = $dim;
14+
parent::__construct('explode delimiter with apostrophe.');
15+
}
16+
17+
public static function test($stringArray, $dim)
18+
{
19+
if (!isset($stringArray[$dim]) && count($stringArray) === 1 && strpos($stringArray[0],'\\\'') !== false) {
20+
throw new self($stringArray, $dim);
21+
}
22+
}
23+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Ganlv\EnphpDecoder\KnownEnphpBugs;
4+
5+
use Exception;
6+
7+
abstract class KnownEnphpBugsException extends Exception
8+
{
9+
}

src/NodeVisitors/FunctionGlobalStringNodeVisitor.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Ganlv\EnphpDecoder\NodeVisitors;
44

5+
use Ganlv\EnphpDecoder\KnownEnphpBugs\ExplodeDelimiterWithApostropheException;
56
use Ganlv\EnphpDecoder\PrettyPrinter\StandardPrettyPrinter;
67
use PhpParser\Node;
78
use PhpParser\NodeTraverser;
@@ -37,6 +38,7 @@ public function leaveNode(Node $node)
3738
&& $node->var instanceof Node\Expr\Variable
3839
&& $node->var->name === $this->localVarName
3940
&& $node->dim instanceof Node\Scalar\LNumber) {
41+
ExplodeDelimiterWithApostropheException::test($this->stringArray, $node->dim->value);
4042
return new Node\Scalar\String_($this->stringArray[$node->dim->value]);
4143
}
4244
return null;

src/NodeVisitors/GlobalStringNodeVisitor.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Ganlv\EnphpDecoder\NodeVisitors;
44

5+
use Ganlv\EnphpDecoder\KnownEnphpBugs\ExplodeDelimiterWithApostropheException;
56
use Ganlv\EnphpDecoder\PrettyPrinter\StandardPrettyPrinter;
67
use PhpParser\Node;
78
use PhpParser\NodeVisitorAbstract;
@@ -28,6 +29,7 @@ public function leaveNode(Node $node)
2829
&& $node->var->dim !== null
2930
&& StandardPrettyPrinter::prettyPrinter()->prettyPrintExpr($node->var->dim) === $this->globalVarKeyExpr
3031
&& $node->dim instanceof Node\Scalar\LNumber) {
32+
ExplodeDelimiterWithApostropheException::test($this->stringArray, $node->dim->value);
3133
return new Node\Scalar\String_($this->stringArray[$node->dim->value]);
3234
}
3335
return null;

tests/bug_samples/Rush.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php /* 遞句コ丈セCMS豺伜ョ晏ョ「邉サ扈 遞句コ丈セ迚域揀謇譛 謚譛ッ隶コ蝮帶髪謖: bbs.chengxuxia.com QQ: 573907419 豁」迚域肢譚�亟豁「蜃コ邇ー貍乗エ槫錘髣ィ
2+
-- enphp : https://git.oschina.net/mz/mzphp2
3+
*/
4+
namespace app\admin\controller;error_reporting(E_ALL^E_NOTICE);define('コ佗', 'ナナツ');湘ゥス鎌゚苻荢ィ屎レ・靫�チ菖ア杦チイェマ嘉ー汯ャfネ瑙恩煜��ェ鼕匆ヒヒハモコ。ツ佩ナ棊蛟�カシ、�ホリ闃�ェキォ寥貍マ虚椒墲ゥ鰈斷陳セィ著;$_SERVER[コ佗] = explode('|\'|%|\'', 'post.|\\\'|%|\\\'site_config|\\\'|%|\\\'隶セ鄂ョ謌仙粥|\\\'|%|\\\'API|\\\'|%|\\\'api_config|\\\'|%|\\\'taobao|\\\'|%|\\\'key|\\\'|%|\\\'taobaoAppkey|\\\'|%|\\\'site');「カーフ飼顯テ・ヒツア珥ユワヌユ撕鞜ラ拓�崧憎゚揵釮鏸ぃェ胯�ケ碑「エ邀跡ナ。「�洌゙邀%抱奠�ウ�ヨ哿娯ニ愡言ョイ燹「∀る�酪墲テ幟鬨メアト言┰レ疲ゥ厘ゥ嶇ソ吝マ郁美セッ�ラソレ;use think\File;use think\Db;use app\common\controller\Admin;use app\admin\model\Config as ConfigModel;class Rush extends Admin{public function index(){$「┷=&$_SERVER{コ佗};if($this->request->isAjax()){$コ「ヘ脣=input($「┷[0]);foreach($コ「ヘ脣 as $ニ賃リ=>$){ConfigModel::updateCofig($ニ賃リ,$「┷{0x001},$);}cache($「┷{0x001},null);return $this->success($「┷[0x0002]);}else{if($=get_config($「┷{0x00003},$「┷[0x000004])){if($$「┷{0x05}][$「┷[0x006]]){$this->assign($「┷{0x0007},trim($$「┷{0x05}][$「┷[0x006]]));}}$=get_config();$this->assign($「┷[0x00008],$);星タイネ威ワ・ホオ。華�モナオ蜀守讎蔕カ励倹届ツロヨ隼鏞釚桒杓慱窒ル�ヌマク譚遇アルコ鴫マ;return $this->fetch();生ヒ。レ岼裾桶缶�;}}}?>

0 commit comments

Comments
 (0)