吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2573|回复: 21
收起左侧

[KeyGenMe] .net 无壳 无混淆 无虚拟机,纯算法的KeyGenMe

[复制链接]
jy04468108 发表于 2020-7-30 11:25
CM是什么?Crackme是什么?这是什么东西?楼主发的什么?
他们都是一些公开给别人尝试破解的小程序,制作 Crackme 的人可能是程序员,想测试一下自己的软件保护技术,也可能是一位 Cracker,想挑战一下其它 Cracker 的破解实力,也可能是一些正在学习破解的人,自己编一些小程序给自己破解,KeyGenMe是要求别人做出它的 keygen (序号产生器), ReverseMe 要求别人把它的算法做出逆向分析, UnpackMe 是要求别人把它成功脱壳,本版块禁止回复非技术无关水贴。

本帖最后由 jy04468108 于 2020-7-30 11:43 编辑

代码是用C#写的,
相互嵌套层数有点多,
既然都没有加壳,没有加混淆,也没有虚拟机
而且所有解密算法都已经包含在程序内部了,
所以,爆破说明不了技术,
当然了,
要是你实在不会玩,也可以爆破。
希望大神能逆向出算法,甚至做出注册机。

以下是软件运行界面。


注册成功之后会弹出消息框(messagebox),回帖中贴出消息框内容即认为是注册成功。



源码的截图,我可不是来找破解的。


Dnspy中打开的截图:




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册[Register]

x

免费评分

参与人数 1吾爱币 +6 热心值 +1 收起 理由
CrazyNut + 6 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

qzhsjz 发表于 2020-7-30 12:07
本帖最后由 qzhsjz 于 2020-7-30 12:16 编辑

分析按钮代码并下断点可得到如下被反序列化并执行的VB代码:
[Visual Basic .NET] 纯文本查看 复制代码
{

'垃圾字符一定要多
Public Class MS
Inherits Methods'继承
Public Function Process() As Boolean
Try
Dim resultFag As Boolean = True
'Public Class MS
'Inherits Methods'继承
'Public Function Process() As Boolean
ModuleForm.registcode=123
if TimeClass.InitRegedit=0 then
'messagebox.show("傻逼了把,这些都不是真的代码")
messagebox.show("懵逼了把,被忽悠成这样!")'大写的懵逼
'messagebox.show("fuck you!")
end if
Return resultFag
Catch ex As Exception
'LogError(ex.ToString()) 大家自己可以打印日志
Return false
'end if
'Return resultFag
'Catch ex As Exception
'End Try
'End Function
End Try
End Function
End Class}

根据这段VB代码可知,点击验证按钮后真正有用的代码是TimeClass.InitRegedit,并且它成功运行的话需要返回0。于是分析之:

