Skip to content

Commit

Permalink
add finalshell algo
Browse files Browse the repository at this point in the history
  • Loading branch information
L-codes committed Jul 9, 2023
1 parent 9caffa8 commit 4cf33f2
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 5 deletions.
6 changes: 3 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -65,4 +65,4 @@ DEPENDENCIES
typhoeus

BUNDLED WITH
2.4.6
2.4.7
Binary file not shown.
135 changes: 135 additions & 0 deletions external/java_ext/classes/com/finalshell/FinalShellDecodePass.java
Original file line number Diff line number Diff line change
@@ -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);
}
}
4 changes: 2 additions & 2 deletions lib/passwd.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
22 changes: 22 additions & 0 deletions plugins/finalshell.rb
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 4cf33f2

Please sign in to comment.