P.Y.G-亮亮 发表于 2023-5-29 10:34

记一次 .net逆向到注册机的编写(listary)

本帖最后由 P.Y.G-亮亮 于 2023-5-30 08:13 编辑

比较小白有不对的地方欢迎指正




# 记一次 .net逆向到注册机的编写(C# 还原算法)



### 参考了``Hangle``大佬发布帖子:https://www.52pojie.cn/forum.php?mod=viewthread&tid=1785147



## 需要工具

### 1. dnSpy

### 2. Listary(6.1.0.38)

## dnspy反编译

##### 找到``Listary.Core.Pro`` 命名空间下的 ``LicenseChecker ``类

##### 看到 ``CheckLicense`` 里面的代码 一开始我想使用直接让函数返回``true``来进行爆破的奈何编译不了 只能编写注册机

```c#
using System;

namespace Listary.Core.Pro
{
        // Token: 0x020001BB RID: 443
        public class LicenseChecker
        {
                // Token: 0x0600080D RID: 2061 RVA: 0x0001905C File Offset: 0x0001725C
                public static bool CheckLicense(string email, string license)
                {
                        if (email == null || license == null)
                        {
                                return false;
                        }
                        if (license.Length != 192)// license长度必须为192
                        {
                                return false;
                        }
                        email = email.ToLowerInvariant(); // 将email转换成小写
                        ulong num = ((ulong)LicenseChecker.\uE000(email) << 32) + (ulong)LicenseChecker.\uE001(email);// 获取一个 num这个很关键
                        string text = "";
                        for (int i = 0; i < 12; i++)
                        {
                                int index = (int)(num >> 64 - (i + 1) * 5) & 31;
                                text += \uE185.\uE071(43381).ToString();// 取 "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"字符串的 第i位 拼接
                        }
                        return license.Substring(160, 12) == text;
            // 判断输入的license第160位到172位是不是等于text
            // 这样说明 注册码的前160位和后18位都可以是随机数
                }

                // Token: 0x0600080E RID: 2062 RVA: 0x000190F4 File Offset: 0x000172F4
                private static uint \uE000(string \uE000)
                {
                        uint num = 0U;
                        foreach (char c in \uE000)
                        {
                                num = 43U * num + (uint)c;
                        }
                        return num;
                }

                // Token: 0x0600080F RID: 2063 RVA: 0x00019128 File Offset: 0x00017328
                private static uint \uE001(string \uE000)
                {
                        uint num = 0U;
                        foreach (char c in \uE000)
                        {
                                num = (num << 4) + (uint)c;
                                uint num2 = num & 4026531840U;
                                if (num2 != 0U)
                                {
                                        num ^= num2 >> 24;
                                        num ^= num2;
                                }
                        }
                        return num;
                }

                // Token: 0x040004B7 RID: 1207
                internal const int \uE000 = 192;

                // Token: 0x040004B8 RID: 1208
                private const string \uE001 = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
        }
}
```

##### 编写注册机

```c#
using System;

public class Program {
    private static uint hash1(string a)
    {
      uint num = 0U;
      foreach (char c in a)
      {
            num = 43U * num + (uint)c;
      }
      return num;
    }
   
    private static uint hash2(string a)
    {
      uint num = 0U;
      foreach (char c in a)
      {
            num = (num << 4) + (uint)c;
            uint num2 = num & 4026531840U;
            if (num2 != 0U)
            {
                num ^= num2 >> 24;
                num ^= num2;
            }
      }
      return num;
    }
   
    public static string getLicense(string email)
    {
      string ALPHA_NUMERIC = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
      ulong num = ((ulong)hash1(email) << 32) + (ulong)hash2(email);
      string license = "";
      for (int i = 0; i < 12; i++)
      {
            int index = (int)(num >> 64 - (i + 1) * 5) & 31;
            license += ALPHA_NUMERIC;
      }
      Random random = new Random();
      string text = "";
      for (int i = 0; i < 192; i++)
      {
            if (i == 172)
            {
                text = text.Substring(0, 160) + license;
            }
            text += ALPHA_NUMERIC;
      }
      return text;
    }

    public static void Main()
    {
      string email = "www.52pojie.cn";
      string license = getLicense(email);
      Console.WriteLine(license);
    }
}
```

## Python代码

```python
import numpy as np
import random


def hash1(a: str) -> np.uint32:
    num = np.uint32(0)
    for c in a:
      num = np.uint32(43) * num + np.uint32(ord(c))
    return num


def hash2(a: str) -> np.uint32:
    num = np.uint32(0)
    for c in a:
      num = (num << np.uint32(4)) + np.uint32(ord(c))
      num2 = num & np.uint32(4026531840)
      if num2 != np.uint32(0):
            num ^= num2 >> np.uint32(24)
            num ^= num2
    return num


def getLicense(email: str) -> str:
    ALPHA_NUMERIC = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"
    num = np.uint64(hash1(email)) << np.uint64(32) | np.uint64(hash2(email))
    license = ""
    for i in range(12):
      index = int((num >> np.uint64(64 - (i + 1) * 5)) & np.uint64(31))
      license += ALPHA_NUMERIC
    random.seed()
    text = ""
    for i in range(192):
      if i == 172:
            text = text[:160] + license
      text += ALPHA_NUMERIC
    return text

email = "2035776757@qq.com"
license = getLicense(email)
print(license)
```

