【文章标题】: FAR4.2注册算法分析
【文章作者】: bithaha
【软件名称】: FARV4.2
【下载地址】: www.helpware.net
【加壳方式】: upx
【保护方式】: 用户名+邮箱+序列号
【软件介绍】: 一个除了能制作chm文件外还有其它N多功能的软件.强烈推荐
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  电脑上有个chw的文件,死活打不开,于是百度发现了这个软件.没找到破解只好自己动手,看雪论坛精华4和5中有本软件V3.0版本的破解过程. 
  upx的壳,esp定律脱了以后能直接运行.里面有两个dll也加了壳的,但是与破解好像没关系..
  用od载入,运行输入用户名,邮箱,注册码分别为 pediy pediy@pediy.com 78787878 点确定后弹出注册错误信息.此时在内存搜索'78787878",下内存断点,修正注册码为1234567,再点确定就会来到注册的地方,一步一步往下跟,哈哈发现注册码为明文的,."FAR22-PEDIY-00000-14360"
  心里好激动,心想这次又遇到软柿子了.赶紧输入.发现弹出:"您输入的v3.0版本的序列号,只能使用v3.0的功能" 一看好多命令果真不能用.
  于是再次用od载入,把注册码修正为FAR4-WPEDDY-00000-143600(第一次输入的不是这个,后面有说明为什么是FAR4')
  这个软件是先把序列号和生成的v3版本的序列号比较,如果不相同则开始v4系列注册验证过程.因为精华4和5中有v3版本的破解过程,而且又是明文比较,所以这里直接开始v4,在上面断点的基础上来一步步来到如下位置:开始v4系列验证.
  
  00549413    53              PUSH EBX
  00549414    56              PUSH ESI
  00549415    57              PUSH EDI
  00549416    894D F4         MOV DWORD PTR SS:[EBP-C],ECX   "FAR4-WPEDDY-00000-143600"
  00549419    8955 F8         MOV DWORD PTR SS:[EBP-8],EDX   "pediy@pediy.com
  0054941C    8945 FC         MOV DWORD PTR SS:[EBP-4],EAX.  "pediy"
  0054941F    8B7D 08         MOV EDI,DWORD PTR SS:[EBP+8]
  00549422    8B75 0C         MOV ESI,DWORD PTR SS:[EBP+C]
  00549425    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
  00549428    E8 43C0EBFF     CALL FAR0.00405470
  0054942D    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-8]
  00549430    E8 3BC0EBFF     CALL FAR0.00405470
  00549435    8B45 F4         MOV EAX,DWORD PTR SS:[EBP-C]
  00549438    E8 33C0EBFF     CALL FAR0.00405470
  0054943D    33C0            XOR EAX,EAX
  0054943F    55              PUSH EBP
  00549440    68 96955400     PUSH FAR0.00549596
  00549445    64:FF30         PUSH DWORD PTR FS:[EAX]
  00549448    64:8920         MOV DWORD PTR FS:[EAX],ESP
  0054944B    33DB            XOR EBX,EBX
  0054944D    8BC6            MOV EAX,ESI
  0054944F    E8 7CBBEBFF     CALL FAR0.00404FD0
  00549454    8D55 F0         LEA EDX,DWORD PTR SS:[EBP-10]                          ;一个堆栈指针变量
  00549457    8B45 F4         MOV EAX,DWORD PTR SS:[EBP-C]                           ;注册码地址放入EAX
  0054945A    E8 05F4FFFF     CALL FAR0.00548864                                     ; 关键1
  0054945F    837D F0 00      CMP DWORD PTR SS:[EBP-10],0
  00549463    74 3B           JE SHORT FAR0.005494A0
  00549465    8D55 EC         LEA EDX,DWORD PTR SS:[EBP-14]                          ; 一个局部指针变量
  00549468    8B45 F0         MOV EAX,DWORD PTR SS:[EBP-10]                          ;"PEDDY00000143600"
  0054946B    E8 00F9FFFF     CALL FAR0.00548D70                                     ; 关键2
  00549470    837D EC 00      CMP DWORD PTR SS:[EBP-14],0
  00549474    74 2A           JE SHORT FAR0.005494A0
  00549476    8D55 E8         LEA EDX,DWORD PTR SS:[EBP-18]
  00549479    8B45 EC         MOV EAX,DWORD PTR SS:[EBP-14]
  0054947C    E8 4BFAFFFF     CALL FAR0.00548ECC                                     ; 关键3
  00549481    837D E8 00      CMP DWORD PTR SS:[EBP-18],0
  00549485    74 19           JE SHORT FAR0.005494A0
  00549487    8D55 E4         LEA EDX,DWORD PTR SS:[EBP-1C]
  0054948A    8B45 E8         MOV EAX,DWORD PTR SS:[EBP-18]
  0054948D    E8 B6FBFFFF     CALL FAR0.00549048                                     ; 关键4
  00549492    8B45 E4         MOV EAX,DWORD PTR SS:[EBP-1C]
  00549495    E8 EEBDEBFF     CALL FAR0.00405288
  0054949A    83F8 12         CMP EAX,12
  0054949D    0F94C3          SETE BL
  005494A0    84DB            TEST BL,BL
  005494A2    0F84 A2000000   JE FAR0.0054954A
  在关键1之前的东西都是无关紧要的,跟入关键1:
  00548864    55              PUSH EBP
  00548865    8BEC            MOV EBP,ESP
  00548867    33C9            XOR ECX,ECX
  00548869    51              PUSH ECX
  0054886A    51              PUSH ECX
  0054886B    51              PUSH ECX
  0054886C    51              PUSH ECX
  0054886D    51              PUSH ECX
  0054886E    53              PUSH EBX
  0054886F    56              PUSH ESI
  00548870    57              PUSH EDI
  00548871    8BFA            MOV EDI,EDX
  00548873    8945 FC         MOV DWORD PTR SS:[EBP-4],EAX                           ; 把输入的注册码地址放入局部变量中
  00548876    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
  00548879    E8 F2CBEBFF     CALL FAR0.00405470                                     ; 
  0054887E    33C0            XOR EAX,EAX
  00548880    55              PUSH EBP
  00548881    68 9D895400     PUSH FAR0.0054899D
  00548886    64:FF30         PUSH DWORD PTR FS:[EAX]
  00548889    64:8920         MOV DWORD PTR FS:[EAX],ESP
  0054888C    8BC7            MOV EAX,EDI                                            ; EDI为本函数除了注册码之外的另一个参数
  0054888E    E8 3DC7EBFF     CALL FAR0.00404FD0                                     ; 如[eax]=0则不做什么操作
  00548893    8D55 F4         LEA EDX,DWORD PTR SS:[EBP-C]
  00548896    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]                           ; 包含注册码地址的局部变量
  00548899    E8 E611ECFF     CALL FAR0.00409A84
  0054889E    8B55 F4         MOV EDX,DWORD PTR SS:[EBP-C]                           ; 把注册码地址放入edx
  005488A1    8D45 FC         LEA EAX,DWORD PTR SS:[EBP-4]
  005488A4    E8 BFC7EBFF     CALL FAR0.00405068                                     ;这个函数多次用到,把eax中指针指向为EDX中
                                                                                      值
  005488A9    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
  005488AC    E8 D7C9EBFF     CALL FAR0.00405288                                      ;多次用到,返回的是注册码长度.
  005488B1    83F8 17         CMP EAX,17                                              ;与17H=23H比较                                           
  005488B4    0F8E C8000000   JLE FAR0.00548982      
  005488BA    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
  005488BD    8A00            MOV AL,BYTE PTR DS:[EAX]
  005488BF    BA B4895400     MOV EDX,FAR0.005489B4                                  ; ASCII "FAR4-"
  005488C4    3A02            CMP AL,BYTE PTR DS:[EDX]
  005488C6    0F85 B6000000   JNZ FAR0.00548982
  005488CC    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
  005488CF    8A40 01         MOV AL,BYTE PTR DS:[EAX+1]
  005488D2    BA B4895400     MOV EDX,FAR0.005489B4                                  ; ASCII "FAR4-"
  005488D7    3A42 01         CMP AL,BYTE PTR DS:[EDX+1]
  005488DA    0F85 A2000000   JNZ FAR0.00548982
  005488E0    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
  005488E3    8A40 02         MOV AL,BYTE PTR DS:[EAX+2]
  005488E6    BA B4895400     MOV EDX,FAR0.005489B4                                  ; ASCII "FAR4-"
  005488EB    3A42 02         CMP AL,BYTE PTR DS:[EDX+2]
  005488EE    0F85 8E000000   JNZ FAR0.00548982
  005488F4    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
  005488F7    8A40 03         MOV AL,BYTE PTR DS:[EAX+3]
  005488FA    BA B4895400     MOV EDX,FAR0.005489B4                                  ; ASCII "FAR4-"
  005488FF    3A42 03         CMP AL,BYTE PTR DS:[EDX+3]
  00548902    75 7E           JNZ SHORT FAR0.00548982
  00548904    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
  00548907    8A40 04         MOV AL,BYTE PTR DS:[EAX+4]
  0054890A    BA B4895400     MOV EDX,FAR0.005489B4                                  ; ASCII "FAR4-"
  0054890F    3A42 04         CMP AL,BYTE PTR DS:[EDX+4]
  00548912    75 6E           JNZ SHORT FAR0.00548982                                 ;前5位与"FAR4-'比较
  00548914    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
  00548917    E8 6CC9EBFF     CALL FAR0.00405288                                     ; 返回注册码长度
  0054891C    8BF0            MOV ESI,EAX
  0054891E    83EE 07         SUB ESI,7
  00548921    7C 2D           JL SHORT FAR0.00548950
  00548923    46              INC ESI
  00548924    BB 07000000     MOV EBX,7
  00548929    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
  0054892C    807C18 FF 2D    CMP BYTE PTR DS:[EAX+EBX-1],2D                         ; 判断是否为'-'
  00548931    74 19           JE SHORT FAR0.0054894C
  00548933    8D45 F0         LEA EAX,DWORD PTR SS:[EBP-10]                          ; 一个局部变量地址
  00548936    8B55 FC         MOV EDX,DWORD PTR SS:[EBP-4]
  00548939    8A541A FF       MOV DL,BYTE PTR DS:[EDX+EBX-1]
  0054893D    E8 6EC8EBFF     CALL FAR0.004051B0
  00548942    8B55 F0         MOV EDX,DWORD PTR SS:[EBP-10]                          ; EDI存放的一个地址,这个地址指向生成的字符串
  00548945    8BC7            MOV EAX,EDI
  00548947    E8 44C9EBFF     CALL FAR0.00405290
  0054894C    43              INC EBX
  0054894D    4E              DEC ESI
  0054894E  ^ 75 D9           JNZ SHORT FAR0.00548929                                ;这个循环结束后,返回的是去掉'-'后的注册码
                                                                                     ;为'FAR4WPEDIY....'
  00548950    8D55 F8         LEA EDX,DWORD PTR SS:[EBP-8]                           ; 一个局部变量
  00548953    8B07            MOV EAX,DWORD PTR DS:[EDI]                             ; [EDI]的地址指向生成的字符串
  00548955    E8 2EFEFFFF     CALL FAR0.00548788                                     ; 关键生成
  0054895A    837D F8 00      CMP DWORD PTR SS:[EBP-8],0                             ; byte ptr [ebp-8]=一个特定字符
  0054895E    74 1B           JE SHORT FAR0.0054897B
  00548960    8D45 EC         LEA EAX,DWORD PTR SS:[EBP-14]                          ; 一个局部变量
  00548963    8B55 FC         MOV EDX,DWORD PTR SS:[EBP-4]                           ; 输入的注册码
  00548966    8A52 05         MOV DL,BYTE PTR DS:[EDX+5]                             ; 注册码的第六位放入dl
  00548969    E8 42C8EBFF     CALL FAR0.004051B0                                     ; 把dl的值放入EBP-8指向的
                                                                                     ;内存中
  0054896E    8B55 EC         MOV EDX,DWORD PTR SS:[EBP-14]
  00548971    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-8]
  00548974    E8 53CAEBFF     CALL FAR0.004053CC                                     ; 关键比较1,把刚才返回的W字符与
                                                                                     ; 注册码的第六位比较
  00548979    74 07           JE SHORT FAR0.00548982
  0054897B    8BC7            MOV EAX,EDI
  0054897D    E8 4EC6EBFF     CALL FAR0.00404FD0
  注意上面那个:
  00548955    E8 2EFEFFFF     CALL FAR0.00548788                                     ; 关键生成
  这个call生成一个特定字符,怎么生成的呢? 我在这个call里面折磨了好长时间.它把注册码经过第一次变换成生的结果
  (PEDDY00000143600,注意PEDDY前面的注册码还有FAR4-W,但是这里没有考虑.)的每一位在字符串DY71CF9Q4G0NTWPAXU3526ERJKM8HL
  中的位置进行计算,计算方法是:位置(*2)相加,是否乘于2决定于edi 与80000001的简单逻辑结果,因为这个函数返回的字符是
  明文的,哈哈.所以我就没仔细看.
  这里这个call返回一个字符,这里=57H=W.字符的地址放在ebp-8里面
  ----------------------------
  通过以上分析,得出注册码前六位也许为FAR4-W...因为W的值决定于后面的值,总是变动的.
  ---------------------------
  上面的这个0054945A    E8 05F4FFFF     CALL FAR0.00548864                                     ; 关键1
  如果上面的比较通过,则返回一串字符串,就是注册码去掉前六位以及中间的'-',在这里=PEDIY00000143600,地址放在
  [EBP-10]
  00549465    8D55 EC         LEA EDX,DWORD PTR SS:[EBP-14]                          ; 一个局部指针变量
  00549468    8B45 F0         MOV EAX,DWORD PTR SS:[EBP-10]                          ;"PEDIY00000143600"
  0054946B    E8 00F9FFFF     CALL FAR0.00548D70                                     ; 关键2
  关键2这个call是最麻烦的地方(对我来说哈哈,搞定真有成就感).这个call接受一个字符串
  :PEDIY00000143600,返回一堆数字见下面说明.跟进:
  00548D70    55              PUSH EBP
  00548D71    8BEC            MOV EBP,ESP
  00548D73    83C4 E8         ADD ESP,-18
  00548D76    53              PUSH EBX
  00548D77    56              PUSH ESI
  00548D78    33C9            XOR ECX,ECX
  00548D7A    894D E8         MOV DWORD PTR SS:[EBP-18],ECX
  00548D7D    894D F0         MOV DWORD PTR SS:[EBP-10],ECX
  00548D80    894D EC         MOV DWORD PTR SS:[EBP-14],ECX
  00548D83    8955 F8         MOV DWORD PTR SS:[EBP-8],EDX
  00548D86    8945 FC         MOV DWORD PTR SS:[EBP-4],EAX
  00548D89    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
  00548D8C    E8 DFC6EBFF     CALL FAR0.00405470
  00548D91    33C0            XOR EAX,EAX
  00548D93    55              PUSH EBP
  00548D94    68 8B8E5400     PUSH FAR0.00548E8B
  00548D99    64:FF30         PUSH DWORD PTR FS:[EAX]
  00548D9C    64:8920         MOV DWORD PTR FS:[EAX],ESP
  00548D9F    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-8]
  00548DA2    E8 29C2EBFF     CALL FAR0.00404FD0
  00548DA7    B2 01           MOV DL,1
  00548DA9    A1 20BC4100     MOV EAX,DWORD PTR DS:[41BC20]                          ; 函数地址
  00548DAE    E8 D9B2EBFF     CALL FAR0.0040408C
  00548DB3    8945 F4         MOV DWORD PTR SS:[EBP-C],EAX
  00548DB6    33C0            XOR EAX,EAX
  00548DB8    55              PUSH EBP
  00548DB9    68 618E5400     PUSH FAR0.00548E61
  00548DBE    64:FF30         PUSH DWORD PTR FS:[EAX]
  00548DC1    64:8920         MOV DWORD PTR FS:[EAX],ESP
  00548DC4    8D45 EC         LEA EAX,DWORD PTR SS:[EBP-14]
  00548DC7    BA A08E5400     MOV EDX,FAR0.00548EA0
  005489BC    E8 97C2EBFF     CALL FAR0.00405068                                     ; 这个函数把EDX与ebp-14交换
  00548DD1    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]                           ; 字符串
  00548DD4    E8 AFC4EBFF     CALL FAR0.00405288                                     ; 返回长度
  00548DD9    8BF0            MOV ESI,EAX
  00548DDB    83FE 01         CMP ESI,1
  00548DDE    7C 60           JL SHORT FAR0.00548E40
  00548DE0    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]                           ;把PEDIY0000...地址放入eax
  00548DE3    8A5430 FF       MOV DL,BYTE PTR DS:[EAX+ESI-1]                         ;从PEDIY00..的最后一个字节开始取
  00548DE7    B9 01000000     MOV ECX,1
  00548DEC    B8 AC8E5400     MOV EAX,FAR0.00548EAC                                  ; ASCII "DY71CF9Q4G0NTWPAXU3526ERJKM8HL"
  00548DF1    E8 B6A7F3FF     CALL FAR0.004835AC                                     ; 返回字符在上面字符串中的位置+1
  00548DF6    8BD8            MOV EBX,EAX
  00548DF8    83FB 01         CMP EBX,1
  00548DFB    7D 07           JGE SHORT FAR0.00548E04
  00548DFD    E8 F6BBEBFF     CALL FAR0.004049F8
  00548E02    EB 64           JMP SHORT FAR0.00548E68
  00548E04    4B              DEC EBX                                                ; 被取的字符在上面字符串中的位置
  00548E05    8D4D F0         LEA ECX,DWORD PTR SS:[EBP-10]                          ; 局部变量
  00548E08    8BD3            MOV EDX,EBX                                            ; 位置
  00548E0A    8B45 EC         MOV EAX,DWORD PTR SS:[EBP-14]                          ; 局部变量
  00548E0D    E8 AAFBFFFF     CALL FAR0.005489BC                                     ;关键
  00548E12    8D4D E8         LEA ECX,DWORD PTR SS:[EBP-18]
  00548E15    8B15 D04E6A00   MOV EDX,DWORD PTR DS:[6A4ED0]                          ;这个值总等于1E=上面那个字符串的长度
  00548E1B    8B45 EC         MOV EAX,DWORD PTR SS:[EBP-14]
  00548E1E    E8 99FBFFFF     CALL FAR0.005489BC
  00548E23    8B55 E8         MOV EDX,DWORD PTR SS:[EBP-18]
  00548E26    8D45 EC         LEA EAX,DWORD PTR SS:[EBP-14]
  00548E29    E8 3AC2EBFF     CALL FAR0.0040506c
  00548E2E    33C9            XOR ECX,ECX
  00548E30    8B55 F0         MOV EDX,DWORD PTR SS:[EBP-10]
  00548E33    8B45 F4         MOV EAX,DWORD PTR SS:[EBP-C]
  00548E36    8B18            MOV EBX,DWORD PTR DS:[EAX]
  00548E38    FF53 3C         CALL DWORD PTR DS:[EBX+3C]                            ;这个函数保存[ebp-10]的结果
  00548E3B    4E              DEC ESI
  00548E3C    85F6            TEST ESI,ESI
  00548E3E  ^ 75 A0           JNZ SHORT FAR0.00548DE0                               ;主要就这个循环
  00548E40    8B55 F8         MOV EDX,DWORD PTR SS:[EBP-8]
  00548E43    8B45 F4         MOV EAX,DWORD PTR SS:[EBP-C]
  00548E46    E8 FDFCFFFF     CALL FAR0.00548B48                                    ;关键call
  
  
  
  005489BC这个call连续出现了两次,先根据[EBP-14]和字符的位置(从最后一个位置开始),生成[EBP-10],然后根据[EBP-14]和1E(=30),生成[EBP-18]
  ,然后再把[EBP-18]的指针放入[EBP-14],..然后如此循环,循环次数为PEDIY000...字符的个数.[EBP-14]的初始化是在00548DCC处,为1.他上面还有两个数字内容,跟踪的时候可以看看,是有用的,这里的每个字符(串)前面都有
  两个双字的内容,有一个代表长度,另一个作为标志 
  跟进005489BC.因为内容太多了,一个call接着一个call,跳转都巨长,所以代码就不放上了.
  它其实就是配合循环,把 字符的位置*30^n(n为0到"PEDDY..."的长度之间的整数)保存起来.比如如果第5个字符在第5个位置(从0开始),
  最后保存的就是5*30^5=121500000 在内存中为 01 02 01 05 00 00 00 00 00
  这个循环循环的次数为"PEDDY...."的长度.因为在给出的固定字符串里面没有I这个字符,所以我把PEDIY换成了PEDDY
  循环结束后,生成一列数字.然后再经过
  00548E40    8B55 F8         MOV EDX,DWORD PTR SS:[EBP-8]
  00548E43    8B45 F4         MOV EAX,DWORD PTR SS:[EBP-C]
  00548E46    E8 FDFCFFFF     CALL FAR0.00548B48     把所有的数字相加
  
  于是关键2这个call的功能就可以确定了,把"PEDDY...."在固定字符串的位置*30^n相加.经过不懂算法大牛的指点,知道了原来
  这就是个数制转换,汗.字符在固定字符串中的位置相连(从第一个字符开始),当成一个三十进制的数字,然后把三十进制转换成
  10进制就是最终的结果.需要注意的是,生成的最终结果必须是24H个字节.在关键3中可以看出.
  
  关键2返回后来到关键3
  00549465    8D55 EC         LEA EDX,DWORD PTR SS:[EBP-14]                          ; 一个局部指针变量
  00549468    8B45 F0         MOV EAX,DWORD PTR SS:[EBP-10]                          ;"PEDDY00000143600"
  0054946B    E8 00F9FFFF     CALL FAR0.00548D70                                     ; 关键2
  00549470    837D EC 00      CMP DWORD PTR SS:[EBP-14],0
  00549474    74 2A           JE SHORT FAR0.005494A0
  00549476    8D55 E8         LEA EDX,DWORD PTR SS:[EBP-18]
  00549479    8B45 EC         MOV EAX,DWORD PTR SS:[EBP-14]
  0054947C    E8 4BFAFFFF     CALL FAR0.00548ECC                                     ; 关键3
  关键3最主要是这个循环
  00548F3D   /7E 2B           JLE SHORT FAR0.00548F6A
  00548F3F   |8D45 F0         LEA EAX,DWORD PTR SS:[EBP-10]
  00548F42   |8B55 FC         MOV EDX,DWORD PTR SS:[EBP-4]
  00548F45   |8A541A FF       MOV DL,BYTE PTR DS:[EDX+EBX-1]
  00548F49   |03D2            ADD EDX,EDX
  00548F4B   |8D1492          LEA EDX,DWORD PTR DS:[EDX+EDX*4]
  00548F4E   |8B4D FC         MOV ECX,DWORD PTR SS:[EBP-4]
  00548F51   |021419          ADD DL,BYTE PTR DS:[ECX+EBX]
  00548F54   |E8 57C2EBFF     CALL FAR0.004051B0
  00548F59   |8B55 F0         MOV EDX,DWORD PTR SS:[EBP-10]
  00548F5C   |8D45 F4         LEA EAX,DWORD PTR SS:[EBP-C]
  00548F5F   |E8 2CC3EBFF     CALL FAR0.00405290
  00548F64   |83C3 02         ADD EBX,2
  00548F67   |4E              DEC ESI
  00548F68  ^|75 D5           JNZ SHORT FAR0.00548F3F
  00548F6A   \8B45 F8         MOV EAX,DWORD PTR SS:[EBP-8]
  把关键2生成的东西进行运算,运算方法是 byte1*0Ah+byte2--->结果1 byte3*0AH+byte4--->结果2...依次累推
  然后把结果1和结果2...相连
  在这个循环之后,还有一个小循环,不过很容易看出,就是把结果的前3个字节分别减去4,4--6个字节-3,7-9个字节-2
  10-12个字节减去1,13-15个字节+1,16-18个字节+2,然后把最终结果相连,返回.
  关键3返回以后来到关键4
  00549479    8B45 EC         MOV EAX,DWORD PTR SS:[EBP-14]
  0054947C    E8 4BFAFFFF     CALL FAR0.00548ECC                                     ; 关键3
  00549481    837D E8 00      CMP DWORD PTR SS:[EBP-18],0
  00549485    74 19           JE SHORT FAR0.005494A0
  00549487    8D55 E4         LEA EDX,DWORD PTR SS:[EBP-1C]
  0054948A    8B45 E8         MOV EAX,DWORD PTR SS:[EBP-18]
  0054948D    E8 B6FBFFFF     CALL FAR0.00549048                                     ; 关键4
  00549492    8B45 E4         MOV EAX,DWORD PTR SS:[EBP-1C]
  00549495    E8 EEBDEBFF     CALL FAR0.00405288
  0054949A    83F8 12         CMP EAX,12                                             ;判断长度是否为12H
  0054949D    0F94C3          SETE BL                                                ;条件不成立就失败
  005494A0    84DB            TEST BL,BL
  关键4里面代码长度巨长,但是比起关键2简单多了,就是把关键3生成的12H个字节进行重新排列.如下.
  4位 13位 17位 15位 11位 16位  18位 5位 12位 14位 1位 2位  6位 10位  9位 8位 7位 3位
  然后返回.
  返回后如上所示有个判断字符长度是否为12H,根据这个可以确定关键2中三十进制转换成10进制的结果必须要是24H位.
  来到下面
  0054949A    83F8 12         CMP EAX,12
  0054949D    0F94C3          SETE BL
  005494A0    84DB            TEST BL,BL
  005494A2    0F84 A2000000   JE FAR0.0054954A
  005494A8    57              PUSH EDI
  005494A9    B9 0A000000     MOV ECX,0A
  005494AE    BA 01000000     MOV EDX,1
  005494B3    8B45 E4         MOV EAX,DWORD PTR SS:[EBP-1C]                        
  005494B6    E8 25C0EBFF     CALL FAR0.004054E0                                    ;取前0AH个字节
  005494BB    56              PUSH ESI
  005494BC    B9 FFFFFF7F     MOV ECX,7FFFFFFF
  005494C1    BA 0B000000     MOV EDX,0B
  005494C6    8B45 E4         MOV EAX,DWORD PTR SS:[EBP-1C]
  005494C9    E8 12C0EBFF     CALL FAR0.004054E0                                    ;取后面剩下的8个字节
  005494CE    8B07            MOV EAX,DWORD PTR DS:[EDI]
  005494D0    E8 B3BDEBFF     CALL FAR0.00405288
  005494D5    83F8 0A         CMP EAX,0A
  005494D8    75 6A           JNZ SHORT FAR0.00549544
  005494DA    8B06            MOV EAX,DWORD PTR DS:[ESI]
  005494DC    E8 A7BDEBFF     CALL FAR0.00405288
  005494E1    83F8 08         CMP EAX,8
  005494E4    75 5E           JNZ SHORT FAR0.00549544
  005494E6    8B06            MOV EAX,DWORD PTR DS:[ESI]
  005494E8    8A00            MOV AL,BYTE PTR DS:[EAX]                 取出的8个字节的第一位是否等于"F"
  005494EA    BA B0955400     MOV EDX,FAR0.005495B0                    ; ASCII "F4"
  005494EF    3A02            CMP AL,BYTE PTR DS:[EDX]
  005494F1    75 51           JNZ SHORT FAR0.00549544
  005494F3    8B06            MOV EAX,DWORD PTR DS:[ESI]
  005494F5    8A40 01         MOV AL,BYTE PTR DS:[EAX+1]               第二位是否等于"4"
  005494F8    BA B0955400     MOV EDX,FAR0.005495B0                    ; ASCII "F4"
  005494FD    3A42 01         CMP AL,BYTE PTR DS:[EDX+1]
  00549500    75 42           JNZ SHORT FAR0.00549544
  00549502    8B06            MOV EAX,DWORD PTR DS:[ESI]
  00549504    8A40 02         MOV AL,BYTE PTR DS:[EAX+2]
  00549507    04 D0           ADD AL,0D0
  00549509    2C 0A           SUB AL,0A                                ;判断剩下的6个字节是否满足这个
  0054950B    73 37           JNB SHORT FAR0.00549544                  ;跳转则错误
  0054950D    8B06            MOV EAX,DWORD PTR DS:[ESI] 
  0054950F    8A40 03         MOV AL,BYTE PTR DS:[EAX+3]
  00549512    04 D0           ADD AL,0D0
  00549514    2C 0A           SUB AL,0A
  00549516    73 2C           JNB SHORT FAR0.00549544
  00549518    8B06            MOV EAX,DWORD PTR DS:[ESI]
  0054951A    8A40 04         MOV AL,BYTE PTR DS:[EAX+4]
  0054951D    04 D0           ADD AL,0D0
  0054951F    2C 0A           SUB AL,0A
  00549521    73 21           JNB SHORT FAR0.00549544
  00549523    8B06            MOV EAX,DWORD PTR DS:[ESI]
  00549525    8A40 05         MOV AL,BYTE PTR DS:[EAX+5]
  00549528    04 D0           ADD AL,0D0
  0054952A    2C 0A           SUB AL,0A
  0054952C    73 16           JNB SHORT FAR0.00549544
  0054952E    8B06            MOV EAX,DWORD PTR DS:[ESI]
  00549530    8A40 06         MOV AL,BYTE PTR DS:[EAX+6]
  00549533    04 D0           ADD AL,0D0
  00549535    2C 0A           SUB AL,0A
  00549537    73 0B           JNB SHORT FAR0.00549544
  00549539    8B06            MOV EAX,DWORD PTR DS:[ESI]
  0054953B    8A40 07         MOV AL,BYTE PTR DS:[EAX+7]
  0054953E    04 D0           ADD AL,0D0
  00549540    2C 0A           SUB AL,0A
  00549542    72 04           JB SHORT FAR0.00549548
  00549544    33DB            XOR EBX,EBX
  00549546    EB 02           JMP SHORT FAR0.0054954A
  00549548    B3 01           MOV BL,1
  0054954A    84DB            TEST BL,BL
  0054954C    74 2D           JE SHORT FAR0.0054957B
  0054954E    837D FC 00      CMP DWORD PTR SS:[EBP-4],0
  00549552    74 27           JE SHORT FAR0.0054957B
  00549554    837D F8 00      CMP DWORD PTR SS:[EBP-8],0
  00549558    74 21           JE SHORT FAR0.0054957B
  0054955A    8D45 E0         LEA EAX,DWORD PTR SS:[EBP-20]
  0054955D    50              PUSH EAX
  0054955E    B9 0A000000     MOV ECX,0A
  00549563    8B55 F8         MOV EDX,DWORD PTR SS:[EBP-8]
  00549566    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
  00549569    E8 0EF1FFFF     CALL FAR0.0054867C                       ; 关键生成
  0054956E    8B45 E0         MOV EAX,DWORD PTR SS:[EBP-20]
  00549571    8B17            MOV EDX,DWORD PTR DS:[EDI]               ;刚才取出的前0Ah个字节
  00549573    E8 54BEEBFF     CALL FAR0.004053CC                       ;与上面的关键生成call生成的字符比较
  00549578    0F94C3          SETE BL                                  ;条件成立则成功
  0054957B    33C0            XOR EAX,EAX
  0054957D    5A              POP EDX
  0054957E    59              POP ECX
  0054957F    59              POP ECX
  00549580    64:8910         MOV DWORD PTR FS:[EAX],EDX
  00549583    68 9D955400     PUSH FAR0.0054959D
  00549588    8D45 E0         LEA EAX,DWORD PTR SS:[EBP-20]
  0054958B    BA 08000000     MOV EDX,8
  00549590    E8 5FBAEBFF     CALL FAR0.00404FF4
  00549595    C3              RETN
  上面那个关键生成函数
  00549569    E8 0EF1FFFF     CALL FAR0.0054867C                       ; 关键生成
  有三个参数,分别为用户名,用户邮箱和0AH
  是先把用户名用户邮箱变成大写,去掉中间的'.',然后把用户名连在邮箱前面,这个排列 用户名+邮箱+用户名+邮箱+用户名依次
  累推.取前0AH个,返回
  然后与刚才在关键4中取出的前0Ah个字节进行比较.相同则注册成功.
  大概流程就这样了.下面开始找注册码.
  首先确定关键四生成的前0AH个字节.因为邮箱名是pediy 邮箱是pediy@pediy.com.则可以确定,这0Ah个字节为
  pediypediy--->50 45 44  49 59 50  45 44 49 59
  再确定后8个字节,为46 34 34 34 34 34 34 34(只要前两个是46 34就可以了,后面六位可以在30-39之间随便取).
  然后根据关键4的结果确定关键3的结果,根据上面的排列变换,生成关键3的结果为
  46 34 34== 50 44 34== 34 34 34== 34 59 49 ==45 59 49 ==50 44 45
  然后把前3位+4,3--5位+2,....根据关键3的运算依次累推
  得出:4A 38 38==53 47 37==36 36 36==35 5A 4A==44 58 48==4E 42 43
  然后把每位都除以0AH,这样排列:商,余数 比如4A除以0A商7余4,则排列为 07 04.....
  依次累推,得出关键2生成的最终结果.为0704 0506 0506==0803 0701 0505==0504 0504 
  0504==0503 0900 0704=0608 0808 0702==0708 0606 0607
  于是进而可以得出三十进制转换为的十进制数字为745656837155545454539074688872786667
  把次数转换为30进制就是注册码的FAR4-W后面几位在固定字符串DY71CF9Q4G0NTWPAXU3526ERJKM8HL中的位置
  在这里三十进制为:2 J642 RLA1 1406 2HIA 4MEI 07C7
  于是可以确定注册码的后面几位字符为:759C7860YYCD97U30CEP3DQTQ
  然后修改FAR4-W这个中的W位,写注册机的时候可以根据位数进行运算,我这里省了,直接
  0054896E    8B55 EC         MOV EDX,DWORD PTR SS:[EBP-14]
  00548971    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-8]
  00548974    E8 53CAEBFF     CALL FAR0.004053CC       
  在这里查看[eax]可以获得,这里为38H-->8
  到这里最终注册码就生成了:
  pediy
  pediy@pediy.com
  FAR4-87 59C7860YYCD97U30CEP3DQTQ
  
  感谢不懂算法大牛的提示,感谢一头老虎帮我算数.非常感谢两位的帮助!!
  
  
  
  
  
  
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2007年08月11日 上午 07:05:51