Articles

Filter Meister 1.0 beta 7序列号算法分析

Filter Meister 是一个制作 Photoshop 插件的软件。大概半年前一个朋友想用这款软件编译个 Photoshop的插件,可是苦于网上一直找不到序列号,所以让我帮忙看看。由于这款软件序列号算法很简单,所以我当时随便帮朋友搞出了个可用的序列号。但是我心里一直想写一个算号器出来的,由于工作繁忙,此事便一直拖到了今天。

下面我大致说一下这个软件序列号的计算方法:

0BB27D15 PUSH AfhFM04B.0BB77B4C ; ASCII "forever"
0BB27D1A PUSH AfhFM04B.0BB96240 ; ASCII "Free"
0BB27D1F PUSH AfhFM04B.0BB96140 ; ASCII "EROSiON"
0BB27D24 CALL AfhFM04B.0BB27E00 ; 第一次验证序列号,正确则跳转
0BB27D29 ADD ESP,0C
0BB27D2C TEST EAX,EAX
0BB27D2E JNZ SHORT AfhFM04B.0BB27D98
0BB27D30 PUSH AfhFM04B.0BB77B44 ; ASCII "1999"
0BB27D35 PUSH AfhFM04B.0BB96240 ; ASCII "Free"
0BB27D3A PUSH AfhFM04B.0BB96140 ; ASCII "EROSiON"
0BB27D3F CALL AfhFM04B.0BB27E00 ; 第二次验证序列号,正确则跳转
0BB27D44 ADD ESP,0C
0BB27D47 TEST EAX,EAX
0BB27D49 JNZ SHORT AfhFM04B.0BB27D98
0BB27D4B PUSH AfhFM04B.0BB77B34 ; ASCII "until V2.0.0"
0BB27D50 PUSH AfhFM04B.0BB779E0 ; ASCII "F}tgp\a45Fepv|ty5Egp8gpyptfp5Zsspg"
0BB27D55 CALL AfhFM04B.0BB288C0
0BB27D5A ADD ESP,4
0BB27D5D PUSH EAX
0BB27D5E PUSH AfhFM04B.0BB96140 ; ASCII "EROSiON"
0BB27D63 CALL AfhFM04B.0BB27E00
0BB27D68 ADD ESP,0C
0BB27D6B TEST EAX,EAX
0BB27D6D JNZ SHORT AfhFM04B.0BB27D98 ; 第三次验证序列号,正确则跳转
0BB27D6F PUSH AfhFM04B.0BB77B34 ; ASCII "until V2.0.0"
0BB27D74 PUSH AfhFM04B.0BB779E0 ; ASCII "F}tgp\a45Fepv|ty5Egp8gpyptfp5Zsspg"
0BB27D79 CALL AfhFM04B.0BB288C0
0BB27D7E ADD ESP,4
0BB27D81 PUSH EAX
0BB27D82 PUSH AfhFM04B.0BB96240 ; ASCII "Free"
0BB27D87 CALL AfhFM04B.0BB27E00
0BB27D8C ADD ESP,0C
0BB27D8F MOV ESI,7
0BB27D94 TEST EAX,EAX
0BB27D96 JE SHORT AfhFM04B.0BB27D9D ; 第四次验证序列号,不正确则跳转
0BB27D98 MOV ESI,1
0BB27D9D CMP ESI,7
0BB27DA0 JNZ SHORT AfhFM04B.0BB27DC0
0BB27DA2 PUSH 64
0BB27DA4 CALL EBP
0BB27DA6 CMP ESI,ESI
0BB27DA8 JNZ SHORT AfhFM04B.0BB27DC0
0BB27DAA PUSH AfhFM04B.0BB77B0C; ASCII "Registration failed or expired. Retry?"
0BB27DAF CALL AfhFM04B.0BB1D7B0

所以,序列号的计算方法总共有四种,而前两种是类似的,后两种也是类似的。我只分 析了前两种,大家有兴趣可以自行分析后两种方法,呵呵。

