纯python实现Finalshell密码解密
Finalshell的解密流程
Finalshell保存的服务器密码解密并不难,网络上也已经有很多的案例,比如:Finalshell密码批量解密(工具) - DayDayUp - HYLUZ
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;
}
关键的密钥计算部分涉及了大量的java随机数运算,因此这些解密脚本往往都是使用java编写运行的。
python对java.util.Random随机数生成算法的实现
但是查阅文档可以知道,java.util.Random中的随机数是使用LCG算法实现的,LCG算法本身是可以使用python去复现的。
python实现 LCG算法 生成与java.util.Random相同的随机数序列 - DayDayUp - HYLUZ
基于python的Finalshell解密实现
整合了一下python中LCG算法的实现方式,与Finalshell中的解密逻辑,制作了基于python不依赖任何java环境的Finalshell密码解密程序。
import base64
import hashlib
import struct
from Crypto.Cipher import DES
import re
def remove_non_printable_chars(input_string):
cleaned_string = re.sub(r'[\x00-\x1F\x7F-\x9F]', '', input_string)
return cleaned_string
class Random:
def __init__(self, seed=None):
if seed is None:
seed = (int((id(self) + id(seed)) * 997) & ((1 << 48) - 1))
self.seed = (seed ^ 0x5DEECE66D) & ((1 << 48) - 1)
def next(self, bits):
self.seed = (self.seed * 0x5DEECE66D + 0xB) & ((1 << 48) - 1)
value = self.seed >> (48 - bits)
return value if value < (1 << (bits - 1)) else value - (1 << bits)
def next_int(self):
return self.next(32)
def next_long(self):
return (self.next(32) << 32) + self.next(32)
def next_float(self):
return self.next(24) / (1 << 24)
def next_double(self):
return ((self.next(26) << 27) + self.next(27)) * (1.0 / (1 << 53))
def des_decode(data, key):
cipher = DES.new(key, DES.MODE_ECB)
return cipher.decrypt(data)
def random_key(head):
ilist=[24,54,89,120,19,49,85,115,14,44,80,110,9,40,75,106,43,73,109,12,38,68,104,7,33,64,99,3,28,59,94,125,112,16,51,82,107,11,46,77,103,6,41,72,98,1,37,67,4,35,70,101,0,30,65,96,122,25,61,91,117,20,56,86,74,104,13,43,69,99,8,38,64,95,3,34,59,90,125,29,93,123,32,62,88,119,27,58,83,114,22,53,79,109,17,48,35,66,101,5,31,61,96,0,26,56,92,122,21,51,87,117,55,85,120,24,50,80,116,19,45,75,111,14,40,71,106,10,50,81,116,20,45,76,111,15,41,71,106,10,36,66,102,5,69,100,8,39,65,95,3,34,60,90,126,29,55,85,121,24,12,42,78,108,7,37,73,103,2,33,68,99,124,28,63,94,31,61,97,0,26,57,92,123,21,52,87,118,17,47,82,113,100,4,39,70,96,126,34,65,91,121,30,60,86,116,25,55,120,23,58,89,115,18,54,84,110,13,49,79,105,9,44,75,62,92,1,31,57,88,123,27,52,83,118,22,48,78,113,17,81,112,20,51,76,107,15,46,72,102,10,41,67,97,6,36]
i=ilist[head[5]]
ks = 3680984568597093857 // i
random = Random(ks)
t = head[0]
for _ in range(t):
random.next_long()
n = random.next_long()
r2 = Random(n)
ld = [head[4], r2.next_long(), head[7], head[3], r2.next_long(), head[1], random.next_long(), head[2]]
byte_stream = bytearray()
for l in ld:
byte_stream.extend(struct.pack('!Q', l& ((1 << 64) - 1)))
#print(' '.join(format(byte, '02X') for byte in byte_stream))
key_data = md5(byte_stream)[:8]
return key_data
def md5(data):
return hashlib.md5(data).digest()
def decode_pass(data):
if data is None:
return None
rs = ""
buf = base64.b64decode(data)
head = buf[:8]
d = buf[8:]
key = random_key(head)
bt = des_decode(d, key)
rs = bt.decode('utf-8')
return remove_non_printable_chars(rs)
while(1):
try:
a=input("Input Password:")
if('exit' in a):
break
print("Decode Result:",decode_pass(a))
except:
print('error')
运行截图