<?php
/**
* FinalShell密码解密工具
* 修复了大整数精度问题
*/
function desDecode($data, $head) {
$key = ranDomKey($head);
// 使用DES-ECB模式解密
$decrypted = openssl_decrypt(
$data,
'des-ecb',
substr($key, 0, 8),
OPENSSL_RAW_DATA | OPENSSL_NO_PADDING
);
// 移除PKCS#5填充
$pad = ord($decrypted[strlen($decrypted) - 1]);
if ($pad > 8) return $decrypted;
if (strspn($decrypted, chr($pad), strlen($decrypted) - $pad) != $pad) return $decrypted;
return substr($decrypted, 0, -$pad);
}
function decodePass($data) {
if ($data === null) {
return null;
}
// 解码Base64数据
$buf = base64_decode($data);
// 提取头部8字节和数据部分
$head = substr($buf, 0, 8);
$d = substr($buf, 8);
// 解密数据
$bt = desDecode($d, $head);
// 转换为字符串
return $bt;
}
function ranDomKey($head) {
// 使用BCMath扩展处理大整数
$seed = ord($head[5]);
$constant = '3680984568597093857'; // 使用字符串表示大整数
// 计算ks = 3680984568597093857 / (1 + (seed % 127))
$divisor = bcadd('1', bcmod((string)$seed, '127'));
$ks = bcdiv($constant, $divisor, 0);
// 模拟Java的Random类(使用BCMath)
$javaRandSeed = (string)$seed;
// 模拟Java Random的nextInt方法
function javaNextInt(&$seed) {
$multiplier = '25214903917';
$addend = '11';
$mask = '281474976710655'; // 2^48 - 1
// seed = (seed * 0x5DEECE66D + 0xB) & 0xFFFFFFFFFFFF
$seed = bcmod(
bcadd(
bcmul($seed, $multiplier),
$addend
),
$mask
);
// 返回 (seed >> 16) & 0x7FFFFFFF
$shifted = bcdiv($seed, '65536', 0); // 右移16位
$maxInt = '2147483647'; // 0x7FFFFFFF
return bcmod(bcadd($shifted, $maxInt), $maxInt);
}
// 模拟Random.nextInt(127)
$nextInt = bcmod(javaNextInt($javaRandSeed), '127');
if (bccomp($nextInt, '0') < 0) {
$nextInt = bcadd($nextInt, '127');
}
// 重新计算ks
$divisor = bcadd($nextInt, '1');
$ks = bcdiv($constant, $divisor, 0);
$r2Seed = $ks;
$t = ord($head[0]);
for ($i = 0; $i < $t; $i++) {
javaNextInt($r2Seed);
}
$n = javaNextInt($r2Seed);
$r3Seed = $n;
// 生成8个long值
$ld = [
ord($head[4]),
(int)javaNextInt($r3Seed),
ord($head[7]),
ord($head[3]),
(int)javaNextInt($r3Seed),
ord($head[1]),
(int)javaNextInt($r2Seed),
ord($head[2])
];
// 将long数组转换为字节流
$keyData = '';
foreach ($ld as $num) {
// 模拟Java DataOutputStream.writeLong()
$keyData .= pack('J', $num);
}
// 计算MD5哈希
return md5($keyData, true);
}
// 修改此处的密文为需要解密的字符串
$encryptedPassword = "QFlpZWYpFgu7kB4SrwzWzzYbZqrgKrS2";
echo decodePass($encryptedPassword);
?>