Finalshell密码批量解密(工具)
经常忘记服务器密码,finalshell里保存了又不能查看
默认配置文件目录
C:\Users\用户名\AppData\Local\finalshell\conn
核心解密代码
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("VS8vGQ5RYU+G1SR5OIMPUybgeZbWTc/t")); } 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(2, securekey, sr); return cipher.doFinal(data); } public static String decodePass(String data) throws Exception { if (data == null) { return null; } else { String rs = ""; byte[] buf = Base64.getDecoder().decode(data); //base64 decode byte[] head = new byte[8]; System.arraycopy(buf, 0, head, 0, head.length); //取解码后前8字节 byte[] d = new byte[buf.length - head.length]; System.arraycopy(buf, head.length, d, 0, d.length); //取剩余字节 byte[] bt = desDecode(d, ranDomKey(head)); //des解密,密文为d,前8字节计算key rs = new String(bt); return rs; } } 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); long[] var15 = ld; int var14 = ld.length; for(int var13 = 0; var13 < var14; ++var13) { long l = var15[var13]; try { dos.writeLong(l); } catch (IOException var18) { var18.printStackTrace(); } } try { dos.close(); } catch (IOException var17) { var17.printStackTrace(); } byte[] keyData = bos.toByteArray(); keyData = md5(keyData); return keyData; } public static byte[] md5(byte[] data) { String ret = null; byte[] res=null; try { MessageDigest m; m = MessageDigest.getInstance("MD5"); m.update(data, 0, data.length); res=m.digest(); ret = new BigInteger(1, res).toString(16); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return res; } }
代码很多,但是都大同小异,需要用java去生成随机数序列,这点无法用python去实现,关键时候电脑可能没有java环境,所以做了个api来在线解密
遍历文件夹解密
本地的json也很多,一个一个扒password太慢,顺便python打包了个程序去遍历当前用户的finalshell数据文件夹
程序下载(会把加密的密文上传到我的服务器,介意慎用)
一个Web_Demo
源代码
客户端
import os import requests import json def list_files(directory): # 获取目录中的所有文件和子目录 files = os.listdir(directory) ret_list=[] # 遍历所有文件和子目录 for file in files: # 获取文件或子目录的完整路径 full_path = os.path.join(directory, file) # 判断是否为文件 if os.path.isfile(full_path): # print(f"文件: {full_path}") ret_list.append(full_path) return ret_list # 获取当前用户目录 user_home = os.path.expanduser("~") print("当前用户目录:", user_home) finalshell_dir=user_home+'\\AppData\\Local\\finalshell\\conn' print(finalshell_dir) use_dir='' if os.path.exists(finalshell_dir): print(f"自动检测到finalshell配置文件路径:'{finalshell_dir}'") use_dir=input('请输入配置文件路径,为空则使用自动检测路径:') if(use_dir==''): use_dir=finalshell_dir else: use_dir=input('未检测到配置文件路径,请手动输入:') print(f"使用finalshell配置文件路径:'{use_dir}'") json_list=list_files(use_dir) if json_list != []: for i in json_list: try: f=open(i) tmp=f.read() f.close() json_info=json.loads(tmp) name=json_info['name'] user_name=json_info['user_name'] port=json_info['port'] host=json_info['host'] password=json_info['password'] data={ 'encrypted_text':password } result=json.loads(requests.post('http://150.158.156.12:50000/decrypt',json=data).text)['decrypted_result'] print(f"{name}\t{host}\t{port}\t{user_name}\t{result}") except: print('err') else: print('请检查目录')
服务端
#coding:utf-8 from flask import Flask, request, jsonify import subprocess app = Flask(__name__) html=""" <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Finalshell密码解密</title> </head> <body> <div> <label for="encryptedText">Encrypted Text:</label> <input type="text" id="encryptedText" placeholder="Enter encrypted text"> <button onclick="decrypt()">解密</button> </div> <div> <label for="decryptedResult">Decrypted Result:</label> <textarea id="decryptedResult" rows="4" cols="50" readonly></textarea> </div> <script> function decrypt() { // 获取输入的密文 const encryptedText = document.getElementById('encryptedText').value; // 发送POST请求给后端 fetch('/decrypt', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ 'encrypted_text': encryptedText }) }) .then(response => response.json()) .then(data => { // 更新解密结果文本框 document.getElementById('decryptedResult').value = data.decrypted_result || data.error || 'Error occurred.'; }) .catch(error => { console.error('Error:', error); document.getElementById('decryptedResult').value = 'Error occurred.'; }); } </script> </body> </html> """ @app.route('/', methods=['GET']) def main(): return html @app.route('/decrypt', methods=['POST']) def decrypt(): try: encrypted_text = request.json.get('encrypted_text') # 调用Java程序执行解密 java_command = ['java', 'main', encrypted_text] #return(java_command) result = subprocess.run(java_command, stdout=subprocess.PIPE) # 获取解密结果 decrypted_result = result.stdout.decode('utf-8').strip() # 返回解密结果给前端 return jsonify({'decrypted_result': decrypted_result}) except Exception as e: return jsonify({'error': str(e)}) if __name__ == '__main__': app.run(host='0.0.0.0',port=50000)