我也不知道自己消失了多久,反正自从上次硬盘挂掉,装系统时一时疏忽,直接装了XP而且全盘NTFS,就很少再碰破解了,只会在98下用TRW拦着hmemcpy的我,除了偶尔给同学解解需要用的软件,就再也没有研究过破解。几年来,BCG一个月一次的作业根本没做,想必早已被除名,说来真是惭愧,对不起BCG的大大,对不起朋友们。
前一阵子,在天空软件站偶然看到了SouSuite这个游戏,想起来我的第一篇破文,那篇01年9月8号发表的,非常幼稚的“SolSuite v8.0破解手记”,看雪老大出于鼓励新人,把它加了精,谢谢你。把SouSuite最新版本下载回来后,破了它,软件强度变大了,但我却发现自己的思路也清晰了。是啊,这么多年来,虽然已经很少研究破解,但是这中间学到的东西,不仅是对破解,更是对整个人生,都是非常有益的。

去天空软件站下载了我第一个破解的软件,一个棋类小游戏,监狱(Quod),当时的我,按着教程上面说的,用TRW载入,bpx hmemcpy,然后一步一步的跟(说是跟,其实是按),每走一步,都要d eax,d ebx…直到把所有寄存器都看完(别笑),终于看到真假注册码比较的时候,那时的心情,现在已经体会不到,也难以言表。

这次当然不止是要跟出注册码而已,先把以前欠的补回来一点吧。

破解:波导终结者
被破软件:监狱(Quod) V1.0
下载地址:http://www.skycn.com/soft/6245.html
工具:OD,W32DASM,FI,脱壳工具若干
监狱是一个棋类游戏,把四个进攻棋子连成一个正方形则即得胜利,每方有20个进攻棋子和6个防守棋子。不过感觉和五子棋相似,先走有很大优势……

先用FI看看加的什么壳,aspack 2.001。用主页的Aspackdie脱,却得修复。试了几个脱壳工具都如此,我又不会修复,无奈之下,用主页的通用脱壳工具File Scanner脱了下,竟然完美脱下来了,哈。
脱完壳,用W32DASM反汇编,很容易找到关键处



:0045F2F3 90                      nop
:0045F2F4 55                      push ebp
:0045F2F5 8BEC                    mov ebp, esp
:0045F2F7 33C9                    xor ecx, ecx
:0045F2F9 51                      push ecx
:0045F2FA 51                      push ecx
:0045F2FB 51                      push ecx
:0045F2FC 51                      push ecx
:0045F2FD 53                      push ebx
:0045F2FE 8BD8                    mov ebx, eax
:0045F300 33C0                    xor eax, eax
:0045F302 55                      push ebp
:0045F303 68ECF34500              push 0045F3EC
:0045F308 64FF30                  push dword ptr fs:[eax]
:0045F30B 648920                  mov dword ptr fs:[eax], esp
:0045F30E 8D55F8                  lea edx, dword ptr [ebp-08]
:0045F311 8B8300030000            mov eax, dword ptr [ebx+00000300]
:0045F317 E8989EFDFF              call 004391B4
:0045F31C 8B45F8                  mov eax, dword ptr [ebp-08]
:0045F31F 50                      push eax
:0045F320 8D55F0                  lea edx, dword ptr [ebp-10]
:0045F323 8B83FC020000            mov eax, dword ptr [ebx+000002FC]
:0045F329 E8869EFDFF              call 004391B4
:0045F32E 8B55F0                  mov edx, dword ptr [ebp-10]
:0045F331 8D4DF4                  lea ecx, dword ptr [ebp-0C]
:0045F334 8BC3                    mov eax, ebx
:0045F336 E8BD010000              call 0045F4F8
:0045F33B 8B55F4                  mov edx, dword ptr [ebp-0C]
:0045F33E 58                      pop eax
:0045F33F E8F854FAFF              call 0040483C
:0045F344 7576                    jne 0045F3BC                                很容易看出,这个跳转决定着注册成功或失败,于是从上面下断点
:0045F346 B201                    mov dl, 01
:0045F348 A1E8EA4500              mov eax, dword ptr [0045EAE8]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0045F2DE(C)
|
:0045F34D E896F8FFFF              call 0045EBE8
:0045F352 8945FC                  mov dword ptr [ebp-04], eax
:0045F355 33C0                    xor eax, eax
:0045F357 55                      push ebp
:0045F358 68B5F34500              push 0045F3B5
:0045F35D 64FF30                  push dword ptr fs:[eax]
:0045F360 648920                  mov dword ptr fs:[eax], esp
:0045F363 B101                    mov cl, 01

* Possible StringData Ref from Code Obj ->"Software\XDZHAN\Quod"
                                  |
:0045F365 BA00F44500              mov edx, 0045F400
:0045F36A 8B45FC                  mov eax, dword ptr [ebp-04]
:0045F36D E87AF9FFFF              call 0045ECEC

* Possible StringData Ref from Code Obj ->"Real Programmers Use Pascal!"
                                  |
:0045F372 B920F44500              mov ecx, 0045F420

* Possible StringData Ref from Code Obj ->"Key"
                                  |
:0045F377 BA48F44500              mov edx, 0045F448
:0045F37C 8B45FC                  mov eax, dword ptr [ebp-04]
:0045F37F E804FBFFFF              call 0045EE88

* Possible StringData Ref from Code Obj ->"软件注册成功,谢谢您的支持!"
                                  |
:0045F384 B854F44500              mov eax, 0045F454
:0045F389 E82A39FDFF              call 00432CB8
:0045F38E A1E83E4600              mov eax, dword ptr [00463EE8]
:0045F393 8B00                    mov eax, dword ptr [eax]

* Possible StringData Ref from Code Obj ->"监狱(Quod)—注册版"
                                  |
:0045F395 BA78F44500              mov edx, 0045F478
:0045F39A E8459EFDFF              call 004391E4
:0045F39F 33C0                    xor eax, eax
:0045F3A1 5A                      pop edx
:0045F3A2 59                      pop ecx
:0045F3A3 59                      pop ecx
:0045F3A4 648910                  mov dword ptr fs:[eax], edx
:0045F3A7 68C6F34500              push 0045F3C6

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0045F3BA(U)
|
:0045F3AC 8B45FC                  mov eax, dword ptr [ebp-04]
:0045F3AF E82043FAFF              call 004036D4
:0045F3B4 C3                      ret


:0045F3B5 E9AE4AFAFF              jmp 00403E68
:0045F3BA EBF0                    jmp 0045F3AC

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0045F344(C)
|

* Possible StringData Ref from Code Obj ->"注册码不正确,无法注册!"
                                  |
:0045F3BC B894F44500              mov eax, 0045F494
:0045F3C1 E8F238FDFF              call 00432CB8
:0045F3C6 33C0                    xor eax, eax
:0045F3C8 5A                      pop edx
:0045F3C9 59                      pop ecx
:0045F3CA 59                      pop ecx
:0045F3CB 648910                  mov dword ptr fs:[eax], edx
:0045F3CE 68F3F34500              push 0045F3F3


-----------------------------------------------------------------

