FinalShell 记住密码解密
FinalShell 在保存连接密码时会对密码进行加密存储,存储在 conn.json 或 config.json 中。本文提供一个 Java 工具类,用于解密这些加密的密码。
解密原理
加密流程(逆向即为解密):
- 从 Base64 编码的密文中提取前 8 字节作为头部(
head)
- 剩余部分为 DES 加密数据
- 使用
head 中的特定字节通过 Random 算法生成 DES 密钥
- 密钥经过 MD5 哈希后用于 DES 解密
Java 解密代码
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
| import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Base64; import java.util.Random;
import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec;
public class FinalShellDecodePass { public static void main(String[] args) throws Exception { System.out.println(decodePass("aT4+S0skaRPWjdVrDwHtdHSlTMRIR3mWAzLRyHsR4p0=")); }
public static String decodePass(String data) throws Exception { if (data == null) { return null; } byte[] buf = Base64.getDecoder().decode(data); byte[] head = new byte[8]; System.arraycopy(buf, 0, head, 0, head.length); byte[] d = new byte[buf.length - head.length]; System.arraycopy(buf, head.length, d, 0, d.length); byte[] bt = desDecode(d, ranDomKey(head)); return new String(bt); }
public static byte[] desDecode(byte[] data, byte[] head) throws Exception { SecureRandom sr = new SecureRandom(); DESKeySpec dks = new DESKeySpec(head); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey securekey = keyFactory.generateSecret(dks); Cipher cipher = Cipher.getInstance("DES"); cipher.init(Cipher.DECRYPT_MODE, securekey, sr); return cipher.doFinal(data); }
static byte[] ranDomKey(byte[] head) { long ks = 3680984568597093857L / (long) (new Random((long) head[5]).nextInt(127)); Random random = new Random(ks); int t = head[0]; for (int i = 0; i < t; i++) { random.nextLong(); } long n = random.nextLong(); Random r2 = new Random(n); long[] ld = new long[] { (long) head[4], r2.nextLong(), (long) head[7], (long) head[3], r2.nextLong(), (long) head[1], random.nextLong(), (long) head[2] }; ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos); for (long l : ld) { dos.writeLong(l); } dos.close(); byte[] keyData = bos.toByteArray(); return md5(keyData); }
public static byte[] md5(byte[] data) { try { MessageDigest m = MessageDigest.getInstance("MD5"); m.update(data, 0, data.length); return m.digest(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } } }
|
使用方法
编译并运行:
1 2
| javac FinalShellDecodePass.java java FinalShellDecodePass
|
在线运行(无需安装 Java):
获取密文:
- 打开 FinalShell 配置目录(通常在
%USERPROFILE%\AppData\Local\FinalShell\ 或 ~/.finalshell/)
- 找到
conn.json 或 config.json 文件
- 查找
password 字段的值(Base64 编码的字符串)
修改代码中的密文:
- 将
main 方法中的 decodePass("...") 参数替换为你要解密的密文字符串
- 重新编译运行即可
注意事项
- 该工具仅用于找回自己忘记的密码,请勿用于非法用途
- 不同的 FinalShell 版本可能使用不同的加密算法,此代码适用于大部分版本
- 需要 JDK 8 或更高版本