万能五笔2001注册码分析及暴力破解
日期:2003年6月9日 作者:poorthinker 人气: 675
此软件比较复杂,未注册前,给出注册框,并限定了使用次数,使用两百次之后,不能继续使用,哪怕是输入正确的注册码也不行,重装也不行。输入注册码之后,软件退出,在每次启动时都要重新判断注册码正确与否。
它在注册时采用了从电脑获取电脑码,并将输入的注册码进行计算,算得的值同电脑码进行比较,相等则表示注册正确。由于每台电脑的电脑码不同,保证了一个注册码只能够用于同一台电脑。
若用注册机的方法进行注册,由于在某些用户的机子上,已经超过了使用次数。这时注册已经晚了。所以没办法,最后还是采取暴力破解更可行。
在注册方面,作者设置了很多的障碍:输入的注册码有固定的前四位和后四位,只有中间的几位才参与计算;在程序入口,也设置了相当多的障碍,加了许多的判断,让我几乎迷失在无穷的跳转中,即使在子程序也加入了跳转。最后很无赖,只好跟踪正确注册的程序,才找到正确的路径。
写的有点长,对不起大家。
以下是对注册码的分析,然后是再对其进行暴力破解
运行TRW,装入!WNM,在出现对话框时,下BPX HMEMCPY,大家都是成年人,不用我说得太具体吧。
跟踪到以下代码:
016F:0048CB74 MOV EDX,[00496D34] 此处存的是“tt98 0615"
016F:0048CB7A MOVSX EAX,CX
016F:0048CB7D MOV DL,[EDX+EAX] 依次取出8,9,t,t
016F:0048CB80 CMP DL,3F
016F:0048CB83 JZ 0048CB8B
016F:0048CB85 CMP [ESP+EAX+1C],DL 依次输入的注册码的第4,3,2,1位
016F:0048CB89 JNZ 0048CB8F
016F:0048CB8B DEC CX
016F:0048CB8D JNS 0048CB74 以上为比较前面四个字节是否为 tt98
016F:0048CB8F CMP CX,BYTE -01
016F:0048CB93 JNZ 0048CB9A
016F:0048CB95 MOV EBP,01 =1 可能表示首四位是正确的
016F:0048CB9A MOV EDI,[00496CBC] 为 "0615"
016F:0048CBA0 MOV ECX,FFFFFFFF
016F:0048CBA5 SUB EAX,EAX
016F:0048CBA7 REPNE SCASB
016F:0048CBA9 NOT ECX
016F:0048CBAB DEC ECX 算出为4位
016F:0048CBAC LEA EDI,[ESP+1C] 为输入的注册码
016F:0048CBB0 MOV DX,CX
016F:0048CBB3 SUB EAX,EAX
016F:0048CBB5 MOV ECX,FFFFFFFF
016F:0048CBBA REPNE SCASB
016F:0048CBBC NOT ECX
016F:0048CBBE DEC ECX 算出输入的注册码位数
016F:0048CBBF SUB CX,DX 减去4位
016F:0048CBC2 TEST CX,CX
016F:0048CBC5 JNG 0048CBF6
016F:0048CBC7 XOR SI,SI
016F:0048CBCA TEST DX,DX
016F:0048CBCD JNG 0048CBF0
016F:0048CBCF MOV EAX,[00496CBC] 存的是0615的地址
016F:0048CBD4 MOVSX EDI,SI
016F:0048CBD7 MOV AL,[EAX+EDI] 0615中的0
016F:0048CBDA CMP AL,3F 小于F
016F:0048CBDC JZ 0048CBE9
016F:0048CBDE MOVSX EBX,CX
016F:0048CBE1 ADD EBX,EDI
016F:0048CBE3 CMP [ESP+EBX+1C],AL
016F:0048CBE7 JNZ 0048CBF0
016F:0048CBE9 INC SI
016F:0048CBEB CMP DX,SI
016F:0048CBEE JG 0048CBCF 以上几行比较后四位是否为0615
016F:0048CBF0 CMP DX,SI
016F:0048CBF3 JNZ 0048CBF6
016F:0048CBF5 INC EBP 由48CB95,可知道 EBP=2,可能表示首四位和末四位都正确
016F:0048CBF6 CMP EBP,BYTE +02
016F:0048CBF9 JZ 0048CC05 跳到下面,
016F:0048CBFB MOV EBP,FFFFFFFE
016F:0048CC00 JMP 0048CD05
016F:0048CC05 MOV EDI,[00496D34] 此处存的是“tt98 0615"
016F:0048CC0B MOV ECX,FFFFFFFF
016F:0048CC10 SUB EAX,EAX
016F:0048CC12 REPNE SCASB
016F:0048CC14 NOT ECX ecx=5,这几行好像没什么用
016F:0048CC16 SUB EAX,EAX
016F:0048CC18 LEA ESI,[ESP+ECX+1B] 为输入的注册码后的第五位,即tt98后面的一位的地址
016F:0048CC1C MOV EDI,ESI
016F:0048CC1E MOV ECX,FFFFFFFF
016F:0048CC23 REPNE SCASB
016F:0048CC25 NOT ECX ecx=b,即tt98后面剩余的位数+1,包括0615
016F:0048CC27 MOV EDI,[00496CBC] edi为0615地址
016F:0048CC2D SUB EAX,EAX
016F:0048CC2F LEA EDX,[ECX-01] edx=a,即tt98后面剩余的位数
016F:0048CC32 MOV ECX,FFFFFFFF
016F:0048CC37 REPNE SCASB
016F:0048CC39 NOT ECX
016F:0048CC3B DEC ECX ECX=4
016F:0048CC3C MOV EAX,ESI
016F:0048CC3E SUB EAX,ECX 即输入的注册码位置
016F:0048CC40 MOV ECX,ESI
016F:0048CC42 MOV BYTE [EAX+EDX],00 即输入注册码的倒数第四位处,改位0,
以便于下面调用函数判断注册码中部(除tt98和
0165)的位数
016F:0048CC46 CALL 00491A20 !! : 判断输入的字符串是否满足要求,见子程序1
016F:0048CC4B TEST EAX,EAX
016F:0048CC4D JNZ 0048CC59 eax=1时,正确,跳转
016F:0048CC4F MOV EBP,FFFFFFFD
016F:0048CC54 JMP 0048CD05
016F:0048CC59 MOV EDX,004930E8 此时存的“0604”字符
016F:0048CC5E MOV ECX,ESI ESI为中间注册码首位地址
016F:0048CC60 MOV EBP,FFFFFFFC
016F:0048CC65 CALL 00491A70 将其由字符串转换成二进制的数,见子程序2
016F:0048CC6A CMP WORD [00496D28],BYTE +01
016F:0048CC72 MOV ESI,EAX
016F:0048CC74 JNZ 0048CCCF
016F:0048CC76 MOV DI,[00496D2E]
016F:0048CC7D MOV EDX,[00496CB0]
016F:0048CC83 SHR DI,08
016F:0048CC87 MOV CX,[00496D2E]
016F:0048CC8E AND CX,FF
016F:0048CC93 CALL 0048C790
016F:0048CC98 ADD ESI,EAX
016F:0048CC9A TEST DI,DI
016F:0048CC9D JNZ 0048CCA9
016F:0048CC9F MOV EDX,[00496CB4]
016F:0048CCA5 MOV ECX,EDI
016F:0048CCA7 JMP SHORT 0048CCB4
016F:0048CCA9 MOV CX,DI
016F:0048CCAC MOV EDX,[00496CB4]
016F:0048CCB2 INC CX
016F:0048CCB4 CALL 0048C790
016F:0048CCB9 MOV ECX,EAX
016F:0048CCBB TEST ECX,ECX
016F:0048CCBD JNZ 0048CCC6
016F:0048CCBF MOV EBP,FFFFFFFB
016F:0048CCC4 JMP SHORT 0048CCFC
016F:0048CCC6 MOV EAX,ESI
016F:0048CCC8 CDQ
016F:0048CCC9 IDIV ECX
016F:0048CCCB MOV EBP,EDX
016F:0048CCCD JMP SHORT 0048CCFC
016F:0048CCCF CMP WORD [00496D28],BYTE +02
016F:0048CCD7 JNZ 0048CCFC
016F:0048CCD9 MOV DX,[00496D2E] 存的是 63 64,即6463
016F:0048CCE0 MOV EAX,[00496CB4] 输入的注册人名地址
016F:0048CCE5 PUSH EAX
016F:0048CCE6 MOV ECX,[00496CB0] 也是 输入的注册人名地址
016F:0048CCEC PUSH ECX
016F:0048CCED MOV ECX,[00496AC4] 取出17EF7,十进制为98039,即我机子上的电脑码
016F:0048CCF3 CALL 0048C820 是由注册人名和电脑码算出一个数值
!!! 若将此值换算成十进制,即为正确的中间注册码
016F:0048CCF8 MOV EBP,EAX
016F:0048CCFA SUB EBP,ESI
016F:0048CCFC TEST EBP,EBP
016F:0048CCFE JZ 0048CD29 !!! 此值与原算得的二进制数比较,
相等表示输入的注册码正确,应跳转
016F:0048CD00 MOV EBP,FFFFFFFB
016F:0048CD05 TEST EBP,EBP
016F:0048CD07 JNL 0048CD29
016F:0048CD09 INC WORD [ESP+12]
016F:0048CD0E MOV AX,[ESP+12]
016F:0048CD13 CMP [00496D38],AX
016F:0048CD1A JG NEAR 0048C913
016F:0048CD20 JMP SHORT 0048CD29
016F:0048CD22 MOV EBP,[ESP+84]
016F:0048CD29 XOR ESI,ESI
016F:0048CD2B TEST EBP,EBP
016F:0048CD2D JL NEAR 0048CE08 若注册码正确,不跳
016F:0048CD33 MOV AX,[ESP+12]
016F:0048CD38 CMP [00496D38],AX
016F:0048CD3F JNG NEAR 0048CE08
016F:0048CD45 MOV EDX,01
016F:0048CD4A MOV ECX,[ESP+12]
016F:0048CD4E CALL 0048C4C0 此处是判断是否过时,若过时,即使注册码对,也不能用
016F:0048CD53 TEST EAX,EAX
016F:0048CD55 JZ 0048CDCD 过时则不跳转,应跳转
016F:0048CD57 PUSH DWORD 1010
016F:0048CD5C MOV EBX,[00496D3C]
016F:0048CD62 MOVSX EAX,WORD [ESP+16]
016F:0048CD67 SHL EAX,02
016F:0048CD6A PUSH DWORD 004930E0
016F:0048CD6F LEA ECX,[EAX+EAX*2]
016F:0048CD72 LEA EDX,[ECX+ECX*4]
016F:0048CD75 MOV ECX,[ESP+1C]
016F:0048CD79 MOV EAX,[EDX+EBX+34]
016F:0048CD7D PUSH EAX
016F:0048CD7E PUSH ECX
016F:0048CD7F CALL `USER32!MessageBoxA` 出现过时框
016F:0048CD85 MOV ECX,[ESP+14]
016F:0048CD89 PUSH DWORD 1001
016F:0048CD8E PUSH ECX
016F:0048CD8F CALL `USER32!GetDlgItem`
016F:0048CD95 MOV ECX,EAX
016F:0048CD97 CALL 0048B910
016F:0048CD9C MOV [00496A5E],SI
016F:0048CDA3 PUSH ESI
016F:0048CDA4 MOV [004931C0],SI
016F:0048CDAB PUSH DWORD 8002
016F:0048CDB0 PUSH DWORD 0111
016F:0048CDB5 MOV ECX,[00496C80]
016F:0048CDBB PUSH ECX
016F:0048CDBC CALL `USER32!SendMessageA`
016F:0048CDC2 POP EBP
016F:0048CDC3 POP EDI
016F:0048CDC4 POP ESI
016F:0048CDC5 POP EBX
016F:0048CDC6 ADD ESP,A8
016F:0048CDCC RET
016F:0048CDCD MOV EAX,[ESP+14]
016F:0048CDD1 MOV ECX,[00496C80]
016F:0048CDD7 MOV BYTE [00496AB3],02
016F:0048CDDE PUSH EAX
016F:0048CDDF PUSH DWORD 8000
016F:0048CDE4 PUSH DWORD 0111
016F:0048CDE9 PUSH ECX
016F:0048CDEA CALL `USER32!SendMessageA`
016F:0048CDF0 MOV ECX,[ESP+14]
016F:0048CDF4 PUSH BYTE +01
016F:0048CDF6 PUSH ECX
016F:0048CDF7 CALL `USER32!EndDialog`
016F:0048CDFD POP EBP
016F:0048CDFE POP EDI
016F:0048CDFF POP ESI
016F:0048CE00 POP EBX
016F:0048CE01 ADD ESP,A8
016F:0048CE07 RET
子程序1
016F:00491A20 PUSH ESI
016F:00491A21 MOV EDX,ECX edx,ecx为注册码中间部分的起始地址
016F:00491A23 PUSH EDI
016F:00491A24 XOR ESI,ESI
016F:00491A26 MOV EDI,EDX edi为注册码中间部分的起始地址
016F:00491A28 MOV ECX,FFFFFFFF
016F:00491A2D SUB EAX,EAX
016F:00491A2F REPNE SCASB
016F:00491A31 NOT ECX
016F:00491A33 DEC ECX 中间部分的位数
016F:00491A34 TEST ECX,ECX
016F:00491A36 JNG 00491A56 位数小于1,跳转,但不出错;位数大于1,不跳
以下循环判断中间注册码是否满足条件
016F:00491A38 MOV AL,[EDX+ESI] 取出字符
016F:00491A3B CMP AL,30
016F:00491A3D JC 00491A5E
016F:00491A3F CMP AL,39
016F:00491A41 JA 00491A5E 是否在0~9之间,不再,则出错输出EAX=0
016F:00491A43 INC ESI
016F:00491A44 MOV EDI,EDX
016F:00491A46 MOV ECX,FFFFFFFF
016F:00491A4B SUB EAX,EAX
016F:00491A4D REPNE SCASB
016F:00491A4F NOT ECX
016F:00491A51 DEC ECX
016F:00491A52 CMP ECX,ESI
016F:00491A54 JG 00491A38 循环判断
016F:00491A56 MOV EAX,01 正确,输出EAX=1
016F:00491A5B POP EDI
016F:00491A5C POP ESI
016F:00491A5D RET
016F:00491A5E XOR EAX,EAX
016F:00491A60 POP EDI
016F:00491A61 POP ESI
016F:00491A62 RET
子程序2
016F:00491A70 SUB ESP,BYTE +08
016F:00491A73 MOV [ESP+04],EDX 0604字符串
016F:00491A77 PUSH EBX
016F:00491A78 MOV DWORD [ESP+04],00
016F:00491A80 PUSH ESI
016F:00491A81 PUSH EDI
016F:00491A82 PUSH EBP
016F:00491A83 MOV ESI,01
016F:00491A88 PUSH ECX
016F:00491A89 MOV EBP,ECX ESI为中间注册码首位地址
016F:00491A8B CALL `KERNEL32!lstrlenA` 求出中间注册码长度
016F:00491A91 LEA EDI,[EAX-01] EDI=长度-1
016F:00491A94 TEST EDI,EDI
016F:00491A96 JL 00491AD3 长度大于0则不跳,否则出错
以下循环
016F:00491A98 MOV BL,[EBP+EDI+00] 依次取出中间注册码末位,末位-1,......
016F:00491A9C CMP BL,30
016F:00491A9F JC 00491AAA
016F:00491AA1 CMP BL,39
016F:00491AA4 JA 00491AAA 是否在0~9之间
016F:00491AA6 TEST EDI,EDI
016F:00491AA8 JNL 00491AB8 肯定要跳
016F:00491AAA MOV ECX,00493504
016F:00491AAF MOV EDX,[ESP+14]
016F:00491AB3 CALL 00491600
016F:00491AB8 XOR EAX,EAX
016F:00491ABA LEA ECX,[ESI+ESI*4] 由491A83知,esi开始1,算得ECX=5,以后依次esi*10,即10,100,1000.....
016F:00491ABD MOV AL,BL
016F:00491ABF SUB EAX,BYTE +30 将此字符转换成二进制数
016F:00491AC2 IMUL EAX,ESI
016F:00491AC5 LEA ESI,[ECX*2+`DOSMGR_BackFill_Allowed`]
DOSMGR_BackFill_Allowed=0
算得ESI=10
016F:00491ACC ADD [ESP+10],EAX 原来的字符
016F:00491AD0 DEC EDI
016F:00491AD1 JNS 00491A98 循环,直至所有的字符
016F:00491AD3 MOV EAX,[ESP+10] 由上面的分析,可知此子程序将输入中间注册码
016F:00491AD7 POP EBP 由字符串转换成二进制的数
016F:00491AD8 POP EDI
016F:00491AD9 POP ESI
016F:00491ADA POP EBX
016F:00491ADB ADD ESP,BYTE +08
016F:00491ADE RET
总结一下,以上代码将输入的注册码进行判断,首先看注册码的起始和结尾的固定码是否正确,若正确判断中间注册码是否满足一定要求。然后取出本机的电脑码,由其算出正确的注册码。
关键点:
在48ccf3处,算出正确的注册码(要转换成十进制才能看到)
在48ccfe处与输入的注册码进行比较。
上面的这一段,其实是我的失败经验。因为我不知怎么乱搞,把注册次数搞成了0次,这下即使得到注册码也没用了,只好用暴力法破解。
分析文件入口处的代码:
016F:0048E01D MOV ECX,01
016F:0048E022 CALL 00490AA0 取得电脑信息码98039
016F:0048E027 XOR EAX,EAX
016F:0048E029 MOV AX,[00496D32]
016F:0048E02F TEST AH,C0 ah=f0
016F:0048E032 JNZ NEAR 0048E066 应该跳转
016F:0048E038 XOR EAX,EAX
016F:0048E03A MOV AX,[00496D32]
016F:0048E040 TEST AH,10
016F:0048E043 JZ NEAR 0048E066 [496d32]=10 表示次数已用完
016F:0048E049 PUSH BYTE +00
016F:0048E04B PUSH DWORD 8003
016F:0048E050 PUSH DWORD 0111
016F:0048E055 MOV EAX,[00496C80]
016F:0048E05A PUSH EAX
016F:0048E05B CALL `USER32!SendMessageA` 次数已用完错误框
016F:0048E061 JMP 0048E06B
016F:0048E066 CALL 0048E680
016F:0048E06B CMP DWORD [00493170],BYTE +00
016F:0048E072 JZ NEAR 0048E08E
016F:0048E078 MOV ECX,[EBP-50]
016F:0048E07B CALL 00490CC0 若注册表中的注册码不对,显示开始的注册框,里面又有跳转见子程序3,要改
016F:0048E080 MOV [EBP-50],EAX
016F:0048E083 MOV ECX,[EBP-50]
016F:0048E086 CALL 00490D80 若注册码正确,即显示正确框,里面有跳转,见子程序4,要改
016F:0048E08B MOV [EBP-50],EAX
016F:0048E08E CMP DWORD [EBP-50],BYTE +01
016F:0048E092 JNZ NEAR 0048E0BF
016F:0048E098 XOR EAX,EAX
016F:0048E09A MOV AX,[004931B8]
016F:0048E0A0 TEST EAX,EAX
016F:0048E0A2 JZ NEAR 0048E0BF
016F:0048E0A8 XOR EAX,EAX
016F:0048E0AA MOV AX,[00496A9F]
016F:0048E0B0 TEST EAX,EAX
016F:0048E0B2 JZ NEAR 0048E0BF
016F:0048E0B8 DEC WORD [00496A9F]
016F:0048E0BF CMP DWORD [EBP-50],BYTE +01
016F:0048E0C3 JNZ NEAR 0048E1D5
016F:0048E0C9 XOR EAX,EAX
016F:0048E0CB MOV AX,[004931B8]
016F:0048E0D1 TEST EAX,EAX
016F:0048E0D3 JZ NEAR 0048E1D5
016F:0048E0D9 XOR EAX,EAX
016F:0048E0DB MOV AX,[0049317C]
016F:0048E0E1 TEST AL,02
016F:0048E0E3 JNZ NEAR 0048E107
016F:0048E0E9 CMP DWORD [00493178],BYTE +00
016F:0048E0F0 JZ NEAR 0048E107 应该跳转
016F:0048E0F6 XOR EAX,EAX
016F:0048E0F8 MOV AX,[0049317C]
016F:0048E0FE OR EAX,BYTE +02
016F:0048E101 MOV [0049317C],AX
016F:0048E107 XOR EAX,EAX
016F:0048E109 MOV AX,[0049317C]
016F:0048E10F TEST AL,02
016F:0048E111 JZ NEAR 0048E146 应该跳转
016F:0048E117 CALL 00491250
016F:0048E11C MOV [004931B8],AX
016F:0048E122 XOR EAX,EAX
016F:0048E124 MOV AX,[004931B8]
016F:0048E12A TEST EAX,EAX
016F:0048E12C JNZ NEAR 0048E146
016F:0048E132 PUSH BYTE +00
016F:0048E134 PUSH DWORD 004930B8
016F:0048E139 PUSH DWORD 004932DC
016F:0048E13E PUSH BYTE +00
016F:0048E140 CALL `USER32!MessageBoxA` server is full 错误信息
016F:0048E146 XOR EAX,EAX
016F:0048E148 MOV AX,[0049317C]
016F:0048E14E TEST AL,01
016F:0048E150 JNZ NEAR 0048E1D5
016F:0048E156 CMP DWORD [00493174],BYTE +00
016F:0048E15D JZ NEAR 0048E198 应该跳转
016F:0048E163 MOVSX EAX,WORD [00496AB1]
016F:0048E16A TEST EAX,EAX
016F:0048E16C JL NEAR 0048E198
016F:0048E172 MOVSX EAX,WORD [00496AB1]
016F:0048E179 SHL EAX,02
016F:0048E17C LEA EAX,[EAX+EAX*2]
016F:0048E17F LEA EAX,[EAX+EAX*4]
016F:0048E182 MOV ECX,[00496D3C]
016F:0048E188 XOR EDX,EDX
016F:0048E18A MOV DX,[EAX+ECX+28]
016F:0048E18F TEST DL,08
016F:0048E192 JNZ NEAR 0048E1C4
016F:0048E198 CMP DWORD [00493174],BYTE +00
016F:0048E19F JZ NEAR 0048E1D5 应该跳转
016F:0048E1A5 MOVSX EAX,WORD [00496AB1]
016F:0048E1AC TEST EAX,EAX
016F:0048E1AE JNL NEAR 0048E1D5
016F:0048E1B4 XOR EAX,EAX
016F:0048E1B6 MOV AX,[00496D44]
016F:0048E1BC TEST AL,08
016F:0048E1BE JZ NEAR 0048E1D5
016F:0048E1C4 XOR EAX,EAX
016F:0048E1C6 MOV AX,[0049317C]
016F:0048E1CC OR EAX,BYTE +01
016F:0048E1CF MOV [0049317C],AX
016F:0048E1D5 XOR EAX,EAX
016F:0048E1D7 MOV AX,[0049317C]
016F:0048E1DD TEST EAX,EAX
016F:0048E1DF JZ NEAR 0048E2B7 应该跳转
016F:0048E1E5 CMP DWORD [EBP-50],BYTE +01
016F:0048E1E9 JNZ NEAR 0048E2B7
016F:0048E1EF XOR EAX,EAX
016F:0048E1F1 MOV AX,[004931B8]
016F:0048E1F7 TEST EAX,EAX
016F:0048E1F9 JZ NEAR 0048E2B7
016F:0048E1FF LEA EAX,[EBP-64]
016F:0048E202 PUSH EAX
016F:0048E203 MOV EDX,00496C70
016F:0048E208 LEA ECX,[00496AA1]
016F:0048E20E CALL 00491B50
016F:0048E213 MOV ECX,00496A40
016F:0048E218 ADD ECX,BYTE +61
016F:0048E21B MOV EDX,[EAX]
016F:0048E21D MOV [ECX],EDX
016F:0048E21F MOV EDX,[EAX+04]
016F:0048E222 MOV [ECX+04],EDX
016F:0048E225 MOV EDX,[EAX+08]
016F:0048E228 MOV [ECX+08],EDX
016F:0048E22B MOV EAX,[EAX+0C]
016F:0048E22E MOV [ECX+0C],EAX
016F:0048E231 CALL 00490640
016F:0048E236 TEST EAX,EAX
016F:0048E238 JNZ NEAR 0048E24D
016F:0048E23E MOV EDX,004932D4
016F:0048E243 MOV ECX,004932B8
016F:0048E248 CALL 00491600
016F:0048E24D MOV EDX,00496B40
016F:0048E252 LEA ECX,[00496AA1]
016F:0048E258 CALL 00490BC0
016F:0048E25D MOV ECX,[EBP+10]
016F:0048E260 CALL 00491100
016F:0048E265 TEST EAX,EAX
016F:0048E267 JZ NEAR 0048E295
016F:0048E26D CALL 00491080
016F:0048E272 MOV [EBP-50],EAX
016F:0048E275 PUSH BYTE +00
016F:0048E277 PUSH BYTE +00
016F:0048E279 PUSH BYTE +10
016F:0048E27B MOV EAX,[00496C80]
016F:0048E280 PUSH EAX
016F:0048E281 CALL `USER32!SendMessageA`
016F:0048E287 MOV WORD [004931B8],00
016F:0048E290 JMP 0048E2B7
016F:0048E295 MOV DWORD [EBP-50],00
016F:0048E29C MOV WORD [004931B8],00
016F:0048E2A5 PUSH BYTE +00
016F:0048E2A7 PUSH BYTE +00
016F:0048E2A9 PUSH BYTE +10
016F:0048E2AB MOV EAX,[00496C80]
016F:0048E2B0 PUSH EAX
016F:0048E2B1 CALL `USER32!SendMessageA`
016F:0048E2B7 LEA EDX,[EBP-4C]
016F:0048E2BA LEA ECX,[EBP-54]
016F:0048E2BD CALL 0048E3D0
016F:0048E2C2 MOV [EBP-48],EAX
016F:0048E2C5 PUSH BYTE +00
016F:0048E2C7 PUSH BYTE +00
016F:0048E2C9 PUSH BYTE +10
016F:0048E2CB MOV EAX,[00496C80]
016F:0048E2D0 PUSH EAX
016F:0048E2D1 CALL `USER32!SendMessageA`
016F:0048E2D7 CMP DWORD [00493180],BYTE +02
016F:0048E2DE JZ NEAR 0048E32C 要改
016F:0048E2E4 CMP DWORD [EBP-50],BYTE +01
016F:0048E2E8 JNZ NEAR 0048E32C 要改
016F:0048E2EE XOR EAX,EAX
016F:0048E2F0 MOV AX,[004931B8]
016F:0048E2F6 TEST EAX,EAX
016F:0048E2F8 JZ NEAR 0048E32C 要改
016F:0048E2FE MOV EAX,[EBP+08]
016F:0048E301 PUSH EAX
016F:0048E302 PUSH DWORD 004931A8
016F:0048E307 CALL `USER32!UnregisterClassA`
016F:0048E30D XOR EAX,EAX
016F:0048E30F MOV AX,[004931BC]
016F:0048E315 TEST EAX,EAX
016F:0048E317 JZ NEAR 0048E32C 要改
016F:0048E31D MOV EAX,[EBP-4C]
016F:0048E320 PUSH EAX
016F:0048E321 LEA EDX,[EBP-54]
016F:0048E324 MOV ECX,[EBP-48]
016F:0048E327 CALL 0048E360 好了,就是它,但此过程中又有跳转,见下面子程序5,要改
016F:0048E32C CMP DWORD [EBP-54],BYTE +00
016F:0048E330 JZ NEAR 0048E33E
016F:0048E336 MOV ECX,[EBP-54]
016F:0048E339 CALL 004915F0
016F:0048E33E MOV EAX,[EBP-50]
016F:0048E341 PUSH EAX
016F:0048E342 CALL `KERNEL32!ExitProcess`
016F:0048E348 MOV EAX,[EBP-50]
016F:0048E34B JMP 0048E350
016F:0048E350 POP EDI
016F:0048E351 POP ESI
016F:0048E352 POP EBX
016F:0048E353 LEAVE
016F:0048E354 RET 10
子程序3:若上次退出前输入的注册码正确,此处不显示注册码对话框,否则要显示
016F:00490CC0 TEST BYTE [00496D33],80
016F:00490CC7 PUSH ESI
016F:00490CC8 PUSH EDI
016F:00490CC9 MOV ESI,ECX
016F:00490CCB JZ NEAR 00490D7A
016F:00490CD1 CMP WORD [004931B8],BYTE +00
016F:00490CD9 JNZ 00490CE4
016F:00490CDB CMP BYTE [00496AB3],02
016F:00490CE2 JNZ 00490D15 跳转
016F:00490CE4 CMP WORD [00496AB1],BYTE +00
016F:00490CEC JL 00490D0B
016F:00490CEE MOVSX EAX,WORD [00496AB1]
016F:00490CF5 SHL EAX,02
016F:00490CF8 LEA ECX,[EAX+EAX*2]
016F:00490CFB MOV EAX,[00496D3C]
016F:00490D00 LEA EDX,[ECX+ECX*4]
016F:00490D03 CMP WORD [EDX+EAX+02],BYTE +00
016F:00490D09 JNZ 00490D15
016F:00490D0B CMP WORD [00493160],BYTE +02
016F:00490D13 JNZ 00490D7A
016F:00490D15 XOR EDX,EDX
016F:00490D17 MOV ECX,68
016F:00490D1C MOV ESI,00
016F:00490D21 CALL 00491510
016F:00490D26 MOV EDX,00496B20
016F:00490D2B MOV ECX,EAX
016F:00490D2D MOV [00496CC0],EAX
016F:00490D32 CALL 0048D4E0
016F:00490D37 TEST EAX,EAX
016F:00490D39 JZ 00490D4C 应该跳转
016F:00490D3B MOV EDX,0048D010
016F:00490D40 MOV ECX,00496B20
016F:00490D45 CALL 0048D680 即注册对话框
016F:00490D4A MOV ESI,EAX
016F:00490D4C MOV ECX,00496B20 到此处
016F:00490D51 CALL 0048B200
016F:00490D56 MOV EAX,[00496CC0]
016F:00490D5B MOV EDI,[00497394]
016F:00490D61 PUSH EAX
016F:00490D62 CALL EDI
016F:00490D64 PUSH EAX
016F:00490D65 CALL `KERNEL32!GlobalUnlock`
016F:00490D6B MOV EAX,[00496CC0]
016F:00490D70 PUSH EAX
016F:00490D71 CALL EDI
016F:00490D73 PUSH EAX
016F:00490D74 CALL `KERNEL32!GlobalFree`
016F:00490D7A MOV EAX,ESI
016F:00490D7C POP EDI
016F:00490D7D POP ESI
子程序4:若上次退出前输入的注册码正确,显示注册人和注册名框,否则不显示
016F:00490D80 TEST BYTE [00496D33],40
016F:00490D87 PUSH ESI
016F:00490D88 PUSH EDI
016F:00490D89 MOV ESI,ECX
016F:00490D8B JZ NEAR 00490E86
016F:00490D91 CMP WORD [00496AB1],BYTE +00
016F:00490D99 JL 00490DBC
016F:00490D9B MOVSX EAX,WORD [00496AB1]
016F:00490DA2 SHL EAX,02
016F:00490DA5 LEA ECX,[EAX+EAX*2]
016F:00490DA8 MOV EAX,[00496D3C]
016F:00490DAD LEA EDX,[ECX+ECX*4]
016F:00490DB0 CMP WORD [EDX+EAX+02],BYTE +00
016F:00490DB6 JNZ NEAR 00490E86
016F:00490DBC CMP WORD [004931B8],BYTE +00
016F:00490DC4 JZ 00490DCF
016F:00490DC6 CMP BYTE [00496AB3],02
016F:00490DCD JZ 00490E00
016F:00490DCF TEST BYTE [00496D33],80
016F:00490DD6 JNZ NEAR 00490E86 不跳
016F:00490DDC TEST BYTE [00496D33],10
016F:00490DE3 JZ 00490E00 应该跳转
016F:00490DE5 MOV ECX,01
016F:00490DEA CALL 0048E700 次数用完对话框
016F:00490DEF TEST EAX,EAX
016F:00490DF1 JZ 00490E00
016F:00490DF3 TEST BYTE [00496D33],10
016F:00490DFA JNZ NEAR 00490E86
016F:00490E00 XOR EDX,EDX
016F:00490E02 MOV ECX,6D
016F:00490E07 MOV ESI,00
016F:00490E0C CALL 00491510
016F:00490E11 MOV EDX,00496C90
016F:00490E16 MOV ECX,EAX
016F:00490E18 MOV [00496D1C],EAX
016F:00490E1D CALL 0048D4E0
016F:00490E22 TEST EAX,EAX
016F:00490E24 JZ 00490E37
016F:00490E26 MOV EDX,0048D6C0
016F:00490E2B MOV ECX,00496C90
016F:00490E30 CALL 0048D680 注册正确框,正确的注册名和注册码
016F:00490E35 MOV ESI,EAX
016F:00490E37 MOV ECX,00496C90
016F:00490E3C CALL 0048B200
016F:00490E41 MOV EAX,[00496D1C]
016F:00490E46 MOV EDI,[00497394]
016F:00490E4C PUSH EAX
016F:00490E4D CALL EDI
016F:00490E4F PUSH EAX
016F:00490E50 CALL `KERNEL32!GlobalUnlock`
016F:00490E56 MOV EAX,[00496D1C]
016F:00490E5B PUSH EAX
016F:00490E5C CALL EDI
016F:00490E5E PUSH EAX
016F:00490E5F CALL `KERNEL32!GlobalFree`
016F:00490E65 TEST BYTE [00496D33],10
016F:00490E6C JNZ 00490E86
016F:00490E6E PUSH BYTE +00
016F:00490E70 MOV EAX,[00496C80]
016F:00490E75 PUSH DWORD 8000
016F:00490E7A PUSH DWORD 0111
016F:00490E7F PUSH EAX
016F:00490E80 CALL `USER32!SendMessageA`
016F:00490E86 MOV EAX,ESI
016F:00490E88 POP EDI
016F:00490E89 POP ESI
ret
子程序5:进入正确的万能五笔程序,但进入前要判断一下。
016F:0048E360 PUSH ESI
016F:0048E361 PUSH EDI
016F:0048E362 MOV ESI,EDX
016F:0048E364 MOV EDI,[ESP+0C]
016F:0048E368 MOV EDX,[ECX+02]
016F:0048E36B XOR EDX,[ECX+06]
016F:0048E36E XOR EDX,[ECX+0A]
016F:0048E371 ADD EDI,EDX
016F:0048E373 XOR EDX,EDX
016F:0048E375 MOV EAX,[ECX+06]
016F:0048E378 INC EDX
016F:0048E379 XOR [EDI+EDX*4-04],EAX
016F:0048E37D INC EDX
016F:0048E37E MOV EAX,[ECX+0A]
016F:0048E381 XOR [EDI+EDX*4-04],EAX
016F:0048E385 CMP EDX,BYTE +14
016F:0048E388 JL 0048E375
016F:0048E38A MOV ECX,[ESI]
016F:0048E38C CALL 004915F0
016F:0048E391 MOV DWORD [ESI],00
016F:0048E397 CMP WORD [004931B8],BYTE +00
016F:0048E39F JZ 0048E3AD 要改
016F:0048E3A1 CMP WORD [004931C0],BYTE +00
016F:0048E3A9 JZ 0048E3AD
016F:0048E3AB CALL EDI 就是它,正确的程序在此处,TNND,找死我了
016F:0048E3AD PUSH BYTE +00
016F:0048E3AF PUSH DWORD 00493328
016F:0048E3B4 PUSH DWORD 00493318
016F:0048E3B9 PUSH BYTE +00
016F:0048E3BB CALL `USER32!MessageBoxA`
016F:0048E3C1 POP EDI
016F:0048E3C2 POP ESI
016F:0048E3C3 RET 04
好,总结以下,其实就是不断的判断障碍,
注册对话框在 48e07b call的子程序中。
正确的程序代码藏在 48e3ab call的子程序中。
知道了这一点(也是最困难的一点),就容易对症下药了。
其中要更改的地方有:
490d39
48e086 改为nop
48e2de
48e2e8
48e2f8
48e39f
48e3a9
当然不一定非得如此,只要能跳到48e3ab,其他的跳转应该也行。