在此行拦断,开始跟踪
0045F302   .  55            PUSH EBP
0045F303   .  68 ECF34500   PUSH QUOD.0045F3EC
0045F308   .  64:FF30       PUSH DWORD PTR FS:[EAX]
0045F30B   .  64:8920       MOV DWORD PTR FS:[EAX],ESP
0045F30E   .  8D55 F8       LEA EDX,DWORD PTR SS:[EBP-8]
0045F311   .  8B83 00030000 MOV EAX,DWORD PTR DS:[EBX+300]
0045F317   .  E8 989EFDFF   CALL QUOD.004391B4
0045F31C   .  8B45 F8       MOV EAX,DWORD PTR SS:[EBP-8]             ;  假码->eax
0045F31F   .  50            PUSH EAX
0045F320   .  8D55 F0       LEA EDX,DWORD PTR SS:[EBP-10]
0045F323   .  8B83 FC020000 MOV EAX,DWORD PTR DS:[EBX+2FC]
0045F329   .  E8 869EFDFF   CALL QUOD.004391B4
0045F32E   .  8B55 F0       MOV EDX,DWORD PTR SS:[EBP-10]            ;  用户名->edx
0045F331   .  8D4D F4       LEA ECX,DWORD PTR SS:[EBP-C]
0045F334   .  8BC3          MOV EAX,EBX
0045F336   .  E8 BD010000   CALL QUOD.0045F4F8                       ;  ①下面一行就出真码了,所以这个CALL肯定是运算注册码的关键,跟进去
0045F33B   .  8B55 F4       MOV EDX,DWORD PTR SS:[EBP-C]             ;  [EBP-C]为真码,真码->edx
0045F33E   .  58            POP EAX                                  ;  假码->eax
0045F33F   .  E8 F854FAFF   CALL QUOD.0040483C                       ;  这个CALL就是进去比较真假注册码了,略过
0045F344   .  75 76         JNZ SHORT QUOD.0045F3BC                  ;  注册码不对就跳
0045F346   .  B2 01         MOV DL,1                                 ;  注册对了之后,下面开始写注册表项
0045F348   .  A1 E8EA4500   MOV EAX,DWORD PTR DS:[45EAE8]
0045F34D   .  E8 96F8FFFF   CALL QUOD.0045EBE8
0045F352   .  8945 FC       MOV DWORD PTR SS:[EBP-4],EAX
0045F355   .  33C0          XOR EAX,EAX
0045F357   .  55            PUSH EBP
0045F358   .  68 B5F34500   PUSH QUOD.0045F3B5
0045F35D   .  64:FF30       PUSH DWORD PTR FS:[EAX]
0045F360   .  64:8920       MOV DWORD PTR FS:[EAX],ESP
0045F363   .  B1 01         MOV CL,1
0045F365   .  BA 00F44500   MOV EDX,QUOD.0045F400                    ;  software\xdzhan\quod
0045F36A   .  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
0045F36D   .  E8 7AF9FFFF   CALL QUOD.0045ECEC
0045F372   .  B9 20F44500   MOV ECX,QUOD.0045F420                    ;  real programmers use pascal!
0045F377   .  BA 48F44500   MOV EDX,QUOD.0045F448                    ;  key
0045F37C   .  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
0045F37F   .  E8 04FBFFFF   CALL QUOD.0045EE88
0045F384   .  B8 54F44500   MOV EAX,QUOD.0045F454                    ;  软件注册成功,谢谢您的支持!
0045F389   .  E8 2A39FDFF   CALL QUOD.00432CB8
0045F38E   .  A1 E83E4600   MOV EAX,DWORD PTR DS:[463EE8]
0045F393   .  8B00          MOV EAX,DWORD PTR DS:[EAX]
0045F395   .  BA 78F44500   MOV EDX,QUOD.0045F478                    ;  监狱(quod)—注册版
0045F39A   .  E8 459EFDFF   CALL QUOD.004391E4
0045F39F   .  33C0          XOR EAX,EAX
0045F3A1   .  5A            POP EDX
0045F3A2   .  59            POP ECX
0045F3A3   .  59            POP ECX
0045F3A4   .  64:8910       MOV DWORD PTR FS:[EAX],EDX
0045F3A7   .  68 C6F34500   PUSH QUOD.0045F3C6
0045F3AC   >  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
0045F3AF   .  E8 2043FAFF   CALL QUOD.004036D4
0045F3B4   .  C3            RETN
0045F3B5   .^ E9 AE4AFAFF   JMP QUOD.00403E68
0045F3BA   .^ EB F0         JMP SHORT QUOD.0045F3AC
0045F3BC      B8 94F44500   MOV EAX,QUOD.0045F494                    ;  注册码不正确,无法注册!
0045F3C1   .  E8 F238FDFF   CALL QUOD.00432CB8
0045F3C6   .  33C0          XOR EAX,EAX
0045F3C8   .  5A            POP EDX
0045F3C9   .  59            POP ECX
0045F3CA   .  59            POP ECX
0045F3CB   .  64:8910       MOV DWORD PTR FS:[EAX],EDX
0045F3CE   .  68 F3F34500   PUSH QUOD.0045F3F3
0045F3D3   >  8D45 F0       LEA EAX,DWORD PTR SS:[EBP-10]
0045F3D6   .  E8 6550FAFF   CALL QUOD.00404440
0045F3DB   .  8D45 F4       LEA EAX,DWORD PTR SS:[EBP-C]
0045F3DE   .  E8 5D50FAFF   CALL QUOD.00404440
0045F3E3   .  8D45 F8       LEA EAX,DWORD PTR SS:[EBP-8]
0045F3E6   .  E8 5550FAFF   CALL QUOD.00404440
0045F3EB   .  C3            RETN
0045F3EC   .^ E9 774AFAFF   JMP QUOD.00403E68
0045F3F1   .^ EB E0         JMP SHORT QUOD.0045F3D3
0045F3F3   .  5B            POP EBX
0045F3F4   .  8BE5          MOV ESP,EBP
0045F3F6   .  5D            POP EBP
0045F3F7   .  C3            RETN

