WillingIce 发表于 2023-7-29 09:55

一款VS的C++代码插件-试用证书分析记录

## 最终效果


   

## 前期准备

下载安装VS2022

下载最新版本的RxShxxpxr C++插件,并安装完成

下载最新版本Dnspy(64位)
## 背景

1. 该插件实在好用,但。。。
2. 网络上找到的资源不能直接使用
      1. 该插件**至少**在2019.2.3版本以后新增了网络登录验证;
      2. 证书服务的算法有所改变,且证书服务器作者停止更新,或无法找到该资料
      3. 现存补丁不能适应最新版本的
3. 近期有点时间整理下家用电脑的开发环境

## 过程

1. 根据旧版本Patch信息,定位到试用证书的过期验证;`System.Boolean JetBrains.Application.License2.Evaluation.EvaluationInfoEx::IsExpired(JetBrains.Application.License2.Evaluation.IEvaluationInfo,JetBrains.Application.License2.ISupportsEvaluation)`; 但发现存在登录验证,这块的逻辑是根本没走到。无奈用不了,所以接下来的**目标**是找到在哪里做的账号是否登录的判断

2. 既然这时的方法重要,说明是核心逻辑,使用“分析”看看都在什么地方使用了;其中Check字样比较突出,打上断点,果然

3. 本想直接修改这个字段,但修改不了,原因:这是个属性方法,效果同字段,但却是个方法。

4. 不能修改值,那看看来源是哪?我们打开堆栈,但委托+方法返回值的形式,一时没明白从哪调过来的。且`Pair` 来自`this.AllModel.Value.Entities.WithEvaluationSupport()`

5. 先看`this.AllModel`从哪来,发现其只存在get,没有set?那值怎么设置的?对了,是直接赋值,但不知为什么,dnspy没搜索到?


6. 下断查看取值及来源(堆栈),但可惜,此时的Value字段为空。

7. 经过分析。。,找到添加的入口;

8. 中间是一段分析。。发现submodule来自这里:this.myLicensedEntities,而这个数据来源如下:

9. 搞错了,这个里没有重点的IsStart;重新分析!

10. 断点后,查看堆栈:

11. 发现LicenseData中的成员`myData`

下断后发现,里面有刚才看到的试用版证书的信息。进一步分析来源:

下图是LoadItems的实现:

断点调试并观察结果可知后续结论。
## 结论
1. 安装完成后,会生成一个试用证书,由 `JetBrains.Application.License2.Persistence.RegistryPersister1<JetBrains.Application.License2.Evaluation.EvaluationInfo> JetBrains.Application.License2.Evaluation.EvaluationInfoPersister::CreateSerializer(JetBrains.Util.ILogger,System.String,System.Boolean,System.Boolean)` 创建;创建时有两个参数,用于控制是否自动启用,是否记录使用时长;
2. 检查自动启用逻辑,在`System.Collections.Generic.IEnumerable1<JetBrains.Application.License2.Evaluation.IEvaluationInfo> JetBrains.Application.License2.Evaluation.EvaluationInfoPersister::LoadItems()中判断,bool flag = lastRunEvalTechnicalNames.Contains(pair.First.TechnicalName);`而TechnicalName经过调试,值为ReSharperCpp,从下图 获得:

经过调试,该注册表项的值为“{ReSharperCpp}”时,会自动启用;像这样

3. 证书创建完成后,由`System.Void JetBrains.Application.License2.Evaluation.EvaluationInfoPersister::SaveItems(System.Collections.Generic.IEnumerable1<JetBrains.Application.License2.Evaluation.IEvaluationInfo>)`方法,保存到注册表;
### 方案一
本想写代码修改dll,但目前没有思路。此方案不用修改dll,仅修改注册表即可。
1. 使用dnspy打开Shell.dll后,打开`System.Void JetBrains.Application.License2.Evaluation.EvaluationInfoPersister::.ctor`,找到注册表地址,在表中添加字符串`ReSharperCpp`; 如果版本能对上,则
```
Windows Registry Editor Version 5.00

"{294AEEB3-D72E-426D-8AF8-2BBA18633156}"="{ReSharperCpp}"
```
   
2. 因存在30天限制,需要30天内清除`{9656c84c-e0b4-4454-996d-977eabdf9e86}`下生成的临时试用证书。如下图所示。