0BB27E00 SUB ESP,380
0BB27E06 MOV ECX,5
0BB27E0B XOR EAX,EAX
0BB27E0D LEA EDX,DWORD PTR SS:[ESP+7C]
0BB27E11 PUSH EBX
0BB27E12 PUSH ESI
0BB27E13 PUSH EDI
0BB27E14 MOV ESI,AfhFM04B.0BB77BCC ; ASCII "aaaa-bbbb-cccc-dddd"
0BB27E19 LEA EDI,DWORD PTR SS:[ESP+1C] ; 从上面很容易看出序列号的形式
0BB27E1D REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
0BB27E1F MOV EDI,DWORD PTR SS:[ESP+398]
0BB27E26 OR ECX,FFFFFFFF
0BB27E29 REPNE SCAS BYTE PTR ES:[EDI]
0BB27E2B NOT ECX
0BB27E2D SUB EDI,ECX
0BB27E2F MOV EAX,ECX
0BB27E31 MOV ESI,EDI
0BB27E33 SHR ECX,2
0BB27E36 MOV EDI,AfhFM04B.0BB96440 ; ASCII "until V2.0.0"
0BB27E3B REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
0BB27E3D MOV ECX,EAX
0BB27E3F XOR EAX,EAX
0BB27E41 AND ECX,3
0BB27E44 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
0BB27E46 MOV EDI,DWORD PTR SS:[ESP+390]
0BB27E4D OR ECX,FFFFFFFF
0BB27E50 REPNE SCAS BYTE PTR ES:[EDI]
0BB27E52 NOT ECX
0BB27E54 SUB EDI,ECX
0BB27E56 MOV EAX,ECX
0BB27E58 MOV ESI,EDI
0BB27E5A SHR ECX,2
0BB27E5D MOV EDI,EDX
0BB27E5F LEA EDX,DWORD PTR SS:[ESP+88]
0BB27E66 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
0BB27E68 MOV ECX,EAX
0BB27E6A XOR EAX,EAX
0BB27E6C AND ECX,3
0BB27E6F REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] ; 移动姓名"EROSiON"
0BB27E71 MOV EDI,AfhFM04B.0BB77998 ; ASCII "/*/"
0BB27E76 OR ECX,FFFFFFFF
0BB27E79 REPNE SCAS BYTE PTR ES:[EDI]
0BB27E7B NOT ECX
0BB27E7D SUB EDI,ECX
0BB27E7F MOV ESI,EDI
0BB27E81 MOV EBX,ECX
0BB27E83 MOV EDI,EDX
0BB27E85 OR ECX,FFFFFFFF
0BB27E88 REPNE SCAS BYTE PTR ES:[EDI]
0BB27E8A MOV ECX,EBX
0BB27E8C DEC EDI
0BB27E8D SHR ECX,2
0BB27E90 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] ; "EROSiON/*/"
0BB27E92 MOV ECX,EBX
0BB27E94 LEA EDX,DWORD PTR SS:[ESP+88]
0BB27E9B AND ECX,3
0BB27E9E REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
0BB27EA0 MOV EDI,DWORD PTR SS:[ESP+394]
0BB27EA7 OR ECX,FFFFFFFF
0BB27EAA REPNE SCAS BYTE PTR ES:[EDI]
0BB27EAC NOT ECX
0BB27EAE SUB EDI,ECX
0BB27EB0 MOV ESI,EDI
0BB27EB2 MOV EBX,ECX
0BB27EB4 MOV EDI,EDX
0BB27EB6 OR ECX,FFFFFFFF
0BB27EB9 REPNE SCAS BYTE PTR ES:[EDI]
0BB27EBB MOV ECX,EBX
0BB27EBD DEC EDI
0BB27EBE SHR ECX,2
0BB27EC1 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] ; "EROSiON/*/Free"
0BB27EC3 MOV ECX,EBX
0BB27EC5 LEA EDX,DWORD PTR SS:[ESP+88]
0BB27ECC AND ECX,3
0BB27ECF REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
0BB27ED1 MOV EDI,AfhFM04B.0BB7799C ; ASCII "-#="
0BB27ED6 OR ECX,FFFFFFFF
0BB27ED9 REPNE SCAS BYTE PTR ES:[EDI]
0BB27EDB NOT ECX
0BB27EDD SUB EDI,ECX
0BB27EDF MOV ESI,EDI
0BB27EE1 MOV EBX,ECX
0BB27EE3 MOV EDI,EDX
0BB27EE5 OR ECX,FFFFFFFF
0BB27EE8 LEA EDX,DWORD PTR SS:[ESP+88]
0BB27EEF REPNE SCAS BYTE PTR ES:[EDI]
0BB27EF1 MOV ECX,EBX
0BB27EF3 DEC EDI
0BB27EF4 SHR ECX,2
0BB27EF7 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] ; "EROSiON/*/Free-#="
0BB27EF9 MOV ECX,EBX
0BB27EFB AND ECX,3
0BB27EFE REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
0BB27F00 MOV EDI,AfhFM04B.0BB96440 ; ASCII "until V2.0.0"
0BB27F05 OR ECX,FFFFFFFF
0BB27F08 REPNE SCAS BYTE PTR ES:[EDI]
0BB27F0A NOT ECX
0BB27F0C SUB EDI,ECX
0BB27F0E MOV ESI,EDI
0BB27F10 MOV EBX,ECX
0BB27F12 MOV EDI,EDX
0BB27F14 OR ECX,FFFFFFFF
0BB27F17 REPNE SCAS BYTE PTR ES:[EDI]
0BB27F19 MOV ECX,EBX
0BB27F1B DEC EDI
0BB27F1C SHR ECX,2
0BB27F1F REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
0BB27F21 MOV ECX,EBX ; "EROSiON/*/Free-#=forever"
0BB27F23 AND ECX,3
0BB27F26 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
0BB27F28 LEA EDI,DWORD PTR SS:[ESP+88]
0BB27F2F OR ECX,FFFFFFFF
0BB27F32 REPNE SCAS BYTE PTR ES:[EDI]
0BB27F34 NOT ECX
0BB27F36 LEA EAX,DWORD PTR SS:[ESP+30]
0BB27F3A DEC ECX
0BB27F3B PUSH EAX
0BB27F3C MOV ESI,ECX
0BB27F3E CALL AfhFM04B.0BB6CE30
0BB27F43 ADD ESP,4
0BB27F46 LEA ECX,DWORD PTR SS:[ESP+88]
0BB27F4D LEA EDX,DWORD PTR SS:[ESP+30]
0BB27F51 PUSH ESI
0BB27F52 PUSH ECX
0BB27F53 PUSH EDX
0BB27F54 CALL AfhFM04B.0BB6CE60
0BB27F59 ADD ESP,0C
0BB27F5C LEA EAX,DWORD PTR SS:[ESP+30]
0BB27F60 LEA ECX,DWORD PTR SS:[ESP+C]
0BB27F64 PUSH EAX
0BB27F65 PUSH ECX
0BB27F66 CALL AfhFM04B.0BB6CF10 ; 此处是MD5算法
0BB27F6B ADD ESP,8
0BB27F6E XOR ECX,ECX
0BB27F70 LEA ESI,DWORD PTR SS:[ESP+1C]
0BB27F74 TEST ECX,ECX
0BB27F76 JE SHORT AfhFM04B.0BB27F89
0BB27F78 MOV EAX,ECX
0BB27F7A CDQ
0BB27F7B XOR EAX,EDX
0BB27F7D SUB EAX,EDX
0BB27F7F AND EAX,3
0BB27F82 XOR EAX,EDX
0BB27F84 SUB EAX,EDX
0BB27F86 JNZ SHORT AfhFM04B.0BB27F89
0BB27F88 INC ESI
0BB27F89 MOV DL,BYTE PTR SS:[ESP+ECX+C] ; 取出一个字节
0BB27F8D SHR EDX,1 ; 右移一位
0BB27F8F AND EDX,3F ; 只保留最低6位
0BB27F92 INC ESI
0BB27F93 INC ECX
0BB27F94 MOV AL,BYTE PTR DS:[EDX+BB779A0] ; 这里是一张表
0BB27F9A CMP ECX,10
0BB27F9D MOV BYTE PTR DS:[ESI-1],AL
0BB27FA0 JL SHORT AfhFM04B.0BB27F74
0BB27FA2 MOV ESI,AfhFM04B.0BB96020 ; ASCII "123456789"
0BB27FA7 LEA EAX,DWORD PTR SS:[ESP+1C] ; 这里是正确的序列号
0BB27FAB MOV DL,BYTE PTR DS:[EAX]
0BB27FAD MOV BL,BYTE PTR DS:[ESI]
0BB27FAF MOV CL,DL
0BB27FB1 CMP DL,BL ; 比较第一字节是否一致
0BB27FB3 JNZ SHORT AfhFM04B.0BB27FD3
0BB27FB5 TEST CL,CL
0BB27FB7 JE SHORT AfhFM04B.0BB27FCF
0BB27FB9 MOV DL,BYTE PTR DS:[EAX+1]
0BB27FBC MOV BL,BYTE PTR DS:[ESI+1]
0BB27FBF MOV CL,DL
0BB27FC1 CMP DL,BL
0BB27FC3 JNZ SHORT AfhFM04B.0BB27FD3
0BB27FC5 ADD EAX,2
0BB27FC8 ADD ESI,2
0BB27FCB TEST CL,CL
0BB27FCD JNZ SHORT AfhFM04B.0BB27FAB
0BB27FCF XOR EAX,EAX
0BB27FD1 JMP SHORT AfhFM04B.0BB27FD8
0BB27FD3 SBB EAX,EAX
0BB27FD5 SBB EAX,-1
0BB27FD8 TEST EAX,EAX
0BB27FDA JNZ AfhFM04B.0BB280F1
0BB27FE0 CALL AfhFM04B.0BB28520
0BB27FE5 TEST EAX,EAX
0BB27FE7 JE AfhFM04B.0BB280F1
0BB27FED MOV EAX,DWORD PTR SS:[ESP+C] ; 下面将正确的注册信息写入注册表
0BB27FF1 MOV ECX,DWORD PTR SS:[ESP+10]
0BB27FF5 MOV EDX,DWORD PTR SS:[ESP+14]
0BB27FF9 MOV ESI,DWORD PTR SS:[ESP+18]
0BB27FFD MOV DWORD PTR DS:[BB96558],EAX
0BB28002 XOR EAX,478F8A55
0BB28007 XOR ECX,948FB7A7
0BB2800D XOR EDX,6782FAC
0BB28013 XOR ESI,FF561302
0BB28019 MOV DWORD PTR DS:[BB96558],EAX
0BB2801E MOV DWORD PTR DS:[BB9655C],ECX
0BB28024 MOV DWORD PTR DS:[BB96560],EDX
0BB2802A MOV DWORD PTR DS:[BB96564],ESI
0BB28030 CALL AfhFM04B.0BB28100
0BB28035 PUSH 10
0BB28037 PUSH AfhFM04B.0BB96130
0BB2803C PUSH AfhFM04B.0BB77BC4 ; ASCII "Key1"
0BB28041 PUSH AfhFM04B.0BB96540 ; ASCII "0.4.21"
0BB28046 PUSH AfhFM04B.0BB77BA0 ; ASCII "SOFTWARE\AFH Systems\FilterMeister"
0BB2804B PUSH 80000002
0BB28050 CALL AfhFM04B.0BB6DB50
0BB28055 ADD ESP,8
0BB28058 PUSH EAX
0BB28059 CALL AfhFM04B.0BB6DB50
0BB2805E ADD ESP,8
0BB28061 PUSH EAX
0BB28062 CALL AfhFM04B.0BB6DE00
0BB28067 ADD ESP,10
0BB2806A PUSH 10
0BB2806C PUSH AfhFM04B.0BB96558
0BB28071 PUSH AfhFM04B.0BB77B98 ; ASCII "Key2"
0BB28076 PUSH AfhFM04B.0BB96540 ; ASCII "0.4.21"
0BB2807B PUSH AfhFM04B.0BB77BA0 ; ASCII "SOFTWARE\AFH Systems\FilterMeister"
0BB28080 PUSH 80000002
0BB28085 CALL AfhFM04B.0BB6DB50
0BB2808A ADD ESP,8
0BB2808D PUSH EAX
0BB2808E CALL AfhFM04B.0BB6DB50
0BB28093 ADD ESP,8
0BB28096 PUSH EAX
0BB28097 CALL AfhFM04B.0BB6DE00
0BB2809C MOV EDI,AfhFM04B.0BB96440 ; ASCII "until V2.0.0"
0BB280A1 OR ECX,FFFFFFFF
0BB280A4 XOR EAX,EAX
0BB280A6 ADD ESP,10
0BB280A9 REPNE SCAS BYTE PTR ES:[EDI]
0BB280AB NOT ECX
0BB280AD DEC ECX
0BB280AE PUSH ECX
0BB280AF PUSH AfhFM04B.0BB96440 ; ASCII "until V2.0.0"
0BB280B4 PUSH AfhFM04B.0BB77B90 ; ASCII "Key3"
0BB280B9 PUSH AfhFM04B.0BB96540 ; ASCII "0.4.21"
0BB280BE PUSH AfhFM04B.0BB77BA0 ; ASCII "SOFTWARE\AFH Systems\FilterMeister"
0BB280C3 PUSH 80000002
0BB280C8 CALL AfhFM04B.0BB6DB50
0BB280CD ADD ESP,8
0BB280D0 PUSH EAX
0BB280D1 CALL AfhFM04B.0BB6DB50
0BB280D6 ADD ESP,8
0BB280D9 PUSH EAX
0BB280DA CALL AfhFM04B.0BB6DE00
0BB280DF ADD ESP,10
0BB280E2 MOV EAX,1 ; 序列号正确,EAX = 1
0BB280E7 POP EDI
0BB280E8 POP ESI
0BB280E9 POP EBX
0BB280EA ADD ESP,380
0BB280F0 RETN
0BB280F1 POP EDI ; 序列号错误,EAX = 0
0BB280F2 POP ESI
0BB280F3 XOR EAX,EAX
0BB280F5 POP EBX
0BB280F6 ADD ESP,380
0BB280FC RETN

上面所说的那张表如下:

0 0123456789ABCDEF
1 GHIJKLMNOPQRSTUV
2 WXYZabcdefghijkl
3 mnopqrstuvwxyzQW

下面总结一下这个算法。

1. 首先将姓名和公司组合如下:

姓名/*/公司-#=forever(或者1999)
EROSiON/*/Free-#=forever

2. 计算上述字符串的MD5值:

MD5(EROSiON/*/Free-#=forever)
= 9D A5 85 73 D5 BE 15 C0 CC EA FD 92 E7 80 61 5E

3.将MD5值的没一字节右移一位:

9D A5 85 73 D5 BE 15 C0 CC EA FD 92 E7 80 61 5E shr 1
= 4E 52 42 39 6A 5F 0A 60 66 75 7E 49 73 40 30 2F

4.上述每一字节与3F进行与操作:

4E 52 42 39 6A 5F 0A 60 66 75 7E 49 73 40 30 2F and 3F…3F
= 0E 12 02 39 2A 1F 0A 20 26 35 3E 09 33 00 30 2F

5.从表格中取相应的字符:

E I 2 v g V A W c r Q 9 p 0 m l

对应的序列号就是:EI2v-gVAW-crQ9-p0ml。