---------------------------------------------
跟进①里的情况
0045F4F8  /$  55            PUSH EBP
0045F4F9  |.  8BEC          MOV EBP,ESP
0045F4FB  |.  6A 00         PUSH 0
0045F4FD  |.  6A 00         PUSH 0
0045F4FF  |.  6A 00         PUSH 0
0045F501  |.  6A 00         PUSH 0
0045F503  |.  6A 00         PUSH 0
0045F505  |.  6A 00         PUSH 0
0045F507  |.  6A 00         PUSH 0
0045F509  |.  53            PUSH EBX
0045F50A  |.  56            PUSH ESI
0045F50B  |.  57            PUSH EDI
0045F50C  |.  894D F8       MOV DWORD PTR SS:[EBP-8],ECX
0045F50F  |.  8955 FC       MOV DWORD PTR SS:[EBP-4],EDX
0045F512  |.  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]             ;  用户名->eax
0045F515  |.  E8 C653FAFF   CALL QUOD.004048E0                       ;  跟进去后发现,仅是判断用户名是否为空,略过,下同
0045F51A  |.  33C0          XOR EAX,EAX
0045F51C  |.  55            PUSH EBP
0045F51D  |.  68 E0F54500   PUSH QUOD.0045F5E0
0045F522  |.  64:FF30       PUSH DWORD PTR FS:[EAX]
0045F525  |.  64:8920       MOV DWORD PTR FS:[EAX],ESP
0045F528  |.  33F6          XOR ESI,ESI
0045F52A  |.  8D45 F4       LEA EAX,DWORD PTR SS:[EBP-C]
0045F52D  |.  8B55 FC       MOV EDX,DWORD PTR SS:[EBP-4]             ;  用户名->edx
0045F530  |.  E8 A34FFAFF   CALL QUOD.004044D8                       ;  同上
0045F535  |.  8B45 F4       MOV EAX,DWORD PTR SS:[EBP-C]
0045F538  |.  E8 BB51FAFF   CALL QUOD.004046F8                       ;  计算用户名位数,位数=>eax
0045F53D  |.  8BF8          MOV EDI,EAX                              ;  用户名位数->edi
0045F53F  |.  85FF          TEST EDI,EDI                             ;  是否0位,这家伙怎么那么关心用户名是否为空
0045F541  |.  7E 57         JLE SHORT QUOD.0045F59A                  ;  不为空继续,要开始算出真码了
0045F543  |.  BB 01000000   MOV EBX,1                                ;  ebx=1,初始化,从第一位开始,一位位算
0045F548  |>  8B45 F4       /MOV EAX,DWORD PTR SS:[EBP-C]            ;  用户名->eax
0045F54B  |.  8A4418 FF     |MOV AL,BYTE PTR DS:[EAX+EBX-1]          ;  EAX+EBX-1,也就是用户名第ebx位,->al
0045F54F  |.  E8 58FFFFFF   |CALL QUOD.0045F4AC                      ;  ②跟进分析,此CALL判断当前位用户名的ASCII码是否素数
0045F554  |.  84C0          |TEST AL,AL                              ;  如果此位的ASCII不为素数,则直接跳过,如果为素数,继续运算
0045F556  |.  74 25         |JE SHORT QUOD.0045F57D
0045F558  |.  8D45 E8       |LEA EAX,DWORD PTR SS:[EBP-18]
0045F55B  |.  8B55 F4       |MOV EDX,DWORD PTR SS:[EBP-C]            ;  用户名->edx
0045F55E  |.  8A541A FF     |MOV DL,BYTE PTR DS:[EDX+EBX-1]
0045F562  |.  E8 B950FAFF   |CALL QUOD.00404620
0045F567  |.  8B45 E8       |MOV EAX,DWORD PTR SS:[EBP-18]
0045F56A  |.  8D55 EC       |LEA EDX,DWORD PTR SS:[EBP-14]
0045F56D  |.  E8 F28EFAFF   |CALL QUOD.00408464                      ;  ③把小写字母改成大写字母的CALL,跟进看看
0045F572  |.  8B55 EC       |MOV EDX,DWORD PTR SS:[EBP-14]
0045F575  |.  8D45 F0       |LEA EAX,DWORD PTR SS:[EBP-10]
0045F578  |.  E8 8351FAFF   |CALL QUOD.00404700                      ;  ④拼接第一部分大写的注册码,跟进看看
0045F57D  |>  83FB 01       |CMP EBX,1                               ;  是不是用户名的第一位,如果是的话
0045F580  |.  74 0A         |JE SHORT QUOD.0045F58C                  ;  位数不往后移,下次计算,还是计算第一位
0045F582  |.  8B45 F4       |MOV EAX,DWORD PTR SS:[EBP-C]
0045F585  |.  0FB64418 FE   |MOVZX EAX,BYTE PTR DS:[EAX+EBX-2]       ;  eax+ebx-2,也就是用户名下一位
0045F58A  |.  EB 06         |JMP SHORT QUOD.0045F592
0045F58C  |>  8B45 F4       |MOV EAX,DWORD PTR SS:[EBP-C]
0045F58F  |.  0FB600        |MOVZX EAX,BYTE PTR DS:[EAX]
0045F592  |>  8D7486 6C     |LEA ESI,DWORD PTR DS:[ESI+EAX*4+6C]     ;  第二部分注册码关键!ESI记录着第二部分注册码,每次都加上EAX*4+6C,也就是用户名ASCII*4+108(十进制),一位一位加
0045F596  |.  43            |INC EBX                                 ;  ebx记录着当前计算用户名的位数,加1
0045F597  |.  4F            |DEC EDI                                 ;  edi和ebx相反,记录着还剩几位没有算
0045F598  |.^ 75 AE         \JNZ SHORT QUOD.0045F548                 ;  没算完上去循环计算下一位用户名
0045F59A  |>  8D55 E4       LEA EDX,DWORD PTR SS:[EBP-1C]
0045F59D  |.  8BC6          MOV EAX,ESI
0045F59F  |.  E8 2C93FAFF   CALL QUOD.004088D0                       ;  ⑤第二部分数字注册码,进去看看
0045F5A4  |.  8B4D E4       MOV ECX,DWORD PTR SS:[EBP-1C]
0045F5A7  |.  8D45 F4       LEA EAX,DWORD PTR SS:[EBP-C]
0045F5AA  |.  8B55 F0       MOV EDX,DWORD PTR SS:[EBP-10]
0045F5AD  |.  E8 9251FAFF   CALL QUOD.00404744                       ;  两部分拼起来,略过
0045F5B2  |.  8B45 F8       MOV EAX,DWORD PTR SS:[EBP-8]
0045F5B5  |.  8B55 F4       MOV EDX,DWORD PTR SS:[EBP-C]
0045F5B8  |.  E8 D74EFAFF   CALL QUOD.00404494
0045F5BD  |.  33C0          XOR EAX,EAX
0045F5BF  |.  5A            POP EDX
0045F5C0  |.  59            POP ECX
0045F5C1  |.  59            POP ECX
0045F5C2  |.  64:8910       MOV DWORD PTR FS:[EAX],EDX
0045F5C5  |.  68 E7F54500   PUSH QUOD.0045F5E7
0045F5CA  |>  8D45 E4       LEA EAX,DWORD PTR SS:[EBP-1C]
0045F5CD  |.  BA 05000000   MOV EDX,5
0045F5D2  |.  E8 8D4EFAFF   CALL QUOD.00404464
0045F5D7  |.  8D45 FC       LEA EAX,DWORD PTR SS:[EBP-4]
0045F5DA  |.  E8 614EFAFF   CALL QUOD.00404440
0045F5DF  \.  C3            RETN




