FXXXXRXXXXX 10.0 另一破解思路

(编辑:jimmy 日期: 2024/10/30 浏览:2)


请问一下论坛里面研究FR的大神,有没有发现这款软件有什么暗装呢?发出来一起交流一下呗。
前些天看了论坛一位大神的帖子https://www.52pojie.cn/thread-1012601-1-1.html,试着弄了一下,真的被FR10的加密给弄崩溃了
于是想到了一个新思路,是否可以在它加载完关键类之后,从jvm里面取出字节码修改后再替换回去呢?
分享一下我的思路吧
启动FR,使用HSDB工具拿到三个类:
1、com.fr.license.selector.EncryptedLicenseSelector
2、com.fr.license.security.LicFileRegistry
3、com.fr.license.entity.FineLicense
FXXXXRXXXXX 10.0 另一破解思路

企业微信截图_20200227124109.png


需要修改以下几个关键的地方:
1、com.fr.license.selector.EncryptedLicenseSelector的decrypt方法:
[Java] 纯文本查看 复制代码
public abstract class EncryptedLicenseSelector extends AbstractLicenseSelector {    byte[] getBytes() {        byte[] var1 = this.readRawBytes();        return this.decrypt(var1);    }    private byte[] decrypt(byte[] var1) {   // 修改为 return var1;        try {            System.getProperties().setProperty("com.ibm.crypto.provider.DoRSATypeChecking", "false");            return (new CommonDecryptChain()).decrypt(var1);        } catch (Throwable var3) {            this.decryptFailed(var3);            return new byte[0];        }    }    protected void decryptFailed(Throwable var1) {        FineLoggerFactory.getLogger().error("Read license failed." + var1.getMessage(), var1);    }    abstract byte[] readRawBytes();}

其实修改这一个地方就够了,另外两处修改可用于方便懒人。
2、com.fr.license.security.LicFileRegistry的check方法:
[Java] 纯文本查看 复制代码
public class LicFileRegistry {    private static Map<Integer, LicFileChecker> _2c75dfba_fdee_47fa_8cf4_74897f6d7e9a = new ConcurrentHashMap(5);    private LicFileRegistry() {    }    static {        register(new LicFileCheckerImpl());    }    public static void register(LicFileChecker var0) {        _2c75dfba_fdee_47fa_8cf4_74897f6d7e9a.put(var0.getTypeCode(), var0);    }    public static boolean check(InputStream var0, Integer var1) {   // 修改为 return true;        LicFileChecker var2 = _2c75dfba_fdee_47fa_8cf4_74897f6d7e9a.get(var1);        return var2 != null && var2.check(var0);    }}

修改这里主要是破解lic上传注册。
3、com.fr.license.entity.FineLicense的两个support方法:
[Java] 纯文本查看 复制代码
public class FineLicense extends AbstractLicense {    public FineLicense(JSONObject var1) {        super(var1);    }    public String getString(String var1, String var2) {        return super.getInnerString(var1, var2);    }    public boolean support(PluginMarker var1) { // 修改为 return true;        if (var1 == null) {            return false;        } else {            try {                JSONObject var2 = this.getJSONObject();                if (var2.has(LicenseItem.Plugin.getKey())) {                    JSONArray var3 = var2.getJSONArray(LicenseItem.Plugin.getKey());                    for(int var5 = 0; var5 < var3.length(); ++var5) {                        String[] var4 = var3.getString(var5).split(",");                        if (var4.length >= 2 && var1.getPluginID().equals(var4[0])) {                            return true;                        }                    }                }            } catch (Exception var6) {                FineLoggerFactory.getLogger().error(var6.getMessage(), var6);            }            return false;        }    }    public boolean support(FunctionPoint var1) {    // 修改为 return true;        String var2 = this.getString(LicenseItem.Function.getKey(), "");        if (StringUtils.isNotBlank(var2)) {            BigInteger var3 = new BigInteger(String.valueOf(var2));            return var3.and(BigInteger.ONE.shiftLeft(var1.getMarker())).compareTo(BigInteger.ZERO) == 1;        } else {            return true;        }    }

主要用于破解收费插件。
修改之后的代码可自行编译为class字节码,使用javaagent替换,不过不推荐。因为每次小更新部分类的成员变量名都会随机变化,使得破解失效,
因此建议拿到加载后的字节码自行进行修改并使用javaagent替换,以第一个关键类为例,代码如下:
[Java] 纯文本查看 复制代码
public class FxxxAgent {    public static void agentmain(String args, Instrumentation inst) throws Exception {        Class<?>[] classes = inst.getAllLoadedClasses();        for (Class<?> clazz : classes) {            if (clazz.getName().equals("com.fr.license.selector.EncryptedLicenseSelector")) {                inst.addTransformer((loader, className, classBeingRedefined, protectionDomain, classfileBuffer) -> {                    if (className.equals("com/fr/license/selector/EncryptedLicenseSelector")) {                        try {                            DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(classfileBuffer));                            ClassFile classFile = new ClassFile(inputStream);                            inputStream.close();                            ConstPool constPool = classFile.getConstPool();                            MethodInfo methodInfo = classFile.getMethod("decrypt");                            CodeAttribute codeAttribute = new CodeAttribute(constPool, 1, 2, new byte[]{43, -80},                                    new ExceptionTable(constPool));                            methodInfo.setCodeAttribute(codeAttribute);                            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();                            DataOutputStream outputStream = new DataOutputStream(byteArrayOutputStream);                            classFile.write(outputStream);                            outputStream.close();                            byte[] result = byteArrayOutputStream.toByteArray();                            byteArrayOutputStream.close();                            return result;                        } catch (Exception e) {                            e.printStackTrace();                            return classfileBuffer;                        }                    } else {                        return classfileBuffer;                    }                });                inst.retransformClasses(clazz);            }        }    }}

在manifest.sf文件中加上一行:Agent-Class: 刚刚编辑的类名,打包成jar文件备用。
为了使这些代码可以运行起来,需要找个地方写上一些自己的代码,我找的是fine-core-10.0.jar下的com.fr.runtime.FineRuntime这个类,
在initEncryptedBridge方法的最下面加上了自己的代码:
[Java] 纯文本查看 复制代码
    private static void initEncryptedBridge() throws Exception {        ClassLoader var0 = (ClassLoader) Class.forName(START_LOADER_FACTORY_NAME).newInstance();        Class.forName("com.fr.plugin.bridge.FinePluginBridge", true, var0);        String name = ManagementFactory.getRuntimeMXBean().getName();        String pid = name.substring(0, name.indexOf('@'));        VirtualMachine virtualMachine = VirtualMachine.attach(pid);        virtualMachine.loadAgent("D:/agent.jar", null); // 这里的路径即为刚刚打的jar包路径        virtualMachine.detach();    }

用winrar打开fr-core-10.0.jar,将编译好的FineRuntime.class替换,或者单独打成jar包,保证文件名能排在fr-core-10.0.jar的前面,放在WEB-INF\lib目录里
用如下内容的注册文件注册即可
[XML] 纯文本查看 复制代码
{"VERSION":"10.0","DEADLINE":"253402271999000","CONCURRENCY":"0"}

最后把自己的代码分享给大家吧。
https://github.com/2316361/FineCrack