标 题:昨天从朋友那里得到一个BCG的CREAKME,这样CREAK对吗?请大家看看。 (4千字)
发信人:赞盛
时 间:2001-10-11 22:32:43
详细信息:
就是那个一开始就说“革命尚未成功”什么的。

工具:Sice 4.05 for win9x
环境:Windows 98 SE
时间:1小时40分钟,好惨。。。。

打开程序,就出来了一个MessageBox,显示没破解成功;按确定,点注册显示同一个MessageBox。
退出程序,呼出Sice下断点Bpx MessageBoxA,重新打开程序,被断。找出以下代码。
0167:0040113B  RET      0010
0167:0040113E  PUSH      00001000
0167:00401143  PUSH      00402026
0167:00401148  PUSH      004020BF
0167:0040114D  PUSH      00
0167:0040114F  CALL      USER32!MessageBoxA
0167:00401154  LEAVE
0167:00401155  RET      0010
0167:00401158  PUSH      00001000
0167:0040115D  PUSH      00402026            //Messagebox的标题"BCG's Official Crackme...(省略)"
0167:00401162  PUSH      00402083            //Messagebox的内容"革命尚未成功....."
0167:00401167  PUSH      00
0167:00401169  CALL      USER32!MessageBoxA        //被断处
0167:0040116E  LEAVE
0167:0040116F  RET      0010
0167:00401172  PUSH      00001000
0167:00401177  PUSH      00402026
0167:0040117C  PUSH      00402036
往上看,上面也有一个Messagebox,和下面的标题相同,内容不同。试着把00401162处的PUSH 00402083该为PUSH 004020BF
发现MesssageBox变成了"注册验证成功...."。证明上面的MessageBox为注册成功时才显示的。继续往上看。
0167:00401095  RET      0010
0167:00401098  PUSH      00
0167:0040109A  PUSH      004020EF
0167:0040109F  PUSH      03
0167:004010A1  PUSH      00
0167:004010A3  PUSH      03
0167:004010A5  PUSH      C0000000
0167:004010AA  PUSH      004020E5
0167:004010AF  CALL      KERNEL32!CreateFileA
0167:004010B4  MOV      [00402000],EAX            //建立的文件的Handle    
0167:004010B9  CMP      DWORD PTR [00402000],-01    //文件建立成功时为为文件的Handle,否则是FFFFFFFF(-1)
0167:004010C0  JZ        00401158            //如果文件建立成功就注册不成功,故应该有一文件
0167:004010C6  PUSH      00                  在当前目录。文件名在004020E5处。为:[BCG].KEY
0167:004010C8  PUSH      00402107
0167:004010CD  PUSH      0A                //读10字节
0167:004010CF  PUSH      004020F3            //存放读出的字符的缓冲区1,即字符串1的地址
0167:004010D4  PUSH      DWORD PTR [00402000]
0167:004010DA  CALL      KERNEL32!ReadFile
0167:004010DF  TEST      EAX,EAX
0167:004010E1  JZ        00401158            //文件读不成功,注册失败
0167:004010E3  PUSH      00
0167:004010E5  PUSH      00402107
0167:004010EA  PUSH      0A                //读10字节
0167:004010EC  PUSH      004020FD            //存放读出的字符的缓冲区2,即字符串2的地址
0167:004010F1  PUSH      DWORD PTR [00402000]
0167:004010F7  CALL      KERNEL32!ReadFile
0167:004010FC  TEST      EAX,EAX
0167:004010FE  JZ        00401158            //文件读不成功,注册失败
0167:00401100  PUSH      DWORD PTR [00402000]
0167:00401106  CALL      KERNEL32!CloseHandle        //关闭Handle
0167:0040110B  XOR      EAX,EAX
0167:0040110D  JMP      00401113
0167:0040110F  LEAVE
0167:00401110  RET      0010
0167:00401113  XOR      BYTE PTR [EAX+004020F3],58    //运算字符串的代码
0167:0040111A  INC      EAX
0167:0040111B  CMP      BYTE PTR [EAX+004020F3],00
0167:00401122  JNZ      00401113
0167:00401124  PUSH      004020F3            //字符串1的地址
0167:00401129  PUSH      004020FD            //字符串2的地址
0167:0040112E  CALL      KERNEL32!lstrcmp        //比较两字符串
0167:00401133  CMP      EAX,00
0167:00401136  JZ        0040113E            //如果相等就注册成功
0167:00401138  JMP      00401158            //否则不成功
0167:0040113A  LEAVE
发现有多处校验,然后跳转到00401158,而00401158就是注册不成功时显示的MessageBox。故从后往前推断,看注册成功的条件。
很显然,00401138处的跳转是当两字符串不相等时。004010FE和004010E1处的跳转是当文件读失败时。004010C0处
的跳转是当文件建立成功时,言外之意当前目录应该有一个文件,文件名放在004020E5处。
:d 004020e5
0030:004020E5 5B 42 43 47 5D 2E 4B 65-79 00 80 00 00 00 00 00  [BCG].Key.......
0030:004020F5 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
我就用WINHex在当前目录下建立一名为[BCG].KEY的文件,大小20字节,内容是同一字符(比如D)。
下面是两缓冲区内容
:d 004020f3
0030:004020F3 44 44 44 44 44 44 44 44-44 44 44 44 44 44 44 44  DDDDDDDDDDDDDDDD
0030:00402103 44 44 44 44 0A 00 00 00-00 04 00 00 00 90 00 00  DDDD............
再次运行程序,中断。按F10逐行执行,观察寄存器内容变化,最后还是注册不成功,问题就在00401113-00401122运算字符串的代码上。
到这里我开始发晕了,这一段费了我至少40分钟。问题就在00402107上,那里存放了第二次读出的字节数(0A)。

最后豁然开朗,其实文件的内容应该就1个字节,ASCII码为58
第一次读10个字节时只读出了1个字节,读出的字节数放在004020FD,为1;第二次读10个字节时什么也没读出来,
就是0,正好把004020FD覆盖,004020FD也成了0,而且读出的字节数为也为0,放在00402107。如下
0030:004020F3 58 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  X...............
0030:00402103 00 00 00 00 00 00 00 00-00 04 00 00 00 90 00 00  ................
0030:00402113 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

004020F3经过XOR运算后为0,现在两个字符串都是空串,比较是自然相等。

拆解完毕。



            shengzan@263.net