【标题】EmEditor 5.00.1 注册算法分析
【作者】forever[RCT]
【语言】VC8
【保护】无壳,注册码
【难度】简单
【工具】ollydbg
【简介】一个不用多说的强大的编辑工具。该语言文件汉化它所支持的相关 Windows 平台上的这个版本。
        EmEditor Professional/Standard v5 只支持 Windows 2003/XP/2000,不再支持 Windows Me/98 。
【正文】
           写这个帖子时不由得赞叹:ollydbg的功能就是强大。如果选择一个合适的工具将会事半功倍。
           这个软件算法简单,找关键点费了点时间。
           注册码格式为 XXXX-XXXX-XXXX-XXXX。随便输入1111-2222-3333-4444点注册会弹出一个对话
       框提示key无效。你可以下断点 bp MessageBoxW 拦截下来。不过这样分析要花些时间。我下的断点
       是 bp GetDlgItemTextW。输入注册码点注册后断下来,返回到一个DLL里。主程序调用一个DLL来弹出
       注册对话框的。在DLL里把注册码写入了注册表。因此我们接着下断点RegQueryValueExW,拦截在下面:


01027B0F  |.  8D45 FC       LEA EAX,DWORD PTR SS:[EBP-4]
01027B12  |.  50            PUSH EAX                                 ; /pBufSize
01027B13  |.  8D45 F0       LEA EAX,DWORD PTR SS:[EBP-10]            ; |
01027B16  |.  50            PUSH EAX                                 ; |Buffer
01027B17  |.  8D45 F8       LEA EAX,DWORD PTR SS:[EBP-8]             ; |
01027B1A  |.  50            PUSH EAX                                 ; |pValueType
01027B1B  |.  57            PUSH EDI                                 ; |Reserved => NULL
01027B1C  |.  8D45 B0       LEA EAX,DWORD PTR SS:[EBP-50]            ; |
01027B1F  |.  50            PUSH EAX                                 ; |ValueName
01027B20  |.  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hKey
01027B23  |.  FFD6          CALL ESI                                 ; \RegQueryValueExW
01027B25  |.  85C0          TEST EAX,EAX
01027B27  |.  75 28         JNZ SHORT <loc_1027B51>
01027B29  |.  0FB745 F0     MOVZX EAX,WORD PTR SS:[EBP-10]           ;  第一组
01027B2D  |.  6A 0A         PUSH 0A
01027B2F  |.  99            CDQ
01027B30  |.  59            POP ECX
01027B31  |.  F7F9          IDIV ECX                                 ;  除以10
01027B33  |.  3D B5000000   CMP EAX,0B5                              ;  除数是否等于0xB5
01027B38  |.  75 12         JNZ SHORT <loc_1027B4C>                  ;  不等则失败
01027B3A  |.  0FB77D F6     MOVZX EDI,WORD PTR SS:[EBP-A]            ;  第四组保存到DI
01027B3E  |.  8D75 F0       LEA ESI,DWORD PTR SS:[EBP-10]
01027B41  |.  E8 B7920100   CALL <sub_1040DFD>                       ;  调用验证注册码的函数
01027B46  |.  66:3B7D F6    CMP DI,WORD PTR SS:[EBP-A]               ;  比较计算的结果和第四组注册码是否相等
01027B4A  |.  74 07         JE SHORT <loc_1027B53>
01027B4C >|>  83C8 FF       OR EAX,FFFFFFFF                          ;  loc_1027B4C
01027B4F  |.  EB 02         JMP SHORT <loc_1027B53>
01027B51 >|>  33C0          XOR EAX,EAX                              ;  loc_1027B51
01027B53 >|>  5F            POP EDI                                  ;  loc_1027B53
01027B54  |.  5E            POP ESI
01027B55  |.  C9            LEAVE
01027B56  \.  C2 0400       RETN 4

    由于软件取注册码是实际用的函数是GetDlgItemIntW,所以取的4组注册码都是整数,下面就不再说明。
    上面这段是验证注册码的第一组除以10后商是否等于0xB5,不等就失败了。相等下面还有进一步的验证:


