新160个CrackMe分析-第2组:11-20(上)
作者:selph
目录:
• 011-wocy.11
• 012-ACG-crcme12
• 013--Acid_burn3
• 014-Splish4
• 015-BradSoblesky.15
• 016-fly_crkme36
• 017-Cabeca7
• 018-crackme_00068
• 019-Acid_Byte.39
• 020-cosh.310
016-020请看下期
011-wocy.1
算法难度:⭐
爆破难度:⭐
信息收集
运行情况:
查壳与脱壳: MFC程序,无壳
查字符串: 提示字符串:Registed
调试分析 老样子,从关键提示字符串入手,交叉引用查校验函数
这里函数里不知道这个[esi+60h]和[esi+64h],通过动态调试执行可知,这里是分别获取的用户名和ID号,然后验证逻辑就很简单了,用户名和ID号需要是倒序的即可
结果:
012-ACG-crcme1
算法难度:⭐⭐
爆破难度:⭐
信息收集 运行情况:
查壳与脱壳: 无壳
查字符串: 有很多看不懂的提示语,还有个文件名
调试分析 抄起IDA直接干,用户函数就3个,这么简洁这应该是纯汇编写的程序吧(猜的),从start开始分析
首先打开一个文件,读取其中的内容,该内容应该长度是12字节:
然后就像下面这样,对12个字节的每个字节进行一个运算,逐一校验结果
然后接下来就是,如果验证全部通过,就弹窗提示ok,否则就直接启动窗口
暴力PJ
把所有判断跳转都nop掉即可
算法分析
序列号运算的核心是异或,异或是可逆的,所以可以反着把序列号生成出来:
#include
int main() { int arr[12] = { 0x168,0x160,0x170,0xec,0x13c,0x1cc,0x1f8,0xec,0x164,0x1f8,0x1a0,0x1bc }; int serial[12] = { 0 }; for (int i = 0; i < 12; i++) { serial[i] ^= arr[i]; serial[i] >>= 2; serial[i] = serial[i]&0x000000FF ^ 0x1b; } for(char var : serial) { printf("%c",var); } }
计算结果是:ACG The Best
执行结果:
总结 很简单无脑的一次算法分析
013--Acid_burn
算法难度:⭐⭐
爆破难度:⭐
信息收集 原160个CM的第一个,以前做过一遍,老费劲了,现在再来一遍看看
暴力pj已经懒得介绍了,看得懂完整分析也肯定知道该改哪里了
运行情况: 启动的时候有Nag:
提供了两种注册方法:用户名+序列号,序列号
查壳与脱壳: 无壳:Delphi程序
调试分析 分析Delph GUI程序借助IDR辅助方便查看窗口事件(纯IDA分析的话,查字符串交叉引用定位也能找到这些函数)
首先是启动窗口:窗口启动的时候调用FromCreate函数里,执行流MessageBox,这就是所谓的NAG,烦人弹窗
然后是序列号验证:
接下来是用户名+序列号验证:
首先对用户名4个字节进行一顿处理,然后把值保存起来,用户名必须大于等于4个字符
这里开头往[431750]赋了个初始值:0x29
接下来计算序列号,然后跟用户输入比对
去除NAG 去除Nag只需要修改该函数直接返回即可:
算法分析 序列号验证:硬编码验证,输入Hello Dude!即可
用户名+序列号验证,序列号可以写出注册机:
#include
int main() { int res = 0x29; char name[20] = {0};
std::cin >> name;
res = name[0] * res * 2;
std::cout <<"CW"<<"-" << res << "-" <<"CRACKED";
}
总结 以前做半天,现在分析起来很快啊,对于特定语言的逆向,如果能有对应的工具帮助识别函数功能,那简直是帮大忙了
PS:用户名+序列号验证这里先校验了用户名长度,校验的时候计算了一堆中间值,真的一点用没有!!!
014-Splish
算法难度:⭐⭐
爆破难度:⭐
信息收集 运行情况: 开始有个启动屏幕,然后进入程序主界面
按照说明,目标是禁用启动屏幕,完成硬编码校验,写用户名序列号注册机
查壳与脱壳:
无壳:
调试分析 用户函数比较少,直接从起点硬刚:
这个call应该就是程序的入口了
![图片 27.png]
这里头是创建了一个窗口,然后延时关闭,要去除NAG,直接把这个函数处理了就好: (https://s2.51cto.com/images/20220908/1662609107329632.png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)![图片 28.png]
然后找到一个函数貌似是消息处理函数:这里根据参数的Msg号进行跳转执行
往下找,发现硬编码check分支:将用户输入和硬编码:HardCoded进行比对,一致了跳转
一致了跳转的最终位置是,说明这里硬编码已经找到了:
接下来找找用户名序列号验证:
验证会进行三次计算,首先是计算用户名得到一个结果:
然后计算序列号得到一个结果:
最后将两个运算结果进行比对:
算法分析 拿用户名计算一个结果,跟序列号计算一个结果进行比对的验证逻辑,写注册机的话则是先用用户名计算一个结果,然后用这个结果反推序列号
#include
int main() { const char* num = "2345678901"; char serial[20] = { 0 }; char name[20] = { 0 }; char name_res[20] = { 0 }; int len = 0;
std::cin >> name;
len = strlen(name);
//std::cin >> serial;
for (int i = 0; i < len; i++)
{
name_res[i] = name[i] % 0xA;
name_res[i] ^= i;
name_res[i] += 2;
if (name_res[i] > 0xA)name_res[i] -= 0xA;
}
//for (int i = 0; i < len; i++)
//{
// serial_res[i] = serial[i] % 0xA;
//}
for (int i = 0; i < len; i++)
{
serial[i] = num[name_res[i]];
}
std::cout << serial << std::endl;
}
结果:
总结 算是个编写注册机的练习,这个cm中练习了汇编转C的操作
015-BradSoblesky.1
算法难度:⭐
爆破难度:⭐
信息收集 运行情况: 序列号验证:
查壳与脱壳: MFC程序,无壳:
查字符串: 存在提示信息:

调试分析 硬编码字符串和用户输入字符串比对,没啥好说的
结果:
版权声明
本文仅代表作者观点,不代表博信信息网立场。