吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 9712|回复: 99
收起左侧

[原创] 关于java-web应用程序的逆向-camunda企业版

  [复制链接]
lvbuqing 发表于 2023-4-21 17:59
本帖最后由 lvbuqing 于 2023-4-21 18:48 编辑

关于camunda ,它是一款工作流组件源自  activity5。

支持 BPMN(工作流和流程自动化)、CMMN(案例管理) 和 DMN(业务决策管理) java 框架。
德国的一个公司开发的。


camunda介绍.png

题外话篇:
     一,如何下载企业版
下载地址:
https://camunda.com/download/
下载之前需要注册去camunda官网注册账号,下载的账号和密码会发送到你的邮箱,如图:
邮件.png

邮件2.png

下载地址.png
点击即可下载。

题外话篇:
    二,关于camunda的体验
注册后,他们的销售会联系你购买他们企业版,也就是推推业务员
会议1.png
基本都是给你发meeting会议链接
会议链接.png
简单的通过文字会议形式了解了一下的结果就是:人家不服务中国,不做中国市场业务。感兴趣伙伴可以注册下沟通就知道。

===========================正文========================================

下载下来后内容如下:

压缩包.png

configuration 一些启动的配置
internal  主要的程序包
start.bat   Windows下的启动脚本。

启动后访问地址:http://localhost:8080/camunda-welcome/index.html
界面

界面1.png

随便点击 tasklist,或其他的几个界面,就如登录界面。
默认账户密码都是 demo

登录后
界面2.png
界面4.png
这是没有注册的

可以看到这个是普通界面,并没有涵盖企业版的功能,需要输入注册的 License Key 才能看到企业级功能。
依次点击:Admin-》License Key
也可直接访问:
http://localhost:8080/camunda/app/admin/default/#/system?section=system-settings-license
进入以下界面:
界面3.png
随便输入点什么,提交一下看看请求地址

请求1.png
请求地址:http://localhost:8080/camunda/api/admin/plugin/license/default/key
返回数据:{"invalidMessage":"License Key has wrong format.","customerId":null,"validUntil":null,"valid":false,"unlimited":false,"licenseProvided":true}
提示格式不对。
启动1.png

通过启动脚本的日志可以看出是使用的Spring-Boot,那么直接可以通过对应的请求地址,直接定位到他的服务类代码

通过启动脚本分析:
启动脚本1.png
启动脚本2.png

结论:start.bat 调用了 internal\run.bat
run.bat执行的程序包为 internal\camunda-bpm-run-core.jar
接下来就是分析这个程序包了,通过jd-gui查看,可以看到是没有加密或者混淆的,可以随便造。

https://github.com/camunda/camunda-bpm-platform
可以看看社区版的代码,这个是开源的,只是功能没有企业版强大。
最后的分析结论:
internal\webapps\camunda-license-check-2.7.0.jar
分析完你会知道,最终验证的代码都在这个程序包里面。

题外话:
这里有很多种追踪方法,
这里说下我所用的方式,remotedebug

在run.bat里面的启动方法-jar前面加入以下代码:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005
通过通过调试模式启动这个服务
使用jd-gui打开camunda-license-check-2.7.0.jar,保存所有文件为源码,保存后直接导入IDE,有报错不管他

存源码.png

启动3.png
双击start.bat
启动4.png
等待debug连接后启动


IDE打断点位置:
代码1.png

去key那边提交一下key,断点会停下来
代码2.png

看看当前堆栈情况

代码3.png

可以看到索引1就是调用这个方法的地方,索引0是当前的类
索引1:
org.camunda.bpm.admin.impl.plugin.resources.LicenseKeyResource

代码4.png
看它的包名可以知道,肯定是plugin模块,刚刚好,当前目录就有一个,
接口地址,请求方式,调用函数,直接拿下!
代码5.png

      LicenseKeyStore.INSTANCE.valIDAteLicense((LicenseKey)licenseKeyImpl);
      LicenseKeyStore.INSTANCE.storeLicenseKey(getProcessEngine(), licenseKeyString);

代码6.png
接着正文部分:

本次的目的就是要分析LicenseKeyImpl的validate()函数。
这里直接贴代码,不贴图了

