【文章标题】: 【看雪读书月】【学习心得】我的第一个CrackMe分析,及注册机制作
【文章作者】: usufu
【软件名称】: echap303.exe
【软件大小】: 303KB
【下载地址】: 附件上传
【加壳方式】: 无壳
【保护方式】: 无壳
【编写语言】: Borland Delphi
【使用工具】: OD VC6 EDITPLUS PEiD
【操作平台】: XPSP3
【软件介绍】: 不知哪位大侠写的crackme,我拿来学习。
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
开始:
拿到《加密与解密三》了,看了几天,现在看到第五章了,本想研究下那个技术挑战参加下看雪读书月活动的,但我等
小辈水平不足,只能研究到用户名的限制,和第一步的一些对应关系后就实在是找不到北了。郁闷之余,决定换种方式来参
加这个活动了。于是找来一个CrackMe,逆向了一下,研究了算法,写出了注册机,不知道这个算不算学习心得了。第一次
写这种文章,错误之处还望大家海涵。
过程:
这个CrackMe的名字叫echap303.exe,是从我电脑上翻出来的,用PEiD查看是用Delphi写的,无壳。程序中采用明码比较
所以算法比较好跟,而注册机呢,就用《加密与解密第三版》中我刚看的内容“直接用程序的反汇编代码”来写注册机,偷个
懒,哈哈。以下是详细步骤:
1、首先运行程序,随意输入注册码与序列号,不错,有错误提示,留心下错误提示的内容。“Wrong Code”
2、用OD载入程序,在汇编代码处,右键,查找-》所有参考文本字串,找到这个“Wrong Code”,双击,来到对应代码
处。
004417FD |. 8B55 F8 mov edx, dword ptr [ebp-8]
00441800 |. 58 pop eax
00441801 |. E8 3E23FCFF call 00403B44 ;这里下断
00441806 |. 75 1A jnz short 00441822 ;这里一跳就错了.
00441808 |. 6A 40 push 40
0044180A |. B9 6C184400 mov ecx, 0044186C ; ASCII "U made it"
0044180F |. BA 78184400 mov edx, 00441878 ; ASCII "Right Code"
00441814 |. A1 302C4400 mov eax, dword ptr [442C30]
00441819 |. 8B00 mov eax, dword ptr [eax]
0044181B |. E8 D4D6FFFF call 0043EEF4
00441820 |. EB 18 jmp short 0044183A
00441822 |> 6A 10 push 10
00441824 |. B9 84184400 mov ecx, 00441884 ; ASCII "Error"
00441829 |. BA 8C184400 mov edx, 0044188C ; ASCII "Wrong Code"《---双击后来到此处
向上找找,看看是从哪儿跳到这儿来的呢?原来是从00441806处跳过来的,紧接着,我们会怀疑上面的call是不是有点可疑呢?
在这个call上F2下断,而后F9让程序跑起来.
3、程序运行起来之后,我们仍旧在用户名和序列号中随便输入,而后点击"OK",程序被断下,而后F7跟进这个Call,我们看看
它搞什么搞.进去之后的代码如下:
00403B44 /$ 53 push ebx
00403B45 |. 56 push esi
00403B46 |. 57 push edi
00403B47 |. 89C6 mov esi, eax
00403B49 |. 89D7 mov edi, edx
00403B4B |. 39D0 cmp eax, edx
00403B4D |. 0F84 8F000000 je 00403BE2
00403B53 |. 85F6 test esi, esi
00403B55 |. 74 68 je short 00403BBF
00403B57 |. 85FF test edi, edi
00403B59 |. 74 6B je short 00403BC6
00403B5B |. 8B46 FC mov eax, dword ptr [esi-4]
00403B5E |. 8B57 FC mov edx, dword ptr [edi-4]
00403B61 |. 29D0 sub eax, edx
00403B63 |. 77 02 ja short 00403B67
00403B65 |. 01C2 add edx, eax
00403B67 |> 52 push edx
00403B68 |. C1EA 02 shr edx, 2
00403B6B |. 74 26 je short 00403B93
00403B6D |> 8B0E /mov ecx, dword ptr [esi]
00403B6F |. 8B1F |mov ebx, dword ptr [edi]
00403B71 |. 39D9 |cmp ecx, ebx
00403B73 |. 75 58 |jnz short 00403BCD
00403B75 |. 4A |dec edx
00403B76 |. 74 15 |je short 00403B8D
00403B78 |. 8B4E 04 |mov ecx, dword ptr [esi+4]
00403B7B |. 8B5F 04 |mov ebx, dword ptr [edi+4]
00403B7E |. 39D9 |cmp ecx, ebx
00403B80 |. 75 4B |jnz short 00403BCD
00403B82 |. 83C6 08 |add esi, 8
00403B85 |. 83C7 08 |add edi, 8
00403B88 |. 4A |dec edx
00403B89 |.^ 75 E2 \jnz short 00403B6D
00403B8B |. EB 06 jmp short 00403B93
00403B8D |> 83C6 04 add esi, 4
00403B90 |. 83C7 04 add edi, 4
00403B93 |> 5A pop edx
00403B94 |. 83E2 03 and edx, 3
00403B97 |. 74 22 je short 00403BBB
00403B99 |. 8B0E mov ecx, dword ptr [esi]
00403B9B |. 8B1F mov ebx, dword ptr [edi]
00403B9D |. 38D9 cmp cl, bl
00403B9F |. 75 41 jnz short 00403BE2
00403BA1 |. 4A dec edx
00403BA2 |. 74 17 je short 00403BBB
00403BA4 |. 38FD cmp ch, bh
00403BA6 |. 75 3A jnz short 00403BE2
00403BA8 |. 4A dec edx
00403BA9 |. 74 10 je short 00403BBB
00403BAB |. 81E3 0000FF00 and ebx, 0FF0000
00403BB1 |. 81E1 0000FF00 and ecx, 0FF0000
00403BB7 |. 39D9 cmp ecx, ebx
00403BB9 |. 75 27 jnz short 00403BE2
00403BBB |> 01C0 add eax, eax
00403BBD |. EB 23 jmp short 00403BE2
00403BBF |> 8B57 FC mov edx, dword ptr [edi-4]
00403BC2 |. 29D0 sub eax, edx
00403BC4 |. EB 1C jmp short 00403BE2
00403BC6 |> 8B46 FC mov eax, dword ptr [esi-4]
00403BC9 |. 29D0 sub eax, edx
00403BCB |. EB 15 jmp short 00403BE2
00403BCD |> 5A pop edx
00403BCE |. 38D9 cmp cl, bl
00403BD0 |. 75 10 jnz short 00403BE2
00403BD2 |. 38FD cmp ch, bh
00403BD4 |. 75 0C jnz short 00403BE2
00403BD6 |. C1E9 10 shr ecx, 10
00403BD9 |. C1EB 10 shr ebx, 10
00403BDC |. 38D9 cmp cl, bl
00403BDE |. 75 02 jnz short 00403BE2
00403BE0 |. 38FD cmp ch, bh
00403BE2 |> 5F pop edi
00403BE3 |. 5E pop esi
00403BE4 |. 5B pop ebx
00403BE5 \. C3 retn
反正看到这些,我是头疼,正打算埋头分析下这个子程序的作用时,发现了旁边的EDX寄存器的内容貌似就是我们所要求的注册
码,而且还有我们的错误注册码,记下正确的,运行程序,输入刚才输入的用户名,并输入这个注册码,点击OK,正确的提示
出现了.那么很明显,注册码不是在这个子程序中产生的,这个子程序只是对输入的注册码和正确的注册码比较看看输入的是否正确
4、重新OD载入,输入错误的注册码,再让OD断下,上次下断的时候没注意,原来在这个call断下之前,edx的内容就已经是
正确的注册码了.那继续向上翻,看看这个edx的内容是在哪儿被修改的呢?
004417F8 |. E8 FBFEFFFF call 004416F8 ; 关键call,根据用户名计算注册码
004417FD |. 8B55 F8 mov edx, dword ptr [ebp-8] ; 原来这里edx被修改了
00441800 |. 58 pop eax
00441801 |. E8 3E23FCFF call 00403B44
同样,在上面那个call处下断(删除原来的断点),跑起来后继续输入错误的注册码,点击ok程序被断,F7跟进这个call,进来后
我们就在寄存器窗口中发现了我们输入的用户名,那么我们可以猜想,这个call可能就是根据用户名来计算注册码了.F8单步跟踪
来了解这段程序的作用.
004416F8 /$ 53 push ebx
004416F9 |. 56 push esi
004416FA |. 57 push edi
004416FB |. 83C4 DC add esp, -24
004416FE |. 891424 mov dword ptr [esp], edx ; edx指向正确序列号待存放地址
00441701 |. 8BF8 mov edi, eax ; 使edi指向用户名首址
00441703 |. BB 05033949 mov ebx, 49390305 ; ebx存放一个常数,参与后面的异或运算
00441708 |. BE 20126348 mov esi, 48631220 ; esi存放另一个常数,参与后面的异或运算
0044170D |. 8BC7 mov eax, edi
0044170F |. E8 2023FCFF call 00403A34 ; 此处的call用来计算用户名长度
00441714 |. 85C0 test eax, eax ; eax存放用户名长度
00441716 |. 7E 2E jle short 00441746
00441718 |. BA 01000000 mov edx, 1 ; 计数器,相当于name[edx]
0044171D |> 33C9 /xor ecx, ecx ; ecx清零
0044171F |. 8A4C17 FF |mov cl, byte ptr [edi+edx-1] ; 取用户名一个字节到cl=name[ecx-1]
00441723 |. 33D9 |xor ebx, ecx ; 将ebx与ecx异或,ecx为取出的用户名的一个字节
00441725 |. 33F3 |xor esi, ebx ; 再将esi与上一步的ebx异或
00441727 |. F6C3 01 |test bl, 1 ; 第一步异或的结果低8位与1的与是否为0
0044172A |. 74 0F |je short 0044173B
0044172C |. D1FB |sar ebx, 1 ; ebx算术右移一位
0044172E |. 79 03 |jns short 00441733 ; 符号为正,跳
00441730 |. 83D3 00 |adc ebx, 0
00441733 |> 81F3 11032001 |xor ebx, 1200311 ; 将ebx中的内容和1200311异或
00441739 |. EB 07 |jmp short 00441742
0044173B |> D1FB |sar ebx, 1 ; ebx算术右移一位
0044173D |. 79 03 |jns short 00441742 ; 符号为正,跳
0044173F |. 83D3 00 |adc ebx, 0
00441742 |> 42 |inc edx ; 循环处理下一位
00441743 |. 48 |dec eax ; 用户名长度减一
00441744 |.^ 75 D7 \jnz short 0044171D ; 未处理完,跳
00441746 |> 8B0424 mov eax, dword ptr [esp]
00441749 |. 50 push eax ;
0044174A |. 8BC3 mov eax, ebx ; ebx为上面循环的运算结果
0044174C |. 25 FFFF0000 and eax, 0FFFF ; 运算结果与0FFFF与,将运算结果高16位清零
00441751 |. 894424 08 mov dword ptr [esp+8], eax ; [esp+8]为第一部分注册码,即ebx的低16位
00441755 |. C64424 0C 00 mov byte ptr [esp+C], 0
0044175A |. C1EB 10 shr ebx, 10 ; ebx逻辑右移16位
0044175D |. 895C24 10 mov dword ptr [esp+10], ebx ; 取运算结果的高16位
00441761 |. C64424 14 00 mov byte ptr [esp+14], 0
00441766 |. 8BC6 mov eax, esi
00441768 |. 25 FFFF0000 and eax, 0FFFF ; 屏蔽esi的高16位
0044176D |. 894424 18 mov dword ptr [esp+18], eax ; 存放运算结果的低16位
00441771 |. C64424 1C 00 mov byte ptr [esp+1C], 0
00441776 |. C1EE 10 shr esi, 10 ; 屏蔽esi的低16位
00441779 |. 897424 20 mov dword ptr [esp+20], esi ; 存放运算结果的高16位
0044177D |. C64424 24 00 mov byte ptr [esp+24], 0
00441782 |. 8D5424 08 lea edx, dword ptr [esp+8]
00441786 |. B9 03000000 mov ecx, 3
0044178B |. B8 A4174400 mov eax, 004417A4 ; ASCII "%.4x-%.4x-%.4x-%.4x"
00441790 |. E8 6F68FCFF call 00408004 ; 将运算的四个部分,转换为上面的格式
00441795 |. 83C4 24 add esp, 24
00441798 |. 5F pop edi
00441799 |. 5E pop esi
0044179A |. 5B pop ebx
0044179B \. C3 retn
到这里,我们就可以看到这个crackme的注册码生成过程了,其中用到了两个常数,参与异或运算,然后根据根据异或后的结果进行
一些算术移位指令,这个过程直到将用户名处理完为止.用户名每个字节的异或结果是累加的,ebx和esi是最终运算结果.
程序最后将esi和ebx寄存器的内容分拆,进而形成"EBX[后16位]-EBX[高16位]-ESI[后16位]-ESI[高16位]"的注册码.
5、由于我比较笨,也比较懒,而且《加密与解密第三版》上说可以直接用原程序的汇编代码来写注册机,那么我就试试了
参考P109-P110页的代码,写出了这个CrackMe的注册机,注册算法代码如下:
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)