01040DFD >/$  51            PUSH ECX                                 ;  sub_1040DFD
01040DFE  |.  51            PUSH ECX
01040DFF  |.  0FB756 02     MOVZX EDX,WORD PTR DS:[ESI+2]            ;  取第二组注册码
01040E03  |.  66:8366 06 00 AND WORD PTR DS:[ESI+6],0                ;  第四组注册码清零
01040E08  |.  66:81FA 0F27  CMP DX,270F
01040E0D  |.  0F87 DF000000 JA <loc_1040EF2>                         ;  第二组注册码要小于等于0x270F
01040E13  |.  0FB746 04     MOVZX EAX,WORD PTR DS:[ESI+4]            ;  取第三组注册码
01040E17  |.  66:3D 0F27    CMP AX,270F                              ;  第三组注册码要小于等于0x270F
01040E1B  |.  0F87 D1000000 JA <loc_1040EF2>
01040E21  |.  0FB70E        MOVZX ECX,WORD PTR DS:[ESI]              ;  取第一组注册码
01040E24  |.  66:81F9 1507  CMP CX,715                               ;  是否等于0x715
01040E29  |.  894C24 04     MOV DWORD PTR SS:[ESP+4],ECX
01040E2D  |.  75 15         JNZ SHORT <loc_1040E44>
01040E2F  |.  66:81FA 1E1C  CMP DX,1C1E                              ;  第二组是否等于0x1C1E
01040E34  |.  75 0E         JNZ SHORT <loc_1040E44>
01040E36  |.  66:3D 9D15    CMP AX,159D                              ;  第三组是否等于0x159D
01040E3A  |.  75 08         JNZ SHORT <loc_1040E44>
01040E3C >|>  6A FE         PUSH -2                                  ;  都相等则注册失败
01040E3E >|>  58            POP EAX
01040E3F  |.  E9 B1000000   JMP <loc_1040EF5>
01040E44 >|>  66:81F9 1A07  CMP CX,71A                               ;  第一组是否等于0x71A
01040E49  |.  75 0D         JNZ SHORT <loc_1040E58>
01040E4B  |.  66:81FA 0910  CMP DX,1009                              ;  第二组是否等于0x1009
01040E50  |.  75 06         JNZ SHORT <loc_1040E58>
01040E52  |.  66:3D 1500    CMP AX,15                                ;  第三组是否等于0x15
01040E56  |.^ 74 E4         JE SHORT <loc_1040E3C>                   ;  都相等则注册失败
01040E58 >|>  66:81F9 1407  CMP CX,714                               ;  第一组是否等于0x714
01040E5D  |.  75 0D         JNZ SHORT <loc_1040E6C>
01040E5F  |.  66:81FA 2113  CMP DX,1321                              ;  第二组是否等于0x1321
01040E64  |.  75 06         JNZ SHORT <loc_1040E6C>
01040E66  |.  66:3D 6C0B    CMP AX,0B6C                              ;  第三组是否等于0xB6C
01040E6A  |.^ 74 D0         JE SHORT <loc_1040E3C>                   ;  都相等则注册失败
01040E6C >|>  53            PUSH EBX
01040E6D  |.  55            PUSH EBP
01040E6E  |.  57            PUSH EDI
01040E6F  |.  0FB7F8        MOVZX EDI,AX                             ;  第三组注册码
01040E72  |.  0FB7C2        MOVZX EAX,DX                             ;  第二组注册码
01040E75  |.  894424 0C     MOV DWORD PTR SS:[ESP+C],EAX
01040E79  |.  6A 64         PUSH 64
01040E7B  |.  5B            POP EBX
01040E7C  |.  8BC7          MOV EAX,EDI
01040E7E  |.  99            CDQ
01040E7F  |.  F7FB          IDIV EBX                                
01040E81  |.  6A 0A         PUSH 0A
01040E83  |.  5D            POP EBP
01040E84  |.  0FB7C9        MOVZX ECX,CX
01040E87  |.  6A 64         PUSH 64
01040E89  |.  8BD8          MOV EBX,EAX                            
01040E8B  |.  8BC1          MOV EAX,ECX
01040E8D  |.  99            CDQ
01040E8E  |.  F7FD          IDIV EBP                                 
01040E90  |.  035C24 10     ADD EBX,DWORD PTR SS:[ESP+10]            ;  第二组注册码加上第三组注册码除以100的商
01040E94  |.  03C3          ADD EAX,EBX                              ;  再加上第一组注册码除以10的商
01040E96  |.  03C7          ADD EAX,EDI                              ;  再加上第三组注册码
01040E98  |.  99            CDQ
01040E99  |.  5F            POP EDI
01040E9A  |.  F7FF          IDIV EDI                                 ;  结果除以100取余数
01040E9C  |.  8B4424 0C     MOV EAX,DWORD PTR SS:[ESP+C]
01040EA0  |.  6A 64         PUSH 64
01040EA2  |.  5B            POP EBX
01040EA3  |.  6A 64         PUSH 64
01040EA5  |.  5D            POP EBP
01040EA6  |.  55            PUSH EBP
01040EA7  |.  66:8B3C95 40F>MOV DI,WORD PTR DS:[EDX*4+106F040]       ;  用前面的余数查表
01040EAF  |.  99            CDQ
01040EB0  |.  66:6BFF 64    IMUL DI,DI,64                            ;  查表结果再乘以100
01040EB4  |.  F7FB          IDIV EBX
01040EB6  |.  8BD8          MOV EBX,EAX
01040EB8  |.  8BC1          MOV EAX,ECX
01040EBA  |.  99            CDQ
01040EBB  |.  F7FD          IDIV EBP
01040EBD  |.  03D9          ADD EBX,ECX                              ;  第一组注册码加上第二组注册码除以100的商
01040EBF  |.  59            POP ECX
01040EC0  |.  03C3          ADD EAX,EBX                              ;  再加上第一组注册码除以100的商
01040EC2  |.  99            CDQ
01040EC3  |.  F7F9          IDIV ECX                                 ;  结果除以100取余数
01040EC5  |.  66:033C95 40F>ADD DI,WORD PTR DS:[EDX*4+106F040]       ;  查表结果和前面的查表结果合并
01040ECD  |.  66:817C24 10 >CMP WORD PTR SS:[ESP+10],717             ;  比较第一组注册码是否为0x717
01040ED4  |.  66:897E 06    MOV WORD PTR DS:[ESI+6],DI
01040ED8  |.  5F            POP EDI
01040ED9  |.  5D            POP EBP
01040EDA  |.  5B            POP EBX
01040EDB  |.  74 0E         JE SHORT <loc_1040EEB>
01040EDD  |.  66:817C24 04 >CMP WORD PTR SS:[ESP+4],716
01040EE4  |.  74 05         JE SHORT <loc_1040EEB>
01040EE6  |.  33C0          XOR EAX,EAX
01040EE8  |.  40            INC EAX                                  ;  不等则返回1
01040EE9  |.  EB 0A         JMP SHORT <loc_1040EF5>
01040EEB >|>  6A 02         PUSH 2                                   ;  相等则返回2
01040EED  |.^ E9 4CFFFFFF   JMP <loc_1040E3E>
01040EF2 >|>  83C8 FF       OR EAX,FFFFFFFF                          ;  loc_1040EF2
01040EF5 >|>  59            POP ECX                                  ;  loc_1040EF5
01040EF6  |.  59            POP ECX
01040EF7  \.  C3            RETN

