• 标 题:浮点运算:代码管理器 (28千字)
  • 作 者:lq7972
  • 时 间:2003-10-19 12:42:13
  • 链 接:http://bbs.pediy.com

Software:VB代码管理器
内制一个AddIn的代码格式化的程序等
Tools:TRW2000、OllyDbg V1.09、MASM32 V8
Cracker:lq7972[bruceyu13@sina.com]
Notes:学习~,§浮点指令§

这是个VB软件,大家知道VB的字符串用宽字符处理,这里用上了浮点运算
【寻找注册算法】
要把VB的运行库拷贝到TRW2000的DLL目录,以便装载、拦截
**TRW不显示浮点堆栈,我没有用fpu插件--用OllyDbg~幸好没壳**

我这里只装载了VB6运行库,断点不需要前缀:“__vbastrcomp”
0167:0049D000 FF1540114000     CALL     `MSVBVM60!__vbaStrCmp`
0167:0049D006 8BD8             MOV      EBX,EAX
0167:0049D008 8D4DE8           LEA      ECX,[EBP-18]
0167:0049D00B F7DB             NEG      EBX
0167:0049D00D 1BDB             SBB      EBX,EBX
0167:0049D00F 43               INC      EBX
0167:0049D010 F7DB             NEG      EBX
0167:0049D012 FF1500134000     CALL     `MSVBVM60!__vbaFreeStr`
0167:0049D018 8D4DD8           LEA      ECX,[EBP-28]
0167:0049D01B FF15FC124000     CALL     `MSVBVM60!__vbaFreeObj`
0167:0049D021 663BDF           CMP      BX,DI ;比较是否输入了用户名
0167:0049D024 7448             JZ       0049D06E ;跳
;……
;省略N行
0167:0049D062 C7458CB08D4100   MOV      DWORD [EBP-74],00418DB0
0167:0049D069 E9DC030000       JMP      0049D44A
0167:0049D06E 8B06             MOV      EAX,[ESI] ;在这里了
0167:0049D070 56               PUSH     ESI
0167:0049D071 FF900C030000     CALL     NEAR [EAX+030C]
;……
;再省去N行
0167:0049D0DC 53               PUSH     EBX
0167:0049D0DD 50               PUSH     EAX
0167:0049D0DE FF1598104000     CALL     `MSVBVM60!__vbaHresultCheckObj`
0167:0049D0E4 8B55E4           MOV      EDX,[EBP-1C] ;用户名
0167:0049D0E7 8B1DB4124000     MOV      EBX,[004012B4]
0167:0049D0ED 8D4DE0           LEA      ECX,[EBP-20]
0167:0049D0F0 897DE4           MOV      [EBP-1C],EDI
0167:0049D0F3 FFD3             CALL     EBX ;移动用户名到某个地址
0167:0049D0F5 8B55E8           MOV      EDX,[EBP-18] ;假码
;先运行一下注册,在到这里看看:接着就有真码啦
0167:0049D0F8 8D45E0           LEA      EAX,[EBP-20] ;用户名地址
0167:0049D0FB 52               PUSH     EDX
0167:0049D0FC 50               PUSH     EAX
0167:0049D0FD E88E0E0000       CALL     0049DF90 ;想想,是时候【跟进】了
0167:0049D102 8BD0             MOV      EDX,EAX
0167:0049D104 8D4DDC           LEA      ECX,[EBP-24]
0167:0049D107 FFD3             CALL     EBX
0167:0049D109 50               PUSH     EAX
0167:0049D10A FF1540114000     CALL     `MSVBVM60!__vbaStrCmp`
0167:0049D110 8BF8             MOV      EDI,EAX
0167:0049D112 8D4DDC           LEA      ECX,[EBP-24]