### 方案二
对`JetBrains.Platform.Shell.dll`打补丁,修改类实现
1. 修改EvaluationInfoEx类的实现为下文所示:
```
      public static class EvaluationInfoEx
      {
                // Token: 0x06002F85 RID: 12165 RVA: 0x0001E013 File Offset: 0x0001C213
                public static bool IsRunning( this IEvaluationInfo info, ISupportsEvaluation supportsEvaluation)
                {
                        return info.IsStarted && !info.IsPaused && !info.IsExpired(supportsEvaluation);
                }

                // Token: 0x06002F86 RID: 12166 RVA: 0x0001E035 File Offset: 0x0001C235
                public static int GetLeftDays( this IEvaluationInfo info, ISupportsEvaluation supportsEvaluation)
                {
                        return int.MaxValue;
                }

                // Token: 0x06002F87 RID: 12167 RVA: 0x00003F12 File Offset: 0x00002112
                public static bool IsExpired( this IEvaluationInfo info, ISupportsEvaluation supportsEvaluation)
                {
                        return false;
                }

                // Token: 0x06002F88 RID: 12168 RVA: 0x00005315 File Offset: 0x00003515
                public static bool IsValid( this IEvaluationInfo info, ISupportsEvaluation supportsEvaluation)
                {
                        return true;
                }
      }
```

2. 修改`JetBrains.Application.License2.Persistence.RegistryPersister<JetBrains.Application.License2.Evaluation.EvaluationInfo> JetBrains.Application.License2.Evaluation.EvaluationInfoPersister::CreateSerializer()`方法的实现为下文所示:

```
                private static RegistryPersister<EvaluationInfo> CreateSerializer(ILogger logger, string guid, bool autoStart, bool trackUsageOnStart)
                {
                        EvaluationInfo evaluationInfo = EvaluationInfo.CreateInstallerValue(guid);
                        evaluationInfo.StartEvaluation();
                        evaluationInfo.SetUsed(true);
                        JsonLikeSerializer jsonLikeSerializer = new JsonLikeSerializer('[', ']', ',', '=', true);
                        return new SafeRegistryPersister<EvaluationInfo>(logger, "Software\\Microsoft\\Windows\\CurrentVersion\\Ext\\Settings\\{9656c84c-e0b4-4454-996d-977eabdf9e86}", guid, jsonLikeSerializer, evaluationInfo);
                }
```

**说明**:1.用于解决30天限制问题;2.用来解决安装后,默认不启用试用版证书问题

WillingIce 发表于 2023-7-30 00:37

算了,补充一句,理论上适用最新版

朱朱你堕落了 发表于 2023-7-31 15:06

这个插件作用是干什么的?

sdieedu 发表于 2023-7-31 15:35

有一,为啥还需要2破解?无限试用不可以吗?

ak0000321 发表于 2023-8-1 08:50

无限试用,为啥还需要破解?

WillingIce 发表于 2023-8-1 23:06

朱朱你堕落了 发表于 2023-7-31 15:06
这个插件作用是干什么的?

写C++代码时使用的辅助插件,可以快速重构代码,很智能

WillingIce 发表于 2023-8-1 23:07

ak0000321 发表于 2023-8-1 08:50
无限试用,为啥还需要破解?
默认情况下不支持试用的,所以需要分析

WillingIce 发表于 2023-8-1 23:09

sdieedu 发表于 2023-7-31 15:35
有一,为啥还需要2破解?无限试用不可以吗?

方法一需要至少每30天处理一次,不觉得麻烦的话,没问题的,可以不考虑方案2;

pjy612 发表于 2023-8-2 09:57

记得 好像 还有哪个地方要改一下。。。
当然 可能是 针对 ReShaper C# 版的
试用时间GetLeftDays 超过 14 天还是 多久 有额外的一个判断。
好像在 CheckLicenseAndFire 里面。
不过 大差不差

PS. 这是直接对VS进行调试的吗?

WillingIce 发表于 2023-8-3 00:58

pjy612 发表于 2023-8-2 09:57
记得 好像 还有哪个地方要改一下。。。
当然 可能是 针对 ReShaper C# 版的
试用时间GetLeftDays 超过...

C#版没用过。。
是直接调试VS的
页: [1]
查看完整版本: 一款VS的C++代码插件-试用证书分析记录