[CRC32算法练习] CRC32CrackMe算法分析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CRC32算法练习] CRC32CrackMe算法分析相关的知识,希望对你有一定的参考价值。

【破文标题】[CRC32算法练习] CRC32CrackMe算法分析
【破文作者】静心学习
【作者邮箱】[email protected]
【作者主页】http://www.cnblogs.com/dacainiao/
【破解工具】OD, DEDE, IDA
【破解平台】xp sp3
【软件名称】CRC32CrackMe
【软件大小】40KB
【原版下载】http://bbs.pediy.com/attachment.php?attachmentid=6579&d=1183561716
【保护方式】无壳
【软件简介】一个CRC32算法练习的CrackMe。
【破解声明】初学密码学,跟着看雪前辈们的脚步学习,错误之处敬请诸位前辈不吝赐教。
------------------------------------------------------------------------
【破解过程】软件无壳,vc编写,bp GetDlgItemTextA可以很快找到入口点。

00401309 > \\8D8424 0C020000 LEA EAX, DWORD PTR SS:[ESP+0x20C]
00401310 . 8D8C24 0C010000 LEA ECX, DWORD PTR SS:[ESP+0x10C]
00401317 . 50 PUSH EAX ; //Buff
00401318 . 51 PUSH ECX ; //用户名
00401319 . E8 F2FDFFFF CALL CRC32Cra.00401110 ; //计算CRC32
0040131E . 8D9424 14020000 LEA EDX, DWORD PTR SS:[ESP+0x214]
00401325 . 8D4424 14 LEA EAX, DWORD PTR SS:[ESP+0x14]
00401329 . 52 PUSH EDX ; //CRC32
0040132A . 50 PUSH EAX ; //注册码
0040132B . E8 D0FCFFFF CALL CRC32Cra.00401000
00401330 . 83C4 10 ADD ESP, 0x10
00401333 . 83F8 01 CMP EAX, 0x1
00401336 . 6A 40 PUSH 0x40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00401338 . 68 8C604000 PUSH CRC32Cra.0040608C ; |Title = "注册提示"
0040133D . 75 18 JNZ SHORT CRC32Cra.00401357 ; |
0040133F . 68 48604000 PUSH CRC32Cra.00406048 ; |Text = "恭喜你,注册码正确!"
00401344 . 56 PUSH ESI ; |hOwner
00401345 . FF15 A8504000 CALL NEAR DWORD PTR DS:[<&USER32.MessageBoxA>] ; \\MessageBoxA
0040134B . 5F POP EDI
0040134C . 5E POP ESI
0040134D . 33C0 XOR EAX, EAX
0040134F . 5B POP EBX
00401350 . 81C4 00030000 ADD ESP, 0x300
00401356 . C3 RETN

 

代码很少,直接看计算CRC32的CALL (CALL 00401110):