;【跟进】
0167:0049DF90 55               PUSH     EBP
0167:0049DF91 8BEC             MOV      EBP,ESP
0167:0049DF93 83EC18           SUB      ESP,BYTE +18
0167:0049DF96 6836454000       PUSH     DWORD 00404536
0167:0049DF9B 64A100000000     MOV      EAX,[FS:00]
0167:0049DFA1 50               PUSH     EAX
0167:0049DFA2 64892500000000   MOV      [FS:00],ESP
0167:0049DFA9 B8A0000000       MOV      EAX,A0
0167:0049DFAE E87D65F6FF       CALL     `MSVBVM60!__vbaChkstk`
0167:0049DFB3 53               PUSH     EBX
0167:0049DFB4 56               PUSH     ESI
0167:0049DFB5 57               PUSH     EDI
0167:0049DFB6 8965E8           MOV      [EBP-18],ESP
0167:0049DFB9 C745EC60434000   MOV      DWORD [EBP-14],00404360 ;**
0167:0049DFC0 C745F000000000   MOV      DWORD [EBP-10],00 ;**
0167:0049DFC7 C745F400000000   MOV      DWORD [EBP-0C],00 ;**
0167:0049DFCE C745FC01000000   MOV      DWORD [EBP-04],01 ;**
0167:0049DFD5 C745FC02000000   MOV      DWORD [EBP-04],02 ;**
0167:0049DFDC 6AFF             PUSH     BYTE -01
0167:0049DFDE FF15D0104000     CALL     `MSVBVM60!__vbaOnError`
0167:0049DFE4 C745FC03000000   MOV      DWORD [EBP-04],03
;*********************************************************************把你的眼球弄到这儿吧
0167:0049DFEB 8B4508           MOV      EAX,[EBP+08] ;用户名地址
0167:0049DFEE 8B08             MOV      ECX,[EAX]
0167:0049DFF0 51               PUSH     ECX
0167:0049DFF1 6870264100       PUSH     DWORD 00412670
0167:0049DFF6 FF1540114000     CALL     `MSVBVM60!__vbaStrCmp` ;用户名输入了吗?
0167:0049DFFC 85C0             TEST     EAX,EAX
0167:0049DFFE 0F8417010000     JZ       NEAR 0049E11B ;不要走喔
0167:0049E004 C745FC04000000   MOV      DWORD [EBP-04],04
0167:0049E00B 8B5508           MOV      EDX,[EBP+08]
0167:0049E00E 8B02             MOV      EAX,[EDX]
0167:0049E010 50               PUSH     EAX
0167:0049E011 FF153C104000     CALL     `MSVBVM60!__vbaLenBstr` ;用户名长度,返回eax
0167:0049E017 8945C8           MOV      [EBP-38],EAX
0167:0049E01A C745FC05000000   MOV      DWORD [EBP-04],05
0167:0049E021 8B4DC8           MOV      ECX,[EBP-38]
0167:0049E024 FF1554114000     CALL     `MSVBVM60!__vbaI2I4`
0167:0049E02A 66898578FFFFFF   MOV      [EBP+FFFFFF78],AX ;用户名长度,要特别注意这些变量
0167:0049E031 66C7857CFFFFFF01+MOV      WORD [EBP+FFFFFF7C],01 ;**
0167:0049E03A 66C745D80100     MOV      WORD [EBP-28],01 ;**
0167:0049E040 EB15             JMP      SHORT 0049E057 ;这里开始作第一个循环

;【算法过程1】依次从用户名中取字符,对获得其ASCII码(10进制)或异,把它们转为字符形式连起来;这不是注册码!
;///////////////////////////////////////////////////////////////////////////
0167:0049E042 668B4DD8         MOV      CX,[EBP-28] ;cx,counter
0167:0049E046 66038D7CFFFFFF   ADD      CX,[EBP+FFFFFF7C] ;cx=cx+1
0167:0049E04D 0F808B040000     JO       NEAR 0049E4DE
0167:0049E053 66894DD8         MOV      [EBP-28],CX ;**