## Gui界面注册机



应各位要求补上编译好的成品 .net6.0编译

P.Y.G-亮亮 发表于 2023-5-29 18:14

补充一个python 代码
import numpy as np
import random


def hash1(a: str) -> np.uint32:
    num = np.uint32(0)
    for c in a:
      num = np.uint32(43) * num + np.uint32(ord(c))
    return num


def hash2(a: str) -> np.uint32:
    num = np.uint32(0)
    for c in a:
      num = (num << np.uint32(4)) + np.uint32(ord(c))
      num2 = num & np.uint32(4026531840)
      if num2 != np.uint32(0):
            num ^= num2 >> np.uint32(24)
            num ^= num2
    return num


def getLicense(email: str) -> str:
    ALPHA_NUMERIC = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"
    num = np.uint64(hash1(email)) << np.uint64(32) | np.uint64(hash2(email))
    license = ""
    for i in range(12):
      index = int((num >> np.uint64(64 - (i + 1) * 5)) & np.uint64(31))
      license += ALPHA_NUMERIC
    random.seed()
    text = ""
    for i in range(192):
      if i == 172:
            text = text[:160] + license
      text += ALPHA_NUMERIC
    return text

email = "www.52pojie.cn"
license = getLicense(email)
print(license)

SnowRen 发表于 2023-5-30 21:50

无意中发现,邮箱中不能含大写字母,否则注册码无效

zgzxp 发表于 2023-5-29 11:53

本帖最后由 zgzxp 于 2023-5-29 12:49 编辑

public static bool CheckLicense(string email, string license)
{
      if (email == null || license == null)
      {
                return false;
      }
      if (license.Length != 192)
      {
                return false;
      }
      email = email.ToLowerInvariant();
      ulong num = ((ulong)LicenseChecker.smethod_0(email) << 32) + (ulong)LicenseChecker.smethod_1(email);
      string text = "";
      for (int i = 0; i < 12; i++)
      {
                int num2 = (int)(num >> 64 - (i + 1) * 5) & 31;
                text += Class466.smethod_0(48245).ToString();
      }
      if (license.Substring(160, 12) != text)
      {
                Clipboard.SetDataObject(string.Concat(new string[]
                {
                        license.Substring(0, 32),
                        "\r\n",
                        license.Substring(32, 32),
                        "\r\n",
                        license.Substring(64, 32),
                        "\r\n",
                        license.Substring(96, 32),
                        "\r\n",
                        license.Substring(128, 32),
                        "\r\n",
                        text,
                        license.Substring(172, 20)
                }));
                MessageBox.Show("注册码已复制到剪贴板!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
      }
      return license.Substring(160, 12) == text;
}

我直接改造原来的,这样的注册码虽然能组成成功,看起来怪怪的{:1_907:}

ernv 发表于 2023-5-29 10:52

大佬,我有个软件,能否帮忙看看。

zgzxp 发表于 2023-5-29 11:41

顶楼主,这样1-159,173-190是随机的。有大神能提示下,这个软件正经的这些位置是怎么得来的吗?

P.Y.G-亮亮 发表于 2023-5-29 11:43

zgzxp 发表于 2023-5-29 11:41
顶楼主,这样1-159,173-190是随机的。有大神能提示下,这个软件正经的这些位置是怎么得来的吗?

看源代码里面写了哦    “return license.Substring(160, 12) == text; ”也就这一段 能看出来

zgzxp 发表于 2023-5-29 11:48

P.Y.G-亮亮 发表于 2023-5-29 11:43
看源代码里面写了哦    “return license.Substring(160, 12) == text; ”也就这一段 能看出来

谢谢回复。我的意思是他的1-159和173-190位是怎么得来的。
这个原软件里不可能是随机{:1_918:}

jyjjf 发表于 2023-5-29 12:20

zgzxp 发表于 2023-5-29 11:48
谢谢回复。我的意思是他的1-159和173-190位是怎么得来的。
这个原软件里不可能是随机

都随机了,那自己手动一个就行啊(或者为了发放注册码统计,自己按规则随便弄点就行了啊),都不用原软件生成了,只要判断长度,然后截取指定位置就行了。

blindcat 发表于 2023-5-29 14:25

感谢分享,学习一下

spray 发表于 2023-5-29 15:05

学习了,感谢分享。

sdieedu 发表于 2023-5-29 15:08

如何用? 看不懂在线运行?没有exe 啊
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: 记一次 .net逆向到注册机的编写(listary)