0106F040  26 00 00 00 5B 00 00 00 62 00 00 00 36 00 00 00  &...[...b...6...
0106F050  34 00 00 00 60 00 00 00 13 00 00 00 35 00 00 00  4...`.......5...
0106F060  19 00 00 00 54 00 00 00 3F 00 00 00 44 00 00 00  ....T...?...D...
0106F070  4C 00 00 00 38 00 00 00 5D 00 00 00 33 00 00 00  L...8...]...3...
0106F080  56 00 00 00 61 00 00 00 42 00 00 00 21 00 00 00  V...a...B...!...
0106F090  3E 00 00 00 2D 00 00 00 23 00 00 00 0E 00 00 00  >...-...#.......
0106F0A0  1E 00 00 00 5F 00 00 00 57 00 00 00 12 00 00 00  ...._...W.......
0106F0B0  1B 00 00 00 17 00 00 00 22 00 00 00 58 00 00 00  ........"...X...
0106F0C0  2C 00 00 00 63 00 00 00 5C 00 00 00 18 00 00 00  ,...c...\.......
0106F0D0  37 00 00 00 41 00 00 00 59 00 00 00 4D 00 00 00  7...A...Y...M...
0106F0E0  15 00 00 00 5A 00 00 00 53 00 00 00 0B 00 00 00  ....Z...S.......
0106F0F0  05 00 00 00 1C 00 00 00 10 00 00 00 2E 00 00 00  ................
0106F100  49 00 00 00 40 00 00 00 0D 00 00 00 07 00 00 00  I...@...........
0106F110  50 00 00 00 3D 00 00 00 32 00 00 00 46 00 00 00  P...=...2...F...
0106F120  0A 00 00 00 43 00 00 00 2B 00 00 00 00 00 00 00  ....C...+.......
0106F130  3B 00 00 00 48 00 00 00 5E 00 00 00 4E 00 00 00  ;...H...^...N...
0106F140  51 00 00 00 1F 00 00 00 20 00 00 00 3A 00 00 00  Q....... ...:...
0106F150  01 00 00 00 2A 00 00 00 45 00 00 00 55 00 00 00  ....*...E...U...
0106F160  4A 00 00 00 02 00 00 00 52 00 00 00 27 00 00 00  J.......R...'...
0106F170  03 00 00 00 4B 00 00 00 08 00 00 00 3C 00 00 00  ....K.......<...
0106F180  0F 00 00 00 14 00 00 00 24 00 00 00 25 00 00 00  ........$...%...
0106F190  28 00 00 00 29 00 00 00 16 00 00 00 1D 00 00 00  (...)...........
0106F1A0  1A 00 00 00 11 00 00 00 2F 00 00 00 39 00 00 00  ......../...9...
0106F1B0  09 00 00 00 47 00 00 00 06 00 00 00 4F 00 00 00  ....G.......O...
0106F1C0  04 00 00 00 31 00 00 00 0C 00 00 00 30 00 00 00  ....1.......0...

    可以看出注册算法很简单:
    1。注册码形如:XXXX-XXXX-XXXX-XXXX,我把这4段分别记做k1,k2,k3,k4
    2。用到了一个表,我把这个表记做t[100]
    3。注册码必须满足下面的条件
       k1 / 10 == 0xB5
       k2,k3 随机生成
       k4 / 100 = t[(k2 + k3 / 100 + k1 / 10 + k3) % 100]
       k4 % 100 = t[(k1 + k2 / 100 + k1 / 100) % 100]
                         
    4。如果 k1 = 0x717 则软件是Academic版,否则软件是注册版。
    5。黑名单有3组:k1 = 0x715 k2 = 0x1c1e k3 = 0x159d
                    k1 = 0x71a k2 = 0x1009 k3 = 0x15
                    k1 = 0x714 k2 = 0x1321 k3 = 0xb6c
                    
    【全文完】

  • 标 题: 答复
  • 作 者:nig
  • 时 间:2006-05-02 03:08

绝好的文本编辑工具, http://www.emeditor.com/
这个算法与之前的4.04 pro版没有任何区别的,我仔细核对了表数据及算法.

附上部分源码的注册机
procedure TForm1.Button1Click(Sender: TObject);
const
  S:array [1..100] of integer=($26,$5B,$62,$36,$34,$60,$13,$35,$19,$54,$3F,$44,$4C,$38,$5D,$33,$56,$61,$42,$21,
$3E,$2D,$23,$0E,$1E,$5F,$57,$12,$1B,$17,$22,$58,$2C,$63,$5C,$18,$37,$41,$59,$4D,
$15,$5A,$53,$0B,$05,$1C,$10,$2E,$49,$40,$0D,$07,$50,$3D,$32,$46,$0A,$43,$2B,$00,
$3B,$48,$5E,$4E,$51,$1F,$20,$3A,$01,$2A,$45,$55,$4A,$02,$52,$27,$03,$4B,$08,$3C,
$0F,$14,$24,$25,$28,$29,$16,$1D,$1A,$11,$2F,$39,$09,$47,$06,$4F,$04,$31,$0C,$30);
var
j,f,a,b,c,d:integer;
begin
  randomize;
  a:=1810+Random(10);
  b:=Random(9999);
  c:=Random(9999);
  f:=s[((a div 10)+b+(c div 100)+c) mod 100 +1]*100;
  j:=s[((b div 100)+a+(a div 100)) mod 100 +1];
  d:=f+j;
  edit1.Text:=inttostr(a);
  edit2.Text:=inttostr(b);
  edit3.Text:=inttostr(c);
  edit4.Text:=inttostr(d);
  if (a=$716) or (a=$717) then label4.Caption:='ACAD/Tech'+#13+' Version' else label4.Caption:='';
end;