0167:0049E057 668B55D8         MOV      DX,[EBP-28] ;dx,第一次是1
0167:0049E05B 663B9578FFFFFF   CMP      DX,[EBP+FFFFFF78] ;同用户名长度比较
0167:0049E062 0F8FB3000000     JG       NEAR 0049E11B ;循环完了就走
0167:0049E068 C745FC06000000   MOV      DWORD [EBP-04],06 ;**
0167:0049E06F C745BC01000000   MOV      DWORD [EBP-44],01 ;**
0167:0049E076 C745B402000000   MOV      DWORD [EBP-4C],02 ;**
0167:0049E07D 8B4508           MOV      EAX,[EBP+08] ;用户名地址
0167:0049E080 89459C           MOV      [EBP-64],EAX ;**
0167:0049E083 C7459408400000   MOV      DWORD [EBP-6C],4008 ;**
0167:0049E08A 8D4DB4           LEA      ECX,[EBP-4C]
0167:0049E08D 51               PUSH     ECX
0167:0049E08E 0FBF55D8         MOVSX    EDX,WORD [EBP-28] ;//
0167:0049E092 52               PUSH     EDX
0167:0049E093 8D4594           LEA      EAX,[EBP-6C]
0167:0049E096 50               PUSH     EAX
0167:0049E097 8D4DA4           LEA      ECX,[EBP-5C]
0167:0049E09A 51               PUSH     ECX
0167:0049E09B FF1520114000     CALL     `MSVBVM60!rtcMidCharVar` ;从用户名中取第i个字符
0167:0049E0A1 8D55A4           LEA      EDX,[EBP-5C]
0167:0049E0A4 52               PUSH     EDX
0167:0049E0A5 FF1538104000     CALL     `MSVBVM60!__vbaStrVarMove` ;把它移到某个地方
0167:0049E0AB 8BD0             MOV      EDX,EAX
0167:0049E0AD 8D4DDC           LEA      ECX,[EBP-24]
0167:0049E0B0 FF15B4124000     CALL     `MSVBVM60!__vbaStrMove`
0167:0049E0B6 8D45A4           LEA      EAX,[EBP-5C]
0167:0049E0B9 50               PUSH     EAX
0167:0049E0BA 8D4DB4           LEA      ECX,[EBP-4C]
0167:0049E0BD 51               PUSH     ECX
0167:0049E0BE 6A02             PUSH     BYTE +02
0167:0049E0C0 FF1548104000     CALL     `MSVBVM60!__vbaFreeVarList`
0167:0049E0C6 83C40C           ADD      ESP,BYTE +0C
0167:0049E0C9 C745FC07000000   MOV      DWORD [EBP-04],07
0167:0049E0D0 8B55D4           MOV      EDX,[EBP-2C]
0167:0049E0D3 52               PUSH     EDX
0167:0049E0D4 8B45DC           MOV      EAX,[EBP-24]
0167:0049E0D7 50               PUSH     EAX
0167:0049E0D8 FF1560104000     CALL     `MSVBVM60!rtcAnsiValueBstr` ;取它的ASCII码(10进制)
0167:0049E0DE 66350500         XOR      AX,05 ;或异
0167:0049E0E2 50               PUSH     EAX
0167:0049E0E3 FF150C104000     CALL     `MSVBVM60!__vbaStrI2` ;它的ASCII码转字符形式
0167:0049E0E9 8BD0             MOV      EDX,EAX
0167:0049E0EB 8D4DC4           LEA      ECX,[EBP-3C]
0167:0049E0EE FF15B4124000     CALL     `MSVBVM60!__vbaStrMove` ;字符串移动操作
0167:0049E0F4 50               PUSH     EAX
0167:0049E0F5 FF157C104000     CALL     `MSVBVM60!__vbaStrCat` ;连接字符串,得到串tempString
0167:0049E0FB 8BD0             MOV      EDX,EAX
0167:0049E0FD 8D4DD4           LEA      ECX,[EBP-2C]
0167:0049E100 FF15B4124000     CALL     `MSVBVM60!__vbaStrMove`
0167:0049E106 8D4DC4           LEA      ECX,[EBP-3C]
0167:0049E109 FF1500134000     CALL     `MSVBVM60!__vbaFreeStr`
0167:0049E10F C745FC08000000   MOV      DWORD [EBP-04],08
0167:0049E116 E927FFFFFF       JMP      0049E042
;第一个循环完
;///////////////////////////////////////////////////////////////////////////

0167:0049E11B C745FC0A000000   MOV      DWORD [EBP-04],0A ;**
0167:0049E122 8B4DD4           MOV      ECX,[EBP-2C] ;上面的运算结果~tempString地址
0167:0049E125 51               PUSH     ECX
0167:0049E126 FF153C104000     CALL     `MSVBVM60!__vbaLenBstr` ;tempString的长度
0167:0049E12C 8945C8           MOV      [EBP-38],EAX ;**
0167:0049E12F C745FC0B000000   MOV      DWORD [EBP-04],0B ;**
0167:0049E136 8B55D4           MOV      EDX,[EBP-2C] ;tempString
0167:0049E139 52               PUSH     EDX
0167:0049E13A FF153C104000     CALL     `MSVBVM60!__vbaLenBstr`
0167:0049E140 898558FFFFFF     MOV      [EBP+FFFFFF58],EAX ;**,tempString长度
0167:0049E146 DB8558FFFFFF     FILD     DWORD [EBP+FFFFFF58] ;浮点指令:装入整数到st(0)
0167:0049E14C DD9D50FFFFFF     FSTP     QWORD [EBP+FFFFFF50] ;浮点指令:保存st(0)到变量,并出栈
0167:0049E152 DD8550FFFFFF     FLD      QWORD [EBP+FFFFFF50] ;浮点指令:装入实数到st(0)
0167:0049E158 833D00004A0000   CMP      DWORD [004A0000],BYTE +00 ;00
0167:0049E15F 7508             JNZ      0049E169
0167:0049E161 DC35E8364000     FDIV     QWORD [004036E8] ;浮点指令:除以一个实数,2
0167:0049E167 EB11             JMP      SHORT 0049E17A

0167:0049E169 FF35EC364000     PUSH     DWORD [004036EC]
0167:0049E16F FF35E8364000     PUSH     DWORD [004036E8]
0167:0049E175 E8DA63F6FF       CALL     `MSVBVM60!_adj_fdiv_m64`

