[反汇编练习] 160个CrackMe之054(eKH.1.exe)算法分析及注册机编写
本帖最后由 pk8900 于 2017-12-28 20:34 编辑【适合破解新手的160个crackme练手】第54个eKH.1.exe,这个比较简单,前两个五星级的可以说难度很大,第52个用了三天多时间,完美反推写出注册机,参考帖子(https://www.52pojie.cn/thread-677861-1-1.html),第53个算法是弄清了,是64位的奇偶较验,用注册机穷举根本不现实,用了一星期的时间,也没有想到简便的算法,等注册机研究成功后再发贴了,今天就分享一下这个Crackme 054的算法及注册机过程。
【crackme简介】
下载地址:http://pan.baidu.com/share/link?shareid=541269&uk=4146939145
Borland Delphi 3.0编写,无壳,是一个用户名+序列号式验证方式,有提示文字。
标注为?,估计难度为1星。
工具:X64dbg,Ldr,注册编写:VS2013
【crackme截图】
【算法部分】
首先用Ldr载入,找到按钮事件地址:方法可以参照下图:
找到事件地址下断点,中断后跟踪,代码如下:
验证注册流程一:检查输入的用户名长度,不为空。
00427B6A | 8B 45 FC | mov eax, dword ptr ss: | :"pk8900"用户名
00427B6D | E8 3E BC FD FF | call ekh.1.4037B0 | 取长度
00427B72 | 48 | dec eax |
00427B73 | 7C 30 | jl ekh.1.427BA5 | 跳去失败
00427B75 | 8D 55 FC | lea edx, dword ptr ss: |
00427B78 | 8B 83 EC 01 00 00 | mov eax, dword ptr ds: |
00427B7E | E8 0D E2 FE FF | call ekh.1.415D90 |
00427B83 | 8B 45 FC | mov eax, dword ptr ss: | :"12345678"
00427B86 | 50 | push eax |
00427B87 | 8D 55 F8 | lea edx, dword ptr ss: |
00427B8A | 8B 83 DC 01 00 00 | mov eax, dword ptr ds: |
00427B90 | E8 FB E1 FE FF | call ekh.1.415D90 |
00427B95 | 8B 45 F8 | mov eax, dword ptr ss: |
00427B98 | 5A | pop edx |
00427B99 | E8 82 FE FF FF | call ekh.1.427A20 | 关键算法
00427B9E | 3D 4E 61 BC 00 | cmp eax, 0xBC614E | 成功比较值:0xBC614E
00427BA3 | 7D 1E | jge ekh.1.427BC3 |
00427BA5 | 6A 00 | push 0x0 |
00427BA7 | 68 08 7C 42 00 | push ekh.1.427C08 | 427C08:"ERROR"
00427BAC | 68 10 7C 42 00 | push ekh.1.427C10 | 427C10:"Wrong Serial Number !"
验证注册流程二:关键算法部分:共两个循环加密部分,先看第一部分:
00427A56 | 8B 45 FC | mov eax, dword ptr ss: | 用户名
00427A59 | E8 52 BD FD FF | call ekh.1.4037B0 | 取长度
00427A5E | 8B F0 | mov esi, eax |
00427A60 | 85 F6 | test esi, esi |
00427A62 | 7E 3C | jle ekh.1.427AA0 |
00427A64 | B8 01 00 00 00 | mov eax, 0x1 |
00427A69 | 8B D0 | mov edx, eax | 循环部分 起点
00427A6B | 8B 4D FC | mov ecx, dword ptr ss: | :"pk8900"
00427A6E | 0F B6 4C 11 FF | movzx ecx, byte ptr ds: | 取用户名 +循环计数器位字符
00427A73 | 03 D9 | add ebx, ecx | EBX累加
00427A75 | 71 05 | jno ekh.1.427A7C |
00427A77 | E8 B4 AF FD FF | call <ekh.1.sub_402A30> |
00427A7C | C1 E3 08 | shl ebx, 0x8 | 左移 8位
00427A7F | 8B 0D 80 88 42 00 | mov ecx, dword ptr ds: | 加密字符串1 &"LANNYDIBANDINGINANAKEKHYANGNGENTOT"
00427A85 | 0F B6 54 11 FF | movzx edx, byte ptr ds: | 取计算数 位置字符
00427A8A | 0B DA | or ebx, edx | 累加
00427A8C | 85 DB | test ebx, ebx |
00427A8E | 7D 0C | jge ekh.1.427A9C | 如果变负数则 乘 -1,转为正数
00427A90 | 6B D3 FF | imul edx, ebx, 0xFFFFFFFF |
00427A93 | 71 05 | jno ekh.1.427A9A |
00427A95 | E8 96 AF FD FF | call <ekh.1.sub_402A30> |
00427A9A | 8B DA | mov ebx, edx |
00427A9C | 40 | inc eax | 累加计数器
00427A9D | 4E | dec esi |
00427A9E | 75 C9 | jne ekh.1.427A69 | 下一循环
00427AA0 | 81 F3 78 56 34 12 | xor ebx, 0x12345678 | 异或 0x12345678
00427AA6 | 8D 55 F0 | lea edx, dword ptr ss: |
00427AA9 | 8B C3 | mov eax, ebx |
00427AAB | E8 44 E9 FD FF | call <ekh.1.sub_4063F4> |
00427AB0 | 8B 45 F0 | mov eax, dword ptr ss: | :"1792442052"转十字制字符
这部分代码,取我们输入的用户名长度为循环次数,逐个取用户名字符加入累加值,左移8位,然后逐个取"LANNYDIBANDINGINANAKEKHYANGNGENTOT"字符累加,如果是负数则乘-1转为正数,循环完成后得到的值,与0x12345678异或,得到一个32位的数值。然后进行一下加密循环:
00427AAB | E8 44 E9 FD FF | call <ekh.1.sub_4063F4> |
00427AB0 | 8B 45 F0 | mov eax, dword ptr ss: | :"1792442052"转十字制字符
00427AB3 | E8 F8 BC FD FF | call ekh.1.4037B0 |
00427AB8 | 8B F0 | mov esi, eax | 得到长度,进行循环
00427ABA | 85 F6 | test esi, esi |
00427ABC | 7E 38 | jle ekh.1.427AF6 |
00427ABE | 8B C3 | mov eax, ebx |
00427AC0 | B9 0A 00 00 00 | mov ecx, 0xA | A:'\n'
00427AC5 | 99 | cdq |
00427AC6 | F7 F9 | idiv ecx | 除0xA(10)除余数
00427AC8 | 62 15 3C 7B 42 00 | bound edx, qword ptr ds: |
00427ACE | 8A 92 84 88 42 00 | mov dl, byte ptr ds: | edx+428884:"LANNY5646521"
00427AD4 | 8D 45 F0 | lea eax, dword ptr ss: |
00427AD7 | E8 FC BB FD FF | call <ekh.1.sub_4036D8> | 取字符串:第余数位
00427ADC | 8B 55 F0 | mov edx, dword ptr ss: |
00427ADF | 8D 45 F4 | lea eax, dword ptr ss: |
00427AE2 | E8 D1 BC FD FF | call <ekh.1.sub_4037B8> |
00427AE7 | 8B C3 | mov eax, ebx |
00427AE9 | B9 0A 00 00 00 | mov ecx, 0xA | A:'\n'
00427AEE | 99 | cdq |
00427AEF | F7 F9 | idiv ecx |
00427AF1 | 8B D8 | mov ebx, eax |
00427AF3 | 4E | dec esi |
00427AF4 | 75 C8 | jne ekh.1.427ABE |
00427AF6 | 8B 45 F4 | mov eax, dword ptr ss: | :"N5LNYYN54A"
这部分是将上个循环得到的数值转为字符,取长度为循环次数,每次除10取余,根据余数取字符串"LANNY5646521"中相应位的字符,组成一个字符串,就是正确的序列号。
算法部分分析完成,根据以上算法编写注册机代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
void main()
{
long key_tmp = 0;
char * key1 = "LANNYDIBANDINGINANAKEKHYANGNGENTOT"; //固定值,用于加密
char * key2 = "LANNY5646521"; //固定值,用于加密
char * yourName;
char * serial=new char;
memset(serial, 0, 260);
yourName = new char;
memset(yourName, 0, 260);
cout << "输入用户名:";
gets(yourName);
if (strlen(yourName) <= 0)
{
cout << "用户名不能为空" << endl;
return;
}
for (unsigned int x = 0; x < strlen(yourName); x++)
{
key_tmp += yourName;
key_tmp = key_tmp << 8;
key_tmp |= key1;
if (key_tmp<0)
{
key_tmp *= -1;
}
}
key_tmp ^= 0x12345678;
long tmp1=0;
while (key_tmp)
{
serial = key2;
tmp1++;
key_tmp /= 10;
}
cout << "序列号为:" << serial << endl;
system("pause");
成功测试注册用户名:52pojie.cn 序列号:Y55565NL4A
分析过程有不对或不到位的地方,欢迎大家回贴交流,共同探讨。
ricroon 发表于 2017-12-28 20:46
对了上次下载了那个crackme的chm,avg报毒,在虚拟机里面打开chm下载了几个出来,没有报毒,可能是几个有病 ...
应该不会有病毒,毕竟很多大家都尝试过,不会有病毒和暗桩,适合练手,杀毒软件报的话可添加信任。 ricroon 发表于 2017-12-28 20:43
非常感谢,一登陆就看到了楼主的续作,收藏先
我也是打算从这160个Crackme开始,一点一点学习逆向和C++,学习逆向不能激进,太高深的东西只能等一点一点积累了,加油,兄弟,业余的不一定就比专业的差。 看不懂呀
非常感谢,一登陆就看到了楼主的续作,收藏先 对了上次下载了那个crackme的chm,avg报毒,在虚拟机里面打开chm下载了几个出来,没有报毒,可能是几个有病毒特征? 谢谢楼主!!
谢谢楼主分享