[C#] 纯文本查看 复制代码
public static int InitRegedit(){
        int result;
        try
        {
                string text = TimeClass.DisEncryPW(ModuleForm.registcode, TimeClass.password);
                bool flag = text == "-1";
                if (flag)
                {
                        result = 1;
                }
                else
                {
                        string softEndDateAllCpuId = TimeClass.GetSoftEndDateAllCpuId(1, text);
                        string cpuId = TimeClass.GetCpuId();
                        bool flag2 = softEndDateAllCpuId != cpuId;
                        if (flag2)
                        {
                                result = 2;
                        }
                        else
                        {
                                string nowDate = TimeClass.GetNowDate();
                                string softEndDateAllCpuId2 = TimeClass.GetSoftEndDateAllCpuId(0, text);
                                bool flag3 = Convert.ToInt32(softEndDateAllCpuId2) - Convert.ToInt32(nowDate) < 0;
                                if (flag3)
                                {
                                        result = 3;
                                }
                                else
                                {
                                        result = 0;
                                }
                        }
                }
        }
        catch (Exception)
        {
                result = 1;
        }
        return result;
}


通过调用分析可知它调用了以下几个方法来构造序列号:


[C#] 纯文本查看 复制代码
public static string GetSoftEndDateAllCpuId(int i, string SerialNumber)
{
        bool flag = i == 1;
        string result;
        if (flag)
        {
                string text = SerialNumber.Substring(0, SerialNumber.LastIndexOf("-"));
                result = text;
        }
        else
        {
                bool flag2 = i == 0;
                if (flag2)
                {
                        string text2 = SerialNumber.Substring(SerialNumber.LastIndexOf("-") + 1);
                        result = text2;
                }
                else
                {
                        result = string.Empty;
                }
        }
        return result;
}


[C#] 纯文本查看 复制代码
public static string GetNowDate()
{
        return DateTime.Now.ToString("yyyyMMdd");
}


[C#] 纯文本查看 复制代码
public static string GetCpuId()
{
        ManagementClass managementClass = new ManagementClass("Win32_Processor");
        ManagementObjectCollection instances = managementClass.GetInstances();
        string str = null;
        using (ManagementObjectCollection.ManagementObjectEnumerator enumerator = instances.GetEnumerator())
        {
                if (enumerator.MoveNext())
                {
                        ManagementObject managementObject = (ManagementObject)enumerator.Current;
                        str = managementObject.Properties["ProcessorId"].Value.ToString();
                }
        }
        return TimeClass.encode(str);
}


构造分析完毕,接下来是加密算法,是普通的DES,密码是52pojie.

算法部分代码如下:

[C#] 纯文本查看 复制代码
public static string encode(string str)
{
        string text = "";
        for (int i = 0; i < str.Length; i++)
        {
                text += str[i].ToString();
                i++;
        }
        for (int j = 1; j < str.Length; j++)
        {
                text += str[j].ToString();
                j++;
        }
        return TimeClass.EncryPW(text, TimeClass.password);
}


[C#] 纯文本查看 复制代码
public static string EncryPW(string Pass, string Key)
{
        return TimeClass.DesEncrypt(Pass, Key);
}


[C#] 纯文本查看 复制代码
public static string DesEncrypt(string encryptString, string key)
{
        byte[] bytes = Encoding.UTF8.GetBytes(key.Substring(0, 8));
        byte[] rgbIV = bytes;
        byte[] bytes2 = Encoding.UTF8.GetBytes(encryptString);
        DESCryptoServiceProvider descryptoServiceProvider = new DESCryptoServiceProvider();
        MemoryStream memoryStream = new MemoryStream();
        CryptoStream cryptoStream = new CryptoStream(memoryStream, descryptoServiceProvider.CreateEncryptor(bytes, rgbIV), CryptoStreamMode.Write);
        cryptoStream.Write(bytes2, 0, bytes2.Length);
        cryptoStream.FlushFinalBlock();
        return Convert.ToBase64String(memoryStream.ToArray());
}


懒得跑注册码了,但是根据那段VB代码,弹窗内容应该是:
懵逼了把,被忽悠成这样!
嗯,我是挺懵逼的。

免费评分

参与人数 3吾爱币 +4 热心值 +1 收起 理由
MaxMadcc + 1 谢谢@Thanks!
socky + 1 我很赞同!
CrazyNut + 2 + 1 用心讨论,共获提升!

查看全部评分

 楼主| jy04468108 发表于 2020-7-30 12:59
wwh1004 发表于 2020-7-30 12:38
比如注册码填

MessageBox.Show("懵逼了把,被忽悠成这样!")

说的对,
但是字符串里面必须要先写两个双引号然后才能填写任意代码执行。因为字符串拼接的前面写的是:"某string="
这个是我们的一个项目里面的VB脚本引擎中的功能提取出来做的,在原功能中本来就是一个VB脚本执行器。
下图为完整功能。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册[Register]

x
 楼主| jy04468108 发表于 2020-7-30 12:20
qzhsjz 发表于 2020-7-30 12:07
分析按钮代码并下断点可得到如下被反序列化并执行的VB代码:
[mw_shl_code=vbnet,true]{

对的,唯一不对的地方是那段VB代码,并非反序列化。
qzhsjz 发表于 2020-7-30 12:27
jy04468108 发表于 2020-7-30 12:20
对的,唯一不对的地方是那段VB代码,并非反序列化。

是Support模块现场编译的,总之挺不错
wwh1004 发表于 2020-7-30 12:29
字符串拼接不是想弹啥就弹啥么
ㄔㄣㄑㄧㄈㄟ 发表于 2020-7-30 12:36
本帖最后由 ㄔㄣㄑㄧㄈㄟ 于 2020-7-30 12:37 编辑

那个代码是固定的吗
wwh1004 发表于 2020-7-30 12:38
本帖最后由 wwh1004 于 2020-7-30 12:42 编辑

比如注册码填

MessageBox.Show("懵逼了把,被忽悠成这样!")

随便填点代码进去就可以,想弹什么就弹什么

或者如果方法没返回值,就

"随便来点字符串" : Action1(arg1,arg2)

这样的,都可以执行任意代码
qzhsjz 发表于 2020-7-30 12:48
wwh1004 发表于 2020-7-30 12:38
比如注册码填

MessageBox.Show("懵逼了把,被忽悠成这样!")

是的,因为用户的输入部分会在拼接出的VB代码里执行,并赋值给ModuleForm.registcode,所以这部分可以运行任意代码
 楼主| jy04468108 发表于 2020-7-30 12:52
qzhsjz 发表于 2020-7-30 12:27
是Support模块现场编译的,总之挺不错

大佬是很仔细!一般人看到那一串字符串估计都不会仔细观察。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止回复与主题无关非技术内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-9 07:53

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表