0167:0049E17A DFE0             FNSTSW   AX ;保存状态字到ax
0167:0049E17C A80D             TEST     AL,0D
0167:0049E17E 0F8555030000     JNZ      NEAR 0049E4D9
0167:0049E184 FF1588124000     CALL     `MSVBVM60!__vbaFpI2`
0167:0049E18A 66898570FFFFFF   MOV      [EBP+FFFFFF70],AX ;**tempString的长度的一半
0167:0049E191 66C78574FFFFFF01+MOV      WORD [EBP+FFFFFF74],01 ;**
0167:0049E19A 66C745D80000     MOV      WORD [EBP-28],00 ;**[ebp-28]清零了
0167:0049E1A0 EB15             JMP      SHORT 0049E1B7 ;这里开始作第二个循环

;【算法过程2】依次从tempString中取两位字符,把它们连起来;但??(请读下去,谢谢)是注册码
;///////////////////////////////////////////////////////////////////////////
0167:0049E1A2 668B45D8         MOV      AX,[EBP-28]
0167:0049E1A6 66038574FFFFFF   ADD      AX,[EBP+FFFFFF74]
0167:0049E1AD 0F802B030000     JO       NEAR 0049E4DE ;溢出转移,玩完
0167:0049E1B3 668945D8         MOV      [EBP-28],AX