代码1:
[Asm] 纯文本查看 复制代码
/*     */   public void validate() throws InvalidLicenseException {
/* 115 */     boolean signatureValid = SignatureValidator.validateSignature(this.validationData.getBytes(Charset.forName("UTF-8")), this.signature);
/*     */ 
/*     */     
/* 118 */     if (!signatureValid)
/* 119 */       throw new InvalidLicenseException("Your license is invalid."); 
/* 120 */     if (isExpired()) {
/* 121 */       throw new InvalidLicenseException("Your license has expired.");
/*     */     }
/*     */   }
/*     */ 

这里主要是验证一下SignatureValidator.validateSignature的返回值,直接往里面查找validateSignature

代码2:
[Asm] 纯文本查看 复制代码
/*     */   public static boolean validateSignature(byte[] data, String base64EncodedSignature) {
/*  33 */     return validateSignature(data, BASE64.decode(base64EncodedSignature));
/*     */   }

继续查找
代码3:
[Asm] 纯文本查看 复制代码
/*     */   public static boolean validateSignature(byte[] data, byte[] signatureBytes) {
/*  44 */     PublicKey publicKey = determinePublicKey(signatureBytes);
/*  45 */     String algorithmName = determineAlgorithmName(signatureBytes);
/*     */     
/*     */     try {
/*  48 */       Signature sig = getSignature(algorithmName);
/*  49 */       sig.initVerify(publicKey);
/*  50 */       sig.update(data);
/*  51 */       return sig.verify(signatureBytes);
/*  52 */     } catch (GeneralSecurityException e) {
/*  53 */       throw new RuntimeException("Cannot verify signature", e);
/*     */     } 
/*     */   }

根据代码

PublicKey publicKey = determinePublicKey(signatureBytes);
可以分析这个得知,服务端通过私钥加密,这里再通过公钥去解密。

代码4:
[Asm] 纯文本查看 复制代码
/*     */   private static PublicKey determinePublicKey(byte[] signatureBytes) {
/*     */     String keyLocation;
/*  82 */     LicenseType licenseType = determineLicenseType(signatureBytes);
/*     */     
/*  84 */     if (licenseType == LicenseType.CAMUNDA_BPM) {
/*  85 */       keyLocation = "camunda_public_key.der";
/*  86 */     } else if (licenseType == LicenseType.OPTIMIZE) {
/*  87 */       keyLocation = "optimize_public_key.der";
/*     */     } else {
/*  89 */       keyLocation = "unified_public_key.der";
/*     */     } 
/*     */     
/*  92 */     return (new PublicKeyFileReader(keyLocation)).getKey();
/*     */   }


