pjy612 发表于 2023-3-10 17:15

某系列文档转换库 注册码逆向分析

本帖最后由 pjy612 于 2023-3-14 00:26 编辑

### 前情提要

因为某个老项目 的 HTML to PDF 组件,有问题了需要修。
然后网上找了下解决方案,结果大部分是收费的。最终用的还是MIT的。
但是也有不少虽然不能用在项目里,但是可以拿来练手的。

### 受害者 来源

https://stackoverflow.com/questions/564650/convert-html-to-pdf-in-net
列表中 **UERGIE1ldGFtb3JwaG9zaXMgLk5ldA==** 所在系列 其中一员 ** RG9jdW1lbnQgLk5ldA== **
虽然它不是 pdf 的,但是里面逻辑全面一点,其他库 核心逻辑 和算法一致

### 正篇开始

先上demo代码。
```C#
// NOTICE: Place this line firstly, before creating of the DocumentCore object.
DocumentCore.Serial = "1234567890";
// Let's create a new document by activated version.
DocumentCore dc = new DocumentCore();
dc.Content.End.Insert("Hello World!", new CharacterFormat() { FontName = "Verdana", Size = 65.5f, FontColor = Color.Orange });
// Save a document to a file in DOCX format.
string filePath = @"Result.docx";
dc.Save(filePath);
```
首先 扔到 dnspy 里面看看情况,发现有自定义混淆。
为了方便后续分析 找到字符串相关的 混淆的Token 用 de4dot 预先处理一下。
然后 license 的关键词是 Serial,查下引用

校验逻辑围绕 Load 和 Save,看着没啥暗桩。
那就直奔主题。


可以看到 校验完 license 之后 跟着的就是水印逻辑。
那么 只要 返回值 不在 switch 逻辑中 也就是 **Enum14** 不是 1-3 就不会有水印。

# b( ̄▽ ̄)d 找到了 我们在这里爆破就可以收工啦!!!#

开个玩笑,用Nuget的包 因为不少都有关联,不推荐去爆破它...还是逆向算法吧...

那么我们继续往里面看 Class121.smethod_1 的逻辑。

有两个函数 Class121.smethod_3 和 Class121.smethod_0
Class121.smethod_3 返回类型 **Enum13**
Class121.smethod_0 返回类型 **Enum14**


然后 Class121.smethod_0 里面又调用了 Class121.smethod_3
那么 重点应该在 Class121.smethod_0 里面
那么 license 的 核心逻辑 就是 Class121.smethod_3
额外校验在 Class121.smethod_0

其中 Class121.smethod_2(out text, out text2, out text3);

可以看到是根据 当前程序集 获取 一些 用于验证的项。
然后根据逻辑分析

```C#
if (@enum <= (Class121.Enum13)2332)
                {
                        if (@enum == (Class121.Enum13)2329 || @enum == (Class121.Enum13)2332)
                        {
                              if (text != "Document .Net")
                              {
                                        return (Class121.Enum14)3;
                              }
                              goto IL_105;
                        }
                }
```
**RG9jdW1lbnQgLk5ldA==** 对应的 **Enum13** 应该为 2329 或 2332
结合 上图 Class121.smethod_3 的内容
那么也就是 我们用的 license 必须满足 下面的条件
```
enum = (Class121.Enum13)((string_0 * '\a' + string_0 * '\r' / (string_0 * '\v' + '\u0001') + string_0 * '_' + string_0 * 'X' + string_0 * 'T' + string_0 * 'E' + string_0 * ',' + string_0 * 'W' + string_0 * '\u0015' + string_0 * 'W') / (string_0 * 'U' - string_0 * 'Y' + string_0 * '-' - string_0 * 'U' - string_0 * '8' + string_0 * '\u0081' - string_0 * 'K' + string_0 * '^' - string_0 * 'X' + string_0 * 'n' - string_0 * 'N'));

// enum == 2329 ||enum == 2332
```
再继续看

里面没有时间限制 但是有版本限制,结合开头部分的代码。
**Enum14** 为 0 则 无水印

好耶!可以在开头爆破了!(bushi...

```
if (major <= num)
                {
                        enum2 = (Class121.Enum14)0;
                }
                return enum2;
```
也就是我们的 license 的 第一位 要大于等于 当前程序集 的 **Version.Major**
然后 如果想长期使用并且能更新的话 第一位最好是 **9**

结论,我们要弄出一个 长度11 (多了没啥用)并且首位是9的字符串。
然后满足上面的等式就行!
那么问题来怎么做呢?
对不起。。。我不会。。。我没看懂。。。我没想出来。。。
我偷懒去问了chatgpt,然后 它 顾左右而言他。。。

最后 穷举吧...(实在太丢人了,穷举的代码就不发了...期待算法大佬逆向下看看这玩意到底怎么算的....)

然后 我们就算出了个结果 **OTAwMDIzOTM3OTg=** !

然后 放到 Demo 代码中跑一下! ok 没水印了!完美(穷举)收工!

### 附录
该产品系列其他库对应 code

|产品|code|
| -------------|--------------------|
|UERGIFZpc2lvbiAuTmV0         |847       |
|VXNlT2ZmaWNlIC5OZXQ=         |2131      |
|RXhjZWwgdG8gUERGIC5OZXQ=       |2118      |
|RG9jdW1lbnQgLk5ldA==         |2329 2332 |
|UlRGIHRvIEhUTUwgLk5ldA==      |2129      |
|SFRNTCB0byBSVEYgLk5ldA==      |3031      |
|UERGIE1ldGFtb3JwaG9zaXMgLk5ldA==|5128      |
|UERGIEZvY3VzIC5OZXQ= |3026 3027 3029 3028|

solly 发表于 2023-3-17 16:06

calc count= 10000000000
key count = 71097
seconds = 30
last key = 99999979588
优化一下算法,30秒可以算完所有key,共71097个。

pjy612 发表于 2023-3-17 23:53

solly 发表于 2023-3-17 16:06
calc count= 10000000000
key count = 71097
seconds = 30


我本来是拿ascii字符去算的然后进位和回退好麻烦...
等实现完了才想到 纯数字就行....&#129315;
那样算起来就简单了...
一个for或者多线程分段算一下汇个总,但实际还是穷举....

pjy612 发表于 2023-3-10 17:37

{:301_1004:}
虽然结尾有些拉跨...
但是 确实没想到 它该怎么正向生成的,咱就倒着穷举了。。。

TobiasCN 发表于 2023-3-10 17:47

学习,这个需要再次处理,不过没水印也行,反正我是截图,ps收拾水印。

chaifengbox 发表于 2023-3-10 18:48

哈哈哈哈, 我的想法第一时间也是穷举。压根不想考虑怎么逆向。
第一位9 后面10位 疯狂+1,然后 把那段验证扔进去,做好判断,跳出。
搞定!

mjcode 发表于 2023-3-11 07:09

学习了,感谢分享

tyjjk 发表于 2023-3-11 13:40

谢谢提供和分享

laustar 发表于 2023-3-11 21:40

谢谢提供和分享

awJYNL 发表于 2023-3-12 00:08


学习了,感谢分享

limingdemingzi 发表于 2023-3-12 12:35


学习了,感谢分享

qiuyoo 发表于 2023-3-13 09:28

谢谢分享
页: [1] 2
查看完整版本: 某系列文档转换库 注册码逆向分析