fortify sca rules分析
原创 sanduo 2024-11-06 10:17 北京
fortify sca rules 一直处于加密状态,只有在扫描的时候才会被加载,网上发现已经有大佬破解了,这里分享给大家,jar包知识星球自取,解密代码如下,自行编译即可:
import java.io.*;import java.nio.file.Files;import java.security.*;import java.util.Properties;import java.util.StringTokenizer;import java.util.zip.GZIPInputStream;import java.util.zip.GZIPOutputStream;public class Main {// 定义常量private static final String MESSAGE_DIGEST_ALGORITHM = "SHA-1"; // 消息摘要算法private static final String CRYPTO_PROVIDER = "SUN"; // 加密提供者private static final int BUFFER_SIZE = 262144; // 缓冲区大小private static final String STD = "1fea047f-dee0ac89-b5db25a6-b0c3a4cf"; // 默认密钥// 构造函数public Main() {}// 获取消息摘要算法实例public static MessageDigest getMessageDigestAlgorithm() {try {return MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM, CRYPTO_PROVIDER);} catch (GeneralSecurityException e) {throw new RuntimeException(e);}}// 计算输入流的摘要public static byte[] makeDigest(InputStream inStream) throws IOException {return makeDigest(inStream, getMessageDigestAlgorithm());}// 计算输入流的摘要,使用指定的消息摘要算法public static byte[] makeDigest(InputStream inStream, MessageDigest md) throws IOException {md.reset();DigestInputStream in = new DigestInputStream(inStream, md);return md.digest(); // 返回摘要结果}// 加密函数private static void encrypt(long[] v, long[] k) {long y = v[0];long z = v[1];long sum = 0L;long delta = 2654435769L; // 常量 deltalong n = 32L; // 迭代次数long top = 4294967295L; // 掩码// 加密循环for (; n-- > 0L; z &= top) {sum += delta;sum &= top;y += (z << 4) + k[0] ^ z + sum ^ (z >> 5) + k[1];y &= top;z += (y << 4) + k[2] ^ y + sum ^ (y >> 5) + k[3];}v[0] = y;v[1] = z;}// 解密函数private static void decrypt(long[] v, long[] k) {long n = 32L; // 迭代次数long y = v[0];long z = v[1];long delta = 2654435769L; // 常量 deltalong top = 4294967295L; // 掩码long sum = delta << 5;// 解密循环for (sum &= top; n-- > 0L; sum &= top) {z -= (y << 4) + k[2] ^ y + sum ^ (y >> 5) + k[3];z &= top;y -= (z << 4) + k[0] ^ z + sum ^ (z >> 5) + k[1];y &= top;sum -= delta;}v[0] = y;v[1] = z;}// 加密输入流到输出流private static void enc(InputStream source, OutputStream dest, long[] usrKey) throws IOException {long[] k = usrKey.clone(); // 克隆密钥byte[] byteBuf = new byte[8]; // 字节缓冲区byte[] tail = new byte[]{32, 32, 32, 32, 32, 32, 32, 8}; // 尾部字节long[] unsigned32Buf = new long[2]; // 无符号32位缓冲区long top = 4294967295L; // 掩码int bytesRead;// 读取输入流并加密while ((bytesRead = source.read(byteBuf)) != -1) {if (bytesRead < 8) {tail[7] = (byte) bytesRead; // 设置尾部字节}byteArrayToUnsigned32(byteBuf, unsigned32Buf); // 字节数组转换为无符号32位数组encrypt(unsigned32Buf, k); // 加密k[0] = k[0] + 17L & top; // 更新密钥k[1] = k[1] + 17L & top;k[2] = k[2] + 17L & top;k[3] = k[3] + 17L & top;unsigned32ToByteArray(unsigned32Buf, byteBuf); // 无符号32位数组转换为字节数组dest.write(byteBuf); // 写入输出流}byteArrayToUnsigned32(tail, unsigned32Buf); // 处理尾部字节encrypt(unsigned32Buf, k);k[0] = k[0] + 17L & top;k[1] = k[1] + 17L & top;k[2] = k[2] + 17L & top;k[3] = k[3] + 17L & top;unsigned32ToByteArray(unsigned32Buf, tail);dest.write(tail); // 写入尾部字节}// 解密输入流到输出流private static void dec(InputStream source, OutputStream dest, long[] usrKey) throws IOException {long[] k = usrKey.clone(); // 克隆密钥byte[] byteBuf = new byte[8]; // 字节缓冲区byte[] byteBufDelay = null; // 延迟字节缓冲区long[] unsigned32Buf = new long[2]; // 无符号32位缓冲区long top = 4294967295L; // 掩码int bytesRead;// 读取输入流并解密while ((bytesRead = source.read(byteBuf)) != -1) {if (bytesRead < 8) {throw new IOException("invalid encrypted stream"); // 无效的加密流}byteArrayToUnsigned32(byteBuf, unsigned32Buf); // 字节数组转换为无符号32位数组decrypt(unsigned32Buf, k); // 解密k[0] = k[0] + 17L & top; // 更新密钥k[1] = k[1] + 17L & top;k[2] = k[2] + 17L & top;k[3] = k[3] + 17L & top;unsigned32ToByteArray(unsigned32Buf, byteBuf); // 无符号32位数组转换为字节数组if (source.available() == 0) {int bytesToWrite = byteBuf[7];if (bytesToWrite > 8 || bytesToWrite < 0 || byteBufDelay == null) {throw new IOException("invalid encrypted stream"); // 无效的加密流}dest.write(byteBufDelay, 0, bytesToWrite); // 写入延迟字节}if (byteBufDelay != null) {dest.write(byteBufDelay, 0, 8); // 写入延迟字节byte[] t = byteBufDelay;byteBufDelay = byteBuf;byteBuf = t;} else {byteBufDelay = byteBuf;byteBuf = new byte[8];}}}// 执行块加密或解密private static void doBlockCipher(InputStream source, OutputStream dest, boolean encrypt, long[] usrKey) throws IOException {if (encrypt) {enc(source, dest, usrKey); // 加密} else {dec(source, dest, usrKey); // 解密}}// 读取加密流中的头部信息public static void readHeaders(InputStream encrypted) throws IOException {Properties props = new Properties();final PushbackInputStream src = new PushbackInputStream(encrypted);props.load(new InputStream() {boolean closed = false;public int read() throws IOException {if (closed) {return -1;} else {int c = src.read();if (c == 0) {src.unread(c);closed = true;return -1;} else {return c;}}}});int read = src.read();if (read != 0) {throw new IOException("invalid encrypted stream"); // 无效的加密流}}// 解密并解压缩加密流中的数据public static byte[] decryptCompressedAfterHeaders(InputStream encrypted, String keyString) throws IOException {return decryptAfterHeaders(encrypted, keyString, true);}// 解密加密流中的数据,可以选择是否解压缩public static byte[] decryptAfterHeaders(InputStream encrypted, String keyString, boolean compressed) throws IOException {long[] key = makeKeyFromString(keyString != null ? keyString : STD); // 生成密钥ByteArrayOutputStream cleartext = new ByteArrayOutputStream();doBlockCipher(encrypted, cleartext, false, key); // 解密cleartext.close();byte[] bytes = cleartext.toByteArray();if (compressed) {bytes = uncompressString(bytes); // 解压缩}return bytes;}// 解密并解压缩加密流中的数据public static byte[] decryptCompressed(InputStream encrypted, String keyString) throws IOException {readHeaders(encrypted); // 读取头部信息return decryptCompressedAfterHeaders(encrypted, keyString);}// 加密并压缩明文数据public static void encryptAndCompress(InputStream cleartext, OutputStream ciphertext, String keyString, Properties properties) throws IOException {if (properties != null) {properties.store(ciphertext, null); // 存储属性}ciphertext.write(new byte[]{0}); // 写入分隔符encryptAfterHeaders(cleartext, ciphertext, keyString, true); // 加密并压缩}// 加密明文数据,可以选择是否压缩public static void encryptAfterHeaders(InputStream stream, OutputStream ciphertext, String keyString, boolean compress) throws IOException {long[] key = makeKeyFromString(keyString != null ? keyString : STD); // 生成密钥if (compress) {stream = compressInputStream(stream); // 压缩输入流}doBlockCipher(stream, ciphertext, true, key); // 加密stream.close();}// 从字符串生成密钥private static long[] makeKeyFromString(String keyString) {long[] k = new long[4];String[] splitString = new String[4];StringTokenizer st = new StringTokenizer(keyString, "-");int i;for (i = 0; i < splitString.length; ++i) {if (!st.hasMoreTokens()) {throw new Error("invalid key"); // 无效的密钥}splitString[i] = st.nextToken();}for (i = 0; i < 4; ++i) {try {k[i] = Long.parseLong(splitString[i], 16); // 解析密钥} catch (NumberFormatException e) {throw new Error("invalid key"); // 无效的密钥}}return k;}// 解压缩字节数组private static byte[] uncompressString(byte[] in) throws IOException {GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(in));ByteArrayOutputStream out = new ByteArrayOutputStream();int bufferSize = 10240;byte[] buffer = new byte[bufferSize];while (true) {int bytesRead = gis.read(buffer, 0, bufferSize);if (bytesRead == -1) {return out.toByteArray(); // 返回解压缩后的数据}out.write(buffer, 0, bytesRead);}}// 压缩输入流private static InputStream compressInputStream(InputStream in) throws IOException {ByteArrayOutputStream baos = new ByteArrayOutputStream();GZIPOutputStream gz = new GZIPOutputStream(baos);int bufferSize = 10240;byte[] buffer = new byte[bufferSize];int var5 = 0;while (true) {int bytesRead = in.read(buffer, 0, bufferSize);if (bytesRead == -1) {gz.close();return new ByteArrayInputStream(baos.toByteArray()); // 返回压缩后的数据}gz.write(buffer, 0, bytesRead);var5 += bytesRead;}}// 字节数组转换为无符号32位数组public static void byteArrayToUnsigned32(byte[] byteBuf, long[] unsigned32Buf) {for (int i = 0; i < unsigned32Buf.length; ++i) {unsigned32Buf[i] = ((long) byteBuf[i * 4] & 255L) + (((long) byteBuf[i * 4 + 1] & 255L) << 8) + (((long) byteBuf[i * 4 + 2] & 255L) << 16) + (((long) byteBuf[i * 4 + 3] & 255L) << 24);}}// 无符号32位数组转换为字节数组public static void unsigned32ToByteArray(long[] unsigned32Buf, byte[] byteBuf) {for (int i = 0; i < unsigned32Buf.length; ++i) {long l = unsigned32Buf[i];byteBuf[i * 4] = (byte) ((int) (l & 255L));byteBuf[i * 4 + 1] = (byte) ((int) (l >> 8 & 255L));byteBuf[i * 4 + 2] = (byte) ((int) (l >> 16 & 255L));byteBuf[i * 4 + 3] = (byte) ((int) (l >> 24 & 255L));}}// 解密文件public static void decryptFile(File src, File dst) throws Exception {InputStream inputStream = Files.newInputStream(src.toPath());byte[] rule = decryptCompressed(inputStream, null); // 解密并解压缩OutputStream outputStream = Files.newOutputStream(dst.toPath());outputStream.write(rule); // 写入解密后的数据outputStream.close();}// 主函数public static void main(String[] args) throws Exception {String rulesDir = "F:\\rules\\2024.2.1.0003-zh_CN\\rules";String decryptDir = "F:\\rules\\2024.2.1.0003-zh_CN\\decrypt";File file = new File(rulesDir);if (file.isDirectory()) {File[] files = file.listFiles();for (File f : files) {if (f.getName().endsWith(".bin")) {decryptFile(f, new File(decryptDir + "/" + f.getName() + ".xml")); // 解密文件}}} else {decryptFile(file, new File(decryptDir + "/" + file.getName() + ".xml")); // 解密文件}}}