代码5
[Asm] 纯文本查看 复制代码
/*     */   public static LicenseType determineLicenseType(byte[] signatureBytes) {
/*     */     LicenseType type;
/*  70 */     if (signatureBytes.length == 128) {
/*  71 */       type = LicenseType.CAMUNDA_BPM;
/*  72 */     } else if (signatureBytes.length == 256) {
/*  73 */       type = LicenseType.OPTIMIZE;
/*     */     } else {
/*  75 */       type = LicenseType.UNIFIED;
/*     */     } 


这里是判断应该使用哪一种公钥,由于注册的时候会给你一个临时的注册码:

注册码.png


代码7.png
可以确定是 unified_public_key.der

代码8.png

代码6:
[Asm] 纯文本查看 复制代码
/*     */   private static Signature getSignature(String algorithmName) {
/*     */     try {
/* 113 */       return Signature.getInstance(algorithmName);
/*     */     }
/* 115 */     catch (NoSuchAlgorithmException e) {
/* 116 */       throw new RuntimeException("Cannot load signature algorithm " + algorithmName);
/*     */     } 
/*     */   }

可以得出:

Signature.getInstance(“SHA256withRSA”);
通过这个方法去创建一个签名算法,
设置公钥publicKey,sig.initVerify(publicKey);
要验证的数据data,sig.update(data);
返回一个验证结果:return sig.verify(signatureBytes);
=============================================
分析data是怎么来的:
代码9.png
观察堆栈,不过四层而已,往上回溯。
代码10.png

再第三个地方直接明了,原来data是通过string类下面的getBytes(Charset.forName("UTF-8"))方法生成的

===============到此所有流程分析完毕============================

解决方式有二,以下将一 一详解。

==========================编码过程=================================
通过以上分析 ,得出需要对数据通过公钥验签
首先我们得需要自己生成的一个公钥对。

这里使用的是hutool-crypto工具类

[Asm] 纯文本查看 复制代码
KeyPair rsa1 = SecureUtil.generateKeyPair("RSA", 4096);

PublicKey publicKey = rsa1.getPublic();
String publicKeyEncode = Base64.encode(publicKey.getEncoded());
PrivateKey aPrivate = rsa1.getPrivate();
String aPrivateEncode = Base64.encode(aPrivate.getEncoded());

System.out.println("publicKeyEncode:" + publicKeyEncode);
System.out.println("aPrivateEncode:" + aPrivateEncode);


编写一段需要验签的数据字符串:
例如:customer = 52pojie-lvbuqing;expiryDate = 2098-04-07;cawemo = true;optimize = true;camundaBPM = true;
对字符串 转byte[]

byte[] validationDataBytes = validationData.getBytes(StandardCharsets.UTF_8);

用刚才生成的私钥进行验签:

[Asm] 纯文本查看 复制代码
  Signature signature = Signature.getInstance("SHA256withRSA");
            signature.initSign(rsa.getPrivateKey());
            signature.update(validationDataBytes);
            byte[] sign1 = signature.sign();
            return Base64.encode(sign1);


记住这个加签的数据

将刚刚生成的私钥存为unified_public_key.der秘钥文件
[Asm] 纯文本查看 复制代码
 
 FileUtil.writeBytes(rsa.getPublicKey().getEncoded(), "unified_public_key.der");


生成的方法使用方法就是替换原来jar包里面公钥文件

对加签
数据处理成以下格式
KMl0OK6eUNCBdznq6Eu1dXUsTrdZU9Ps7mGjhB9GdlIG6xUEePTyPTbpz
FEPAqrIlbGZFgaZubemqyGphyr935im51j5JWGCQzmf13/KMIL+60QoUJ
Gad3FN0J+2+UlxwD3lxDuubjfiQdsEVlRZR7VJ00vFECOfeO/qD6kUwP8
s1hRnyg9Q0XcdCGBYqjkEVol0X7A6azX0JSmTO8CiGE8zCqla8sn0+uEg
0raU+ydGcUpF5lbhPYOkU0PFx39eZ1KfwTAnATlY3DXURB+5mEwBfnjgx
Rima5OHUHzdi0U9wO6oduGjcgToP6+dS22desY8K7c1AEzTlYsXQ6+Lqf
PRZNIqXSqGu7FTByzxycxtV2sWWfm1YqnUV3fFK94CLaNhX+I5RlSqcf5
1pBaY+tqvmYKiMPSBkHY52sLkKKpy768a3LvktTeZ5g3pHOL6YHFgtaAq
8sS7/BFyABBYxG4X3BKhJbkp5xd8FuJ/KhEltLAwnc7LMw9UiSnxGWgGj
9uEuEXzi0dqpT3MQQf5qPZtFNf1xWGGwBABNZxQf95u6DWN12ISlPWjnW
CvYLye3rsCAxOQtOESFJm5dzlrhWOUFFz4SuIsRYPG3AsEaNmDalMeQco
HeWc012bCEIWwWYEaJ/Ir0uX88DOGRWIRSCTACbgXCj6N9x33QhCeYWM=;
customer = 52pojie-lvbuqing;
expiryDate = 2098-04-07;
cawemo = true;
optimize = true;
camundaBPM = true;


验证成功1.png

可以看到验证成功了,企业功能也出来了
验证成功2.png

=============================================
上面是解决方式1,现在讲讲高阶的方法二,需要用到javassist
代码的大概意思是这样的,具体就是替换里面的公钥
[Asm] 纯文本查看 复制代码
 static byte[] getbytes(string classname) {
if (classname == null) {
return null;
}
class_pool.appendclasspath(new loaderclasspath(thread.currentthread().getcontextclassloader()));
string class_name = “org.camunda.bpm.licensecheck.publickeyfilereader”;
string class_name_internal = class_name.replace('.', '/');
if (!class_name_internal.equals(classname)) {
return null;
}
try {
ctclass ctclass = class_pool.get(class_name);
ctmethod cm = ctclass.getdeclaredmethod("readpublickeyfromclasspath");
string source = "这里填写公钥秘钥";
cm.insertbefore(source);
return ctclass.tobytecode();
} catch (exception e) {
return null;
}
    }


主类代码:
[Asm] 纯文本查看 复制代码
    public static void premain(String agentArgs, Instrumentation inst) {
        inst.addtransformer((loader, classname, classbeingredefined, protectiondomain, classfilebuffer) -> getbytes(classname));
    }


打包.png
打包成jar包的调用
调用.png

这样就可以啦!!!!

完结,撒花!

ps:camunda公司真的是地域歧视

免费评分

参与人数 34吾爱币 +35 热心值 +31 收起 理由
freeboy40 + 1 + 1 谢谢@Thanks!
sparkshine + 1 + 1 我很赞同!
fengbu401 + 1 + 1 我很赞同!
gqdsc + 1 + 1 非常感谢大神分享
cp5458 + 1 + 1 用心讨论,共获提升!
笙若 + 1 + 1 谢谢@Thanks!
wanjingbo + 1 谢谢@Thanks!
soyadokio + 1 + 1 用心讨论,共获提升!
wuxiaojie + 1 + 1 用心讨论,共获提升!
lookerJ + 1 我很赞同!
it_harry + 1 + 1 我很赞同!
onlywey + 1 + 1 用心讨论,共获提升!
落叶回不来 + 1 + 1 用心讨论,共获提升!
无痕567 + 1 + 1 谢谢@Thanks!
gaosld + 1 + 1 谢谢@Thanks!
侠骨留香喵 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
二十瞬 + 1 + 1 我很赞同!
Pojawa + 1 好长,阅读困难症犯了
yixi + 1 + 1 谢谢@Thanks!
julien + 1 + 1 我很赞同!
sorryzzital + 1 + 1 谢谢@Thanks!
LinkSun + 1 + 1 谢谢@Thanks!
D3M1 + 1 + 1 谢谢@Thanks!
疯狂の马甲 + 1 我很赞同!
xlwllm + 1 + 1 我很赞同!
fengbolee + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
allspark + 1 + 1 用心讨论,共获提升!
alalalsk163 + 1 + 1 我很赞同!
0106yingzi + 1 + 1 我很赞同!
侃遍天下无二人 + 4 + 1 谢谢@Thanks!
rox + 1 + 1 谢谢@Thanks!
ClementLevi + 1 我很赞同!
Caraciold_Jr + 1 + 1 用心讨论,共获提升!
janny82 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

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

zxw7606_1 发表于 2023-4-25 10:17
小白请问下,学习你这种java调试 IntelliJ IDEA 的方法碰到几个问题,第一个就是idea的调试添加之后,控制台只打印警告【WARN】等级信息怎么办,还有一个就是IDEA不提供激活的触发事件,随便输入LICENSE KEY的话没有触发点,根据关键词搜索的话 只能搜索到配置文件

Snipaste_2023-04-25_10-14-46.jpg

22222.png


soyadokio 发表于 2023-12-6 15:02
wjmzbmr 发表于 2023-11-22 20:02
大佬,分享过期了,可以重新上传一下吗。现在已经不开放7的企业版下载了

camunda-bpm-run-ee-7.18.5-ee.zip
https://dokio.lanzout.com/i0qzK1gzqush

camunda-bpm-run-ee-7.19.0-ee.zip
https://dokio.lanzout.com/iOwSI1gzt32h

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
wjmzbmr + 1 + 1 热心回复!

查看全部评分

jingyao066 发表于 2023-4-24 09:27
感谢分享,这个是真的学习了,破解其他的也是这种思路
cxxcdz 发表于 2023-4-21 18:19
虽然不知道干什么用的软件  但是顶一下
px307 发表于 2023-4-22 00:06
感谢分享
px307 发表于 2023-4-22 00:08
大神能提供企业版下载,我就不去注册了,谢谢
222shuai 发表于 2023-4-22 01:05
虽然没看懂,但是不明觉厉
头像被屏蔽
moruye 发表于 2023-4-22 10:59
感谢分享,顶一下
ameiz 发表于 2023-4-22 19:48
感谢分享,学习了。
crystalZ 发表于 2023-4-22 22:43
真没看懂,只看懂了springboot
 楼主| lvbuqing 发表于 2023-4-23 09:24
px307 发表于 2023-4-22 00:08
大神能提供企业版下载,我就不去注册了,谢谢

注册信息随便填,只要邮箱是对的,能接收下载地址就行了,我就不发了,自己去官网获取更官方
bluesky20210721 发表于 2023-4-23 13:11

感谢分享。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-12-21 23:58

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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