0167:0049E1B7 668B4DD8         MOV      CX,[EBP-28] ;从0开始
0167:0049E1BB 663B8D70FFFFFF   CMP      CX,[EBP+FFFFFF70] ;比较
0167:0049E1C2 0F8FA7020000     JG       NEAR 0049E46F ;循环结束则跳
0167:0049E1C8 C745FC0C000000   MOV      DWORD [EBP-04],0C ;**
0167:0049E1CF 0FBF55D8         MOVSX    EDX,WORD [EBP-28] ;//
0167:0049E1D3 85D2             TEST     EDX,EDX
0167:0049E1D5 7570             JNZ      0049E247 ;循环第一次,则不跳
;不是第一次,则跳
;------------------------------------------------------------------------
0167:0049E1D7 C745FC0D000000   MOV      DWORD [EBP-04],0D ;**这个不同
0167:0049E1DE C745BC02000000   MOV      DWORD [EBP-44],02 ;**
0167:0049E1E5 C745B402000000   MOV      DWORD [EBP-4C],02 ;**
0167:0049E1EC 8D45D4           LEA      EAX,[EBP-2C] ;tempString地址
0167:0049E1EF 89459C           MOV      [EBP-64],EAX
0167:0049E1F2 C7459408400000   MOV      DWORD [EBP-6C],4008 ;**
0167:0049E1F9 8D4DB4           LEA      ECX,[EBP-4C] ;tempString地址
0167:0049E1FC 51               PUSH     ECX
0167:0049E1FD 668B55D8         MOV      DX,[EBP-28] ;dx=[EBP-28]中值
0167:0049E201 6683C201         ADD      DX,BYTE +01 ;++dx
0167:0049E205 0F80D3020000     JO       NEAR 0049E4DE ;溢出转移
0167:0049E20B 0FBFC2           MOVSX    EAX,DX ;eax=dx
0167:0049E20E 50               PUSH     EAX
0167:0049E20F 8D4D94           LEA      ECX,[EBP-6C]
0167:0049E212 51               PUSH     ECX
0167:0049E213 8D55A4           LEA      EDX,[EBP-5C]
0167:0049E216 52               PUSH     EDX
0167:0049E217 FF1520114000     CALL     `MSVBVM60!rtcMidCharVar`
0167:0049E21D 8D45A4           LEA      EAX,[EBP-5C]
0167:0049E220 50               PUSH     EAX
0167:0049E221 FF1538104000     CALL     `MSVBVM60!__vbaStrVarMove` ;从tempStr取头两个移到某个位置,返回eax
0167:0049E227 8BD0             MOV      EDX,EAX
0167:0049E229 8D4DCC           LEA      ECX,[EBP-34]
0167:0049E22C FF15B4124000     CALL     `MSVBVM60!__vbaStrMove` 
0167:0049E232 8D4DA4           LEA      ECX,[EBP-5C]
0167:0049E235 51               PUSH     ECX
0167:0049E236 8D55B4           LEA      EDX,[EBP-4C]
0167:0049E239 52               PUSH     EDX
0167:0049E23A 6A02             PUSH     BYTE +02
0167:0049E23C FF1548104000     CALL     `MSVBVM60!__vbaFreeVarList`
0167:0049E242 83C40C           ADD      ESP,BYTE +0C
0167:0049E245 EB78             JMP      SHORT 0049E2BF ;是循环第一次
;------------------------------------------------------------------------
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++;不是循环第一次,跳在这里
0167:0049E247 C745FC0F000000   MOV      DWORD [EBP-04],0F ;**这个不同
0167:0049E24E C745BC02000000   MOV      DWORD [EBP-44],02 ;**
0167:0049E255 C745B402000000   MOV      DWORD [EBP-4C],02 ;**
0167:0049E25C 8D45D4           LEA      EAX,[EBP-2C] ;tempStr地址
0167:0049E25F 89459C           MOV      [EBP-64],EAX
0167:0049E262 C7459408400000   MOV      DWORD [EBP-6C],4008 ;**
0167:0049E269 8D4DB4           LEA      ECX,[EBP-4C]
0167:0049E26C 51               PUSH     ECX
0167:0049E26D 668B55D8         MOV      DX,[EBP-28]
0167:0049E271 666BD202         IMUL     DX,DX,BYTE +02 ;这里第一次肯定没有
0167:0049E275 0F8063020000     JO       NEAR 0049E4DE
0167:0049E27B 6683C201         ADD      DX,BYTE +01
0167:0049E27F 0F8059020000     JO       NEAR 0049E4DE
0167:0049E285 0FBFC2           MOVSX    EAX,DX
0167:0049E288 50               PUSH     EAX
0167:0049E289 8D4D94           LEA      ECX,[EBP-6C]
0167:0049E28C 51               PUSH     ECX
0167:0049E28D 8D55A4           LEA      EDX,[EBP-5C];0
0167:0049E290 52               PUSH     EDX
0167:0049E291 FF1520114000     CALL     `MSVBVM60!rtcMidCharVar`
0167:0049E297 8D45A4           LEA      EAX,[EBP-5C]
0167:0049E29A 50               PUSH     EAX
0167:0049E29B FF1538104000     CALL     `MSVBVM60!__vbaStrVarMove` ;移动两个字符
0167:0049E2A1 8BD0             MOV      EDX,EAX
0167:0049E2A3 8D4DCC           LEA      ECX,[EBP-34] ;上两个字符
0167:0049E2A6 FF15B4124000     CALL     `MSVBVM60!__vbaStrMove`
0167:0049E2AC 8D4DA4           LEA      ECX,[EBP-5C]
0167:0049E2AF 51               PUSH     ECX
0167:0049E2B0 8D55B4           LEA      EDX,[EBP-4C];2
0167:0049E2B3 52               PUSH     EDX
0167:0049E2B4 6A02             PUSH     BYTE +02
0167:0049E2B6 FF1548104000     CALL     `MSVBVM60!__vbaFreeVarList`
0167:0049E2BC 83C40C           ADD      ESP,BYTE +0C
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;这里就是关键,通过浮点数比较,决定如何处理取出的两个字符:直接转为字符形式?还是取它们(当其为ASCII码)对应的字符?
0167:0049E2BF C745FC11000000   MOV      DWORD [EBP-04],11 ;**
0167:0049E2C6 8B45CC           MOV      EAX,[EBP-34] ;从tempString取出的两个字符
0167:0049E2C9 50               PUSH     EAX
0167:0049E2CA FF1528124000     CALL     `MSVBVM60!__vbaR8Str` ;这两个字符转为数值形式,并入栈
;浮点数入st(0),10
0167:0049E2D0 DC1D00444000     FCOMP    QWORD [00404400] ;浮点指令:浮点数比较
{DS段:
004043E8   . 0000000000C05E40   DQ FLOAT 123.0000000000000
004043F0   . 0000000000405840   DQ FLOAT 97.00000000000000
004043F8   . 0000000000805640   DQ FLOAT 90.00000000000000
00404400   . 0000000000005040   DQ FLOAT 64.00000000000000
}
0167:0049E2D6 DFE0             FNSTSW   AX ;浮点指令:保存状态字的值到ax
0167:0049E2D8 F6C441           TEST     AH,41 
0167:0049E2DB 740C             JZ       0049E2E9 ;☆★

0167:0049E2DD C7854CFFFFFF0100+MOV      DWORD [EBP+FFFFFF4C],01 ;**
0167:0049E2E7 EB0A             JMP      SHORT 0049E2F3 ;☆▲

0167:0049E2E9 C7854CFFFFFF0000+MOV      DWORD [EBP+FFFFFF4C],00 ;☆★
;**
;☆▲
0167:0049E2F3 8B4DCC           MOV      ECX,[EBP-34] ;tempString取出的两个字符
0167:0049E2F6 51               PUSH     ECX
0167:0049E2F7 FF1528124000     CALL     `MSVBVM60!__vbaR8Str`
0167:0049E2FD DC1DF8434000     FCOMP    QWORD [004043F8]
0167:0049E303 DFE0             FNSTSW   AX
0167:0049E305 F6C401           TEST     AH,01
0167:0049E308 750C             JNZ      0049E316 ;☆■

