吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2566|回复: 42
收起左侧

[CrackMe] 一个.NET平台的CrackMe(无虚拟化)

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

如题:一个.NET平台的CrackMe,无虚拟化
尝试正确解密,并获取密码
祝各位好运!!!

本帖子中包含更多资源

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

x

免费评分

参与人数 1吾爱币 +1 收起 理由
jaffa + 1 谢谢@Thanks!

查看全部评分

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

 楼主| wujiayang2007 发表于 2025-8-6 10:09
本帖最后由 wujiayang2007 于 2025-8-6 12:06 编辑

注意:
1.软件无虚拟化,但是有混淆
2.密码提示会在控制台中输出
3.有反调试
4.密码会在软件打开时生成
5.密码是不可见字符
heartingrass 发表于 2025-8-8 20:50
【先patch掉反调试线程。】
Class12.smethod_3(){【将其字节码直接改为2A即可】
        object objectTmp = null;
        IntPtr method = ldftn(smethod_9);
        Thread thread = new Thread(new ParameterizedThreadStart(objectTmp, method));
        thread.IsBackground = true;
        thread.Start();
        System.Threading.Thread.Sleep(1000);//注释掉....,确保 smethod_9 由充足时间运行
        System.Environment.Exit(0);
}

【密码生成位置】
在 >        mscorlib.dll!System.Text.Encoding.GetBytes(string s) 下断点:可以获取到有用的信息

Class0.smethod_0()
        string password = Delegate40.smethod_0(text, Delegate40.delegate40_0);
                调用 0x06000004                Class0.smethod_2(string string_0)       
                               
                                object object_ = Delegate56.smethod_0(delegate56_);
                                byte[] array2 = Delegate51.smethod_0(object_, string_0, delegate51_);
                                                调用 0x0A00003A                System.Text.Encoding.GetBytes
                                                                        s        "1F017EA6"        string 当前字符串,这个每次均不一样,应该是与时间有关。

在 public Rfc2898DeriveBytes(string password, byte[] salt, int iterations, HashAlgorithmName hashAlgorithm) 处下断点:此处的 password 就是密码。
比如此时结果就是:
2B200F200C200B200E200C200E202C200E202A200F200C200F202B200E200E20

Class2.Main()
        Delegate112.smethod_0(new GForm0(), Delegate112.delegate112_0);
                调用 Form.GForm0()       
                        Delegate68.smethod_0(Delegate68.delegate68_0);///实际是 0x06000002,Class0.smethod_0()
                                        string password;
                                        byte[] array12;
                                        byte[] array11 = Delegate43.smethod_0(new Rfc2898DeriveBytes(password, array12, Delegate20.smethod_0(10008.517193191416 - Delegate28.smethod_0(5000.0, Delegate28.delegate28_0), Delegate20.delegate20_0), Delegate42.smethod_0(Delegate42.delegate42_0)), Delegate20.smethod_0(31.6993677579761 + Delegate19.smethod_0(16.0, Delegate19.delegate19_0), Delegate20.delegate20_0), Delegate43.delegate43_0);
///一个疑问:password 是生命,但是没有赋值,怎么后面的password就有值了?
///可能是 dnSpy 将 IL 转换成 C# 代码的问题,查IL,得知该变量名称为 V_4,只有两处引用,
                                        string password = Delegate40.smethod_0(text, Delegate40.delegate40_0);//生成密码。text 哪儿来的?
                                       
                                       

【密码校验位置】
输入 16 个空格,调试时候进行覆盖
               
GForm0.method_0(object sender, EventArgs e):按钮单击
        Delegate70.smethod_0(Delegate69.smethod_0(this.textBox_0, Delegate69.delegate69_0), Delegate70.delegate70_0);
                Delegate70--》0x06000003         Class0.smethod_1(string string_0)【string_0 输入字符串】
                                Delegate55.smethod_0(Delegate54.smethod_0(Class0.byte_0, string_0, Delegate54.delegate54_0), Delegate55.delegate55_0);
                                         Delegate54--》Class0.smethod_3(byte[] byte_1, string string_0)
                                                        byte[] array3 = Delegate43.smethod_0(new Rfc2898DeriveBytes(string_0, salt, Delegate20.smethod_0(9993.6123577971557 - Delegate19.smethod_0(5000.0, Delegate19.delegate19_0), Delegate20.delegate20_0), Delegate42.smethod_0(Delegate42.delegate42_0)), Delegate20.smethod_0(36.0 - Delegate32.smethod_0(16.0, Delegate32.delegate32_0), Delegate20.delegate20_0), Delegate43.delegate43_0);
                                                                public Rfc2898DeriveBytes(string password, byte[] salt, int iterations, HashAlgorithmName hashAlgorithm) : this(new UTF8Encoding(false).GetBytes(password), salt, iterations, hashAlgorithm)
                                                                        查看局部变量:
                                                                                                password        "                "        string
                                                                                                直接 在其内存处,将 2B200F200C200B200E200C200E202C200E202A200F200C200F202B200E200E20 拷贝进去即可。
