From 4cf33f2cf8979f9d104ef015a72165b58f8ea203 Mon Sep 17 00:00:00 2001 From: L Date: Sun, 9 Jul 2023 18:20:13 +0800 Subject: [PATCH] add finalshell algo --- Gemfile.lock | 6 +- .../com/finalshell/FinalShellDecodePass.class | Bin 0 -> 3626 bytes .../com/finalshell/FinalShellDecodePass.java | 135 ++++++++++++++++++ lib/passwd.rb | 4 +- plugins/finalshell.rb | 22 +++ 5 files changed, 162 insertions(+), 5 deletions(-) create mode 100644 external/java_ext/classes/com/finalshell/FinalShellDecodePass.class create mode 100644 external/java_ext/classes/com/finalshell/FinalShellDecodePass.java create mode 100644 plugins/finalshell.rb diff --git a/Gemfile.lock b/Gemfile.lock index a6b7155..3fcf7d0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -37,11 +37,11 @@ GEM ffi (1.15.5) http-cookie (1.0.5) domain_name (~> 0.5) - msgpack (1.6.0) + msgpack (1.7.0) multipart-post (2.3.0) rainbow (3.1.1) rjb (1.6.7) - ruby-progressbar (1.11.0) + ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) thwait (0.2.0) e2mmap @@ -65,4 +65,4 @@ DEPENDENCIES typhoeus BUNDLED WITH - 2.4.6 + 2.4.7 diff --git a/external/java_ext/classes/com/finalshell/FinalShellDecodePass.class b/external/java_ext/classes/com/finalshell/FinalShellDecodePass.class new file mode 100644 index 0000000000000000000000000000000000000000..8ee860b4e099811e6543e6ff06c610d070c014f0 GIT binary patch literal 3626 zcmai1Yj9L&8Gg?0IeX5YoP`ib=!O90+GLZkErHN(XelA229iL#X=T9zhs_~b*jx8f z2(meiUz_N~eiI=aFz^ZaK51ez4(d2$A|N{f91fCVn>d1`?2XId z=r|h01SW+gC6r?_J1(=dj*N-L!n_z+13B5rYdy`UKRWW^Yk$%4l!;apWGKo|(or_C z0{eA5ZQ^d6km00`DHCgON*1SO`x(K0*1#uCJcs9HctN~W44*df z8GKgs{+!G{FT)pfysYDk3ekrzaI#LpE;;>ECEB62 z50OJbaNH^GbYW>5VO$`OJm9KL^44U!>KrqkD;JW^U`kvO9!zEJbbQiDr@fj=ZhG!jRoW~EC52l45;*ELK zaw(OLdPyK?Z(6v3A6fV@-cqpKm7B^%#betG1$$~wxs)%L7;4APD7b5Wf50x;^;?4U z6AKsdrh>)uhlcjlqG{o6anDa>_!%x)cofW1|H!~*9q(AUjCU>kTu5!gd@`CWOyx_t zXff|3qXRqR40)VWk@5?&k)op_Y||EI@Jk)<$zs;R1Bh9;f?rvf6SOtSTqb%{Vpf!x zMQ<0rdB3>c-gD%blPt~K;F4-Ku&N||d$2EM}jkz}B6pQwRGmx5aid3e7E*#1h86h$G zzIv1A8?~>kb7Xf3Z+R;rLJxlsMR2Eje=8R1rFNDQm(*k>bawkJ2Fwsg86Rj z0V?RN!qgOVtG!z4eO@ST1tgN&U}`%%Qu#@#jgJ4Xm3Nc~sx)^oq*??u6)3%$95oWv zy?$%Di7=jX`v_L?8t&z5!v{keIcJ76Abw3KY*kx1KFHN_et9cEi%dg#hZ6-4aSXV` z76j#@;9QPwBbblhrpWuy)Qgb{e8Wxt&I;6vr21UGCa9dZaa>M}m1y8YVmm2*C;@`? zV+Rik*xS%}0N5{J%B3d%aAXGBtJpn@Kw=s?(T$PI2wpKpyZqh$?ztJ5U31-Y<5!HB z+SNT5R{ddBh+(yR1`RW?V%jW1iLiDV3#R!}=)6R9PpOT(^ni6#YCUDPQ;!ZbB0@Dg zv6`=#PIU8Cwt?< z10$z1Zi^YYWsKTd#%%-r*GFd$G9aRs%JYLf%NyGBt@015x`;a;Ex}#0XiY?np0m?f z*7#fnZD%tN3uz_SqY-~kuj=pBnzd&2JQh%!<@?TP%7trxm+2Pzvo+D8@nlSIG_Eux z{1Lt9?B0YL*15emp+y?qbs!QDvR)+{5mlCr0RiDxk7!)Sj9ILp%`0QUS=^ln2dA+r zW`>PeL)e(>wfw!I=1{YB9_zvl&7tU)1!1#=j$C~KW~?#XSi#!nkb3xBZ|K6cKZMN+ z*2zXF9O6beSiyRk&)^>UT%s3d@f-Y>!TJDy#Gm-}@*qnef}v|+Kv&XtYZ=H5^ji0oEFpOOo!OIxME7*hAu@`UfHSiYVd;p9Q_2b0dPvm`g9|`=P^bc^5GHgmYgg@gj z{)!|%#5n#5$IYRmFs|VqXgYSOI(93pwX0Zk4MkYZlf*7FE=wn;`zqtnf#b7NY*p%ks??|}_0A%-|1I))g1&%-c#&E4 n5}V!`_LsADA`Rxue6L;M#)6Hc(RdfZo15)Y?(U--d`SEk35HX) literal 0 HcmV?d00001 diff --git a/external/java_ext/classes/com/finalshell/FinalShellDecodePass.java b/external/java_ext/classes/com/finalshell/FinalShellDecodePass.java new file mode 100644 index 0000000..26e9237 --- /dev/null +++ b/external/java_ext/classes/com/finalshell/FinalShellDecodePass.java @@ -0,0 +1,135 @@ +package com.finalshell; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Random; +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.DESKeySpec; +import sun.misc.BASE64Decoder; +import sun.misc.BASE64Encoder; + +/** + * @author jas502n + */ + +public class FinalShellDecodePass { + static int Size = 8; + static SecureRandom sr; + + + public static boolean checkStr(String str) { + if (str == null) { + return true; + } else { + String s2 = str.trim(); + return "".equals(s2); + } + } + + public static String decodePass(String data) throws IOException, Exception { + if (data == null) { + return null; + } else { + String rs = ""; + if (!checkStr(data)) { + byte[] buf = (new BASE64Decoder()).decodeBuffer(data); + byte[] head = new byte[Size]; + 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)); + rs = new String(bt, StandardCharsets.UTF_8); + } + + return rs; + } + } + + public static String encodePass(String content) throws Exception { + byte[] head = generateByte(Size); + byte[] d = desEncode(content.getBytes(StandardCharsets.UTF_8), head); + byte[] result = new byte[head.length + d.length]; + System.arraycopy(head, 0, result, 0, head.length); + System.arraycopy(d, 0, result, head.length, d.length); + String var1 = (new BASE64Encoder()).encodeBuffer(result); + String rs = var1.replace("\n", ""); + return rs; + } + + static byte[] ranDomKey(byte[] head) throws NoSuchAlgorithmException { + 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[] arrayOfLong1 = ld; + int j = ld.length; + + for(byte b = 0; b < j; ++b) { + long l = arrayOfLong1[b]; + + 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) throws NoSuchAlgorithmException { + return MessageDigest.getInstance("MD5").digest(data); + } + + static byte[] generateByte(int len) { + byte[] data = new byte[len]; + + for(int i = 0; i < len; ++i) { + data[i] = (byte)(new Random()).nextInt(127); + } + + return data; + } + + public static byte[] desEncode(byte[] data, byte[] head) throws Exception { + DESKeySpec dks = new DESKeySpec(ranDomKey(head)); + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); + SecretKey secretKey = keyFactory.generateSecret(dks); + Cipher cipher = Cipher.getInstance("DES"); + cipher.init(1, secretKey, sr); + return cipher.doFinal(data); + } + + public static byte[] desDecode(byte[] data, byte[] key) throws Exception { + DESKeySpec dks = new DESKeySpec(key); + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); + SecretKey secretKey = keyFactory.generateSecret(dks); + Cipher cipher = Cipher.getInstance("DES"); + cipher.init(2, secretKey, sr); + return cipher.doFinal(data); + } +} diff --git a/lib/passwd.rb b/lib/passwd.rb index 262b698..59eae89 100644 --- a/lib/passwd.rb +++ b/lib/passwd.rb @@ -13,7 +13,7 @@ module PasswdLib xshell securecrt securecrt_v2 dahan_jis uportal2800 navicat11 navicat12 flashfxp lsrunase qizhi_php seeyon_a8 h3c_imc landray_ekp d3des_vnc finereport zfsoft grafana trswcm mobaxterm seeyon_analyze_icloud - richmail signer h3c_cvm seeyon_nc + richmail signer h3c_cvm seeyon_nc finalshell } Passwd = Struct.new(:cipher, :algos) do @@ -68,7 +68,7 @@ def find_hash_type(passwd) cipher = base64_to_hex(cipher) algorithms += [ :gpp, :dongao_rc4, :druid_rsa, :xshell, :xftp, :dahan_jis, :websphere, :qizhi_php, :seeyon_a8, :landray_ekp, - :h3c_cvm + :h3c_cvm, :finalshell ] algorithms << :lsrunase if cipher.size <= 1024 algorithms << :grafana if cipher.size >= 50 or (cipher.start_with?('2a') and cipher.size >= 44) diff --git a/plugins/finalshell.rb b/plugins/finalshell.rb new file mode 100644 index 0000000..918d160 --- /dev/null +++ b/plugins/finalshell.rb @@ -0,0 +1,22 @@ +#!/usr/bin/env ruby +# +# Plugin finalshell password decrypt +# Author L +# Reference https://github.com/jas502n/FinalShellDecodePass +# +# ~/Library/FinalShell/conn/xxxxxx/xxxxxx_connect_config.json +# + +if Kernel.const_defined? :Rjb + +plugin 'finalshell' do + supported_algorithm :finalshell + + crack { + cipher = [passwd.hex2ascii].pack 'm0' + plain = Rjb.import('com.finalshell.FinalShellDecodePass').decodePass(cipher) + plain if plain.printable? + } +end + +end