吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5552|回复: 4
收起左侧

[会员申请] 申请会员ID: benzcomp【申请通过】

[复制链接]
吾爱游客  发表于 2018-10-17 20:07
1、申 请 I D : benzcomp
2、个人邮箱:cjgszy@163.com
3、原创技术文章:FineReport 8.0 注册码加解密分析及破解



FineReport 8.0的注册使用RSA加密,关于RSA算法很容易搜到,破解思路就是,替换原版的公钥,用自己的RSA私钥加密格式化的注册信息,即可成功注册。
首先,加解密算法在FRCoreContext.class里,通过反编class文件可以得到FRCoreContext的源码,可以得到RSA的N、e,用他们就可以吧正版的license文件解密。
通过对FRCoreContext的分析可以知道,license的生成算法是:
1、license授权信息的HEX每32字节分成若干组;
2、每组前导插入7F;
3、各组做RSA加密运算;
4、各组之间插入RSA的N值,最终得到的HEX串就是注册文件的二进制内容。

license制作步骤:
1、按照格式编辑lic文件明文,如下格式:
{"BI_MAKER":"0","CONCURRENCY":"0","FS_USER":"0","PRICE":"","APPNAME":"","MACADDRESS":"","BI_USER":"0","FUNCTION":"265735294061","ISAFTER701":true,"MOBILE_FS_USER":"0","REPORTLETSCOUNT":"","APPCONTENT":"","DEADLINE":4102444799499,"VERSION":"8.0","reportletscount":"","PRINCIPAL":"","COMPANYNAME":"","UUID":"","MUTICONNECTION":"0","BI_MOBILE":"0","PROJECTNAME":"","KEY":""}
对于这段明文来说    "DEADLINE":4102444799499    (2100-1-1到1970-1-1的毫秒数)
                    "FUNCTION":"265735294061"  (定制版对应的编号,可以在fr-core-8.0.jar中的FUNC.class找到定义)
保存成UTF-8编码格式的文本文件 lic.txt
2、用WinHEX打开lic.txt,复制HEX码
3、文件明码的HEX码每64个字符为一组分割,最前面加"7F"或"7E"、"7D"等,目的是让加密后的密文保证为256位字符,
4、RSA分组加密,加密后的密文要保证双字节数256个(手工做的话可以使用,大数计算器等程序)
5、每一组中间插入公钥(N),结尾不加!最终是一串6400位的字符。
6、用WinHEX粘贴ascii-hex,保存文件就是 FineReport.lic 了
7、用winrar打开fr-core-8.0.jar,拖出 com\fr\base\FRCoreContext.class
8、用UltraEdit找原版的N,用自己的 N 替换
9、再把FRCoreContext.class替换回去
10、替换fr-core-8.0.jar文件
11、FineReport.lic 放到 resources 目录下

如上方式替换文件的方法,有一个缺点,每次升级fr-core-8.0.jar都会被替换为新版本,还需要再次操作第7-11步,后来想到一个不影响升级的办法:

把fr-core-8.0.jar复制一份,并且重命名为cr_FRCoreContext.jar,文件名可以随意命名,只要保证文件名升序排序,在fr-core-8.0.jar之前就行。
用winrar打开cr_FRCoreContext.jar,把cr_FRCoreContext.jar\com\fr\base\FRCoreContext.class以外的所有文件都删掉,然后用替换N的FRCoreContext.class覆盖同名文件。
最后,把cr_FRCoreContext.jar放到\WebReport\WEB-INF\lib目录里,只要能排在fr-core-8.0.jar前面就行了。
===========================================================================================
FRCoreContext源码:
public class FRCoreContext
{
  public static final ThreadLocal TMAP = new ThreadLocal();
  private static byte[] lic_bytes = null;
  private static byte[] lock_bytes = null;
  private static final long ONE_YEAR_MILLISECOND = 31536000000L;
  private static final int MAX_DIGIT = 255;
  private static boolean onlinePassed = true;
  private static String;
  private static final String uuid = UUID.randomUUID().toString();
  private static final long ONLINE_CHECK_TIME_DELAY = 0L;
  private static final long ONLINE_CHECK_TIME_PERIOD = 10800000L;
  private static Timer ONLINE_CHECK_TIMER;
  private static int failCount;
  private static boolean shouldFireLicChange = false;
  private static final int MAX_FAIL_COUNT = 8;
  private static final BigInteger N = new BigInteger("61103299352066102812915201580370346997919089893149305765565972348630053713717591736527153881172892494135635969333391530396986735629281282430026953431657619628355730192943385620088393498664105803897708601718035436482482749378713844253725606147581454234307387984660050507963063894825237808748868429675256901161");  //RSA的N
  private static final BigInteger D = new BigInteger("65537");

  ……  
    private static String byte2hex(byte[] paramArrayOfByte)    //byte转hex码,paramArrayOfByte输入license文件
  {
    StringBuffer localStringBuffer = new StringBuffer();
    String str = "";
    for (int i = 0; i < paramArrayOfByte.length; i++)
    {
      str = Integer.toHexString(paramArrayOfByte & 0xFF);
      if (str.length() == 1) {
        localStringBuffer.append('0');
      }
      localStringBuffer.append(str);
    }
    return localStringBuffer.toString().toUpperCase();
  }

  private static void decode(String paramString, OutputStream paramOutputStream)  //解密函数
  {
    String[] arrayOfString = paramString.split(byte2hex(N.toByteArray()));        //删除license中插入的 N ,还原出有效注册信息的加密内容
    try
    {
      for (int i = 0; i < arrayOfString.length; i++) {
        paramOutputStream.write(tinyDecode(hex2byte(arrayOfString)));        //删掉密文数组的第一个元素,然后tinyDecode执行RSA解密,得到license明文

      }                                                                                
    }
    catch (IOException localIOException)
    {
      FRContext.getLogger().error(localIOException.getMessage(), localIOException);
    }
  }
……
  private static byte[] hex2byte(String paramString)    //hex转byte
  {
    if (paramString == null) {
      return null;
    }
    int i = paramString.length();
    if (i % 2 == 1) {                                                //每一段加密后的密文必须保证双字节数256个,而要保证双字节靠每一段明文前面插入的7F、7E等来控制,反正最后都是要截掉的,插入的字符就是控制密文长度的作用
      return null;
    }
    byte[] arrayOfByte = new byte[i / 2];
    for (int j = 0; j != i / 2; j++) {
      arrayOfByte[j] = ((byte)Integer.parseInt(paramString.substring(j * 2, j * 2 + 2), 16));
    }
    return arrayOfByte;
  }


  private static byte[] tinyDecode(byte[] paramArrayOfByte)    //RSA解密算法
  {
    paramArrayOfByte = new BigInteger(paramArrayOfByte).modPow(D, N).toByteArray();
    return ArrayUtils.subarray(paramArrayOfByte, 1, paramArrayOfByte.length);
  }
}

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Hmily 发表于 2018-10-19 14:39
请问这是原创分析吗?
吾爱游客  发表于 2018-10-20 11:18
当然是啊,这两天刚做了FR10的加密分析,网上是找不到的。要不要证实一下
Hmily 发表于 2018-10-22 14:54
I D:benzcomp
邮箱:cjgszy@163.com

申请通过,欢迎光临吾爱破解论坛,期待吾爱破解有你更加精彩,ID和密码自己通过邮件密码找回功能修改,请即时登陆并修改密码!
登陆后请在一周内在此帖报道,否则将删除ID信息。

ps:登录后把文章整理下发到脱壳破解区。
benzcomp 发表于 2018-10-30 10:07
终于申请到帐号,来报个到
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 15:54

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表