记一次对3D打印切片软件的逆向

warning: 这篇文章距离上次修改已过305天,其中的内容可能已经有所变动。

前情提要:
  高中时期使用的紫熙3D打印机,当时公司正在发展期,能够联系公司进行授权。目前公司倒闭了,又刚好碰上学校电脑重装,结果发现从其他电脑移植过去的许可证代码无效,没办法导出分层后的文件了,于是需要找到激活的方法。
  该切片软件正常导出时会提示许可证代码无效页面,如下:

许可证代码无效提示许可证代码无效提示

逆向方法:
(1)找到上述提示框所对应的exe程序,为C盘目录下ZXPrint文件夹内的ZXFomer.exe
(2)使用Detect It Easy分析程序。结果:该程序为.NET框架,无加壳(2015年代的软件安全性可能也不会太强)

Detect It Easy分析结果Detect It Easy分析结果

(3)使用dnSpy对程序进行反编译,通过代码审计找到ZX_G2P下的encodecomputer和From1_Load方法为验证许可证代码的逻辑。
dnSpy页面-ZXFormerdnSpy页面-ZXFormer

dnSpy页面-ZXFormer部分目录dnSpy页面-ZXFormer部分目录

dnSpy页面-ZXFormer部分目录dnSpy页面-ZXFormer部分目录

逆向得到的部分代码如下:

// textbook.ZX_G2P
// Token: 0x06000023 RID: 35 RVA: 0x000024CC File Offset: 0x000006CC
private int encodecompter(string inputstr)
{
    int num = 0;
    int[] array = new int[]
    {
        100,
        104,
        107,
        31,
        45,
        51
    };
    int num2 = 4;
    string currentDirectory = Environment.CurrentDirectory;
    if (!File.Exists(currentDirectory + "\\\\licence.dat"))
    {
        return num;
    }
    StreamReader streamReader = File.OpenText(currentDirectory + "\\\\licence.dat");
    string text = streamReader.ReadToEnd();
    streamReader.Close();
    if (text.Length < 110)
    {
        return num;
    }
    string text2 = "";
    int num3 = 0;
    foreach (char c in inputstr)
    {
        num3 += 656;
        int num4 = int.Parse(c.ToString());
        num4 = num4 * num4 * num3;
        if (num4 < 10)
        {
            num4 += 13;
        }
        text2 += num4.ToString();
    }
    for (int j = text2.Length; j < 100; j++)
    {
        text2 += 0;
    }
    if (string.Compare(text2.Substring(0, 100), text.Substring(0, 100)) != 0)
    {
        return num;
    }
    int num5 = int.Parse(text.Substring(array[0], num2)) - 1897;
    int num6 = int.Parse(text.Substring(array[1], num2 - 1)) / 51;
    int num7 = int.Parse(text.Substring(array[2], num2)) / 290;
    DateTime now = DateTime.Now;
    DateTime t = DateTime.ParseExact(num5.ToString("d4") + num6.ToString("d2") + num7.ToString("d2"), "yyyyMMdd", CultureInfo.InvariantCulture);
    new TimeSpan(now.Ticks);
    new TimeSpan(t.Ticks);
    if (DateTime.Compare(t, now) >= 0)
    {
        string text3 = ZX_G2P.MD5Encrypt(text.Substring(77, 34));
        if (text.Length < text3.Length + 111)
        {
            return num;
        }
        if (string.Compare(text.Substring(111, text3.Length), text3) == 0)
        {
            this.help_txt = string.Concat(new string[]
            {
                this.help_txt,
                "本软件有效期至:",
                num5.ToString(),
                "/",
                num6.ToString(),
                "/",
                num7.ToString()
            });
            num++;
        }
    }
    return num;
}
 
// textbook.ZX_G2P
// Token: 0x06000025 RID: 37 RVA: 0x00002778 File Offset: 0x00000978
private void Form1_Load(object sender, EventArgs e)
{
    this.openfile.FlatAppearance.BorderSize = 0;
    this.openfile.FlatAppearance.MouseDownBackColor = Color.Transparent;
    this.openfile.FlatStyle = FlatStyle.Flat;
    string inputstr = "ZX2016";
    try
    {
        int num = 0;
        string text = "";
        string text2 = new ManagementObject("win32_logicaldisk.deviceid=\"c:\"").Properties["VolumeSerialNumber"].Value.ToString();
        if (text2 == "")
        {
            text2 = this.GetCpuId();
        }
        foreach (char c in text2)
        {
            num++;
            text += (int)((c - '\u001e') % '\n');
            text += ((int)c + num) % 10;
        }
        inputstr = text;
    }
    catch (Exception)
    {
        inputstr = "ZX20161117";
    }
    this.getcump_id(inputstr);
    if (1 > this.encodecompter(this.cumputer_id))
    {
        this.tex_message.Visible = true;
        this.license_state = 0;
    }
    else
    {
        this.Text = this.title;
        this.license_state = 1;
        this.tex_message.Visible = false;
        if (Program.patharg != null && Program.patharg.Length != 0)
        {
            base.WindowState = FormWindowState.Minimized;
            base.ShowInTaskbar = false;
            this.startbycmd(Program.patharg);
        }
    }
    this.tex_message.Text = "本软件尚未成功激活,许可证代码无效(licence error);\r\n请联系紫熙发展技术支持部门,购买获取激活码;\r\n请访问www.zixichina.com 或致电:010-56147060\r\n如果您已经激活,请将激活文件放于 " + Environment.CurrentDirectory + "\r\n北京紫熙科技发展有限公司\r\nID:" + this.cumputer_id;
}

(4)encodecompter方法使用一套检验方法对inputstr也就是本机硬盘码和licence.dat里的内容进行对比校验,若正确返回1,若过程中任何地方不正确则返回0。
(5)将encodecompter方法中的第一句“int num = 0;”修改为“int num = 1;”。然后删除掉倒数第5行的“num++;”。目的是使该函数一直返回1,即验证通过。
(6)将修改后的ZXFormer.exe放回软件安装目录,能够正常使用无失败弹窗。

声明:仅供学习交流使用

已有 2 条评论

  1. 软件下载地址:吾爱破解论坛网盘(爱盘)
    https://down.52pojie.cn/Tools/

  2. 文章已发表至吾爱破解论坛,可以来观摩其他大神的操作:https://www.52pojie.cn/thread-1939356-1-1.html

添加新评论