前言
逛论坛看到一个师傅发了个《关于解密之后未进行发放 tubi》的帖子,顺着找到了原讨论。帖子只给了结果,没有解密方法,所以试试用 echo 大法能不能解开。
分析
原代码省略长字符串后是这样:
<?php
$table = base64_decode("...");
$decoder = $table[3].$table[6].$table[33].$table[30];
$decoder .= $table[22].$table[36].$table[29].$table[26];
eval($decoder("..."));
?>
函数名通过字符表索引动态拼接,真正的代码放在 eval() 参数中。
把 eval 改成 echo:
-eval($decoder("..."));
+echo($decoder("..."));
输出仍然是 PHP:
$payload = "...";
eval('?>'.$decoder($transform($payload)));
把输出插回 ?> 前,接着把新一层的 eval 改成 echo。后面又出现两个结构相同的代码块,输出分别要插在 ?> 前后。
解密
规律已经比较明显:把 eval 改成 echo 执行;输出以 <?php 开头就接在尖括号外,否则接在括号内。不过一直手工重复不知道要解多少次,还是写个脚本跑。
当时的思路:
- 把
eval改成echo。 - 执行 PHP 文件拿到输出。
- 把输出插回 PHP。
- 删除上一轮的
echo语句,继续循环。
脚本:
import os
import re
origin_data = ""
new_data = ""
file = "unknown.php"
with open(file, "r", encoding="utf-8") as f:
for line in f:
if "echo" in line:
line = re.sub(r"echo.*?;", "", line)
if "eval" in line:
line = line.replace("eval", "echo")
origin_data += line
with open(file, "w", encoding="utf-8") as f:
f.write(origin_data)
result = os.popen(f"php {file}").read()
print(result)
with open(file, "r", encoding="utf-8") as f:
new_data = f.read()
new_data = re.sub(r"\?>$", "", new_data)
with open(file, "w", encoding="utf-8") as f:
if "<?php" not in result:
f.write(new_data + result + "?>")
else:
f.write(new_data + result)
结果
执行 4 次就出了源码,看来不太难,手动其实也能解开。结果和帖子里师傅解出来的一样。

参考
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。