selph
selph
发布于 2022-08-26 / 189 阅读
0
0

新160个CrackMe练习:056-diablo2oo2‘s Crackme 01

算法难度:⭐⭐⭐⭐

爆破难度:⭐

信息收集

运行情况:

image

查壳与脱壳:

image

调试分析

IDA走起~

一开始调用了一个call,跟进去

image

这个call在是创建窗口的,这里一开始就在填充窗口类,这里有个窗口函数,跟进

image

老样子,在窗口函数里找nMsg=0x111,wParam=3(通过xspy查的)的分支:

首先是获取Name,判断长度,合法长度是5–0x20字节

image

紧接着是一个循环,处理前5个字节,生成5个字节填充到字符数组里,这里有一堆跳转就是确保生成的字节满足大小要求

image

接下来:再次循环前五字节,以类似的方法生成另外5字节数字填充到字符数组的后面

image

再往下就是获取序列号了:

序列号长度必须满足10字节要求

image

最后就是比对环节:

取一位序列号,取一位生成字符数组,对生成数组的字符进行处理,处理完成之后,和序列号做对比,相同则判断下一位,全部相同则成功~

image

注册机

注册码生成算法:

string? name = Console.ReadLine();
char[] nameCheck = new char[11];
if(name!=null && name.Length >= 5 && name.Length<=0x20)
{
    // 处理前5字节
    byte i = 5;
    while (i >0)
    {
        byte cl = (byte)name[5 - i];
        cl ^= 0x29;
        cl += i;
        if(cl<0x41 || cl > 0x5A)
        {
            cl = 0x52;
            cl += i;
        }
        nameCheck[5 - i] = (char)cl;
        i--;
    }

    // 处理后五字节
    i = 5;
    while (i > 0)
    {
        byte cl = (byte)name[5 - i];
        cl ^= 0x27;
        cl += i;
        cl += 1;
        if (cl < 0x41 || cl > 0x5A)
        {
            cl = 0x4D;
            cl += i;
        }
        nameCheck[10 - i] = (char)cl;
        i--;
    }

    // 生成序列号
    char[] serial = new char[11];
    i = 0;
    while (i < 10)
    {
        byte dl = (byte)nameCheck[i];
        dl += 5;
        if (dl > 0x5A) dl -= 0x0d;
        dl ^= 0x0c;
        if (dl < 0x41)
        {
            dl = 0x4B;
            dl += i;
        }
        if (dl > 0x5A)
        {
            dl = 0x4B;
            dl -= i;
        }
        serial[i] = (char)dl;
        i++;
    }

    Console.WriteLine(serial);
}

效果:

image


评论