0167:0049E30A C78548FFFFFF0100+MOV      DWORD [EBP+FFFFFF48],01 ;**
0167:0049E314 EB0A             JMP      SHORT 0049E320 ;☆◆

0167:0049E316 C78548FFFFFF0000+MOV      DWORD [EBP+FFFFFF48],00 ;☆■
;**
;☆◆
0167:0049E320 8B55CC           MOV      EDX,[EBP-34] ;tempString取出的两个字符
0167:0049E323 52               PUSH     EDX
0167:0049E324 FF1528124000     CALL     `MSVBVM60!__vbaR8Str`
0167:0049E32A DC1DF0434000     FCOMP    QWORD [004043F0]
0167:0049E330 DFE0             FNSTSW   AX
0167:0049E332 F6C441           TEST     AH,41
0167:0049E335 740C             JZ       0049E343 ;☆●

0167:0049E337 C78544FFFFFF0100+MOV      DWORD [EBP+FFFFFF44],01 ;**
0167:0049E341 EB0A             JMP      SHORT 0049E34D ;☆★

0167:0049E343 C78544FFFFFF0000+MOV      DWORD [EBP+FFFFFF44],00 ;☆●
;**
;☆★
0167:0049E34D 8B45CC           MOV      EAX,[EBP-34] ;tempString取出的两个字符
0167:0049E350 50               PUSH     EAX
0167:0049E351 FF1528124000     CALL     `MSVBVM60!__vbaR8Str`
0167:0049E357 DC1DE8434000     FCOMP    QWORD [004043E8]
0167:0049E35D DFE0             FNSTSW   AX
0167:0049E35F F6C401           TEST     AH,01
0167:0049E362 750C             JNZ      0049E370 ;☆※

0167:0049E364 C78540FFFFFF0100+MOV      DWORD [EBP+FFFFFF40],01 ;**
0167:0049E36E EB0A             JMP      SHORT 0049E37A ;☆◎

0167:0049E370 C78540FFFFFF0000+MOV      DWORD [EBP+FFFFFF40],00 ;☆※
;**E
;☆◎
0167:0049E37A 8B8D4CFFFFFF     MOV      ECX,[EBP+FFFFFF4C] ;??
0167:0049E380 0B8D48FFFFFF     OR       ECX,[EBP+FFFFFF48] ;??
0167:0049E386 F7D9             NEG      ECX ;将操作数按位求反后末位加1
0167:0049E388 1BC9             SBB      ECX,ECX ;带借位减
0167:0049E38A F7D9             NEG      ECX
0167:0049E38C 8B9544FFFFFF     MOV      EDX,[EBP+FFFFFF44]
0167:0049E392 0B9540FFFFFF     OR       EDX,[EBP+FFFFFF40]
0167:0049E398 F7DA             NEG      EDX
0167:0049E39A 1BD2             SBB      EDX,EDX
0167:0049E39C F7DA             NEG      EDX
0167:0049E39E 23CA             AND      ECX,EDX
0167:0049E3A0 85C9             TEST     ECX,ECX
0167:0049E3A2 0F859B000000     JNZ      NEAR 0049E443