后面即可验证通过。

实在是不知道咋输入 空白字符。

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
wujiayang2007 + 1 + 1 我很赞同!

查看全部评分

PercyDan 发表于 2025-8-10 18:34
投降,我不会,问一个大佬解出来的
[C#] 纯文本查看 复制代码
using System.Text;

namespace CfgGraph;

public class KeyGen
{
    public static void Run()
    {
        const string INPUT = "20250810183225";

        int state1 = 0x2BAABACC;
        int state2 = state1;
        for (int i = 0; i < INPUT.Length - 1; i += 2)
        {
            if (i % 4 == 0)
                state1 = ((state1 << 5) + state1 + (state1 >> 27)) ^ (INPUT[i] | (INPUT[i + 1] << 16));
            else
                state2 = ((state2 << 5) + state2 + (state2 >> 27)) ^ (INPUT[i] | (INPUT[i + 1] << 16));
        }

        var key = $"{(uint)(state1 + state2 * 0xC2A12B34L):X}";
        Console.WriteLine(key);

        char[] invisChars =
        [
            '\u200B', '\u200C', '\u200D', '\u200E', '\u200F',
            '\u202A', '\u202B', '\u202C', '\u202D', '\u202E',
            '\u206A', '\u206B', '\u206C', '\u206D', '\u206E', '\u206F'
        ];
        var keyArr = Encoding.Default.GetBytes(key);
        var sb = new StringBuilder();
        int num19 = keyArr[0];
        for (int num20 = 1; num20 < keyArr.Length; num20++)
        {
            num19 = (num19 << 8) + keyArr[num20];
            while (num19 >= invisChars.Length)
            {
                num19 = Math.DivRem(num19, invisChars.Length, out int num5);
                sb.Append(invisChars[num5]);
            }
        }
        sb.Append(invisChars[num19]);
        File.WriteAllText("key.txt", sb.ToString());
    }
}

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
wujiayang2007 + 1 + 1 我很赞同!

查看全部评分

liuxinzx152 发表于 2025-8-6 14:34
感谢分享

免费评分

参与人数 1吾爱币 -15 违规 +1 收起 理由
bian96 -15 + 1 警告:CM区等技术板块禁止回复与主题无关非技术内容,违者重罚!

查看全部评分

heartingrass 发表于 2025-8-7 22:18
方法的两个参数:内置计算出来的字节数组、用户输入字符串
0:000> !dumpobj rcx
Name:        System.Byte[]
MethodTable: 00007ff9cc315848
EEClass:     00007ff9cc438920
Size:        80(0x50) bytes
Array:       Rank 1, Number of elements 56, Type Byte (Print Array)
Content:     L..q.^.l.)P....gY.........+..."..n.*..>S....9$.....{?.sh
Fields:
None
4C BD 1D 71 11 5E 85 6C 1F 29 50 F7 1F 9B 03 67
59 BF A9 84 ED 0D EC 07 10 13 2B 0C B3 FE 22 13
8B 6E 8A 2A 8B E1 3E 53 D9 08 BD 85 39 24 04 CF
B4 9B A9 7B 3F DD 73 68 00 00 00 00 00 00 00 00 【初始值到 0x68】



0:000> !dumpobj rdx
Name:        System.String
MethodTable: 00007ff9cc3107a0
EEClass:     00007ff9cc2c4868
Size:        46(0x2e) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:      kctf123456
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
00007ff9cc313368  4000283        8         System.Int32  1 instance               10 m_stringLength
00007ff9cc311610  4000284        c          System.Char  1 instance               6b m_firstChar
00007ff9cc3107a0  4000288       e0        System.String  0   shared           static Empty
                                 >> Domain:Value  000001e097b27bb0:NotInit  <<
