无壳保护,直接用OD加载后,直接运行。试注册,有提示:“Invalid registration code!”
查找字符串:
文本字符串参考位于 MP3Strea:CODE,项目 9555
地址=00535F7A
反汇编=mov edx,MP3Strea.005360DC
文本字符串=UNICODE "Invalid registration code!"
双击来到这里:
00535F56 |> \8BC3 mov eax,ebx
00535F58 |. E8 B7010000 call MP3Strea.00536114
00535F5D |. 85C0 test eax,eax
00535F5F |. 74 19 je short MP3Strea.00535F7A
00535F61 |. BA 5C605300 mov edx,MP3Strea.0053605C ; UNICODE "Thank you for registration! All limitations are removed now."
00535F66 |. 8B83 80030000 mov eax,dword ptr ds:[ebx+380]
00535F6C |. E8 238FFAFF call MP3Strea.004DEE94
00535F71 |. 8BC3 mov eax,ebx
00535F73 |. E8 84030000 call MP3Strea.005362FC
00535F78 |. EB 1E jmp short MP3Strea.00535F98
00535F7A |> BA DC605300 mov edx,MP3Strea.005360DC ; UNICODE "Invalid registration code!"
初步判断,发现:call MP3Strea.00536114是关键CALL,返回值EAX,如果EAX==0,则显示注册失败,反之则注册成功。
不过,我们先不管这些,直接在段首下断,然后重新试注册。
00535E9C /. 55 push ebp
00535E9D |. 8BEC mov ebp,esp
00535E9F |. 33C9 xor ecx,ecx
00535EA1 |. 51 push ecx
00535EA2 |. 51 push ecx
00535EA3 |. 51 push ecx
00535EA4 |. 51 push ecx
00535EA5 |. 53 push ebx
00535EA6 |. 8BD8 mov ebx,eax
00535EA8 |. 33C0 xor eax,eax
00535EAA |. 55 push ebp
00535EAB |. 68 C65F5300 push MP3Strea.00535FC6
00535EB0 |. 64:FF30 push dword ptr fs:[eax]
00535EB3 |. 64:8920 mov dword ptr fs:[eax],esp
00535EB6 |. 8D55 F8 lea edx,dword ptr ss:[ebp-8]
00535EB9 |. 8B83 50030000 mov eax,dword ptr ds:[ebx+350]
00535EBF |. E8 B8A8F2FF call MP3Strea.0046077C ; 取用户名
00535EC4 |. 8B45 F8 mov eax,dword ptr ss:[ebp-8]
00535EC7 |. 8D55 FC lea edx,dword ptr ss:[ebp-4]
00535ECA |. E8 7936EDFF call MP3Strea.00409548
00535ECF |. 8B55 FC mov edx,dword ptr ss:[ebp-4]
00535ED2 |. 8D83 70040000 lea eax,dword ptr ds:[ebx+470]
00535ED8 |. E8 E7EDECFF call MP3Strea.00404CC4
00535EDD |. 8D55 F0 lea edx,dword ptr ss:[ebp-10]
00535EE0 |. 8B83 58030000 mov eax,dword ptr ds:[ebx+358]
00535EE6 |. E8 91A8F2FF call MP3Strea.0046077C ; 取注册码
00535EEB |. 8B45 F0 mov eax,dword ptr ss:[ebp-10]
00535EEE |. 8D55 F4 lea edx,dword ptr ss:[ebp-C]
00535EF1 |. E8 5236EDFF call MP3Strea.00409548
00535EF6 |. 8B55 F4 mov edx,dword ptr ss:[ebp-C]
00535EF9 |. 8D83 74040000 lea eax,dword ptr ds:[ebx+474]
00535EFF |. E8 C0EDECFF call MP3Strea.00404CC4
00535F04 |. 83BB 70040000 00 cmp dword ptr ds:[ebx+470],0 ; 判断用户名是否为空
00535F0B |. 75 20 jnz short MP3Strea.00535F2D
00535F0D |. BA D85F5300 mov edx,MP3Strea.00535FD8 ; UNICODE "Please input your name!"
00535F12 |. 8B83 80030000 mov eax,dword ptr ds:[ebx+380]
00535F18 |. E8 778FFAFF call MP3Strea.004DEE94
00535F1D |. 8B83 50030000 mov eax,dword ptr ds:[ebx+350]
00535F23 |. 8B10 mov edx,dword ptr ds:[eax]
00535F25 |. FF92 C4000000 call dword ptr ds:[edx+C4]
00535F2B |. EB 6B jmp short MP3Strea.00535F98
00535F2D |> 83BB 74040000 00 cmp dword ptr ds:[ebx+474],0 ; 判断注册码是否为空
00535F34 |. 75 20 jnz short MP3Strea.00535F56
00535F36 |. BA 0C605300 mov edx,MP3Strea.0053600C ; UNICODE "Please input your registration code!"
00535F3B |. 8B83 80030000 mov eax,dword ptr ds:[ebx+380]
00535F41 |. E8 4E8FFAFF call MP3Strea.004DEE94
00535F46 |. 8B83 58030000 mov eax,dword ptr ds:[ebx+358]
00535F4C |. 8B10 mov edx,dword ptr ds:[eax]
00535F4E |. FF92 C4000000 call dword ptr ds:[edx+C4]
00535F54 |. EB 42 jmp short MP3Strea.00535F98
00535F56 |> 8BC3 mov eax,ebx
单步跟过,发现上面只是取用户名与注册码,然后比较用户名与注册码是否为空。看来刚才的判断:
call MP3Strea.00536114是关键CALL是正确的了,我们F7跟进:
00536114 /$ 55 push ebp
00536115 |. 8BEC mov ebp,esp
00536117 |. B9 05000000 mov ecx,5
0053611C |> 6A 00 /push 0
0053611E |. 6A 00 |push 0
00536120 |. 49 |dec ecx
00536121 |.^ 75 F9 \jnz short MP3Strea.0053611C
00536123 |. 51 push ecx
00536124 |. 53 push ebx
00536125 |. 56 push esi
00536126 |. 57 push edi
00536127 |. 8BD8 mov ebx,eax
00536129 |. 33C0 xor eax,eax
0053612B |. 55 push ebp
0053612C |. 68 DE625300 push MP3Strea.005362DE
00536131 |. 64:FF30 push dword ptr fs:[eax]
00536134 |. 64:8920 mov dword ptr fs:[eax],esp
00536137 |. 33FF xor edi,edi
00536139 |. 8D45 FC lea eax,dword ptr ss:[ebp-4]
0053613C |. 8B93 70040000 mov edx,dword ptr ds:[ebx+470]
00536142 |. E8 C1EBECFF call MP3Strea.00404D08
00536147 |. 8D45 F8 lea eax,dword ptr ss:[ebp-8]
0053614A |. 8B93 74040000 mov edx,dword ptr ds:[ebx+474]
00536150 |. E8 B3EBECFF call MP3Strea.00404D08
00536155 |. 8B45 F8 mov eax,dword ptr ss:[ebp-8]
00536158 |. E8 E3EDECFF call MP3Strea.00404F40 ; 取注册码长度
0053615D |. 83F8 16 cmp eax,16 ; 与0x16比较
00536160 |. 0F85 5D010000 jnz MP3Strea.005362C3 ; 不等则跳转清0退出,提示注册失败
00536166 |. 8D4D EC lea ecx,dword ptr ss:[ebp-14]
00536169 |. BA 03000000 mov edx,3
0053616E |. 8B83 74040000 mov eax,dword ptr ds:[ebx+474]
00536174 |. E8 0332F0FF call MP3Strea.0043937C ; 取注册码前3个字符
00536179 |. 8B45 EC mov eax,dword ptr ss:[ebp-14]
0053617C |. BA F8625300 mov edx,MP3Strea.005362F8 ; ASCII "EXP"
00536181 |. E8 06EFECFF call MP3Strea.0040508C ; 与固定字符串“EXP”比较
00536186 |. 0F85 37010000 jnz MP3Strea.005362C3 ; 不等则跳转清0退出,提示注册失败
0053618C |. 8D4D F8 lea ecx,dword ptr ss:[ebp-8]
0053618F |. BA 13000000 mov edx,13
00536194 |. 8B83 74040000 mov eax,dword ptr ds:[ebx+474]
0053619A |. E8 4D32F0FF call MP3Strea.004393EC ; 取余下的0x13位注册码
0053619F |. 837D FC 00 cmp dword ptr ss:[ebp-4],0 ; 再次测试用户名是否为空
005361A3 |. 0F84 1A010000 je MP3Strea.005362C3 ; 为空则跳转清0退出,提示注册失败
005361A9 |. 837D F8 00 cmp dword ptr ss:[ebp-8],0 ; 再次测试注册码是否为空
005361AD |. 0F84 10010000 je MP3Strea.005362C3 ; 为空则跳转清0退出,提示注册失败
005361B3 |. 33F6 xor esi,esi
005361B5 |> 8B45 F8 /mov eax,dword ptr ss:[ebp-8] ; 让EAX指向注册码
005361B8 |. 8A1C30 |mov bl,byte ptr ds:[eax+esi] ; 以ESI为索引
005361BB |. 80FB 2D |cmp bl,2D ; 按位取ASCII值,与0x2D,即"-"比较
005361BE |. 74 15 |je short MP3Strea.005361D5 ; 不等则继续,相等则跳过,继续下一过
005361C0 |. 8D45 E8 |lea eax,dword ptr ss:[ebp-18]
005361C3 |. 8BD3 |mov edx,ebx
005361C5 |. E8 8EECECFF |call MP3Strea.00404E58
005361CA |. 8B55 E8 |mov edx,dword ptr ss:[ebp-18]
005361CD |. 8D45 F4 |lea eax,dword ptr ss:[ebp-C]
005361D0 |. E8 73EDECFF |call MP3Strea.00404F48
005361D5 |> 46 |inc esi
005361D6 |. 83FE 13 |cmp esi,13
005361D9 |.^ 75 DA \jnz short MP3Strea.005361B5
//这个循环的作用是过滤剩下的19位注册码中含有的字符"-"后,生成一个新的字符串:str1
005361DB |. 8D45 F8 lea eax,dword ptr ss:[ebp-8]
005361DE |. 8B55 F4 mov edx,dword ptr ss:[ebp-C]
005361E1 |. E8 22EBECFF call MP3Strea.00404D08
005361E6 |. 8D45 F4 lea eax,dword ptr ss:[ebp-C]
005361E9 |. E8 82EAECFF call MP3Strea.00404C70
005361EE |. 8B45 F8 mov eax,dword ptr ss:[ebp-8]
005361F1 |. E8 4AEDECFF call MP3Strea.00404F40 ; 取str1的长度
005361F6 |. 83F8 10 cmp eax,10 ; 与0x10比较
005361F9 |. 0F85 C4000000 jnz MP3Strea.005362C3 ; 不等则跳转清0退出,提示注册失败
//这样一来就表明,后面的19位注册码里,必须含有3个"-"
005361FF |. 33F6 xor esi,esi ; 清0ESI,以ESI为索引
00536201 |> 8BC6 /mov eax,esi
00536203 |. 25 01000080 |and eax,80000001 ; 将索引与0x80000001进行AND运算
00536208 |. 79 05 |jns short MP3Strea.0053620F
0053620A |. 48 |dec eax
0053620B |. 83C8 FE |or eax,FFFFFFFE
0053620E |. 40 |inc eax
0053620F |> 85C0 |test eax,eax
00536211 |. 75 1B |jnz short MP3Strea.0053622E
00536213 |. 8D45 E4 |lea eax,dword ptr ss:[ebp-1C]
00536216 |. 8B55 F8 |mov edx,dword ptr ss:[ebp-8]
00536219 |. 8A1432 |mov dl,byte ptr ds:[edx+esi]
0053621C |. E8 37ECECFF |call MP3Strea.00404E58
00536221 |. 8B55 E4 |mov edx,dword ptr ss:[ebp-1C]
00536224 |. 8D45 F0 |lea eax,dword ptr ss:[ebp-10]
00536227 |. E8 1CEDECFF |call MP3Strea.00404F48
0053622C |. EB 19 |jmp short MP3Strea.00536247
0053622E |> 8D45 E0 |lea eax,dword ptr ss:[ebp-20]
00536231 |. 8B55 F8 |mov edx,dword ptr ss:[ebp-8]
00536234 |. 8A1432 |mov dl,byte ptr ds:[edx+esi]
00536237 |. E8 1CECECFF |call MP3Strea.00404E58
0053623C |. 8B55 E0 |mov edx,dword ptr ss:[ebp-20]
0053623F |. 8D45 F4 |lea eax,dword ptr ss:[ebp-C]
00536242 |. E8 01EDECFF |call MP3Strea.00404F48
00536247 |> 46 |inc esi
00536248 |. 83FE 10 |cmp esi,10
0053624B |.^ 75 B4 \jnz short MP3Strea.00536201
//这个循环是上面得到的Str1按奇偶位,分成2个字符串:
//奇数位为:oddStr
//偶数位为:evenStr
0053624D |. 8D45 FC lea eax,dword ptr ss:[ebp-4]
00536250 |. E8 1BEAECFF call MP3Strea.00404C70
00536255 |. 33F6 xor esi,esi
00536257 |> 8D45 DC /lea eax,dword ptr ss:[ebp-24]
0053625A |. BA 08000000 |mov edx,8
0053625F |. 2BD6 |sub edx,esi
00536261 |. 8B4D F4 |mov ecx,dword ptr ss:[ebp-C]
00536264 |. 8A5411 FF |mov dl,byte ptr ds:[ecx+edx-1]
00536268 |. E8 EBEBECFF |call MP3Strea.00404E58
0053626D |. 8B55 DC |mov edx,dword ptr ss:[ebp-24]
00536270 |. 8D45 FC |lea eax,dword ptr ss:[ebp-4]
00536273 |. E8 D0ECECFF |call MP3Strea.00404F48
00536278 |. 46 |inc esi
00536279 |. 83FE 08 |cmp esi,8
0053627C |.^ 75 D9 \jnz short MP3Strea.00536257 ; 对偶数位字符串:evenStr进行逆序
0053627E |. 8D55 D8 lea edx,dword ptr ss:[ebp-28] ; 得revEvenStr
00536281 |. 8B45 F0 mov eax,dword ptr ss:[ebp-10]
00536284 |. E8 E757FFFF call MP3Strea.0052BA70 ; 对奇数位oddStr取MD5值
00536289 |. 8B55 D8 mov edx,dword ptr ss:[ebp-28]
0053628C |. 8D45 F0 lea eax,dword ptr ss:[ebp-10]
0053628F |. E8 74EAECFF call MP3Strea.00404D08
00536294 |. 8D4D D4 lea ecx,dword ptr ss:[ebp-2C]
00536297 |. BA 08000000 mov edx,8
0053629C |. 8B45 F0 mov eax,dword ptr ss:[ebp-10]
0053629F |. E8 CC31F0FF call MP3Strea.00439470 ; 截取MD5值的后8位,得Md5OddStr
005362A4 |. 8B55 D4 mov edx,dword ptr ss:[ebp-2C]
005362A7 |. 8D45 F0 lea eax,dword ptr ss:[ebp-10]
005362AA |. E8 59EAECFF call MP3Strea.00404D08
005362AF |. 8B45 FC mov eax,dword ptr ss:[ebp-4] ; revEvenStr
005362B2 |. 8B55 F0 mov edx,dword ptr ss:[ebp-10]
005362B5 |. E8 D2EDECFF call MP3Strea.0040508C ; 将revEvenStr与Md5OddStr比较
005362BA |. 75 05 jnz short MP3Strea.005362C1 ; 相等则不跳
005362BC |. 83CF FF or edi,FFFFFFFF ; 置EDI值为0xFFFFFFFF
005362BF |. EB 02 jmp short MP3Strea.005362C3
005362C1 |> 33FF xor edi,edi ; 否则清0EDI
005362C3 |> 33C0 xor eax,eax
005362C5 |. 5A pop edx
005362C6 |. 59 pop ecx
005362C7 |. 59 pop ecx
005362C8 |. 64:8910 mov dword ptr fs:[eax],edx
005362CB |. 68 E5625300 push MP3Strea.005362E5
005362D0 |> 8D45 D4 lea eax,dword ptr ss:[ebp-2C]
005362D3 |. BA 0B000000 mov edx,0B
005362D8 |. E8 B7E9ECFF call MP3Strea.00404C94
005362DD \. C3 retn
005362DE .^ E9 F1E2ECFF jmp MP3Strea.004045D4
005362E3 .^ EB EB jmp short MP3Strea.005362D0
005362E5 . 8BC7 mov eax,edi
005362E7 . 5F pop edi
005362E8 . 5E pop esi
005362E9 . 5B pop ebx
005362EA . 8BE5 mov esp,ebp
005362EC . 5D pop ebp
005362ED . C3 retn
由上分析,可得看到:
1、用户名对没有参与运算,只需要用户名不为空即可.
2、注册码的长度为22位,且前3位固定为“EXP”
3、后19位注册码中有3个“-”字符,位置不固定
好了,开始编写KeyGen代码了,呵呵,如下:
#include
#include
#include
#include"md5.h"
const char strC[]="0123456789ABCDEF";
int main(){
srand((unsigned)time(NULL));
//第一步:随机生成奇数位注册码
unsigned char OddStr[9]={0};
for(int i=0;i<8;i++){
int tmp=(int)(((double) rand() / (double) RAND_MAX) * 0xF + 0);
OddStr[i]=strC[tmp];
}
printf("OddStr=%s\n",OddStr); //测试输出
//第二步:获取奇数位注册码的MD5值
unsigned char szHash[256]={0};
char szBuffer[256]={0};
MD5_CTX context;
MD5Init(&context);
MD5Update(&context, OddStr, 8);
MD5Final(szHash, &context);
for(int i=0; i < 16; i++) // 将szHash[]中的16进制转换成字符形式显示
wsprintf(&szBuffer[i*2], "%02X", *(byte*)(szHash+i));
printf("Md5OddStr=%s\n",szBuffer); //测试输出
//第三步:获取偶数位的注册码的逆序值
char revEvenStr[9]={0};
strncpy(revEvenStr,&szBuffer[24],8);
printf("revEvenStr=%s\n",revEvenStr); //测试输出
//第四步:获取偶数位的注册码
char EvenStr[9]={0};
for(int i=0;i<8;i++)
EvenStr[i]=revEvenStr[8-i-1];
printf("EvenStr=%s\n",EvenStr); //测试输出
//第5步:合成最终注册码的后19位
char strCode[20]={0};
strCode[2]='-';
strCode[7]='-';
strCode[12]='-';
int j=0,k=0;
for(int i=0;i<18;){
if(strCode[i]=='-')
i++;
strCode[i]=OddStr[j];
i++;
if(strCode[i]=='-')
i++;
strCode[i]=EvenStr[k];
i++;
j++;
k++;
}
//第六步:直接拼接上前3位的固定字符串以输出
printf("你的注册码是:EXP%s\n",strCode);
return 0;
}
测试运行结果:
E:\PlusCode\MD5\MD5(cpp)>KeyGen
OddStr=5392B953
Md5OddStr=8CC53540F9E78BB99301CFB0EFC0041A
revEvenStr=EFC0041A
EvenStr=A1400CFE
你的注册码是:EXP5A-3194-20B0-9C5F3E
学习学习了