--------------------------------
跟进②里的情况
0045F4AC  /$  55            PUSH EBP
0045F4AD  |.  8BEC          MOV EBP,ESP
0045F4AF  |.  51            PUSH ECX
0045F4B0  |.  53            PUSH EBX
0045F4B1  |.  56            PUSH ESI
0045F4B2  |.  8845 FF       MOV BYTE PTR SS:[EBP-1],AL
0045F4B5  |.  C645 FD 02    MOV BYTE PTR SS:[EBP-3],2
0045F4B9  |.  C645 FE 01    MOV BYTE PTR SS:[EBP-2],1
0045F4BD  |.  8A4D FF       MOV CL,BYTE PTR SS:[EBP-1]               ;  这一位用户名的ASCII->ecx
0045F4C0  |.  49            DEC ECX                                  ;  
0045F4C1  |.  80E9 02       SUB CL,2                                 ;  
0045F4C4  |.  72 2A         JB SHORT QUOD.0045F4F0
0045F4C6  |.  41            INC ECX
0045F4C7  |.  B3 02         MOV BL,2                                 ;  ebx=2,作为被除数初始化
0045F4C9  |>  33C0          /XOR EAX,EAX
0045F4CB  |.  8A45 FF       |MOV AL,BYTE PTR SS:[EBP-1]              ;  这一位用户名的ASCII->eax
0045F4CE  |.  33D2          |XOR EDX,EDX                             ;  清空edx
0045F4D0  |.  8AD3          |MOV DL,BL                               ;  ebx->edx
0045F4D2  |.  8BF2          |MOV ESI,EDX                             ;  edx->esi
0045F4D4  |.  33D2          |XOR EDX,EDX                             ;  清空edx
0045F4D6  |.  F7F6          |DIV ESI                                 ;  eax除以esi,由于前面ebx->edx,edx->esi,其实也就是用户名ASCII除以一直增加的被除数ebx,经典的判断素数的方法
0045F4D8  |.  85D2          |TEST EDX,EDX                            ;  商->eax,余数->edx
0045F4DA  |.  75 03         |JNZ SHORT QUOD.0045F4DF                 ;  有余数,即除不尽就跳
0045F4DC  |.  FE45 FD       |INC BYTE PTR SS:[EBP-3]                 ;  
0045F4DF  |>  807D FD 02    |CMP BYTE PTR SS:[EBP-3],2               ;  
0045F4E3  |.  76 06         |JBE SHORT QUOD.0045F4EB                 ;  如果除不尽,则此处跳过下面的JMP,继续除至循环结束
0045F4E5  |.  C645 FE 00    |MOV BYTE PTR SS:[EBP-2],0               ;  置0,表示此位用户名ASCII不是素数
0045F4E9  |.  EB 05         |JMP SHORT QUOD.0045F4F0                 ;  如果除得尽,则此时此位用户名ASCII已经不是素数,直接跳出循环
0045F4EB  |>  43            |INC EBX                                 ;  ebx+1,从2一直往上加,作为被除数
0045F4EC  |.  FEC9          |DEC CL                                  ;  ecx-1
0045F4EE  |.^ 75 D9         \JNZ SHORT QUOD.0045F4C9                 ;  ecx减至为零时表示已经判断完,不跳,出循环
0045F4F0  |>  8A45 FE       MOV AL,BYTE PTR SS:[EBP-2]               ;  刚才堆栈里置0的标志->eax,出了CALL以后以此标志判断是否素数
0045F4F3  |.  5E            POP ESI
0045F4F4  |.  5B            POP EBX
0045F4F5  |.  59            POP ECX
0045F4F6  |.  5D            POP EBP
0045F4F7  \.  C3            RETN

-----------------------
跟进③里情况
前面略过部分代码
00408485  |> /8A02          /MOV AL,BYTE PTR DS:[EDX]
00408487  |. |3C 61         |CMP AL,61                               ;  小写字母a
00408489  |. |72 06         |JB SHORT QUOD.00408491
0040848B  |. |3C 7A         |CMP AL,7A                               ;  小写字母z
0040848D  |. |77 02         |JA SHORT QUOD.00408491
0040848F  |. |2C 20         |SUB AL,20                               ;  如果是小写字母,变成大写字母
00408491  |> |8806          |MOV BYTE PTR DS:[ESI],AL                ;  储存这一位注册码
00408493  |. |42            |INC EDX
00408494  |. |46            |INC ESI                                 ;  移位
00408495  |. |4B            |DEC EBX
00408496  |. |85DB          |TEST EBX,EBX
00408498  |.^\75 EB         \JNZ SHORT QUOD.00408485
0040849A  |>  5F            POP EDI
0040849B  |.  5E            POP ESI
0040849C  |.  5B            POP EBX
0040849D  \.  C3            RETN


--------------------
跟进④里面情况
00404700   $  85D2          TEST EDX,EDX
00404702   .  74 3F         JE SHORT QUOD.00404743
00404704   .  8B08          MOV ECX,DWORD PTR DS:[EAX]               ;  ecx数值指向上一位注册码地址
00404706   .  85C9          TEST ECX,ECX
00404708   .^ 0F84 86FDFFFF JE QUOD.00404494
0040470E   .  53            PUSH EBX                                 ;  ebx记录着目前算到用户名第几位
0040470F   .  56            PUSH ESI
00404710   .  57            PUSH EDI
00404711   .  89C3          MOV EBX,EAX
00404713   .  89D6          MOV ESI,EDX
00404715   .  8B79 FC       MOV EDI,DWORD PTR DS:[ECX-4]
00404718   .  8B56 FC       MOV EDX,DWORD PTR DS:[ESI-4]
0040471B   .  01FA          ADD EDX,EDI
0040471D   .  39CE          CMP ESI,ECX
0040471F   .  74 17         JE SHORT QUOD.00404738
00404721   .  E8 56030000   CALL QUOD.00404A7C                       ;  此位注册码->esi,略过
00404726   .  89F0          MOV EAX,ESI                              ;  此位注册码->eax
00404728   .  8B4E FC       MOV ECX,DWORD PTR DS:[ESI-4]
0040472B   >  8B13          MOV EDX,DWORD PTR DS:[EBX]               ;  edx指向已计算注册码的开头
0040472D   .  01FA          ADD EDX,EDI                              ;  移一位,这一位注册码要接上去了
0040472F   .  E8 A8E1FFFF   CALL QUOD.004028DC                       ;  这个CALL把新一位注册码接到前一位后面,略过
00404734   .  5F            POP EDI
00404735   .  5E            POP ESI
00404736   .  5B            POP EBX
00404737   .  C3            RETN


----------------------------
跟进⑤里面的情况
前面略去一些代码和CALL的跟进
00409256  |$  B9 0A000000   MOV ECX,0A                               ;  被除数10(十进制)
0040925B  |>  8D75 9F       LEA ESI,DWORD PTR SS:[EBP-61]
0040925E  |>  31D2          /XOR EDX,EDX                             ;  清空edx,存放余数用
00409260  |.  F7F1          |DIV ECX                                 ;  ESI刚才存放着第二部分注册码,在上面已经压进eax,除以10,商->eax,余数->edx
00409262  |.  80C2 30       |ADD DL,30                               ;  余数加30(十六进制)
00409265  |.  80FA 3A       |CMP DL,3A                               ;  是不是3A,其实也就是判断余数是否为10(十进制)。此处有点看糊涂,既然被除数为A,那么余数肯定小于A,加上30以后,肯定小于3A,不知道这样理解对不对
00409268  |.  72 03         |JB SHORT QUOD.0040926D
0040926A  |.  80C2 07       |ADD DL,7                                ;  如果余数为10,则此位数字注册码变为字母A(3A+7为41,为字母A的十六进制ASCII码)
0040926D  |>  4E            |DEC ESI                                 ;  移位
0040926E  |.  8816          |MOV BYTE PTR DS:[ESI],DL                ;  储存
00409270  |.  09C0          |OR EAX,EAX                              ;  除完就跳走喽
00409272  |.^ 75 EA         \JNZ SHORT QUOD.0040925E