;**************************************************************
;不跳,就把这个字符串转为整数,再取其对应的字符,最后化大写~终于知道了
0167:0049E3A8 C745FC12000000   MOV      DWORD [EBP-04],12
0167:0049E3AF FF1558124000     CALL     `MSVBVM60!rtcErrObj`
0167:0049E3B5 8945BC           MOV      [EBP-44],EAX
0167:0049E3B8 C745B409000000   MOV      DWORD [EBP-4C],09
0167:0049E3BF 8D45B4           LEA      EAX,[EBP-4C]
0167:0049E3C2 50               PUSH     EAX
0167:0049E3C3 FF1508114000     CALL     `MSVBVM60!__vbaBoolVarNull`
0167:0049E3C9 66894580         MOV      [EBP-80],AX
0167:0049E3CD 8D4DB4           LEA      ECX,[EBP-4C]
0167:0049E3D0 FF1530104000     CALL     `MSVBVM60!__vbaFreeVar`
0167:0049E3D6 0FBF4D80         MOVSX    ECX,WORD [EBP-80]
0167:0049E3DA 85C9             TEST     ECX,ECX
0167:0049E3DC 7413             JZ       0049E3F1
0167:0049E3DE C745FC13000000   MOV      DWORD [EBP-04],13
0167:0049E3E5 8B55CC           MOV      EDX,[EBP-34]
0167:0049E3E8 8D4DCC           LEA      ECX,[EBP-34]
0167:0049E3EB FF1540124000     CALL     `MSVBVM60!__vbaStrCopy`
0167:0049E3F1 C745FC15000000   MOV      DWORD [EBP-04],15
0167:0049E3F8 8B55CC           MOV      EDX,[EBP-34] ;操作对象
0167:0049E3FB 52               PUSH     EDX
0167:0049E3FC FF1544124000     CALL     `MSVBVM60!__vbaI4Str` ;整数取对应字符
0167:0049E402 50               PUSH     EAX
0167:0049E403 8D45B4           LEA      EAX,[EBP-4C]
0167:0049E406 50               PUSH     EAX
0167:0049E407 FF15DC114000     CALL     `MSVBVM60!rtcVarBstrFromAnsi`
0167:0049E40D 8D4DB4           LEA      ECX,[EBP-4C]
0167:0049E410 51               PUSH     ECX
0167:0049E411 8D55A4           LEA      EDX,[EBP-5C]
0167:0049E414 52               PUSH     EDX
0167:0049E415 FF1538114000     CALL     `MSVBVM60!rtcUpperCaseVar` ;大写
0167:0049E41B 8D45A4           LEA      EAX,[EBP-5C]
0167:0049E41E 50               PUSH     EAX
0167:0049E41F FF1538104000     CALL     `MSVBVM60!__vbaStrVarMove`
0167:0049E425 8BD0             MOV      EDX,EAX
0167:0049E427 8D4DCC           LEA      ECX,[EBP-34]
0167:0049E42A FF15B4124000     CALL     `MSVBVM60!__vbaStrMove`
0167:0049E430 8D4DA4           LEA      ECX,[EBP-5C]
0167:0049E433 51               PUSH     ECX
0167:0049E434 8D55B4           LEA      EDX,[EBP-4C]
0167:0049E437 52               PUSH     EDX
0167:0049E438 6A02             PUSH     BYTE +02
0167:0049E43A FF1548104000     CALL     `MSVBVM60!__vbaFreeVarList`
0167:0049E440 83C40C           ADD      ESP,BYTE +0C
;********************************************************************

0167:0049E443 C745FC17000000   MOV      DWORD [EBP-04],17 ;**
0167:0049E44A 8B45D0           MOV      EAX,[EBP-30] ;00
0167:0049E44D 50               PUSH     EAX
0167:0049E44E 8B4DCC           MOV      ECX,[EBP-34] ;从tempString取出的或经过计算了的
0167:0049E451 51               PUSH     ECX
0167:0049E452 FF157C104000     CALL     `MSVBVM60!__vbaStrCat` ;这里连接的就是注册码
0167:0049E458 8BD0             MOV      EDX,EAX
0167:0049E45A 8D4DD0           LEA      ECX,[EBP-30]
0167:0049E45D FF15B4124000     CALL     `MSVBVM60!__vbaStrMove`
0167:0049E463 C745FC18000000   MOV      DWORD [EBP-04],18
0167:0049E46A E933FDFFFF       JMP 0049E1A2
;第二个循环完
;///////////////////////////////////////////////////////////////////////////

【总结】
算法不难,见上
我希望表达清楚了……

【注册机】
;KeyGen.asm
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; The KeyGen by lq7972,with MASM32 V8
; E-mail:bruceyu13@sina.com
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat,stdcall
option casemap:none

;Include文件定义
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
include gdi32.inc
includelib gdi32.lib
include comdlg32.inc
includelib comdlg32.lib
include masm32.inc
includelib masm32.lib

;Equ等值定义
ICO_MAIN equ 1000H
DLG_MAIN equ 1
EditName equ 10
EditSN equ 11

;*************************************************************************************
.data?
hInstance dd ?
szSN            db 255 dup (?)
szName db 255 dup (?)
regStr db 255 dup (?)
theString db 8   dup (?)
lenString db 8   dup (?)

.data
szErr db '请输入用户名!',0 
szCaption db '错误!',0 

.const
Num01 dq 64.00000000000000
Num02 dq 90.00000000000000
Num03 dq 97.00000000000000
Num04 dq 123.0000000000000

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;***************************************************************************************
_testStr proc uses ebx edi esi ebp, @tempStr
local @tempStr00
local @temp01, @temp02, @temp03, @temp04

invoke atodw, @tempStr
mov dword ptr @tempStr00, eax
xor eaxeax
fild @tempStr00
fcomp Num01
fnstsw ax
test ah,41h
jz @F
mov dword ptr @temp01, 01
jmp a10
@@:
mov dword ptr @temp01, 00
a10:
xor eaxeax
fild @tempStr00
fcomp Num02
fnstsw ax
test ah, 1
jnz @F
mov dword ptr @temp02, 01
jmp a20
@@:
mov dword ptr @temp02, 00
a20:
xor eaxeax
fild @tempStr00
fcomp Num03
fnstsw ax
test ah, 41
jz @F
mov dword ptr @temp03, 01
jmp a30
@@:
mov dword ptr @temp03, 00
a30:
xor eaxeax
fild @tempStr00
fcomp Num04
fnstsw ax
test ah, 01
jnz @F
mov dword ptr @temp04, 01
jmp a40
@@:
mov dword ptr @temp04, 00
a40:
mov ecxdword ptr @temp01
or ecx, @temp02
neg ecx
sbb ecxecx
neg ecx
mov edxdword ptr @temp03
or edx, @temp04
neg edx
sbb edxedx
neg edx
and ecxedx