heartingrass 发表于 2025-8-7 22:15
验证SN的主要算法在 0x6000005
方法解析顺序:
Click()                060000e
        0000000006000154(0000000006000153 所在类的静态构造方法)
        0000000006000153        public static string smethod_0(object object_0, Delegate69 delegate69_1)
        DynamicClass.(System.Object)
        0000000006000158(0000000006000157 所在类的静态构造方法)
        0000000006000157        public static void smethod_0(string string_0, Delegate70 delegate70_1)
       
0000000006000003        internal static void smethod_1(string string_0) 猜测是委托 Delegate70 delegate70_1
        重点执行:Delegate55.smethod_0(Delegate54.smethod_0(Class0.byte_0, string_0, Delegate54.delegate54_0), Delegate55.delegate55_0);
        调用了 0000000006000117
0000000006000118        (0000000006000117 所在类的静态构造方法)
0000000006000117        public static string smethod_0(byte[] byte_0, string string_0, Delegate54 delegate54_1)

0000000006000005        private static string smethod_3(byte[] byte_1, string string_0) 关键算法在里面。string_0 为 用户输入的字符串
0000000006000134        (0000000006000133 所在类的静态构造方法)
0000000006000133        public static int smethod_0(object object_0, byte[] byte_0, int int_0, int int_1, Delegate61 delegate61_1)
DynamicClass.(System.Object, Byte[], Int32, Int32)
0000000006000138        (0000000006000137 所在类的静态构造方法)
0000000006000137        public static ICryptoTransform smethod_0(object object_0, Delegate62 delegate62_1)
DynamicClass.(System.Object)
000000000600013c        (000000000600013b 所在类的静态构造方法)
000000000600013b        public static void smethod_0(object object_0, Stream stream_0, Delegate63 delegate63_1)

DynamicClass.(System.Object, System.IO.Stream)
000000000600011c        (000000000600011b 所在类的静态构造方法)
000000000600011b        public static DialogResult smethod_0(string string_0, Delegate55 delegate55_1)

本帖子中包含更多资源

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

x
 楼主| wujiayang2007 发表于 2025-8-12 10:42
本帖最后由 wujiayang2007 于 2025-8-12 11:09 编辑
xjwebs 发表于 2025-8-11 10:02
请问楼主的反调试是如何实现的呢?谢谢

net4.0以上用native检测(用的是委托而不是dllimport)
.net2.0~3.5因为不支持native检测,所以进行的managed检测
战股神 发表于 2025-8-6 12:25
很久不玩破解了~

免费评分

参与人数 1吾爱币 -15 违规 +1 收起 理由
bian96 -15 + 1 警告:CM区等技术板块禁止回复与主题无关非技术内容,违者重罚!

查看全部评分

Vandy520 发表于 2025-8-6 15:01
测试一下看看好不好玩

免费评分

参与人数 1吾爱币 -15 违规 +1 收起 理由
bian96 -15 + 1 警告:CM区等技术板块禁止回复与主题无关非技术内容,违者重罚!

查看全部评分

 楼主| wujiayang2007 发表于 2025-8-6 16:48
Vandy520 发表于 2025-8-6 15:01
测试一下看看好不好玩

测试结果咋样?
LiParanoid 发表于 2025-8-6 20:57
学习学习

免费评分

参与人数 1吾爱币 -15 违规 +1 收起 理由
bian96 -15 + 1 警告:CM区等技术板块禁止回复与主题无关非技术内容,违者重罚!

查看全部评分

BCDHY 发表于 2025-8-6 21:41
反调试应该有两层判断
1.检查进程是否有常见调试器(程序用普通od打开就退出,但是用吾爱的od就不会退出)
2.检查自身是否被调试器附加(这一点可以用ScyllaHide绕过)
myh889988 发表于 2025-8-7 08:37
谢谢学习到了

免费评分

参与人数 1吾爱币 -15 违规 +1 收起 理由
勇者为王 -15 + 1 警告:CM区等技术板块禁止回复与主题无关非技术内容,违者重罚!

查看全部评分

Raohz520 发表于 2025-8-7 10:11
BCDHY 发表于 2025-8-6 21:41
反调试应该有两层判断
1.检查进程是否有常见调试器(程序用普通od打开就退出,但是用吾爱的od就不会退出) ...

丢dnspy直接看代码不是更快吗? .net程序直接走dnspy看大概代码就行了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2026-2-14 18:17

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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