PCL2的反编译以及主题破解(除秋仪金)(修改版)

· · 个人记录

原始文章

为了不太影响龙猫,删改些内容。

【2023.8.15】之前忘了写,这里简单吗说一下,公开版用的是.Net Reactor 6.x系列的混淆,可以被轻松脱壳;内测版(非最新版)用了VMProtect加.Net壳(VMProtect v3.3.4 - 3.6.1 2022),使用VMUnprotect.Dumper可以让dnspy读取,理论上VMUnprotect可以完全搞定,但目前看来还有问题,等待后续研究。公开版把关于主题的相关代码都删掉了,但是一部分资源还保留着。

【2023.5.13再次更新】因为正好无意间找到了可以脱壳最新的.Net Reactor 6.x的de4dot,所以打算过段时间再尝试一下。

友情提示:由于龙猫把混淆软件更新到了最新版,所以本篇中所述的脱壳方式已经失效,不用想着再尝试了。

侵删

借助本篇文章,可以解锁我已知的11种隐藏主题中的10种。

如果有其它没讲到的隐藏主题,可以在评论区说一声。

出于版权考虑,不会提供直接解锁的工具,仅介绍研究PCL2的思路

偶尔会玩MC,由于穷而且很少玩使用的是PCL2的离线模式。

看到PCL2的个性化功能需要赞助才能用,由于没钱于是就从朋友那里搞了一个内部版。

提前说清楚,我反编译的是公开的正式版,内部版只是放在虚拟机里面测试看效果,不会使用的(要不然我朋友会go die的)。

但是隐藏主题并不会主动解锁,需要各种条件。(好吧有些条件挺简单的比如铁杆粉要使用99次PCL2,跳票红要用正版账号登录)

所以我就想看看能不能把这些主题破解了。

由于是.net,所以首先直接用dnspy反编译,发现混淆过了。

刚开始没想到去混淆,想试试通过行为分析和x64dbg来解决。由于太菜没有成功。

所以后来就去试着反混淆。先用ScanID v1.5查混淆,发现是.NET Reactor 4.8(好吧.NET Reactor我也在用,不过我不知道它这个4.8是程序版本还是混淆版本,因为这东西的6.5都出来了)。所以直接用de4dot反混淆,再用dnspy打开并生成项目。

生成项目之后我发现:

……

也不知道是哪里出了问题,这里卡了我很久。(但是最后还是没找出来)

没办法,不能改代码然后直接生成程序了。

最开始我傻傻的去找各隐藏主题的判断条件。例子如下:

(所以铁杆粉怎么解锁大家都知道了吧?)

再比如

其中

也就是说其中一个解锁条件是4月1日。

而另一个找了很久,最后发现表示是否点了一个放弃的按钮。

所以我开了个虚拟机,把时间调到4月1日,然后试图去点开始游戏按钮……(因为我发现长时间点不到会有个放弃按钮)

最后,我开了连点器……

然后就成功解锁了滑稽彩。

而极客蓝(没错,就是那个恶心人的游戏)的解锁条件如下:

这个代码我有一点小小的改动(看的时候为了方便理解),不过意思不变。

其实极客蓝的条件很简单,比如你的识别码是2JD2-8FDH-0SJ2-JC3S。那么只要在解锁码那里输入“PuzzleUnlock-JC3S”就可以了。(不知道那些通关的大佬发现时会不会崩溃)

干上面这些花了我一个晚上(约7h)

今天早上看时,突然想到PCL2会不会把这些东西存在注册表里。(为什么会想到这个还是因为我之前看到过可疑的代码)

然后去看了看,发现有个东西:

值是加密的,翻了翻源代码,使用的是DES加密,具体密码每个设备都不一样(要依据识别码)

解密代码如下:

public static string SecureRemove(string SourceString, string Key = "")
{
    Key = SecureKey(Key);
    byte[] bytes = Encoding.UTF8.GetBytes(Key);
    byte[] bytes2 = Encoding.UTF8.GetBytes("95168702");
    DESCryptoServiceProvider descryptoServiceProvider = new DESCryptoServiceProvider();
    string @string;
    using (MemoryStream memoryStream = new MemoryStream())
    {
        byte[] array = Convert.FromBase64String(SourceString);
        using (CryptoStream cryptoStream = new CryptoStream(memoryStream, descryptoServiceProvider.CreateDecryptor(bytes, bytes2), CryptoStreamMode.Write))
        {
            cryptoStream.Write(array, 0, array.Length);
            cryptoStream.FlushFinalBlock();
            @string = Encoding.UTF8.GetString(memoryStream.ToArray());
        }
    }
    return @string;
}

我又去找了找加密代码:

public static string SecureAdd(string SourceString, string Key = "")
{
    Key = ModBase.SecureKey(Key);
    byte[] bytes = Encoding.UTF8.GetBytes(Key);
    byte[] bytes2 = Encoding.UTF8.GetBytes("95168702");
    DESCryptoServiceProvider descryptoServiceProvider = new DESCryptoServiceProvider();
    string result;
    using (MemoryStream memoryStream = new MemoryStream())
    {
        byte[] bytes3 = Encoding.UTF8.GetBytes(SourceString);
        using (CryptoStream cryptoStream = new CryptoStream(memoryStream, descryptoServiceProvider.CreateEncryptor(bytes, bytes2), CryptoStreamMode.Write))
        {
            cryptoStream.Write(bytes3, 0, bytes3.Length);
            cryptoStream.FlushFinalBlock();
            result = Convert.ToBase64String(memoryStream.ToArray());
        }
    }
    return result;
}

这两个函数都要用到以下函数:

public static ulong GetHash(string Str)
{
    //内容删除
}
public static string StrFill(string Str, string Code, byte Length)
{
    //内容删除
}
private static string SecureKey(string Key)
{
    //内容删除
}

这些需要添加以下语句:

using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
using System.Security.Cryptography;
using System.IO;

同时还要引用Microsoft.VisualBasic(要不然找不到Microsoft.VisualBasic.CompilerServices;)

解密的参数如下:

text = ModBase.SecureRemove(text, "PCL" + ModBase.GetUniqueAddress());
//加密同理,ModBase.GetUniqueAddress()就是获取识别码的意思。所以第二个参数就是“PCL”+你的识别码

将UiLauncherThemeHide2解密,发现它大概是这样的:

0|1|2|3|4

这里指的是解锁的主题编号

所以只要把“0|1|2|3|4|5|6|7|8|9|10|11|12|13|14”加密后写入注册表即可解锁。

(干这些只花了一个小时不到,要是早点发现该多好……)

不过由于第八个也就是秋仪金的解锁方式与这个不同,所以不能这样解锁。

秋仪金使用RSA验证,所以目前没想到有什么办法(蒟蒻不会改程序)。

另外,PCL2还有一个隐藏主题,好像叫星空蓝,解锁方法很简单,只要把PCL文件夹中的Setup.ini中的UiLauncherTheme项的值改成42即可(如果没有就自己加上去)。

同时,也看了下正式版和内部版的区别,正式版里面有一部分内部版的代码,但把内部版反编译后发现还是有差别的(不知道为什么内部版反编译出来错误只有五千多个,神奇)。

其实我挺佩服龙猫的,整个项目足足有7.22MB(约等于7570000Byte,相当于3785000个汉字,已经是一本小说的大小了),我自问我现在是做不到的(我做的程序源文件大小没有一个超过1MB的)。