00401110 /$ 83EC 0C SUB ESP, 0xC
00401113 |. 56 PUSH ESI
00401114 |. 57 PUSH EDI
00401115 |. E8 B6FFFFFF CALL CRC32Cra.004010D0 ; //生成CRC32表
0040111A |. 8B7424 18 MOV ESI, DWORD PTR SS:[ESP+0x18] ; //用户名
0040111E |. 83C9 FF OR ECX, 0xFFFFFFFF
00401121 |. 8BFE MOV EDI, ESI
00401123 |. 33C0 XOR EAX, EAX
00401125 |. 83CA FF OR EDX, 0xFFFFFFFF
00401128 |. F2:AE REPNE SCAS BYTE PTR ES:[EDI]
0040112A |. F7D1 NOT ECX
0040112C |. 49 DEC ECX ; //取用户名长度
0040112D |. 85C9 TEST ECX, ECX
0040112F |. 7E 1F JLE SHORT CRC32Cra.00401150 ; //小于等于0则跳
00401131 |. 53 PUSH EBX
00401132 |> 8BC2 /MOV EAX, EDX ; //上一次CRC值
00401134 |. 33DB |XOR EBX, EBX
00401136 |. 8A1E |MOV BL, BYTE PTR DS:[ESI] ; //用户名1字节
00401138 |. 25 FF000000 |AND EAX, 0xFF ; //eax & 0xff
0040113D |. 33C3 |XOR EAX, EBX ; //(eax & 0xff) ^ ebx
0040113F |. C1EA 08 |SHR EDX, 0x8 ; //edx >> 8
00401142 |. 8B0485 20854000 |MOV EAX, DWORD PTR DS:[EAX*4+0x408520] ; //408250[(eax & 0xff) ^ ebx]
00401149 |. 33D0 |XOR EDX, EAX ; //(edx >> 8) ^ 408250[(eax & 0xff) ^ ebx]
0040114B |. 46 |INC ESI
0040114C |. 49 |DEC ECX
0040114D |.^ 75 E3 \\JNZ SHORT CRC32Cra.00401132
0040114F |. 5B POP EBX
00401150 |> 33C9 XOR ECX, ECX
00401152 |. 8D4424 08 LEA EAX, DWORD PTR SS:[ESP+0x8]
00401156 |. 894C24 09 MOV DWORD PTR SS:[ESP+0x9], ECX
0040115A |. 6A 10 PUSH 0x10
0040115C |. F7D2 NOT EDX ; //~edx
0040115E |. 894C24 11 MOV DWORD PTR SS:[ESP+0x11], ECX
00401162 |. 50 PUSH EAX
00401163 |. 52 PUSH EDX
00401164 |. C64424 14 00 MOV BYTE PTR SS:[ESP+0x14], 0x0
00401169 |. 884C24 1D MOV BYTE PTR SS:[ESP+0x1D], CL
0040116D |. E8 24380000 CALL CRC32Cra.00404996
00401172 |. 8D7C24 14 LEA EDI, DWORD PTR SS:[ESP+0x14]
00401176 |. 83C9 FF OR ECX, 0xFFFFFFFF
00401179 |. 33C0 XOR EAX, EAX
0040117B |. 83C4 0C ADD ESP, 0xC
0040117E |. 33F6 XOR ESI, ESI
00401180 |. F2:AE REPNE SCAS BYTE PTR ES:[EDI]
00401182 |. F7D1 NOT ECX
00401184 |. 49 DEC ECX ; //CRC32长度
00401185 |. 74 25 JE SHORT CRC32Cra.004011AC ; //长度为0则跳
00401187 |> 0FBE4C34 08 /MOVSX ECX, BYTE PTR SS:[ESP+ESI+0x8] ; //取CRC32第1字节
0040118C |. 51 |PUSH ECX
0040118D |. E8 4E020000 |CALL CRC32Cra.004013E0 ; //小写字母转大写
00401192 |. 884434 0C |MOV BYTE PTR SS:[ESP+ESI+0xC], AL
00401196 |. 83C4 04 |ADD ESP, 0x4
00401199 |. 8D7C24 08 |LEA EDI, DWORD PTR SS:[ESP+0x8]
0040119D |. 83C9 FF |OR ECX, 0xFFFFFFFF
004011A0 |. 33C0 |XOR EAX, EAX
004011A2 |. 46 |INC ESI
004011A3 |. F2:AE |REPNE SCAS BYTE PTR ES:[EDI]
004011A5 |. F7D1 |NOT ECX
004011A7 |. 49 |DEC ECX ; //求CRC32长度
004011A8 |. 3BF1 |CMP ESI, ECX ; //大于等于则跳出循环
004011AA |.^ 72 DB \\JB SHORT CRC32Cra.00401187
004011AC |> 8B4424 1C MOV EAX, DWORD PTR SS:[ESP+0x1C]
004011B0 |. 8D5424 08 LEA EDX, DWORD PTR SS:[ESP+0x8]
004011B4 |. 52 PUSH EDX ; /String2
004011B5 |. 50 PUSH EAX ; |String1
004011B6 |. FF15 00504000 CALL NEAR DWORD PTR DS:[<&KERNEL32.lstrcpyA>] ; \\lstrcpyA
004011BC |. 5F POP EDI
004011BD |. 5E POP ESI
004011BE |. 83C4 0C ADD ESP, 0xC
004011C1 \\. C3 RETN

 

首先动态初始化CRC32表 (CALL 004010D0):

004010D0 /$ 56 PUSH ESI
004010D1 |. 33D2 XOR EDX, EDX
004010D3 |. B9 20854000 MOV ECX, CRC32Cra.00408520 ; //CRC32表首地址
004010D8 |> 8BC2 /MOV EAX, EDX
004010DA |. BE 08000000 |MOV ESI, 0x8
004010DF |> A8 01 |/TEST AL, 0x1
004010E1 |. 74 09 ||JE SHORT CRC32Cra.004010EC
004010E3 |. D1E8 ||SHR EAX, 1
004010E5 |. 35 2083B8ED ||XOR EAX, 0xEDB88320
004010EA |. EB 02 ||JMP SHORT CRC32Cra.004010EE
004010EC |> D1E8 ||SHR EAX, 1 ; //动态生成CRC32表
004010EE |> 4E ||DEC ESI
004010EF |.^ 75 EE |\\JNZ SHORT CRC32Cra.004010DF
004010F1 |. 8901 |MOV DWORD PTR DS:[ECX], EAX
004010F3 |. 83C1 04 |ADD ECX, 0x4
004010F6 |. 42 |INC EDX
004010F7 |. 81F9 20894000 |CMP ECX, CRC32Cra.00408920
004010FD |.^ 7C D9 \\JL SHORT CRC32Cra.004010D8
004010FF |. 5E POP ESI
00401100 \\. C3 RETN

 