ret
_testStr endp
;***************************************************************************************
;***************************************************************************************
_regCodCalc proc
local @temp[8], @temp00[8], @temp01, @temp02

pushad
invoke lstrlen, addr szName
mov edieax 
sub esiesi
xor ebxebx
;计算中间字串变量
.while esi < edi
sub edxedx
mov dlbyte ptr [szName+esi]
xor dx, 5
mov dword ptr @temp01, edx
invoke dwtoa, @temp01, addr @temp02
;MASM32库函数
mov eaxdword ptr @temp02
mov dword ptr [regStr+ebx], eax
invoke lstrlen, addr regStr
mov ebxeax
inc esi
.break .if esi > edi
.continue
.endw

;计算注册码 
invoke lstrlen, addr regStr
inc eax
mov ecx, 2
cdq
idiv ecx
mov dword ptr lenString, eax
mov esieax
xor ebxebx
xor ediedi
.while edi < esi
invoke RtlZeroMemory, addr @temp, 8
invoke RtlZeroMemory, addr @temp00, 8
movsx eaxbyte ptr [regStr+2*edi]
movsx edxbyte ptr [regStr+2*edi+1]
mov byte ptr @temp, al
mov byte ptr @temp00, dl
invoke lstrcat, addr @temp, addr @temp00
invoke _testStr, addr @temp
;子程序,带一个参数,返回在ecx中
test ecxecx
jnz @F
invoke atodw, addr @temp
;MASM32库函数
jmp a10
@@:
mov eaxdword ptr @temp
a10:
mov dword ptr [szSN+ebx], eax
invoke lstrlen, addr szSN
mov ebxeax
inc edi
.break .if edi > esi
.continue
.endw

popad
ret

_regCodCalc endp
;**************************************************************************************
_ProcDlgMain proc uses ebx edi esi ebp, hWnd,wMsg,wParam,lParam
mov eax,wMsg 
.if eax==WM_CLOSE 
invoke  EndDialog,hWnd,NULL
.elseif eax==WM_COMMAND 
mov eax,wParam 
.if eax == IDOK
invoke RtlZeroMemory,addr szSN,255
invoke  GetDlgItemText,hWnd,EditName,offset szName,255
.if eax !=  NULL
invoke  _regCodCalc
invoke SetDlgItemText, hWnd, EditSN, offset szSN
mov eax,FALSE
ret
                 .else 
invoke MessageBox,NULL,offset szErr,offset szCaption,MB_OK
mov eax,FALSE
ret
.endif
.elseif eax  ==  IDCANCEL 
invoke  EndDialog,hWnd,NULL 
.endif 
.else 
mov    eax,FALSE 
ret 
.endif
mov eax,TRUE
ret
_ProcDlgMain endp 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:

invoke GetModuleHandle,NULL
mov hInstance,eax
invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,NULL
invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
end start


//KeyGen.rc
#include  

#define ICO_MAIN 0x1000
#define DLG_MAIN 1
#define EDITName 10
#define EDITSN 11

ICO_MAIN ICON "01.ico"
DLG_MAIN DIALOG 100,150,250,60
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "豪杰超级解霸3K~英雄版 注册机" 
FONT 9,"宋体" 

{
 CONTROL "Name:" ,-1,"Static",SS_LEFT,10,13,40,17
 CONTROL "SN:" ,-2,"Static",SS_CENTER,10,40,20,17
 CONTROL "" ,10,"Edit",ES_LEFT,30,13,150,10
 CONTROL "" ,11,"Edit",ES_LEFT,30,40,150,10
 DEFPUSHBUTTON "GENERATE",IDOK,200,11,40,15
 PUSHBUTTON "EXIT",IDCANCEL,200,36,41,14
}


#makefile
NAME = KeyGen 
OBJS = $(NAME).obj #需要的目标文件
RES = $(NAME).res #需要的资源文件

LINK_FLAG = /subsystem:windows #连接选项
ML_FLAG = /c /coff #编译选项

$(NAME).exe: $(OBJS) $(RES)
Link $(LINK_FLAG) $(OBJS) $(RES)

.asm.obj:
ml $(ML_FLAG) $<
.rc.res:
rc $<

clean:
del *.obj
del *.res