这个CALL里看来只是把前面已经算好的第二部分注册码由十六进制转化为十进制(比如我填的用户名alifriend,十六进制为1278,此处把它转化为4728)
有点看不明白的是,既然被除数为10,那么余数就不可能为10,所以上面判断余数若为10,把此位注册码转为字母A的语句岂不是永远不会实现?请高手指教!


---------------------------------
总结一下算法
主流程中,ebx和edi都记录着计算的用户名为当前第几位
edi和第一部分注册码有关,正常的一位一位数
第一部分注册码算法:
判断每一位用户名的ASCII码是否为素数,不为素数则不参与第一部分注册码。
如果是素数,再判断此位用户名是否为小写字母,如果是小写字母,转化为大写字母,然后作为第一部分注册码的一位
ebx和第二部分注册码有关,在④CALL处以下那两句,使得用户名的第一位计算两次(如果用户名不少于两位),而最后一位则不参与第二部分注册码的运算
第二部分注册码算法:
每一位用户名的ASCII码乘以4加上108(十进制),各位结果相加,其中第一位用户名计算两次,最后一位不计算

---------------------------------
注册机,VC6,XPSP1编译通过
#include<iostream.h>
#include <stdio.h>
void main()
{
  int i=0,j=2,codeb=0,ss=0;
  char name[100];
  gets(name);
  cout<<endl;
  codeb=codeb+name[0]*4+108;
  while(name[i]!='\0')
  {
    codeb=codeb+name[i]*4+108;
    for(j=2;j<name[i];j++)
      {if (name[i]%j==0) 
      ss=1;}
    if (ss==0)
      {if(name[i]>='a' && name[i]<='z')
        cout<<char(name[i]-32);
      else 
        cout<<char(name[i]);}
    i++,ss=0;
  }
  codeb=codeb-name[i-1]*4-108;
  cout<< codeb;
  cout<<endl;
}

---------------------------------
自己显示注册码
由于这个软件有明码比较,而且注册错误会弹出提示框,于是想到,可以让它注册错误时,弹出的提示框自己显示正确的注册码

0045F3BC      B8 94F44500   MOV EAX,QUOD.0045F494                    ;  注册码不正确,无法注册!
0045F3C1   .  E8 F238FDFF   CALL QUOD.00432CB8
0045F3C6   .  33C0          XOR EAX,EAX
0045F3C8   .  5A            POP EDX
0045F3C9   .  59            POP ECX
0045F3CA   .  59            POP ECX
0045F3CB   .  64:8910       MOV DWORD PTR FS:[EAX],EDX
0045F3CE   .  68 F3F34500   PUSH QUOD.0045F3F3
0045F3D3   >  8D45 F0       LEA EAX,DWORD PTR SS:[EBP-10]
0045F3D6   .  E8 6550FAFF   CALL QUOD.00404440
0045F3DB   .  8D45 F4       LEA EAX,DWORD PTR SS:[EBP-C]
0045F3DE   .  E8 5D50FAFF   CALL QUOD.00404440
0045F3E3   .  8D45 F8       LEA EAX,DWORD PTR SS:[EBP-8]
0045F3E6   .  E8 5550FAFF   CALL QUOD.00404440
0045F3EB   .  C3            RETN


0045F3BC      B8 94F44500   MOV EAX,QUOD.0045F494                    ;  注册码不正确,无法注册!
此行就是注册错误时弹出框的内容了,跟踪至此,从堆栈窗口中知道正确的注册码存放在[EBP-C]里,所以改一下

0045F3BC      8B45 F4       MOV EAX,DWORD PTR SS:[EBP-C]             
0045F3BF      90            NOP
0045F3C0      90            NOP

补上两个NOP
修改以后,只要注册错误,则弹出的信息框中就会乖乖的显示正确的注册码了!



---------------------------------
游戏作弊

其实这游戏没什么好作弊的,主要是熟悉一下OD的操作,还有在游戏背后的一些秘密……

游戏中每方有六个防守棋子,于是打开游戏修改器,搜索6,用掉一个,再搜索5,马上找到唯一的地址00972020,多次试验后,发现这个地址是固定的,爽。

用OD载入游戏,下硬件断点hw 972020,放置防守棋子,中断来到如下代码

004623D2      83AE C8030000 01     SUB DWORD PTR DS:[ESI+3C8],1    哈哈,棋子减1,把它改成减0吧
004623D9  |.  71 05                JNO SHORT QUOD.004623E0
004623DB  |.  E8 3412FAFF          CALL QUOD.00403614
004623E0  |>  EB 5E                JMP SHORT QUOD.00462440



004623D2      83AE C8030000 00     SUB DWORD PTR DS:[ESI+3C8],0
004623D9  |.  71 05                JNO SHORT QUOD.004623E0
004623DB  |.  E8 3412FAFF          CALL QUOD.00403614
004623E0  |>  EB 5E                JMP SHORT QUOD.00462440

这样你就有无限的防守棋子了


-----------------------------
00972018  00 00 00 00 14 00 00 00 05 00 00 00 14 00 00 00  .............
00972028  06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ...............
00972038  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00972048  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................


又从数据窗口中看到,很显然,14,05,14, 06的数据,前面表示的是我方的进攻棋子,下断hw 97201c,然后自己放下一枚进攻棋子,被中断


004623D9  |. /71 05         JNO SHORT QUOD.004623E0
004623DB  |. |E8 3412FAFF   CALL QUOD.00403614
004623E0  |> \EB 5E         JMP SHORT QUOD.00462440
004623E2  |>  83BE D0030000>CMP DWORD PTR DS:[ESI+3D0],0
004623E9  |.  0F84 AF000000 JE QUOD.0046249E
004623EF  |.  83AE D0030000>SUB DWORD PTR DS:[ESI+3D0],1
004623F6  |.  71 05         JNO SHORT QUOD.004623FD
004623F8  |.  E8 1712FAFF   CALL QUOD.00403614
004623FD  |>  EB 41         JMP SHORT QUOD.00462440
004623FF  |>  80BE 78420000>CMP BYTE PTR DS:[ESI+4278],0
00462406  |.  75 1F         JNZ SHORT QUOD.00462427
00462408  |.  83BE C4030000>CMP DWORD PTR DS:[ESI+3C4],0
0046240F  |.  0F84 89000000 JE QUOD.0046249E
00462415  |.  B3 01         MOV BL,1
00462417  |.  83AE C4030000>SUB DWORD PTR DS:[ESI+3C4],1
0046241E  |.  71 05         JNO SHORT QUOD.00462425
00462420  |.  E8 EF11FAFF   CALL QUOD.00403614
00462425  |>  EB 19         JMP SHORT QUOD.00462440
00462427  |>  83BE CC030000>CMP DWORD PTR DS:[ESI+3CC],0
0046242E  |.  74 6E         JE SHORT QUOD.0046249E
00462430  |.  B3 02         MOV BL,2
00462432  |.  83AE CC030000>SUB DWORD PTR DS:[ESI+3CC],1
00462439  |.  71 05         JNO SHORT QUOD.00462440
0046243B  |.  E8 D411FAFF   CALL QUOD.00403614
00462440  |>  8B45 F8       MOV EAX,DWORD PTR SS:[EBP-8]
00462443  |.  83F8 0A       CMP EAX,0A
00462446  |.  76 05         JBE SHORT QUOD.0046244D
00462448  |.  E8 BF11FAFF   CALL QUOD.0040360C
0046244D  |>  8B55 FC       MOV EDX,DWORD PTR SS:[EBP-4]
00462450  |.  83FA 0A       CMP EDX,0A
00462453  |.  76 05         JBE SHORT QUOD.0046245A
00462455  |.  E8 B211FAFF   CALL QUOD.0040360C
0046245A  |>  6BD2 0B       IMUL EDX,EDX,0B
0046245D  |.  71 05         JNO SHORT QUOD.00462464
0046245F  |.  E8 B011FAFF   CALL QUOD.00403614
00462464  |>  8D1416        LEA EDX,DWORD PTR DS:[ESI+EDX]
00462467      889C02 480300>MOV BYTE PTR DS:[EDX+EAX+348],BL         ;  这一行很可疑,BL=01,试着把BL改成0
0046246E      8B4D F8       MOV ECX,DWORD PTR SS:[EBP-8]
00462471  |.  8B55 FC       MOV EDX,DWORD PTR SS:[EBP-4]
00462474  |.  8BC6          MOV EAX,ESI
00462476  |.  E8 5DF4FFFF   CALL QUOD.004618D8
0046247B  |.  8BC6          MOV EAX,ESI
0046247D  |.  E8 1AF0FFFF   CALL QUOD.0046149C
00462482  |.  8BC6          MOV EAX,ESI
00462484  |.  E8 8FEBFFFF   CALL QUOD.00461018
00462489  |.  80BE 9A420000>CMP BYTE PTR DS:[ESI+429A],0
00462490  |.  75 0C         JNZ SHORT QUOD.0046249E
00462492  |.  80FB 03       CMP BL,3
00462495  |.  74 07         JE SHORT QUOD.0046249E
00462497  |.  8BC6          MOV EAX,ESI
00462499  |.  E8 FEEEFFFF   CALL QUOD.0046139C
0046249E  |>  5E            POP ESI
0046249F  |.  5B            POP EBX
004624A0  |.  59            POP ECX
004624A1  |.  59            POP ECX
004624A2  |.  5D            POP EBP
004624A3  \.  C2 0C00       RETN 0C

改完以后F9运行,发现我刚刚下的那枚棋子没了!原来这一句就是写入放下进攻棋子的语句。
把防守棋子多安几个,随便走一步后再在这里下断,数据窗口查看[EDX+EAX+348],往上拉一点




00971FA5  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00971FB5  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00971FC5  00 00 00 00 00 00 00 00 00 00 00 03 03 00 00 00  ..............
00971FD5  00 00 00 00 00 02 03 01 00 00 00 00 00 00 00 00  .............
00971FE5  00 03 03 03 00 00 00 00 00 00 00 00 00 00 00 00  .............
00971FF5  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00972005  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00972015  00 00 00 00 00 00 00 12 00 00 00 00 00 00 00 13  ..............
00972025  00 00 00 06 00 00 00 05 00 00 00 03 00 00 00 02  ............

很明显,00代表无棋子,01代表的是我的棋子,02是对方的棋子,而03则是防守棋子,用一整块连续的内存,来存放棋盘的情况,所以要作弊

的话,稍微分析一下内存地址和棋盘的关系,修改即可,这里略过了。


-------------------------------------
退出游戏后,再次载入游戏,由于前面的硬件断点,被中断了几次,第二次的中断,正是初始化双方棋子的关键


00461D36  |.  8983 A4420000            MOV DWORD PTR DS:[EBX+42A4],EAX
00461D3C  |.  33D2                     XOR EDX,EDX
00461D3E  |>  33C0                     /XOR EAX,EAX
00461D40  |>  83F8 0A                  |/CMP EAX,0A                             ;  第十行
00461D43  |.  76 05                    ||JBE SHORT QUOD.00461D4A
00461D45  |.  E8 C218FAFF              ||CALL QUOD.0040360C
00461D4A  |>  83FA 0A                  ||CMP EDX,0A                             ;  第十列
00461D4D  |.  76 05                    ||JBE SHORT QUOD.00461D54
00461D4F  |.  E8 B818FAFF              ||CALL QUOD.0040360C
00461D54  |>  6BCA 0B                  ||IMUL ECX,EDX,0B
00461D57  |.  71 05                    ||JNO SHORT QUOD.00461D5E
00461D59  |.  E8 B618FAFF              ||CALL QUOD.00403614
00461D5E  |>  8D0C0B                   ||LEA ECX,DWORD PTR DS:[EBX+ECX]
00461D61  |.  C68401 48030000 00       ||MOV BYTE PTR DS:[ECX+EAX+348],0        ;  置0喽,每局开始,棋子当然要全部清除
00461D69  |.  40                       ||INC EAX
00461D6A  |.  83F8 0B                  ||CMP EAX,0B                             ;  是不是第十一行,也就是最后一行
00461D6D  |.^ 75 D1                    |\JNZ SHORT QUOD.00461D40
00461D6F  |.  42                       |INC EDX
00461D70  |.  83FA 0B                  |CMP EDX,0B                              ;  是不是第十一列
00461D73  |.^ 75 C9                    \JNZ SHORT QUOD.00461D3E                 ;  这个嵌套的循环,正是生成棋盘的内存数据的程序
00461D75  |.  C783 C4030000 14000000   MOV DWORD PTR DS:[EBX+3C4],14
00461D7F  |.  C783 CC030000 14000000   MOV DWORD PTR DS:[EBX+3CC],14            ;  这行被中断,很明显,这里初始化了双方的棋子数
00461D89  |.  C783 C8030000 06000000   MOV DWORD PTR DS:[EBX+3C8],6
00461D93  |.  C783 D0030000 06000000   MOV DWORD PTR DS:[EBX+3D0],6
00461D9D  |.  8BC3                     MOV EAX,EBX
00461D9F  |.  E8 30FCFFFF              CALL QUOD.004619D4
00461DA4  |.  8BC3                     MOV EAX,EBX
00461DA6  |.  E8 F1F6FFFF              CALL QUOD.0046149C
00461DAB  |.  C683 78420000 00         MOV BYTE PTR DS:[EBX+4278],0
00461DB2  |.  C683 9A420000 00         MOV BYTE PTR DS:[EBX+429A],0
00461DB9  |.  C683 79420000 00         MOV BYTE PTR DS:[EBX+4279],0
00461DC0  |.  80BB 7A420000 00         CMP BYTE PTR DS:[EBX+427A],0
00461DC7  |.  74 13                    JE SHORT QUOD.00461DDC
00461DC9  |.  BE 4C1E4600              MOV ESI,QUOD.00461E4C
00461DCE  |.  8DBB 84420000            LEA EDI,DWORD PTR DS:[EBX+4284]
00461DD4  |.  A5                       MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ES>
00461DD5  |.  A5                       MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ES>
00461DD6  |.  A5                       MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ES>
00461DD7  |.  66:A5                    MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI]
00461DD9  |.  A4                       MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
00461DDA  |.  EB 10                    JMP SHORT QUOD.00461DEC
00461DDC  |>  BE 5C1E4600              MOV ESI,QUOD.00461E5C                    ;  \n(双人游戏)
00461DE1  |.  8DBB 84420000            LEA EDI,DWORD PTR DS:[EBX+4284]
00461DE7  |.  A5                       MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ES>
00461DE8  |.  A5                       MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ES>
00461DE9  |.  66:A5                    MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI]
00461DEB  |.  A4                       MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
00461DEC  |>  BA 681E4600              MOV EDX,QUOD.00461E68
00461DF1  |.  8D45 DC                  LEA EAX,DWORD PTR SS:[EBP-24]
00461DF4  |.  E8 A710FAFF              CALL QUOD.00402EA0
00461DF9  |.  8D93 84420000            LEA EDX,DWORD PTR DS:[EBX+4284]
00461DFF  |.  8D45 DC                  LEA EAX,DWORD PTR SS:[EBP-24]
00461E02  |.  B1 1F                    MOV CL,1F
00461E04  |.  E8 6710FAFF              CALL QUOD.00402E70
00461E09  |.  8D55 DC                  LEA EDX,DWORD PTR SS:[EBP-24]
00461E0C  |.  8D45 FC                  LEA EAX,DWORD PTR SS:[EBP-4]
00461E0F  |.  E8 8828FAFF              CALL QUOD.0040469C
00461E14  |.  8B55 FC                  MOV EDX,DWORD PTR SS:[EBP-4]
00461E17  |.  8BC3                     MOV EAX,EBX
00461E19  |.  E8 C673FDFF              CALL QUOD.004391E4
00461E1E  |.  8BC3                     MOV EAX,EBX
00461E20  |.  E8 23FDFFFF              CALL QUOD.00461B48
00461E25  |.  33C0                     XOR EAX,EAX
00461E27  |.  5A                       POP EDX
00461E28  |.  59                       POP ECX
00461E29  |.  59                       POP ECX
00461E2A  |.  64:8910                  MOV DWORD PTR FS:[EAX],EDX
00461E2D  |.  68 421E4600              PUSH QUOD.00461E42
00461E32  |>  8D45 FC                  LEA EAX,DWORD PTR SS:[EBP-4]
00461E35  |.  E8 0626FAFF              CALL QUOD.00404440
00461E3A  \.  C3                       RETN



棋盘是如下形状的,11X11的盘,最角落的四个是没有的,所以用上面两个cmp 0A控制掉了
X000000000X
00000000000
00000000000
00000000000
………
X000000000X

--------------------------------
代码窗口往上卷,哈哈,看到有趣的东西


00461B48  /$  55                       PUSH EBP
00461B49  |.  8BEC                     MOV EBP,ESP
00461B4B  |.  81C4 74FFFFFF            ADD ESP,-8C
00461B51  |.  53                       PUSH EBX
00461B52  |.  33D2                     XOR EDX,EDX
00461B54  |.  8995 74FFFFFF            MOV DWORD PTR SS:[EBP-8C],EDX
00461B5A  |.  8955 AC                  MOV DWORD PTR SS:[EBP-54],EDX
00461B5D  |.  8955 FC                  MOV DWORD PTR SS:[EBP-4],EDX
00461B60  |.  8BD8                     MOV EBX,EAX
00461B62  |.  33C0                     XOR EAX,EAX
00461B64  |.  55                       PUSH EBP
00461B65  |.  68 A51C4600              PUSH QUOD.00461CA5
00461B6A  |.  64:FF30                  PUSH DWORD PTR FS:[EAX]
00461B6D  |.  64:8920                  MOV DWORD PTR FS:[EAX],ESP
00461B70  |.  80BB 78420000 00         CMP BYTE PTR DS:[EBX+4278],0             ;  判断是谁下的,为0不跳,显示红方下,为1跳,显示蓝方下(或者计算机正在思考),试着把它改了
00461B77      75 51                    JNZ SHORT QUOD.00461BCA
00461B79  |.  BA B41C4600              MOV EDX,QUOD.00461CB4
00461B7E  |.  8D45 DC                  LEA EAX,DWORD PTR SS:[EBP-24]
00461B81  |.  E8 1A13FAFF              CALL QUOD.00402EA0
00461B86  |.  8D93 84420000            LEA EDX,DWORD PTR DS:[EBX+4284]
00461B8C  |.  8D45 DC                  LEA EAX,DWORD PTR SS:[EBP-24]
00461B8F  |.  B1 1F                    MOV CL,1F
00461B91  |.  E8 DA12FAFF              CALL QUOD.00402E70
00461B96  |.  8D55 DC                  LEA EDX,DWORD PTR SS:[EBP-24]
00461B99  |.  8D45 B0                  LEA EAX,DWORD PTR SS:[EBP-50]
00461B9C  |.  E8 FF12FAFF              CALL QUOD.00402EA0
00461BA1  |.  BA C01C4600              MOV EDX,QUOD.00461CC0                    ;  \t 红方下!
00461BA6  |.  8D45 B0                  LEA EAX,DWORD PTR SS:[EBP-50]
00461BA9  |.  B1 28                    MOV CL,28
00461BAB  |.  E8 C012FAFF              CALL QUOD.00402E70
00461BB0  |.  8D55 B0                  LEA EDX,DWORD PTR SS:[EBP-50]
00461BB3  |.  8D45 FC                  LEA EAX,DWORD PTR SS:[EBP-4]
00461BB6  |.  E8 E12AFAFF              CALL QUOD.0040469C
00461BBB  |.  8B55 FC                  MOV EDX,DWORD PTR SS:[EBP-4]
00461BBE  |.  8BC3                     MOV EAX,EBX
00461BC0  |.  E8 1F76FDFF              CALL QUOD.004391E4
00461BC5  |.  E9 B2000000              JMP QUOD.00461C7C
00461BCA  |>  80BB 7A420000 00         CMP BYTE PTR DS:[EBX+427A],0             ;  是不是与计算机下,是的话就往下走喽,不是的话跳走
00461BD1  |.  74 57                    JE SHORT QUOD.00461C2A
00461BD3  |.  BA B41C4600              MOV EDX,QUOD.00461CB4                    ;  00461CB4存放的是标题前辍“监狱(Quod)”
00461BD8  |.  8D45 DC                  LEA EAX,DWORD PTR SS:[EBP-24]
00461BDB  |.  E8 C012FAFF              CALL QUOD.00402EA0
00461BE0  |.  8D93 84420000            LEA EDX,DWORD PTR DS:[EBX+4284]
00461BE6  |.  8D45 DC                  LEA EAX,DWORD PTR SS:[EBP-24]
00461BE9  |.  B1 1F                    MOV CL,1F
00461BEB  |.  E8 8012FAFF              CALL QUOD.00402E70
00461BF0  |.  8D55 DC                  LEA EDX,DWORD PTR SS:[EBP-24]
00461BF3  |.  8D85 78FFFFFF            LEA EAX,DWORD PTR SS:[EBP-88]
00461BF9  |.  E8 A212FAFF              CALL QUOD.00402EA0
00461BFE  |.  BA CC1C4600              MOV EDX,QUOD.00461CCC                    ;  00461CCC存放的是“计算机正在思考”
00461C03  |.  8D85 78FFFFFF            LEA EAX,DWORD PTR SS:[EBP-88]
00461C09  |.  B1 31                    MOV CL,31
00461C0B  |.  E8 6012FAFF              CALL QUOD.00402E70
00461C10  |.  8D95 78FFFFFF            LEA EDX,DWORD PTR SS:[EBP-88]
00461C16  |.  8D45 AC                  LEA EAX,DWORD PTR SS:[EBP-54]
00461C19  |.  E8 7E2AFAFF              CALL QUOD.0040469C
00461C1E  |.  8B55 AC                  MOV EDX,DWORD PTR SS:[EBP-54]
00461C21  |.  8BC3                     MOV EAX,EBX
00461C23  |.  E8 BC75FDFF              CALL QUOD.004391E4
00461C28  |.  EB 52                    JMP SHORT QUOD.00461C7C
00461C2A  |>  BA B41C4600              MOV EDX,QUOD.00461CB4                    ;  00461CB4存放的是标题前辍“监狱(Quod)”
00461C2F  |.  8D45 DC                  LEA EAX,DWORD PTR SS:[EBP-24]
00461C32  |.  E8 6912FAFF              CALL QUOD.00402EA0
00461C37  |.  8D93 84420000            LEA EDX,DWORD PTR DS:[EBX+4284]
00461C3D  |.  8D45 DC                  LEA EAX,DWORD PTR SS:[EBP-24]
00461C40  |.  B1 1F                    MOV CL,1F
00461C42  |.  E8 2912FAFF              CALL QUOD.00402E70
00461C47  |.  8D55 DC                  LEA EDX,DWORD PTR SS:[EBP-24]
00461C4A  |.  8D45 B0                  LEA EAX,DWORD PTR SS:[EBP-50]
00461C4D  |.  E8 4E12FAFF              CALL QUOD.00402EA0
00461C52  |.  BA E01C4600              MOV EDX,QUOD.00461CE0                    ;  \t 蓝方下!
00461C57  |.  8D45 B0                  LEA EAX,DWORD PTR SS:[EBP-50]
00461C5A  |.  B1 28                    MOV CL,28
00461C5C  |.  E8 0F12FAFF              CALL QUOD.00402E70
00461C61  |.  8D55 B0                  LEA EDX,DWORD PTR SS:[EBP-50]
00461C64  |.  8D85 74FFFFFF            LEA EAX,DWORD PTR SS:[EBP-8C]
00461C6A  |.  E8 2D2AFAFF              CALL QUOD.0040469C
00461C6F  |.  8B95 74FFFFFF            MOV EDX,DWORD PTR SS:[EBP-8C]
00461C75  |.  8BC3                     MOV EAX,EBX
00461C77  |.  E8 6875FDFF              CALL QUOD.004391E4
00461C7C  |>  33C0                     XOR EAX,EAX
00461C7E  |.  5A                       POP EDX
00461C7F  |.  59                       POP ECX
00461C80  |.  59                       POP ECX
00461C81  |.  64:8910                  MOV DWORD PTR FS:[EAX],EDX
00461C84  |.  68 AC1C4600              PUSH QUOD.00461CAC
00461C89  |>  8D85 74FFFFFF            LEA EAX,DWORD PTR SS:[EBP-8C]
00461C8F  |.  E8 AC27FAFF              CALL QUOD.00404440
00461C94  |.  8D45 AC                  LEA EAX,DWORD PTR SS:[EBP-54]
00461C97  |.  E8 A427FAFF              CALL QUOD.00404440
00461C9C  |.  8D45 FC                  LEA EAX,DWORD PTR SS:[EBP-4]
00461C9F  |.  E8 9C27FAFF              CALL QUOD.00404440
00461CA4  \.  C3                       RETN                                     ;  这个RETN走回去,回到上一级CALL


把判断红方或蓝方下的那一句00461B70  |.  80BB 78420000 00         CMP BYTE PTR DS:[EBX+4278],0改了,再试,双方还是可以正常下,只是窗口标题不变,证明这个CALL里只是根据哪一方下的来改变窗口标题,这还不够,最后的RETN走回上一层CALL看看!

----------------------------
哈哈,这正是我要的!

00461399      8D40 00                  LEA EAX,DWORD PTR DS:[EAX]
0046139C  /$  55                       PUSH EBP
0046139D  |.  8BEC                     MOV EBP,ESP
0046139F  |.  53                       PUSH EBX
004613A0  |.  8BD8                     MOV EBX,EAX
004613A2  |.  80BB 78420000 00         CMP BYTE PTR DS:[EBX+4278],0             ;  判断是哪一方下的
004613A9  |.  75 09                    JNZ SHORT QUOD.004613B4                  ;  把这一句改了!于是只有一方可以下了……
004613AB  |.  C683 78420000 01         MOV BYTE PTR DS:[EBX+4278],1
004613B2  |.  EB 07                    JMP SHORT QUOD.004613BB
004613B4  |>  C683 78420000 00         MOV BYTE PTR DS:[EBX+4278],0
004613BB  |>  8BC3                     MOV EAX,EBX
004613BD  |.  E8 86070000              CALL QUOD.00461B48                       ;  这个CALL进去也就是上面改变标题的程序
004613C2  |.  80BB 78420000 01         CMP BYTE PTR DS:[EBX+4278],1
004613C9  |.  75 28                    JNZ SHORT QUOD.004613F3
004613CB  |.  80BB 7A420000 00         CMP BYTE PTR DS:[EBX+427A],0
004613D2  |.  74 1F                    JE SHORT QUOD.004613F3
004613D4  |.  C683 79420000 01         MOV BYTE PTR DS:[EBX+4279],1
004613DB  |.  8383 80420000 01         ADD DWORD PTR DS:[EBX+4280],1
004613E2  |.  71 05                    JNO SHORT QUOD.004613E9
004613E4  |.  E8 2B22FAFF              CALL QUOD.00403614                       
004613E9  |>  8BC3                     MOV EAX,EBX
004613EB  |.  E8 28F9FFFF              CALL QUOD.00460D18                       ;  这个CALL中的语句看起来非常像判断胜利的代码
004613F0  |.  5B                       POP EBX
004613F1  |.  5D                       POP EBP
004613F2  |.  C3                       RETN
004613F3  |>  C683 79420000 00         MOV BYTE PTR DS:[EBX+4279],0
004613FA  |.  5B                       POP EBX
004613FB  |.  5D                       POP EBP
004613FC  \.  C3                       RETN


到这里这篇文章想必可以告一段落了,不然越裹越长,有兴趣的可以跟进上面的两个CALL,改改棋子颜色啊,甚至把胜利条件改一下,把进攻棋子围成一个正方形,改成围成三角形等等之类的。