然后获取用户名长度,开始循环计算CRC:

0040111A |. 8B7424 18 MOV ESI, DWORD PTR SS:[ESP+0x18] ; //用户名
0040111E |. 83C9 FF OR ECX, 0xFFFFFFFF
00401121 |. 8BFE MOV EDI, ESI
00401123 |. 33C0 XOR EAX, EAX
00401125 |. 83CA FF OR EDX, 0xFFFFFFFF
00401128 |. F2:AE REPNE SCAS BYTE PTR ES:[EDI]
0040112A |. F7D1 NOT ECX
0040112C |. 49 DEC ECX ; //取用户名长度
0040112D |. 85C9 TEST ECX, ECX
0040112F |. 7E 1F JLE SHORT CRC32Cra.00401150 ; //小于等于0则跳
00401131 |. 53 PUSH EBX
00401132 |> 8BC2 /MOV EAX, EDX ; //上一次CRC值
00401134 |. 33DB |XOR EBX, EBX
00401136 |. 8A1E |MOV BL, BYTE PTR DS:[ESI] ; //用户名1字节
00401138 |. 25 FF000000 |AND EAX, 0xFF ; //eax & 0xff
0040113D |. 33C3 |XOR EAX, EBX ; //(eax & 0xff) ^ ebx
0040113F |. C1EA 08 |SHR EDX, 0x8 ; //edx >> 8
00401142 |. 8B0485 20854000 |MOV EAX, DWORD PTR DS:[EAX*4+0x408520] ; //408250[(eax & 0xff) ^ ebx]
00401149 |. 33D0 |XOR EDX, EAX ; //(edx >> 8) ^ 408250[(eax & 0xff) ^ ebx]
0040114B |. 46 |INC ESI
0040114C |. 49 |DEC ECX
0040114D |.^ 75 E3 \\JNZ SHORT CRC32Cra.00401132
0040114F |. 5B POP EBX
00401150 |> 33C9 XOR ECX, ECX
00401152 |. 8D4424 08 LEA EAX, DWORD PTR SS:[ESP+0x8]
00401156 |. 894C24 09 MOV DWORD PTR SS:[ESP+0x9], ECX
0040115A |. 6A 10 PUSH 0x10
0040115C |. F7D2 NOT EDX ; //~edx

 

最终将CRC32中的小写字母转大写字母:

00401172 |. 8D7C24 14 LEA EDI, DWORD PTR SS:[ESP+0x14]
00401176 |. 83C9 FF OR ECX, 0xFFFFFFFF
00401179 |. 33C0 XOR EAX, EAX
0040117B |. 83C4 0C ADD ESP, 0xC
0040117E |. 33F6 XOR ESI, ESI
00401180 |. F2:AE REPNE SCAS BYTE PTR ES:[EDI]
00401182 |. F7D1 NOT ECX
00401184 |. 49 DEC ECX ; //CRC32长度
00401185 |. 74 25 JE SHORT CRC32Cra.004011AC ; //长度为0则跳
00401187 |> 0FBE4C34 08 /MOVSX ECX, BYTE PTR SS:[ESP+ESI+0x8] ; //取CRC32第1字节
0040118C |. 51 |PUSH ECX
0040118D |. E8 4E020000 |CALL CRC32Cra.004013E0 ; //小写字母转大写
00401192 |. 884434 0C |MOV BYTE PTR SS:[ESP+ESI+0xC], AL
00401196 |. 83C4 04 |ADD ESP, 0x4
00401199 |. 8D7C24 08 |LEA EDI, DWORD PTR SS:[ESP+0x8]
0040119D |. 83C9 FF |OR ECX, 0xFFFFFFFF
004011A0 |. 33C0 |XOR EAX, EAX
004011A2 |. 46 |INC ESI
004011A3 |. F2:AE |REPNE SCAS BYTE PTR ES:[EDI]
004011A5 |. F7D1 |NOT ECX
004011A7 |. 49 |DEC ECX ; //求CRC32长度
004011A8 |. 3BF1 |CMP ESI, ECX ; //大于等于则跳出循环
004011AA |.^ 72 DB \\JB SHORT CRC32Cra.00401187

 

最终和输入的注册码比较,相同则注册成功。
------------------------------------------------------------------------
【破解总结】软件使用CRC32算法,将输入的用户名计算出CRC32的值,并将里面的小写字母转成大写,然后与输入的注册码比较,相同则注册成功。
------------------------------------------------------------------------
【版权声明】无

以上是关于[CRC32算法练习] CRC32CrackMe算法分析的主要内容,如果未能解决你的问题,请参考以下文章

crc32 — 计算一个字符串的 crc32 多项式?

CRC32的计算方法

CRC32加密算法的识别

求助crc32的原理

指定CRC32反构数据

指定CRC32反构数据