【软件名称】: FrostyKid's Crackme3
【软件大小】: 133 KB
【下载地址】: 自己搜索下载
【加壳方式】: UPX 0.89
【编写语言】: Borland Delphi
【使用工具】: OLLYDBG
【操作平台】: winxp sp2
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
一个繁琐的crackme,需要耐性。脱壳略过,直接进入分析。代码很长,只挑关键的几段。
注册码有三种形式,先看第一种,注册码形式:XX-XXX-XX。
00444B78 |> \BB 01000000 MOV EBX ,1 ; EBX赋值1
00444B7D |. EB 25 JMP SHORT unpacked.00444BA4
00444B7F |> 8B45 FC /MOV EAX ,DWORD PTR SS :[EBP -4] ; 注册码
00444B82 |. 807C18 FF 2D |CMP BYTE PTR DS :[EAX +EBX -1],2D ; 注册码中是否含有“-”号
00444B87 |. 74 1A |JE SHORT unpacked.00444BA3
00444B89 |. 8B45 FC |MOV EAX ,DWORD PTR SS :[EBP -4] ; 注册码置EAX
00444B8C |. 8A4418 FF |MOV AL ,BYTE PTR DS :[EAX +EBX -1] ; 逐个取注册码ASCII
00444B90 |. 3C 30 |CMP AL ,30 ; 是否大于0
00444B92 |. 0F82 8C070000 |JB unpacked.00445324
00444B98 |. 8B55 FC |MOV EDX ,DWORD PTR SS :[EBP -4] ; 注册码置EDX
00444B9B |. 3C 39 |CMP AL ,39 ; 是否小于9
00444B9D |. 0F87 81070000 |JA unpacked.00445324
00444BA3 |> 43 |INC EBX ; EBX累加
00444BA4 |> 8B45 FC MOV EAX ,DWORD PTR SS :[EBP -4] ; 注册码放入EAX
00444BA7 |. E8 00F0FBFF |CALL unpacked.00403BAC ; 这个CALL取注册码长度
00444BAC |. 3BD8 |CMP EBX ,EAX ; 注册码是否取完
00444BAE |.^ 7E CF \JLE SHORT unpacked.00444B7F
00444BB0 |. 8B45 FC MOV EAX ,DWORD PTR SS :[EBP -4] ; 注册码
00444BB3 |. E8 F4EFFBFF CALL unpacked.00403BAC
00444BB8 |. 8BD8 MOV EBX ,EAX ; 取长度
00444BBA |. 83FB 09 CMP EBX ,9 ; 是否大于9
00444BBD |. 0F8C 61070000 JL unpacked.00445324
00444BC3 |. 83FB 0B CMP EBX ,0B ; 是否小于12
00444BC6 |. 0F8F 58070000 JG unpacked.00445324
00444BCC |. 83FB 09 CMP EBX ,9 ; 是否为9位
00444BCF |. 0F85 0C020000 JNZ unpacked.00444DE1
=========判断注册码类型、长度,并确定含有“-”号,注册码必须为数字
00444BD5 |. 8B45 FC MOV EAX ,DWORD PTR SS :[EBP -4] ; 注册码入EAX
00444BD8 |. 8078 02 2D CMP BYTE PTR DS :[EAX +2],2D ; 第三位是否为-号,注意EAX+2
00444BDC |. 0F85 42070000 JNZ unpacked.00445324 ; 不是就跳错
00444BE2 |. 8B45 FC MOV EAX ,DWORD PTR SS :[EBP -4] ; 第7位是否为-号
00444BE5 |. 8078 06 2D CMP BYTE PTR DS :[EAX +6],2D ; 不是就跳错
00444BE9 |. 0F85 35070000 JNZ unpacked.00445324
=========判断-号的位置,确定-号在第3和第7位
00444C08 |. 8D45 EC LEA EAX ,DWORD PTR SS :[EBP -14]
00444C0B |. 8B55 FC MOV EDX ,DWORD PTR SS :[EBP -4] ; 注册码
00444C0E |. 8A52 01 MOV DL ,BYTE PTR DS :[EDX +1] ; 注册码第2位
00444C11 |. 8850 01 MOV BYTE PTR DS :[EAX +1],DL ; 放入EAX+1
00444C14 |. C600 01 MOV BYTE PTR DS :[EAX ],1 ; DS:[EAX]置1
00444C17 |. 8D55 EC LEA EDX ,DWORD PTR SS :[EBP -14]
00444C1A |. 8D45 F0 LEA EAX ,DWORD PTR SS :[EBP -10]
00444C1D |. B1 02 MOV CL ,2 ; CL=2,新字符串位置
00444C1F |. E8 28DCFBFF CALL unpacked.0040284C ; 将注册码按位置重新组合
00444C24 |. 8D55 F0 LEA EDX ,DWORD PTR SS :[EBP -10] ; 堆栈地址=0012F3F8, (ASCII 02,"17" )
00444C27 |. 8D45 E8 LEA EAX ,DWORD PTR SS :[EBP -18]
00444C2A |. E8 4DDCFBFF CALL unpacked.0040287C
=========去“-”号位后将注册码按照顺序依次组成成新码
00444CF2 |. 8B45 F8 MOV EAX ,DWORD PTR SS :[EBP -8] ; 去-号后的注册码
00444CF5 |. E8 6A2EFCFF CALL unpacked.00407B64 ; 判断去-号后的注册码是否为数字,并转为16进制
00444CFA |. 8BF0 MOV ESI ,EAX ; 结果,新码转16进制后的结果
/////////////
00407B64 53 PUSH EBX
00407B65 56 PUSH ESI
00407B66 83C4 F4 ADD ESP ,-0C
00407B69 8BD8 MOV EBX ,EAX ; 去所有-号后
00407B6B 8BD4 MOV EDX ,ESP
00407B6D 8BC3 MOV EAX ,EBX
00407B6F E8 68AEFFFF CALL unpacked.004029DC ; 判断去-号后的注册码是否为数字,并转为16进制
00407B74 8BF0 MOV ESI ,EAX ; EAX放着结果,新码转16进制后的结果
00407B76 833C24 00 CMP DWORD PTR SS :[ESP ],0
00407B7A 74 19 JE SHORT unpacked.00407B95
00407B7C 895C24 04 MOV DWORD PTR SS :[ESP +4],EBX
00407B80 C64424 08 0B MOV BYTE PTR SS :[ESP +8],0B
00407B85 8D5424 04 LEA EDX ,DWORD PTR SS :[ESP +4]
00407B89 A1 746B4400 MOV EAX ,DWORD PTR DS :[446B74]
00407B8E 33C9 XOR ECX ,ECX
00407B90 E8 BBFCFFFF CALL unpacked.00407850
00407B95 8BC6 MOV EAX ,ESI
00407B97 83C4 0C ADD ESP ,0C
00407B9A 5E POP ESI
00407B9B 5B POP EBX
00407B9C C3 RETN
/////////////
004029DC 53 PUSH EBX
004029DD 56 PUSH ESI
004029DE 57 PUSH EDI
004029DF 89C6 MOV ESI ,EAX
004029E1 50 PUSH EAX
004029E2 85C0 TEST EAX ,EAX
004029E4 74 73 JE SHORT unpacked.00402A59
004029E6 31C0 XOR EAX ,EAX
004029E8 31DB XOR EBX ,EBX
004029EA BF CCCCCC0C MOV EDI ,0CCCCCCC
004029EF 8A1E MOV BL ,BYTE PTR DS :[ESI ] ; 逐个取注册码
004029F1 46 INC ESI
004029F2 80FB 20 CMP BL ,20 ; 是否为20
004029F5 ^ 74 F8 JE SHORT unpacked.004029EF
004029F7 B5 00 MOV CH ,0
004029F9 80FB 2D CMP BL ,2D ; 是否为2D
004029FC 74 69 JE SHORT unpacked.00402A67
004029FE 80FB 2B CMP BL ,2B ; 是否为2B
00402A01 74 66 JE SHORT unpacked.00402A69
00402A03 80FB 24 CMP BL ,24 ; 是否为24
00402A06 74 66 JE SHORT unpacked.00402A6E
00402A08 80FB 78 CMP BL ,78 ; 是否为78
00402A0B 74 61 JE SHORT unpacked.00402A6E
00402A0D 80FB 58 CMP BL ,58 ; 是否为58
00402A10 74 5C JE SHORT unpacked.00402A6E
00402A12 80FB 30 CMP BL ,30 ; 是否为30
00402A15 75 13 JNZ SHORT unpacked.00402A2A
00402A17 8A1E MOV BL ,BYTE PTR DS :[ESI ]
00402A19 46 INC ESI
00402A1A 80FB 78 CMP BL ,78
00402A1D 74 4F JE SHORT unpacked.00402A6E
00402A1F 80FB 58 CMP BL ,58
00402A22 74 4A JE SHORT unpacked.00402A6E
00402A24 84DB TEST BL ,BL
00402A26 74 20 JE SHORT unpacked.00402A48
00402A28 EB 04 JMP SHORT unpacked.00402A2E
00402A2A 84DB TEST BL ,BL ; 是否为0
00402A2C 74 34 JE SHORT unpacked.00402A62
00402A2E 80EB 30 SUB BL ,30 ; 减30H
00402A31 80FB 09 CMP BL ,9 ; 是否大于9
00402A34 77 2C JA SHORT unpacked.00402A62
00402A36 39F8 CMP EAX ,EDI
00402A38 77 28 JA SHORT unpacked.00402A62
00402A3A 8D0480 LEA EAX ,DWORD PTR DS :[EAX +EAX *4]
00402A3D 01C0 ADD EAX ,EAX
00402A3F 01D8 ADD EAX ,EBX ; 加这个值
00402A41 8A1E MOV BL ,BYTE PTR DS :[ESI ]
00402A43 46 INC ESI ; 取下一位
00402A44 84DB TEST BL ,BL ; 是否为0
00402A46 ^ 75 E6 JNZ SHORT unpacked.00402A2E
00402A48 FECD DEC CH
00402A4A 74 10 JE SHORT unpacked.00402A5C
00402A4C 85C0 TEST EAX ,EAX ; 结果是否为0
00402A4E 7C 12 JL SHORT unpacked.00402A62
00402A50 59 POP ECX
00402A51 31F6 XOR ESI ,ESI
00402A53 8932 MOV DWORD PTR DS :[EDX ],ESI
00402A55 5F POP EDI
00402A56 5E POP ESI
00402A57 5B POP EBX
00402A58 C3 RETN
==============判断新码的有效性,并转成相应的10进制数字
00444D07 |. 8A12 MOV DL ,BYTE PTR DS :[EDX ] ; 取注册码第一位
00444D09 |. E8 C6EDFBFF CALL unpacked.00403AD4
00444D0E |. 8B45 C4 MOV EAX ,DWORD PTR SS :[EBP -3C]
00444D11 |. E8 4E2EFCFF CALL unpacked.00407B64
00444D16 |. 8BD3 MOV EDX ,EBX
00444D18 |. E8 03FEFFFF CALL unpacked.00444B20 ; 取该注册码的6次方
00444D1D |. 8BF8 MOV EDI ,EAX ; 计算的结果放入EDI
00444D1F |. 8D45 C0 LEA EAX ,DWORD PTR SS :[EBP -40]
00444D22 |. 8B55 FC MOV EDX ,DWORD PTR SS :[EBP -4]
00444D25 |. 8A52 01 MOV DL ,BYTE PTR DS :[EDX +1] ; 取注册码第2位
00444D28 |. E8 A7EDFBFF CALL unpacked.00403AD4
00444D2D |. 8B45 C0 MOV EAX ,DWORD PTR SS :[EBP -40]
00444D30 |. E8 2F2EFCFF CALL unpacked.00407B64
00444D35 |. 8BD3 MOV EDX ,EBX
00444D37 |. E8 E4FDFFFF CALL unpacked.00444B20 ; 取该注册码的6次方
00444D3C |. 03F8 ADD EDI ,EAX ; 加上上次的计算结果
/////////////////
00444B20 /$ 8BC8 MOV ECX ,EAX ; 该注册码放入ECX
00444B22 |. 83EA 02 SUB EDX ,2 ; EDX=7-2=5
00444B25 |. 7C 07 JL SHORT unpacked.00444B2E ; 小于0就跳走
00444B27 |. 42 INC EDX ; EDX=5+1
00444B28 |> 0FAFC1 /IMUL EAX ,ECX ; EAX=EAX*ECX
00444B2B |. 4A |DEC EDX ; EDX=EDX-1
00444B2C |.^ 75 FA \JNZ SHORT unpacked.00444B28 ; EDX不伪则继续循环
00444B2E \> C3 RETN
=============逐个取新码,将每个数字6次方后相加
00444DD9 |. 3BF7 CMP ESI ,EDI ; EDI为最终相加的结果,ESI为新码转16进制后的值,两者是否相等
00444DDB |. 0F84 4F050000 JE unpacked.00445330 ; 相等的话就跳向成功
============判断新码转16进制后的值和它的每位数值的7次方和是否相等,相等话就成功
第二种情况注册码也必须为数字,长度必须为10位:CMP EBX ,0A,第3和第7位必须为“-”号:CMP BYTE PTR DS :[EAX +2],2D,CMP BYTE PTR DS :[EAX +6],2D。
去“-”号的注册码对应的10进制数值等于每位注册码对应的10进制数字的8次方的和。注册码形式:XX-XXX-XXX。
第二种情况注册码也必须为数字,长度必须为10位:CMP EBX ,0B,第4和第8位必须为“-”号:CMP BYTE PTR DS :[EAX +3],2D,CMP BYTE PTR DS :[EAX +7],2D。
去“-”号的注册码对应的10进制数值等于每位注册码对应的10进制数字的9次方的和。注册码形式:XXX-XXX-XXX。
--------------------------------------------------------------------------------
【经验总结】
算法基本上是这样:注册码必须为数字,而且含有两个“-”号,去“-”号的注册码对应的10进制数值等于每位注册码对应
的10进制数字的注册码长度(除“-”号后)次方的和。
比如:1741725=1的7次方+7的7次方+4的7次方+1的7次方+7的7次方+2的7次方+5的7次方
算法容易分析,但是写注册机比较难,而且作者要求: find all valid serial numbers 。
#include <stdio.h>
#include <stdlib.h>
#include <string .h>
#define power(t) t*t*t*t*t*t*t
const int M=1000000;
const int N=9999999;
int vaild(int m)
{
int r,t=m,sum=0;
while (m)
{
r=m%10;
m/=10;
sum+=power(r);
}
return sum==t?1:0;
}
int main()
{
int s;
char sn[50]={0};
printf ("keygen for FrostyKid's Crackme3.\n" );
printf ("please wait moment...\n\n" );
for (s=M;s<N;s++)
{
if (vaild(s))
{
_itoa(s,sn,10);
printf ("%c%c-%c%c%c-%c%c\n" ,sn[0],sn[1],sn[2],sn[3],sn[4],sn[5],sn[6]);
}
}
printf ("these are all valid serial numbers. enjoy it! " );
getchar(); ;
}
求出的结果为:
17-417-25
42-108-18
98-008-17
99-263-15
24-678-050
24-678-051
88-593-477
146-511-208
472-335-975
534-494-836
912-985-153
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2006年08月29日
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
上传的附件: