破文作者: David Nash
破解平台: WinXP Sp2
软件名称: ChessGenius Classic V7.138R
软件大小: 576 KB
软件语言: 英文
软件类别: 国外软件 / 共享版 / 棋牌游戏
应用平台: Win9x/NT/2000/XP
开 发 商: http://www.chessgenius.com/
软件介绍:   
    。一个世界冠军级的国际象棋程序。附有40种由初学者至专家级的游戏级别:10级「容易」,10级「攻棋」,10级「限时下棋」,10「棋局解柝」 - 国际象棋计时钟 - 每步棋的记录 - 显示思考程序 - 叁种棋盘大小:小型,大型或巨大型 - 提示 - 起步设定。强大的游戏功能。此国际象棋棋程序的撰写者已赢取过10项世界电脑国际象棋棋冠军的荣誉。 


保护方式:用户名+ 序列号
破解目的:学习.........
破解工具:Peid,OD
破解声明:我乃小菜鸟一只,偶得一点心得,愿与大家分享:)

破解过程: 

用PEiD查看,没加壳,Microsoft Visual C++ 4.x,那就不好意思了。
注册失败后会显示:Error - Incorrect key. Please enter name and key as supplied by www.chessgenius.com 
用OD载入,查找字符串,双击来到00411F31:

00411F19   |> \391D 9C764600     |cmp dword ptr ds:[46769C],ebx 向上来到这里。发现可以从00411DF9,00411E09,00411E40,00411EFB 跳到这里。全部下断,呵呵

00411F1F       75 22             |jnz short GEN32WIN.00411F43
00411F21   |.  66:833D C27E4600 >|cmp word ptr ds:[467EC2],1       
00411F29   |.  75 18             |jnz short GEN32WIN.00411F43
00411F2B   |.  A1 48764600       |mov eax,dword ptr ds:[467648]
00411F30   |.  50                |push eax
00411F31   |.  68 E8FB4400       |push GEN32WIN.0044FBE8          ;  ASCII "Error -Incorrect key. Please enter name and key as supplied by www.chessgenius.com"  双击来到这里,向上找

00411F36   |.  E8 FE4D0200       |call GEN32WIN.00436D39
00411F3B   |.  83C4 08           |add esp,8
00411F3E   |.^ E9 D0FCFFFF       \jmp GEN32WIN.00411C13
00411F43   |>  833D 9C764600 01  cmp dword ptr ds:[46769C],1
00411F4A   |.  75 2A             jnz short GEN32WIN.00411F76
00411F4C   |.  BE 58DE4400       mov esi,GEN32WIN.0044DE58        ;  ASCII "  Unregistered"
00411F51   |.  8D85 B0FDFFFF     lea eax,dword ptr ss:[ebp-250]
00411F57   |.  56                push esi
00411F58   |.  68 D4FB4400       push GEN32WIN.0044FBD4  ;ASCII "  Registered to %s"
00411F5D   |.  50                push eax
00411F5E   |.  E8 3DAD0200       call GEN32WIN.0043CCA0

输入用户名:david
注册码:123456

结果发现它是从00411E0E  call GEN32WIN.00411845 跳过来的。那里可是关键跳转哦。
重新载入,用F7进入。
单步跟踪到:
0041198D   |.  56                push esi                         ; /Arg6
0041198E   |.  8B15 5C764600     mov edx,dword ptr ds:[46765C]    ; |GEN32WIN.0044FDFC
00411994   |.  6A 0E             push 0E                          ; |Arg5 = 0000000E
00411996   |.  33C9              xor ecx,ecx                      ; |
00411998   |.  6A 46             push 46                          ; |Arg4 = 00000046
0041199A   |.  68 B4000000       push 0B4                         ; |Arg3 = 000000B4
0041199F   |.  6A 28             push 28                          ; |Arg2 = 00000028
004119A1   |.  68 42060000       push 642                         ; |Arg1 = 00000642
004119A6   |.  E8 34230100       call GEN32WIN.00423CDF           ; \GEN32WIN.00423CDF
004119AB   |.  E8 3E370100       call GEN32WIN.004250EE     <---------要求输入用户名和注册码 

继续向下走,来到这里:
00411A61   |.  389D FCFEFFFF     cmp byte ptr ss:[ebp-104],bl
00411A67   |.  74 63             je short GEN32WIN.00411ACC
00411A69   |> /0FBE843D FCFEFFFF /movsx eax,byte ptr ss:[ebp+edi-104]   将字符赋给eax
00411A71   |. |50                |push eax                              将eax压入堆栈
00411A72   |. |E8 89B50200       |call GEN32WIN.0043D000 跟进去后发现是eax赋给ecx,eax=2, edx=45163A
00411A77   |. |83C4 04           |add esp,4                             esp加上4
00411A7A   |. |85C0              |test eax,eax         如果eax为零,设置ZF为1
00411A7C   |. |74 43             |je short GEN32WIN.00411AC1                 
00411A7E   |. |A1 58E04400       |mov eax,dword ptr ds:[44E058]         将原来压在ptr ds:44E058]的数赋给eax
00411A83   |. |43                |inc ebx                                    
00411A84   |. |69C0 354E5A01     |imul eax,eax,15A4E35                  eax = eax * 15A4E35
00411A8A   |. |0FBE8C3D FCFEFFFF |movsx ecx,byte ptr ss:[ebp+edi-104]   再次将字符赋给ecx
00411A92   |. |40                |inc eax                                    
00411A93   |. |51                |push ecx                                   
00411A94   |. |A3 58E04400       |mov dword ptr ds:[44E058],eax         将eax的值传到44E058处
00411A99   |. |E8 B2C40200       |call GEN32WIN.0043DF50                跟进去你会发现eax的值等于它的ASCII值减去20
00411A9E   |. |83C4 04           |add esp,4                             esp加上4
00411AA1   |. |8B0D 58E04400     |mov ecx,dword ptr ds:[44E058]         将ptr ds:[44E058]赋给ecx
00411AA7   |. |C1E9 10           |shr ecx,10                            ecx右移10位
00411AAA   |. |66:81E1 FF7F      |and cx,7FFF                           其实就是将ecx的后四位加上7FFF
00411AAF   |. |0FBFD1            |movsx edx,cx                          将cx赋值给edx
00411AB2   |. |0FAFC2            |imul eax,edx                          eax = eax * edx 
00411AB5   |. |05 4E070E00       |add eax,0E074E                        eax = eax + 0E074E 
00411ABA   |. |03F0              |add esi,eax                           esi = esi + eax
00411ABC   |. |83FB 0C           |cmp ebx,0C                            比较ebx与12,(限制位数小于12)

00411ABF   |. |7F 0B             |jg short GEN32WIN.00411ACC            如果大于,就跳转
00411AC1   |> |47                |inc edi                               edi加上1
00411AC2   |. |80BC3D FCFEFFFF 0>|cmp byte ptr ss:[ebp+edi-104],0       比较下一字符是否为零
00411ACA   |.^\75 9D             \jnz short GEN32WIN.00411A69           为零则跳转
00411ACC   |>  83FB 05           cmp ebx,5                                   
00411ACF   |.  7C 20             jl short GEN32WIN.00411AF1                  
00411AD1   |.  B9 40420F00       mov ecx,0F4240                          将0F4240赋给ecx
00411AD6   |.  8BC6              mov eax,esi                             将esi赋给eax
00411AD8   |.  2BD2              sub edx,edx                             edx置为零
00411ADA   |.  F7F1              div ecx      eax/ecx,商保存在eax,   余数保存在edx。真正注册码就是这里的edx
00411ADC   |.  3955 FC           cmp dword ptr ss:[ebp-4],edx            比较edx中的真正注册码与加注册码     
00411ADF   |.  75 10             jnz short GEN32WIN.00411AF1             若相等就跳,不跳就挂
00411AE1   |.  C705 60764600 010>mov dword ptr ds:[467660],1             没跳,值标志位为1,后面比较时用
00411AEB   |.  8915 74764600     mov dword ptr ds:[467674],edx         把真的注册码放到地址467674
00411AF1   |>  5F                pop edi
00411AF2   |.  5E                pop esi
00411AF3   |.  5B                pop ebx
00411AF4   |.  8BE5              mov esp,ebp
00411AF6   |.  5D                pop ebp
00411AF7   \.  C3                retn


Name: david
Code: 445478

总体上来说,是比较简单的。我这样的菜鸟就可以搞定的。^o^

语言算法总结:
    dword ptr ds:[44E058]初识值是1,然后与15A4E35相乘,保存在eax中。eax再加上1。接着,右移10位,得到8位数,后四位与7FFF作与运算,其结果与eax的(ASCII-20h)的积再加上0E074E。最后,与esi(esi初识值为0)相加。然后再继续计算直到计算完所有的用户名字符。把"最终结果"(esi)与0F4240作除法运算,余数(换算成十进制)就是注册码。

附上C算法:

#include<stdio.h>

main()
{
  unsigned long flag, eax = 0X1, dword = 0X1, esi = 0X0; 
  const const1 = 0x15A4E35, const2 = 0x7FFF, const3 = 0xE074E, const4 = 0XF4240;
  char name[64];
  printf("************* Keygen for ChessGenius Classic 7.138R *************\n");
  printf("Powered by David Nash\n");
  printf("Please enter your name:");
  gets(name);
  for ( flag = 0; name[flag]; flag++ )
  { 
      if ( name[flag] > 64 && name[flag] < 91 )
    name[flag] += 32;
      eax = (const1 * dword) + 1;
            dword = eax;
      eax = eax / 0X10000;     
      eax &= const2;
      eax *= (name[flag] - 0x20);
      eax += const3;
      esi += eax;  
  }
  esi = esi % const4;
  printf("The code is: %d", esi);
  getchar();
}    

当然了,程序对注册名还有一些限制,如不能包含数字、特殊字符等,大家有兴趣就自己看看好了。呵呵............