记一次 .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编译
补充一个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) 无意中发现,邮箱中不能含大写字母,否则注册码无效 本帖最后由 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:} 大佬,我有个软件,能否帮忙看看。 顶楼主,这样1-159,173-190是随机的。有大神能提示下,这个软件正经的这些位置是怎么得来的吗? zgzxp 发表于 2023-5-29 11:41
顶楼主,这样1-159,173-190是随机的。有大神能提示下,这个软件正经的这些位置是怎么得来的吗?
看源代码里面写了哦 “return license.Substring(160, 12) == text; ”也就这一段 能看出来 P.Y.G-亮亮 发表于 2023-5-29 11:43
看源代码里面写了哦 “return license.Substring(160, 12) == text; ”也就这一段 能看出来
谢谢回复。我的意思是他的1-159和173-190位是怎么得来的。
这个原软件里不可能是随机{:1_918:} zgzxp 发表于 2023-5-29 11:48
谢谢回复。我的意思是他的1-159和173-190位是怎么得来的。
这个原软件里不可能是随机
都随机了,那自己手动一个就行啊(或者为了发放注册码统计,自己按规则随便弄点就行了啊),都不用原软件生成了,只要判断长度,然后截取指定位置就行了。
感谢分享,学习一下 学习了,感谢分享。 如何用? 看不懂在线运行?没有exe 啊