【破文标题】CRACKME算法分析
【破文作者】逍遥风
【破解工具】OD
【破解平台】WINXP
【破解声明】初次接触加密算法
参考文章:http://bbs.pediy.com/showthread.php?s=&threadid=26237
----------------------------------------------------------------------
00401180 |. E8 6D020000 CALL <JMP.&user32.GetDlgItemTextA> ; \取注册名位数
00401185 |. 83F8 04 CMP EAX,4 ; 注册名位数与4比较。
00401188 |. 73 05 JNB SHORT CrackMe_.0040118F ; 注册名必须大于4位
0040118A |. E9 11020000 JMP CrackMe_.004013A0
0040118F |> A3 8F354000 MOV DWORD PTR DS:[40358F],EAX
00401194 |. 68 FF000000 PUSH 0FF ; /Count = FF (255.)
00401199 |. 68 93354000 PUSH CrackMe_.00403593 ; |Buffer = CrackMe_.00403593
0040119E |. 68 ED030000 PUSH 3ED ; |ControlID = 3ED (1005.)
004011A3 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
004011A6 |. E8 47020000 CALL <JMP.&user32.GetDlgItemTextA> ; \取注册码的位数
004011AB |. BA 1B344000 MOV EDX,CrackMe_.0040341B
004011B0 |. 8902 MOV DWORD PTR DS:[EDX],EAX
004011B2 |. E8 49FEFFFF CALL CrackMe_.00401000 ; 初始化CRC32数据表
004011B7 |. 8D1D 1B344000 LEA EBX,DWORD PTR DS:[40341B] ; 储存注册码的位数准备进行CRC32计算
004011BD |. E8 78FEFFFF CALL CrackMe_.0040103A ; 开始对注册码的位数进行CRC32计算
004011C2 |. 3D F716602F CMP EAX,2F6016F7 ; 注册码位数的计算结果等于0x2F6016F7吗?
004011C7 |. 0F85 D3010000 JNZ CrackMe_.004013A0 ; 不相等就跳向失败
说明注册码的位数经过计算后必须等于0x2F6016F7。用工具可以计算出注册码的位数必须等于26位
----------------------------------------------------------------------004011CD |. 6A 08 PUSH 8 ; /Length = 8
004011CF |. 68 7F344000 PUSH CrackMe_.0040347F ; |Destination = CrackMe_.0040347F
004011D4 |. E8 FB010000 CALL <JMP.&kernel32.RtlZeroMemory> ; \RtlZeroMemory
004011D9 |. 8D05 93354000 LEA EAX,DWORD PTR DS:[403593] ; 使EAX等于输入的注册码
004011DF |. 83C0 08 ADD EAX,8 ; EAX=EAX+8(指向注册码的第9位)
004011E2 |. 8A18 MOV BL,BYTE PTR DS:[EAX] ; 使BL等于注册码的第9位
004011E4 |. 8D15 7F344000 LEA EDX,DWORD PTR DS:[40347F]
004011EA |. 881A MOV BYTE PTR DS:[EDX],BL ; 储存注册码的第9位
004011EC |. 42 INC EDX
004011ED |. 83C0 09 ADD EAX,9 ; EAX=EAX+9(指向注册码的第18位)
004011F0 |. 8A18 MOV BL,BYTE PTR DS:[EAX] ; 使BL等于注册码的第18位
004011F2 |. 881A MOV BYTE PTR DS:[EDX],BL ; 注册码第9位与第18位合并在一起储存在EDX中
004011F4 |. E8 07FEFFFF CALL CrackMe_.00401000 ; 初始化CRC32数据表
004011F9 |. 8D1D 7F344000 LEA EBX,DWORD PTR DS:[40347F] ; 注册码第9位与第18位作为一个整体,准备进行CRC计算
004011FF |. E8 36FEFFFF CALL CrackMe_.0040103A ; 对整体进行CRC32计算
00401204 |. 3D 65142C24 CMP EAX,242C1465 ; 计算结果等于0x242C1465吗?
00401209 |. 0F85 91010000 JNZ CrackMe_.004013A0 ; 不相等就跳向失败
注册码的第9位与第18位连接为一个整体,对整体做CRC32计算。计算的结果必须等于0x242C1465。
可以穷举出注册码的第9位与第18位必须为“--”。所以可以得到注册码的形式应该为:12345678-01234567-90123456
现在以每8位为一组将注册码分为3个部分。下文会用到。
----------------------------------------------------------------------0040120F |. 6A 0A PUSH 0A ; /Length = A (10.)
00401211 |. 8D45 EA LEA EAX,DWORD PTR SS:[EBP-16] ; |
00401214 |. 50 PUSH EAX ; |Destination
00401215 |. E8 BA010000 CALL <JMP.&kernel32.RtlZeroMemory> ; \RtlZeroMemory
0040121A |. 6A 0A PUSH 0A ; /Length = A (10.)
0040121C |. 8D45 E0 LEA EAX,DWORD PTR SS:[EBP-20] ; |
0040121F |. 50 PUSH EAX ; |Destination
00401220 |. E8 AF010000 CALL <JMP.&kernel32.RtlZeroMemory> ; \RtlZeroMemory
00401225 |. 33C9 XOR ECX,ECX
00401227 |. 8D05 93354000 LEA EAX,DWORD PTR DS:[403593] ; 使EAX等于输入的注册码
0040122D |> 8A1401 /MOV DL,BYTE PTR DS:[ECX+EAX]
00401230 |. 80FA 39 |CMP DL,39
00401233 |. 76 05 |JBE SHORT CrackMe_.0040123A
00401235 |. 80FA 41 |CMP DL,41
00401238 |. 72 0A |JB SHORT CrackMe_.00401244
0040123A |> 80FA 30 |CMP DL,30
0040123D |. 72 05 |JB SHORT CrackMe_.00401244
0040123F |. 80FA 46 |CMP DL,46
00401242 |. 76 05 |JBE SHORT CrackMe_.00401249
00401244 |> E9 57010000 |JMP CrackMe_.004013A0
00401249 |> 41 |INC ECX
0040124A |. 83F9 08 |CMP ECX,8 ; 取注册码的前8位(注册码第一部分)
0040124D |.^ 75 DE \JNZ SHORT CrackMe_.0040122D ; 格式验证
0040124F |. 33C9 XOR ECX,ECX
00401251 |. 33DB XOR EBX,EBX
00401253 |. 8D75 EA LEA ESI,DWORD PTR SS:[EBP-16]
00401256 |> C1E3 04 /SHL EBX,4
00401259 |. 8A1401 |MOV DL,BYTE PTR DS:[ECX+EAX]
0040125C |. 8816 |MOV BYTE PTR DS:[ESI],DL
0040125E |. 80FA 41 |CMP DL,41
00401261 |. 72 0A |JB SHORT CrackMe_.0040126D
00401263 |. 80FA 46 |CMP DL,46
00401266 |. 77 05 |JA SHORT CrackMe_.0040126D
00401268 |. 80EA 37 |SUB DL,37
0040126B |. EB 03 |JMP SHORT CrackMe_.00401270
0040126D |> 80EA 30 |SUB DL,30
00401270 |> 80E2 0F |AND DL,0F
00401273 |. 0ADA |OR BL,DL
00401275 |. 46 |INC ESI
00401276 |. 41 |INC ECX
00401277 |. 83F9 08 |CMP ECX,8
0040127A |. 895D FC |MOV DWORD PTR SS:[EBP-4],EBX
0040127D |.^ 75 D7 \JNZ SHORT CrackMe_.00401256 ; 将注册码的第一部分转换成对应的16进制
----------------------------------------------------------------------0040127F |. E8 7CFDFFFF CALL CrackMe_.00401000 ; 初始化CRC32数据表
00401284 |. 8D1D 8C344000 LEA EBX,DWORD PTR DS:[40348C] ; 取注册名准备进行CRC32计算
0040128A |. E8 ABFDFFFF CALL CrackMe_.0040103A ; 对输入的注册名进行CRC32计算
0040128F |. 3945 FC CMP DWORD PTR SS:[EBP-4],EAX ; 对注册名计算的结果与注册码的前8位进行比较
00401292 |. 0F85 08010000 JNZ CrackMe_.004013A0 ; 不相等就跳向失败
对输入的注册名进行CRC32计算,并将计算后的结果与注册码的前8位(第一部分)进行比较。不相等就跳向失败
即:注册名CRC计算后的结果就是注册码的前8位。
---------------------------------------------------------------------00401298 |. 33C9 XOR ECX,ECX ; ECX清空
0040129A |. 8D05 93354000 LEA EAX,DWORD PTR DS:[403593] ; 使EAX等于注册码
004012A0 |. 83C0 09 ADD EAX,9 ; 从注册码的第10位开始,取8位(取注册码的第2部分)
004012A3 |> 8A1401 /MOV DL,BYTE PTR DS:[ECX+EAX]
004012A6 |. 80FA 39 |CMP DL,39
004012A9 |. 76 05 |JBE SHORT CrackMe_.004012B0
004012AB |. 80FA 41 |CMP DL,41
004012AE |. 72 0A |JB SHORT CrackMe_.004012BA
004012B0 |> 80FA 30 |CMP DL,30
004012B3 |. 72 05 |JB SHORT CrackMe_.004012BA
004012B5 |. 80FA 46 |CMP DL,46
004012B8 |. 76 05 |JBE SHORT CrackMe_.004012BF
004012BA |> E9 E1000000 |JMP CrackMe_.004013A0
004012BF |> 41 |INC ECX
004012C0 |. 83F9 08 |CMP ECX,8
004012C3 |.^ 75 DE \JNZ SHORT CrackMe_.004012A3 ; 格式验证
004012C5 |. 33C9 XOR ECX,ECX
004012C7 |. 33DB XOR EBX,EBX
004012C9 |. 8D75 E0 LEA ESI,DWORD PTR SS:[EBP-20]
004012CC |> C1E3 04 /SHL EBX,4
004012CF |. 8A1401 |MOV DL,BYTE PTR DS:[ECX+EAX]
004012D2 |. 8816 |MOV BYTE PTR DS:[ESI],DL
004012D4 |. 8810 |MOV BYTE PTR DS:[EAX],DL
004012D6 |. 80FA 41 |CMP DL,41
004012D9 |. 72 0A |JB SHORT CrackMe_.004012E5
004012DB |. 80FA 46 |CMP DL,46
004012DE |. 77 05 |JA SHORT CrackMe_.004012E5
004012E0 |. 80EA 37 |SUB DL,37
004012E3 |. EB 03 |JMP SHORT CrackMe_.004012E8
004012E5 |> 80EA 30 |SUB DL,30
004012E8 |> 80E2 0F |AND DL,0F
004012EB |. 0ADA |OR BL,DL
004012ED |. 46 |INC ESI
004012EE |. 41 |INC ECX
004012EF |. 83F9 08 |CMP ECX,8
004012F2 |. 895D F8 |MOV DWORD PTR SS:[EBP-8],EBX
004012F5 |.^ 75 D5 \JNZ SHORT CrackMe_.004012CC ; 将注册码的第2部分转换成对应的16进制
----------------------------------------------------------------------
004012F7 |. E8 04FDFFFF CALL CrackMe_.00401000 ; 初始化CRC32数据表
004012FC |. 8D5D EA LEA EBX,DWORD PTR SS:[EBP-16] ; 取注册码的前8位准备进行CRC32计算
004012FF |. E8 36FDFFFF CALL CrackMe_.0040103A ; 对注册码的前8位进行CRC32计算
00401304 |. 3945 F8 CMP DWORD PTR SS:[EBP-8],EAX ; 对注册码的前8位计算后的结果与注册码的第2部分进行比较
00401307 |. 0F85 93000000 JNZ CrackMe_.004013A0 ; 不相等就跳向失败
对注册码的前8位进行CRC32计算,并将计算后的结果与注册码的第2部分进行比较。不相等就跳向失败。
即:注册码的第一部分CRC32计算后的值即为注册码的第2部分
----------------------------------------------------------------------
0040130D |. E8 EEFCFFFF call 00401000 ; 初始化CRC32数据表
00401312 |. 8D5D E0 lea ebx, [ebp-20] ; 取注册码的第2部分准备计算
00401315 |. E8 20FDFFFF call 0040103A ; 对注册码的第2部分进行CRC32计算
0040131A |. 8945 F8 mov [ebp-8], eax
0040131D |. 33C9 xor ecx, ecx
0040131F |. 8D05 93354000 lea eax, [403593] ; 取输入的注册码
00401325 |. 83C0 12 add eax, 12 ; 从注册码的第19位开始取值(取注册码的第3部分)
00401328 |> 8A1401 /mov dl, [ecx+eax]
0040132B |. 80FA 39 |cmp dl, 39
0040132E |. 76 05 |jbe short 00401335
00401330 |. 80FA 41 |cmp dl, 41
00401333 |. 72 0A |jb short 0040133F
00401335 |> 80FA 30 |cmp dl, 30
00401338 |. 72 05 |jb short 0040133F
0040133A |. 80FA 46 |cmp dl, 46
0040133D |. 76 02 |jbe short 00401341
0040133F |> EB 5F |jmp short 004013A0
00401341 |> 41 |inc ecx
00401342 |. 83F9 08 |cmp ecx, 8
00401345 |.^ 75 E1 \jnz short 00401328 ; 格式验证
00401347 |. 33C9 xor ecx, ecx ; ECX清零
00401349 |. 33DB xor ebx, ebx ; EBX清零
0040134B |> C1E3 04 /shl ebx, 4
0040134E |. 8A1401 |mov dl, [ecx+eax]
00401351 |. 8810 |mov [eax], dl
00401353 |. 80FA 41 |cmp dl, 41
00401356 |. 72 0A |jb short 00401362
00401358 |. 80FA 46 |cmp dl, 46
0040135B |. 77 05 |ja short 00401362
0040135D |. 80EA 37 |sub dl, 37
00401360 |. EB 03 |jmp short 00401365
00401362 |> 80EA 30 |sub dl, 30
00401365 |> 80E2 0F |and dl, 0F
00401368 |. 0ADA |or bl, dl
0040136A |. 41 |inc ecx
0040136B |. 83F9 08 |cmp ecx, 8
0040136E |. 895D F4 |mov [ebp-C], ebx
00401371 |.^ 75 D8 \jnz short 0040134B ; 将第3部分转换成对应的16进制
00401373 |. 8B45 FC mov eax, [ebp-4] ; 注册码第一部分放进EAX
00401376 |. 3345 F8 xor eax, [ebp-8] ; XOR(注册码第一部分,CRC注册码第二部分),结果放进EAX
00401379 |. 3B45 F4 cmp eax, [ebp-C] ; 注册码第3部分与上面计算结果相比较。不相等就失败
0040137C |. 75 22 jnz short 004013A0
0040137E |. 68 D2204000 push 004020D2 ; /good job, man!
00401383 |. FF75 08 push dword ptr [ebp+8] ; |hWnd
00401386 |. E8 8B000000 call <jmp.&user32.SetWindowTe>; \SetWindowTextA
----------------------------------------------------------------------算法总结:
1)注册码必须为26位,第9位与第18位必须是:-
注册码的形式为12345678-01234567-90123456
2)将注册名进行CRC32计算,将注册码的第1部分转换成对应的16进制。两个值必须相等
3)将注册码的第1部分进行CRC32计算(设为A),将注册码的第2部分转换成对应的16进制。两个值必须相等
4)将注册码的第2部分进行CRC32计算(设为B)。
5)将A,B做XOR运算,将注册码的第3部分转换成对应的16进制。两个值必须相等
即。注册码
第一部分:CRC(注册名)
第二部分:CRC(注册码第一部分)
第三部分:XOR [ 第一部分,CRC(第二部分)]
----------------------------------------------------------------------
【版权声明】本文只为交流,转载请保留作者及文章完整性。
[招生]系统0day安全班,企业级设备固件漏洞挖掘,Linux平台漏洞挖掘!