谁能找出BrainsBreaker3.0(巨好的拼图游戏)注册码?《论坛精华2》没搞定!
破这种既好玩又有极大难度的软件才过瘾!
http://www.brainsbreaker.com/download.htm或
http://ourworld.compuserve.com/homepages/jtrujillo/bbsetup.exe
==========================================================================
1、Pack:我不填
Name:zest
Your ID:aaaa
Key:CCCCCCCCCCCCCCCC
--------------------------------------------------------------------------
2、此程序老在0167:00452509~0167:0045278F处循环,循环结束后出注册错误框,
注意0167:00452543 PUSH DWORD [EBP-0C]处PUSH之值,你可下断点
bpx 452546 do"d*esp"看看,我用TRW2K122。
值依次变为full,entry,brainsbreaker,summer96,spring96,winter96,contry。
--------------------------------------------------------------------------
3、我做如下3个断点跟踪:①bpx 452546 do"d*esp" ②bpx 452653 ③bpx 45274e
如KEY个数小于16个,正常中断顺序为①②①②①②......
如KEY个数大于等于16个,正常中断顺序为①②③①②③......
为了便于跟踪,我的KEY填16个c,你或许会曰:NOP掉45274e此行(key数<16还要
NOP掉452653)不就行了?的确,你注册成功了!上WC轻松一刻!
--------------------------------------------------------------------------
4、一泡尿工夫你会发觉你的程序DIE得很惨!
--------------------------------------------------------------------------
5、程序注册后(强迫注册)会在BBRK.INI加入:
[PACKBrainsBreaker]
0=zest
1=aaaa
2=1076e9867711e9867711e9867711e9867711
3=2100
4=4e37d9b1
5=5533cba4
注:上[PACK***]中***有可能就是full,entry,brainsbreaker,summer96,spring96,
winter96,contry其中之一,细观察断点①。我发觉[PACKfull]会出错,见上第3点,
[PACKentry]和[PACKBrainsBreaker]可注册成功!其余[PACK***]说是成功了,
但功能有限制。我爱[PACKBrainsBreaker],使用后没任何功能限制!
--------------------------------------------------------------------------
6、每次想玩时得跟踪注册一次才能消除其功能限制,麻烦!谁叫我没$19.95呢。
你可试做一个PATCH看看,或用SMC方法。
--------------------------------------------------------------------------
7、谁能找到注册码?
==========================================================================
0167:00452509 FF36 PUSH DWORD [ESI]-------->循环开始处!
0167:0045250B 8D4DF0 LEA ECX,[EBP-10]
0167:0045250E E891990100 CALL 0046BEA4
0167:00452513 8D45F0 LEA EAX,[EBP-10]
0167:00452516 B9B05C4B00 MOV ECX,004B5CB0
0167:0045251B 50 PUSH EAX
0167:0045251C E84D54FDFF CALL 0042796E
0167:00452521 837DF802 CMP DWORD [EBP-08],BYTE +02
0167:00452525 8945D0 MOV [EBP-30],EAX
0167:00452528 6A2C PUSH BYTE +2C
0167:0045252A 752A JNZ 00452556
0167:0045252C E8EA380400 CALL 00495E1B
0167:00452531 8BF0 MOV ESI,EAX
0167:00452533 59 POP ECX
0167:00452534 85F6 TEST ESI,ESI
0167:00452536 7440 JZ 00452578
0167:00452538 FF75E4 PUSH DWORD [EBP-1C]-------->$$CCCCCCCCCCCCCCCC
0167:0045253B 8BCE MOV ECX,ESI
0167:0045253D FF75DC PUSH DWORD [EBP-24]-------->aaaa
0167:00452540 FF75C8 PUSH DWORD [EBP-38]-------->zest
0167:00452543 FF75F4 PUSH DWORD [EBP-0C]-------->注意变化!
0167:00452546 E8EC55FDFF CALL 00427B37
0167:0045254B C706847C4A00 MOV DWORD [ESI],004A7C84
0167:00452551 8975FC MOV [EBP-04],ESI
0167:00452554 EB26 JMP SHORT 0045257C
0167:00452556 E8C0380400 CALL 00495E1B
0167:0045255B 85C0 TEST EAX,EAX
0167:0045255D 59 POP ECX
0167:0045255E 7418 JZ 00452578
0167:00452560 FF75E4 PUSH DWORD [EBP-1C]
0167:00452563 8BC8 MOV ECX,EAX
0167:00452565 FF75DC PUSH DWORD [EBP-24]
0167:00452568 FF75C8 PUSH DWORD [EBP-38]
0167:0045256B FF75F4 PUSH DWORD [EBP-0C]
0167:0045256E E8C455FDFF CALL 00427B37
0167:00452573 8945FC MOV [EBP-04],EAX
0167:00452576 EB04 JMP SHORT 0045257C
0167:00452578 8365FC00 AND DWORD [EBP-04],BYTE +00
0167:0045257C 8B4DFC MOV ECX,[EBP-04]
0167:0045257F 8D951CFFFFFF LEA EDX,[EBP+FFFFFF1C]
0167:00452585 52 PUSH EDX
0167:00452586 8B01 MOV EAX,[ECX]
0167:00452588 FF5008 CALL NEAR [EAX+08]-------->此CALL估计重要!
0167:0045258B 8BF0 MOV ESI,EAX-------->注意EAX值变化!
0167:0045258D 6A08 PUSH BYTE +08
0167:0045258F 59 POP ECX
0167:00452590 0FB63E MOVZX EDI,BYTE [ESI]
0167:00452593 8BC7 MOV EAX,EDI
0167:00452595 6A01 PUSH BYTE +01
0167:00452597 99 CDQ
0167:00452598 F7F9 IDIV ECX
0167:0045259A 8BC7 MOV EAX,EDI
0167:0045259C 5B POP EBX
0167:0045259D C1E803 SHR EAX,03
0167:004525A0 0FB6443001 MOVZX EAX,BYTE [EAX+ESI+01]
0167:004525A5 8BCA MOV ECX,EDX
0167:004525A7 D3E3 SHL EBX,CL
0167:004525A9 23D8 AND EBX,EAX
0167:004525AB 895D08 MOV [EBP+08],EBX
0167:004525AE 7406 JZ 004525B6
0167:004525B0 6A01 PUSH BYTE +01
0167:004525B2 5B POP EBX
0167:004525B3 895D08 MOV [EBP+08],EBX
0167:004525B6 8A4604 MOV AL,[ESI+04]
0167:004525B9 6A08 PUSH BYTE +08
0167:004525BB 0C04 OR AL,04
0167:004525BD 59 POP ECX
0167:004525BE C0E002 SHL AL,02
0167:004525C1 884604 MOV [ESI+04],AL
0167:004525C4 8BC7 MOV EAX,EDI
0167:004525C6 99 CDQ
0167:004525C7 F7F9 IDIV ECX
0167:004525C9 6A08 PUSH BYTE +08
0167:004525CB 8BC8 MOV ECX,EAX
0167:004525CD 8BC7 MOV EAX,EDI
0167:004525CF 99 CDQ
0167:004525D0 5F POP EDI
0167:004525D1 F7FF IDIV EDI
0167:004525D3 85DB TEST EBX,EBX
0167:004525D5 751B JNZ 004525F2
0167:004525D7 8D7C3101 LEA EDI,[ECX+ESI+01]
0167:004525DB 8D4A01 LEA ECX,[EDX+01]
0167:004525DE B001 MOV AL,01
0167:004525E0 B301 MOV BL,01
0167:004525E2 D2E0 SHL AL,CL
0167:004525E4 8BCA MOV ECX,EDX
0167:004525E6 D2E3 SHL BL,CL
0167:004525E8 F6D0 NOT AL
0167:004525EA 0A1F OR BL,[EDI]
0167:004525EC 22C3 AND AL,BL
0167:004525EE 8807 MOV [EDI],AL
0167:004525F0 EB0E JMP SHORT 00452600
0167:004525F2 8D443101 LEA EAX,[ECX+ESI+01]
0167:004525F6 B301 MOV BL,01
0167:004525F8 8BCA MOV ECX,EDX
0167:004525FA D2E3 SHL BL,CL
0167:004525FC F6D3 NOT BL
0167:004525FE 2018 AND [EAX],BL
0167:00452600 0FB63E MOVZX EDI,BYTE [ESI]
0167:00452603 8BC7 MOV EAX,EDI
0167:00452605 6A08 PUSH BYTE +08
0167:00452607 99 CDQ
0167:00452608 59 POP ECX
0167:00452609 F7F9 IDIV ECX
0167:0045260B 8BC8 MOV ECX,EAX
0167:0045260D 8D4101 LEA EAX,[ECX+01]
0167:00452610 3D80000000 CMP EAX,80
0167:00452615 7E02 JNG 00452619
0167:00452617 33C0 XOR EAX,EAX
0167:00452619 8A543001 MOV DL,[EAX+ESI+01]
0167:0045261D 8D443001 LEA EAX,[EAX+ESI+01]
0167:00452621 80CA04 OR DL,04
0167:00452624 BBDE100000 MOV EBX,10DE
0167:00452629 C0EA02 SHR DL,02
0167:0045262C 8810 MOV [EAX],DL
0167:0045262E A1E86C4B00 MOV EAX,[004B6CE8]
0167:00452633 99 CDQ
0167:00452634 F7FB IDIV EBX
0167:00452636 85D2 TEST EDX,EDX
0167:00452638 750E JNZ 00452648
0167:0045263A 8BC7 MOV EAX,EDI
0167:0045263C 6A08 PUSH BYTE +08
0167:0045263E 99 CDQ
0167:0045263F 5F POP EDI
0167:00452640 8D4C3102 LEA ECX,[ECX+ESI+02]
0167:00452644 F7FF IDIV EDI
0167:00452646 0811 OR [ECX],DL
0167:00452648 FF05E86C4B00 INC DWORD [004B6CE8]
0167:0045264E 8A4601 MOV AL,[ESI+01]
0167:00452651 A804 TEST AL,04
0167:00452653 740B JZ 00452660-------->NOP掉它!!!!!!
0167:00452655 33C9 XOR ECX,ECX
0167:00452657 394D08 CMP [EBP+08],ECX
0167:0045265A 0F94C1 SETZ CL
0167:0045265D 894D08 MOV [EBP+08],ECX
0167:00452660 F6D0 NOT AL
0167:00452662 884601 MOV [ESI+01],AL
0167:00452665 33C0 XOR EAX,EAX
0167:00452667 394508 CMP [EBP+08],EAX
0167:0045266A 0F84F2000000 JZ NEAR 00452762
0167:00452670 8B4DFC MOV ECX,[EBP-04]
0167:00452673 50 PUSH EAX
0167:00452674 50 PUSH EAX
0167:00452675 8D45B0 LEA EAX,[EBP-50]
0167:00452678 8B11 MOV EDX,[ECX]
0167:0045267A 50 PUSH EAX
0167:0045267B FF5210 CALL NEAR [EDX+10]
0167:0045267E 8BF0 MOV ESI,EAX
0167:00452680 6A08 PUSH BYTE +08
0167:00452682 59 POP ECX
0167:00452683 0FB63E MOVZX EDI,BYTE [ESI]
0167:00452686 8BC7 MOV EAX,EDI
0167:00452688 6A01 PUSH BYTE +01
0167:0045268A 99 CDQ
0167:0045268B F7F9 IDIV ECX
0167:0045268D 8BC7 MOV EAX,EDI
0167:0045268F 5B POP EBX
0167:00452690 C1E803 SHR EAX,03
0167:00452693 0FB6443001 MOVZX EAX,BYTE [EAX+ESI+01]
0167:00452698 8BCA MOV ECX,EDX
0167:0045269A D3E3 SHL EBX,CL
0167:0045269C 23D8 AND EBX,EAX
0167:0045269E 7403 JZ 004526A3
0167:004526A0 6A01 PUSH BYTE +01
0167:004526A2 5B POP EBX
0167:004526A3 8A4604 MOV AL,[ESI+04]
0167:004526A6 6A08 PUSH BYTE +08
0167:004526A8 0C04 OR AL,04
0167:004526AA 59 POP ECX
0167:004526AB C0E002 SHL AL,02
0167:004526AE 884604 MOV [ESI+04],AL
0167:004526B1 8BC7 MOV EAX,EDI
0167:004526B3 99 CDQ
0167:004526B4 F7F9 IDIV ECX
0167:004526B6 6A08 PUSH BYTE +08
0167:004526B8 8BC8 MOV ECX,EAX
0167:004526BA 8BC7 MOV EAX,EDI
0167:004526BC 99 CDQ
0167:004526BD 5F POP EDI
0167:004526BE F7FF IDIV EDI
0167:004526C0 85DB TEST EBX,EBX
0167:004526C2 7521 JNZ 004526E5
0167:004526C4 8D7C3101 LEA EDI,[ECX+ESI+01]
0167:004526C8 8D4A01 LEA ECX,[EDX+01]
0167:004526CB B001 MOV AL,01
0167:004526CD D2E0 SHL AL,CL
0167:004526CF 8BCA MOV ECX,EDX
0167:004526D1 F6D0 NOT AL
0167:004526D3 88450B MOV [EBP+0B],AL
0167:004526D6 B001 MOV AL,01
0167:004526D8 D2E0 SHL AL,CL
0167:004526DA 8A4D0B MOV CL,[EBP+0B]
0167:004526DD 0A07 OR AL,[EDI]
0167:004526DF 22C8 AND CL,AL
0167:004526E1 880F MOV [EDI],CL
0167:004526E3 EB14 JMP SHORT 004526F9
0167:004526E5 8D443101 LEA EAX,[ECX+ESI+01]
0167:004526E9 B101 MOV CL,01
0167:004526EB 884D0B MOV [EBP+0B],CL
0167:004526EE 8BCA MOV ECX,EDX
0167:004526F0 8A550B MOV DL,[EBP+0B]
0167:004526F3 D2E2 SHL DL,CL
0167:004526F5 F6D2 NOT DL
0167:004526F7 2010 AND [EAX],DL
0167:004526F9 0FB606 MOVZX EAX,BYTE [ESI]
0167:004526FC 894508 MOV [EBP+08],EAX
0167:004526FF 6A08 PUSH BYTE +08
0167:00452701 99 CDQ
0167:00452702 59 POP ECX
0167:00452703 F7F9 IDIV ECX
0167:00452705 8BF8 MOV EDI,EAX
0167:00452707 8D4701 LEA EAX,[EDI+01]
0167:0045270A 3D80000000 CMP EAX,80
0167:0045270F 7E02 JNG 00452713
0167:00452711 33C0 XOR EAX,EAX
0167:00452713 8A4C3001 MOV CL,[EAX+ESI+01]
0167:00452717 8D443001 LEA EAX,[EAX+ESI+01]
0167:0045271B 80C904 OR CL,04
0167:0045271E C0E902 SHR CL,02
0167:00452721 8808 MOV [EAX],CL
0167:00452723 A1E86C4B00 MOV EAX,[004B6CE8]
0167:00452728 99 CDQ
0167:00452729 B9DE100000 MOV ECX,10DE
0167:0045272E F7F9 IDIV ECX
0167:00452730 85D2 TEST EDX,EDX
0167:00452732 750F JNZ 00452743
0167:00452734 8B4508 MOV EAX,[EBP+08]
0167:00452737 6A08 PUSH BYTE +08
0167:00452739 8D4C3E02 LEA ECX,[ESI+EDI+02]
0167:0045273D 5F POP EDI
0167:0045273E 99 CDQ
0167:0045273F F7FF IDIV EDI
0167:00452741 0811 OR [ECX],DL
0167:00452743 FF05E86C4B00 INC DWORD [004B6CE8]
0167:00452749 8A4601 MOV AL,[ESI+01]
0167:0045274C A804 TEST AL,04
0167:0045274E 7409 JZ 00452759-------->NOP掉它!!!!!!!!
0167:00452750 33C9 XOR ECX,ECX
0167:00452752 85DB TEST EBX,EBX
0167:00452754 0F94C1 SETZ CL-------->CL应为1
0167:00452757 8BD9 MOV EBX,ECX-------->赋值
0167:00452759 F6D0 NOT AL
0167:0045275B 85DB TEST EBX,EBX-------->ebx不应为0
0167:0045275D 884601 MOV [ESI+01],AL
0167:00452760 7539 JNZ 0045279B-------->应该让它跳!
0167:00452762 837DFC00 CMP DWORD [EBP-04],BYTE +00
0167:00452766 7411 JZ 00452779
0167:00452768 8B4DFC MOV ECX,[EBP-04]
0167:0045276B E819F3FAFF CALL 00401A89
0167:00452770 FF75FC PUSH DWORD [EBP-04]
0167:00452773 E8002F0400 CALL 00495678
0167:00452778 59 POP ECX
0167:00452779 8B75D4 MOV ESI,[EBP-2C]
0167:0045277C 83C604 ADD ESI,BYTE +04
0167:0045277F 8975D4 MOV [EBP-2C],ESI
0167:00452782 833E00 CMP DWORD [ESI],BYTE +00
0167:00452785 740D JZ 00452794
0167:00452787 8D4DF0 LEA ECX,[EBP-10]
0167:0045278A E8B5970100 CALL 0046BF44
0167:0045278F E975FDFFFF JMP 00452509-------->大循环,跳到上面第一行!
0167:00452794 33F6 XOR ESI,ESI
0167:00452796 E9ED010000 JMP 00452988-------->此JMP跳过了注册成功的CALL!
0167:0045279B 33FF XOR EDI,EDI
0167:0045279D 397DD0 CMP [EBP-30],EDI
0167:004527A0 7C11 JL 004527B3
0167:004527A2 FF75D0 PUSH DWORD [EBP-30]
0167:004527A5 BBB05C4B00 MOV EBX,004B5CB0
0167:004527AA 8BCB MOV ECX,EBX
0167:004527AC E865730000 CALL 00459B16
0167:004527B1 EB05 JMP SHORT 004527B8
0167:004527B3 BBB05C4B00 MOV EBX,004B5CB0
0167:004527B8 393D845A4B00 CMP [004B5A84],EDI
0167:004527BE 7518 JNZ 004527D8
0167:004527C0 6A05 PUSH BYTE +05
0167:004527C2 C705BC584B000100+MOV DWORD [004B58BC],01
0167:004527CC E821560000 CALL 00457DF2
0167:004527D1 59 POP ECX
0167:004527D1 59 POP ECX
0167:004527D2 893DBC584B00 MOV [004B58BC],EDI
0167:004527D8 6848010000 PUSH DWORD 0148
0167:004527DD E8D0E20200 CALL 00480AB2
0167:004527E2 3BC7 CMP EAX,EDI
0167:004527E4 59 POP ECX
0167:004527E5 7410 JZ 004527F7
0167:004527E7 FF75DC PUSH DWORD [EBP-24]
0167:004527EA 8BC8 MOV ECX,EAX
0167:004527EC FF75C8 PUSH DWORD [EBP-38]
0167:004527EF FF75F4 PUSH DWORD [EBP-0C]
0167:004527F2 E83660FEFF CALL 0043882D-------->此CALL注册成功!
0167:004527F7 8B45EC MOV EAX,[EBP-14]
0167:004527FA FF7004 PUSH DWORD [EAX+04]
0167:004527FD FF1564754A00 CALL `USER32!UpdateWindow`
0167:00452803 8B75FC MOV ESI,[EBP-04]
0167:00452806 8D4508 LEA EAX,[EBP+08]
0167:00452809 6A01 PUSH BYTE +01
/\zest/\2000.2
标 题:半破BrainsBreaker3.0!!改1字节!!一点补充。 (1千字)
发信人:zest
时 间:2001-2-28 23:27:52
详细信息:
半破BrainsBreaker3.0!!改1字节!!一点补充。
1、首先:
在BBRK.INI加入:
[PACKBrainsBreaker]
0=zest
1=aaaa
2=1076e9867711e9867711e9867711e9867711
3=2100
4=4e37d9b1
5=5533cba4
详见上篇找出注册假成功部分!
2、[HKEY_CLASSES_ROOT\BrainsBreaker_Puzzle\ID]
@="af123835144e2f34a8a56cbb980357a8b43055347f980017"
因为注册假成功还会在注册表改为此值。如你已经注册假成功了则不需改动。
详见上篇怎样注册假成功部分!
3、改:BBRK32.EXE
0167:00426B85 1BC0 SBB EAX,EAX
0167:00426B87 40 INC EAX
0167:00426B88 85C0 TEST EAX,EAX
0167:00426B8A 0F8504010000 JNZ NEAR 00426C94
^^
84
0167:00426B90 8D8500FFFFFF LEA EAX,[EBP+FFFFFF00]
0167:00426B96 8BCB MOV ECX,EBX
0167:00426B98 50 PUSH EAX
4、运行程序已无功能限制!在Options显示注册成功。
5、但有文件被改动的nag和自己做的拼图有限制。
6、注册码不知怎么找!估计就在附近!没找到对比处,太乱。
7、00452337~00452A4B是检测注册码正确与否部分,004265C4~00426D0B是文件启动
检测是否注册部分,程序段非常相似,我是依此找突破口的。
8、你可把上[PACKBrainsBreaker]改[PACKFull]、[PACKEntry]、[PACKCountry]等
试试,[PACKFull]有问题,[PACKCountry]是DEMO。
/\zest/\2000.2
标 题:给篇教程,虽然是针对老版本的,但基本的scheme没太大变化 (85字)
发信人:1212
时 间:2001-3-3 18:18:18
详细信息:
Output: Brains Breaker v2.1 crack
Indeed a fun game to play! In fact I spent about 2-3 hours just playing the game before I started to crack it. It seems like some puzzles are only demos? Hmm, must be a nasty bug...but mr. Juan Trujillo Tarradas dont have to worry, we'll fix that for him! We'll just go to the "enter registraion name/serial" window and crack it like any other program... yeah...right...eh..only one problem... where is it?! At times like this I always go to the helpfile to try to find some usefull information, and look what I found:
Once your payment is processed, you'll receive an e-mail message containing your registration code with the instructions to enter it in the program that makes fully playable all the puzzles (if registered the Full pack) or the puzzles in the Entry set.Ah...The registration window is hidden! How to find it then?
Step 1 - finding the registration window!
I choosed to disasemble the program, and searched after some well- choosen
strings like "registration". I found this hit (after disasming with Wdasm,
no need to use IDA if we dont have to):
* Possible StringData Ref from Data Obj ->"Registration info. Program version "Interesting indeed! I browsed down a bit through the code and found alot of even more interesting strings there, including "Pack", "Name", "Your ID" and "Key:". Looks like this could be the place where we enter our registration details. Now we want to know how we execute this code, so we browse upwards through the code. We notice that this code is called from another location:
* Referenced by a CALL at Address: |:0044C881Now we know where this code was executed from. Go up to that location and have a look:
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0044B8CF(C) | :0044C852 6A06 push 00000006 :0044C854 FFB381010000 push dword ptr [ebx+00000181] :0044C85A E8CF49FDFF call 0042122E :0044C85F E9EB0C0000 jmp 0044D54F :0044C864 6A1C push 0000001C :0044C866 E8723FFDFF call 004207DD :0044C86B 898590FEFFFF mov dword ptr [ebp+FFFFFE90], eax :0044C871 85C0 test eax, eax :0044C873 0F84D60C0000 je 0044D54F :0044C879 6A00 push 00000000 :0044C87B FFB590FEFFFF push dword ptr [ebp+FFFFFE90] :0044C881 E85FE40100 call 0046ACE5 <-- here is the intersting call :0044C886 E9C40C0000 jmp 0044D54FHmm, judging from this code, we'd say that the call to the interesting routine will never be executed because the program will jump at offset 44C85F, and we dont see any other jump references...Here is a good example of how bad wdasm disassembles sometimes. There ARE references to the interesting call, if you use IDA you'll see them. The problem is that it referenced through the instruction "jmp dword ptr [4*eax+0044B96B]" and that's why Wdasm doesnt find it. Go to offset 44B964, you'll find this offset using IDA.
:0044B964 FF24856BB94400 jmp dword ptr [4*eax+0044B96B] :0044B96B C7C34400 DWORD 0044C3C7 :0044B96F 5CC44400 DWORD 0044C45C :0044B973 CEC44400 DWORD 0044C4CE :0044B977 C0C84400 DWORD 0044C8C0 :0044B97B 64C84400 DWORD 0044C864 <-- You'll land here if you're using Wdasm :0044B97F C0C84400 DWORD 0044C8C0 :0044B983 8BC84400 DWORD 0044C88B :0044B987 C0C84400 DWORD 0044C8C0 :0044B98B C0C84400 DWORD 0044C8C0 :0044B98F C0C84400 DWORD 0044C8C0 :0044B993 C0C84400 DWORD 0044C8C0 :0044B997 C0C84400 DWORD 0044C8C0 :0044B99B C0C84400 DWORD 0044C8C0 :0044B99F C0C84400 DWORD 0044C8C0 :0044B9A3 C0C84400 DWORD 0044C8C0 :0044B9A7 C0C84400 DWORD 0044C8C0 :0044B9AB C0C84400 DWORD 0044C8C0 :0044B9AF C0C84400 DWORD 0044C8C0 :0044B9B3 C0C84400 DWORD 0044C8C0 :0044B9B7 FEC54400 DWORD 0044C5FEAh - great! At offset 44B964, based on the value in eax, a jump is taken. So in order to execute our interesting call, eax should hold a value of 4 (4h*4h = 10h. 44B96Bh+10h = 44B97Bh and that's the offset where the interesting jump address is stored).
:0044B8A2 8B4607 mov eax, dword ptr [esi+07] :0044B8A5 3D50040000 cmp eax, 00000450 :0044B8AA 0F8F99000000 jg 0044B949 :0044B8B0 0F849A0E0000 je 0044C750 ... :0044B949 3D68040000 cmp eax, 00000468 :0044B94E 7F6B jg 0044B9BB :0044B950 0F84EB080000 je 0044C241 :0044B956 05AEFBFFFF add eax, FFFFFBAE ;Same as "sub eax,452" :0044B95B 83F813 cmp eax, 00000013 :0044B95E 0F875C0F0000 ja 0044C8C0 :0044B964 FF24856BB94400 jmp dword ptr [4*eax+0044B96B]There, now it's pretty easy to figure out what value we need to execute our "enter registation information" call. First of all it has to be over 450h, becuase we want to take the jump at offset 44B8AA. It must be lower than 468h because we DONT want to take the jump at offset 44B94E or at 44B950. Substract 452 from our value, and if the result is below or equal to 13h execute the jump at 44B964. We already know that we want eax to be 4 when the jump is beeing executed so therefor we want eax to be 452+4=456h at offset 44B8A2 in order to bring up the registraion window. To see if this theory is correct, lets test it in practice! Boot up the game, and put a breakpoint on cs:44B8A2 (make sure that brainsbreaker has control when you set the breakpoint, otherwise CS wont point to brainsbreakers code). Now choose a menu item, and softice will break due to our breakpoint. You will see that a value is moved into eax (the value depends on what menu-item we choosed). Step over the instruction and edit the eax register using the r command. Change to value to 456 instaed and let it run...YES! The "enter registraion information" windows pops up!
Step 2 - What pack do we want?
Ok, we got four edit fields that we must fill in, where the first one is "Pack:".
Remember what the help file said? There are two different registraion "packs",
one called Entry pack and another one called Full pack so we
can easily guess that we shall enter either "full pack", "full" or something.
To find out if we are right, let's enter "full pack" in the first field, and
just some bogus info in the other fields. Now we go on as we normally do when
cracking a name/serial protection, set a breakpoint on a string fetching function
(GetDlgItemTextA, GetWindowTextA, hmemcpy or whatever, you know them :)) or
try the breakpoint on windows message (bmsg) way...do
whatever you want, just as long as you break in, I choosed to break on the
windows message wm_gettext.
You all problaby know how to proceed from now on. Find our entered string
(Full pack), and put a breakpoing on memory range (bpr)
on it and then feel the code. You'll see ALOT of "repnz scasb" function (used
alot for length checking if al=0), and a few "repz movsb functions. Just step
through them, and put a new bpr everytime the string is copied. Remove an
old breakpoint only when you see that it's overwritten with something else.
If you're having trouble telling the interesting code from the uninteresting
I'll give you the offset where the interesting part begins, it's at offset
4012BD:
:004012BD 0FBE06 movsx eax, byte ptr [esi] :004012C0 50 push eax :004012C1 E8EE560000 call 004069B4 :004012C6 59 pop ecx :004012C7 8BD8 mov ebx, eax :004012C9 50 push eax :004012CA 0FBE17 movsx edx, byte ptr [edi]We start out by moving the first letter in our entered string into eax (in our case it's 46h, 'F'). What the next few lines do is that it copies that value into other registers (not really interesting), but the last instruction is very interesting. It takes a byte from what edi is pointing to and moves it into edx. I wonder what edi points to, dont you? Let's find out! "d edi" in softice, and now look in the datawindow. "Entry Full Upgrade..." and so on. Weee! We now know (ok, not exactly know, but it's a VERY good guess) that we shall enter "Full" in the first edit field, because we do want the fully registered copy, dont we?
Step 3 - Examining the protection scheme Time for the real pain, the
real protection scheme. So, start out by entering something in the edit fields,
I entered "Full", "Cruehead", "111", "1230123". Now we do like we did last
time, but this time we're only interested in when the program is doing anything
with our entered serial, so we choose to breakpoing on that string (1230123
in my case). Same story as before, a lot of length checking and string copying...I
know it's pretty boring, but just hang in there. After some time you'll get
to offset 401440. This is where its finally gets somewhat first interesting.
What the program does is that it compares all characters in the serial with
"-", but as our serial doesnt have a "-", we continue without any change.
After some more uninteresting length checkings we get to the same offset again,
but this time the program compares every character in our serial with "0".
If it finds a match, the zero is removed and instead an O is put there. Our
new code will be "123O123". We find ourself at this offset once again after
some more time in softice. This time the program checks if any of the characters
in the serial is '1'. If they are, replace them with a "L" instead. Our new
code will be "L23OL23". After this, each of our characters in the serial will
be compared to (in order and in hex): 00,3B,0D and 0A. We dont have to care
about this because these bytes wont be found in our serial.
Geez, so much debuging and yet nothing really interesting, but fear not -
we are getting there. After a while we'll land at offset 46AC55 and
here is where the fun part begins.
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0046ACB3(C) | :0046AC4C FF35BC554800 push dword ptr [004855BC] :0046AC52 8B45E8 mov eax, dword ptr [ebp-18] :0046AC55 0FBE10 movsx edx, byte ptr [eax] <-- We'll land here :0046AC58 52 push edx :0046AC59 E856BDF9FF call 004069B4 :0046AC5E 59 pop ecx :0046AC5F 50 push eax :0046AC60 E8BDBAFAFF call 00416722 :0046AC65 8845EF mov byte ptr [ebp-11], al :0046AC68 33C0 xor eax, eax * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0046ACA5(C) | :0046AC6A 8BC8 mov ecx, eax :0046AC6C BA01000000 mov edx, 00000001 :0046AC71 D3E2 shl edx, cl :0046AC73 33C9 xor ecx, ecx :0046AC75 8A4DEF mov cl, byte ptr [ebp-11] :0046AC78 23D1 and edx, ecx :0046AC7A 740E je 0046AC8A :0046AC7C 8BCB mov ecx, ebx :0046AC7E B201 mov dl, 01 :0046AC80 D2E2 shl dl, cl :0046AC82 8B4DF6 mov ecx, dword ptr [ebp-0A] :0046AC85 081431 or byte ptr [ecx+esi], dl :0046AC88 EB0E jmp 0046AC98 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0046AC7A(C) | :0046AC8A 8BCB mov ecx, ebx :0046AC8C B201 mov dl, 01 :0046AC8E D2E2 shl dl, cl :0046AC90 F6D2 not dl :0046AC92 8B4DF6 mov ecx, dword ptr [ebp-0A] :0046AC95 201431 and byte ptr [ecx+esi], dl * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0046AC88(U) | :0046AC98 43 inc ebx :0046AC99 83FB08 cmp ebx, 00000008 :0046AC9C 7503 jne 0046ACA1 :0046AC9E 46 inc esi :0046AC9F 33DB xor ebx, ebx * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0046AC9C(C) | :0046ACA1 40 inc eax :0046ACA2 83F805 cmp eax, 00000005 :0046ACA5 7CC3 jl 0046AC6A :0046ACA7 FF45F0 inc [ebp-10] :0046ACAA FF45E8 inc [ebp-18] :0046ACAD 8B45F0 mov eax, dword ptr [ebp-10] :0046ACB0 3B45FC cmp eax, dword ptr [ebp-04] :0046ACB3 7C97 jl 0046AC4CWhoah, quite some code there! But dont worry, we really dont have to understand it (as you will see later), we just need to know where the output is stored. The code here isnt very hard to understand either, but we'll deal with it later. To save some time, I'll tell you now that output will be created at offset 46AC85 and 46AC95. You will see that after the loop, a few bytes (how many depends on the length of the serial entered) have been generated from our serial and saved at the address that ecx+esi points to at offset 46AC85. You can now remove all breakpoints and put one (breakpoint on memory range - bpr) on our nely created bytes (in our case it will be 5 of them). Just to make sure you got the correct spot, the bytes for "L23OL23" is 4B,6F,B7,F4,06. As you will see this string will be copied around a bit, but just follow the same procedure as last time (same procedure as every year, james). After a little while you'll land in the next interesting spot:
:00459B50 8BC1 mov eax, ecx :00459B52 99 cdq :00459B53 F7FB idiv ebx :00459B55 8B45E4 mov eax, dword ptr [ebp-1C] :00459B58 03C2 add eax, edx :00459B5A 8A16 mov dl, byte ptr [esi] <-- You'll be here :00459B5C 3010 xor byte ptr [eax], dl :00459B5E 41 inc ecx :00459B5F 46 inc esi * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00459B4E(U) | :00459B60 8B45FC mov eax, dword ptr [ebp-04] :00459B63 2BC3 sub eax, ebx :00459B65 3BC8 cmp ecx, eax :00459B67 7CE7 jl 00459B50Not that hard to understand. One byte will be XOR'd with each of our new bytes, and a few others as well (these are constants). This final byte will have a value of 0E in our case. You should always be very suspicious when you see an instruction that uses XOR. The only exception is when it's followed by two registers of the same kind, because then (as you all problaby already know) it just sets the register to zero. Now after this loop we'll get to the first check. If you start stepping through the code you'll soon see that the byte which were XOR'd with our "registraion bytes" will be compared to zero. If it matches, go on, otherwise it's a fake code. Finally we're getting somewhere! We now know that after quite a lot of different manipulations of our serial (remember that we had two different manipulations, the first created a couple of bytes based on our serial, and the other XOR'ed them together along with a few other constant bytes) we shall have a final value of zero! Remember this as we'll use it later, but for now, just change the program so it continues, preferable by changing the final byte from 0E to 00 (you should always try to patch as little as possible, atleast while investigating a protection scheme). One can almost guess that somewhere nearby there will be another (or more) checks, and therefor we start stepping through the next piece of code. This is pretty hard, you have to feel where something interesting happends, but I'll tell you that at offset 459d01 something is happening:
:00459D01 3B4DEC cmp ecx, dword ptr [ebp-14] :00459D04 7D4F jge 00459D55 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00459D53(C) | :00459D06 8BC1 mov eax, ecx :00459D08 99 cdq :00459D09 F7FF idiv edi :00459D0B 8B45E0 mov eax, dword ptr [ebp-20] :00459D0E 8A1C10 mov bl, byte ptr [eax+edx] :00459D11 0FB745F0 movzx eax, word ptr [ebp-10] :00459D15 3BC8 cmp ecx, eax :00459D17 7D09 jge 00459D22 :00459D19 0FB7D1 movzx edx, cx :00459D1C 8B45F4 mov eax, dword ptr [ebp-0C] :00459D1F 321C10 xor bl, byte ptr [eax+edx] * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00459D17(C) | :00459D22 0FB7560C movzx edx, word ptr [esi+0C] :00459D26 3BCA cmp ecx, edx :00459D28 7D09 jge 00459D33 :00459D2A 0FB7C1 movzx eax, cx :00459D2D 8B5610 mov edx, dword ptr [esi+10] :00459D30 321C02 xor bl, byte ptr [edx+eax] * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00459D28(C) | :00459D33 0FB74614 movzx eax, word ptr [esi+14] :00459D37 3BC8 cmp ecx, eax :00459D39 7D09 jge 00459D44 :00459D3B 0FB7D1 movzx edx, cx :00459D3E 8B4618 mov eax, dword ptr [esi+18] :00459D41 321C10 xor bl, byte ptr [eax+edx] * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00459D39(C) | :00459D44 8BC1 mov eax, ecx :00459D46 99 cdq :00459D47 F7FF idiv edi :00459D49 8B45E0 mov eax, dword ptr [ebp-20] :00459D4C 881C10 mov byte ptr [eax+edx], bl :00459D4F 41 inc ecx :00459D50 3B4DEC cmp ecx, dword ptr [ebp-14] :00459D53 7CB1 jl 00459D06A pretty easy to understand protection here. Take the first char in the "pack" field, xor it with the first char in the "Username" field and finally xor this with the first char in the "ID" field. Save this byte and then proceed with the second character, the third and so on. I suppose a table will describe it better:
| Pack string: | 46 | 75 | 6C | 6C | ||||
| Username String: | 43 | 72 | 75 | 65 | 68 | 65 | ||
| ID string: | 31 | 32 | 33 | |||||
| Result after XOR: | 34 | 35 | 2A | 09 | 68 | 65 |
"Hey! You only got 6 characters in the table, but the strings can be longer
(and one of them in fact is)!" Calm down, That's because something is happening
after 6 bytes has been processed. Now the first byte in our "result string"
(34 in our case) will also be included the scheme. So, 34 will be xor'ed to
every 7'th char in the other strings, and in our case the "username" string
will be the only one effected, as the others are too small. The result is
written in the first position in the "result string", thus removing the old
value. After 6 more bytes, it does the same again , thus keeping the size
of the result string to 6 bytes. When 20h (=32 dec) characters has been processed
the routine is done.
Something has to be happening with these 6 bytes (why write that routine otherwise),
so lets put a bpr on them. You will break in a string comparing routine. So...this
string is compared to another string! Very interesting indeed... I wonder
what happends if they matches??? let's see! Change one of the strings so it
matches the other and let the program run...
YEEEEES! Program registered!
So, now all we have to do is to make the strings match...just one BIG problem...One would have thought that the string that our "pack, username, ID" string was compared with should be constant...but this is not true! It changes everytime, so there is not a chance to make these strings match eachother! First I thought this was some anti-cracking feature, but that is not true either. I changed the program so it would display a little messagebox with the first bytes of the string, and I ran it without softice (for the first time in months, softice wasnt loaded on my machine :)). No luck, it still changed! One alternative still remains...patching!
Step 4 - Cracking it! First of all I'd like to say that I dont really like patches because one never knows what comes with a patch. It could be a nasty checksum, or even worse - a delayed checksum. That's why I always like to find/calculate a valid serial when cracking name/serial protections, but when you're out of ideas, I guess patching can be justified. But even if we are going to patch, let's patch as little as we have too. We dont have to patch the first check (remember? one byte is compared to zero...) as we can pretty easily find a serial that justifies that. As most crackers are lazy by nature (well, atleast I am :)), lets just write a quick and dirty bruteforcer. You can find my source and the executable for it here. Run it, and we'll get the serial 125000. If our bruteforcer does what it's suppose to do we would now get by the first check by using this seriall, so let's test it! Go back to the register window, and enter the same information as before, but change the serial to 125000. Wow! It worked! Of course we didnt get the "thanks for registering" message, but we didnt expect that either, because the last check is still there. For reasons that I told you about earlier we have to patch that (or spend the next couple of weeks trying to figure out a way how to crack it without patching, but as I said - we're all lazy).
Of course the next question will be Where shall we patch? Before we can answer that we have to make sure we understand what we want to do. In this case we want two strings to match eachother (or atleast making the program think they do). If we investigate the comparision routine we see that the routine compares the number of bytes specified in edi. In our case edi=6 and therefor 6 bytes are compared. If we look at the code right after the comparison routine we will also see that dl is set to 1 if the strings matches. If they dont dl is set to zero. Now we can make a small list of possible patches:
1) Action: Set edi to zero so that zero bytes will be compared. Consequence: The strings wont be compared. 2) Action: Overwrite the two strings with the same 6 bytes. Consequence: The strings will match. 3) Action: Fake the return value so dl will be set to one either way. Consequence: The program thinks that the strings matches. 4) Action: Fake a conditional jump Consequence: The program thinks that the strings matches.There are even more possibilites but these are more than enough. We can choose any of these and the program would, in theory, think our entered serial is valid. Let's try for example to set edi to zero. First of all lets find where the program sets edi to 6:
:00459C43 8B7508 mov esi, dword ptr [ebp+08] :00459C46 807E2400 cmp byte ptr [esi+24], 00 :00459C4A 7415 je 00459C61 :00459C4C BF06000000 mov edi, 00000006Can we change this into "mov edi,0" instead? Yes we can but the program would crash later due to a couple of "IDIV" instructions that relies on edi not beeing zero. So where can we change edi to zero then? Look at this:
:00459CFF 33C9 xor ecx, ecx :00459D01 3B4DEC cmp ecx, dword ptr [ebp-14] :00459D04 7D4F jge 00459D55 ...This is the begining of the code that creates the 6 bytes long string from our entered Name, ID and Pack. This code is completely useless if we change edi to zero (because zero bytes will be compared) so we can saftly patch here. Let's change the code so it looks like this instead:
:00459CFF 33FF xor edi,edi ;set edi to zero :00459D01 EB52 jmp 00459D55 ;Jump over the rest ;of the functionOh yeah! This works very nicely! Patch it using your favourite hex-editor and run it.
Integrity check:
Program seems to be altered from his original contents
Of course...a checksum function as well. How can we crack this then?
In fact, the author has already done half the work for us. Notice how the message is presented - through a messagebox! Very good news for us crackers, we just have to put a bpx on MessageBoxA now in order to land right in the interesting code. So, do just that and trace upward and you'll see this:
:00442CC2 E870DBFFFF call 00440837 :00442CC7 3D22334455 cmp eax, 55443322 ;Whoah! What a nice hardcoded value! :00442CCC 7472 je 00442D40 ;Take this jump if you want to jump ;over the messagebox! :00442CCE 6810200100 push 00012010 :00442CD3 FF35843B4800 push dword ptr [00483B84] :00442CD9 83C4FC add esp, FFFFFFFC :00442CDC 66C70424BE00 mov word ptr [esp], 00BE :00442CE2 E8C16FFFFF call 00439CA8 :00442CE7 50 push eax :00442CE8 6A00 push 00000000 :00442CEA E80AEF0300 call USER32!MessageBoxAYou can see directly that something is fuzzy about the "cmp eax, 55443322" line. That looks VERY suspicious if you ask me (why not say "Hey Cracker! I'm here!!!" instead). Now we could quickly crack this just by changing the "je 00442D40" instruction to "jmp 00442D40" but we wont do that. The program might save the value returned in eax and use it later on for more checksum-checking (this is infact true for this program) so instead we want the above call to return 55443322. So, let's trace the call! You'll soon find this piece of code:
:00440DAE E8B504FCFF call 00401268 :00440DB3 83C40C add esp, 0000000C :00440DB6 85C0 test eax, eax :00440DB8 752E jne 00440DE8 :00440DBA A1803B4800 mov eax, dword ptr [00483B80] :00440DBF 8B10 mov edx, dword ptr [eax] :00440DC1 8B0D243B4800 mov ecx, dword ptr [00483B24] :00440DC7 8911 mov dword ptr [ecx], edx :00440DC9 B822334455 mov eax, 55443322 ;We want this! :00440DCE 50 push eaxNow, this isnt very hard either. As the program is already patched the call at line 440DAE will return eax<>0 and thus the jump will be taken. Btw that call is our good old "comparision" call. As you see it's used quite a lot in the program so it was a good idea not to patch there! Now just nop away the jump. 55443322 will be stored in eax and the checksum routine thinks that everything is alright and we have a fully functional registered copy of BrainsBreaker!
Step 5 - Making a nice crack!
You can skip this part if you want to. This step is not really necessary,
but if we were to release a crack for this program we had to make a nice looking
patcher. The problem is that we dont know how to bring up the "enter registraion
info" window, and thus the user wouldnt have anywhere to enter his name. We
can solve this by making our own little "registraion window" that asks for
a username in our patcher. If you look where BrainsBreaker saves the registraion
information you will see that all of the reg-info is saved in the "BBRK.INI"
file. It will save both plaintext and encrypted values. It will look something
like this:
[PackFull] ;What pack we're using 0=Cruehead ;Username plain text 1=123 ;ID plain text 2=7E15AB3D1516D6 ;Serial encrypted 3=2100 ;Not sure. I believe it's version number 4=192BEC6D323CF86C ;Username encrypted 5=6B6BAA ;ID encryptedOf course I didnt know all of this before I fully examined the program. I started out by putting a breakpoint on GetPrivateProfileStringA and when the encrypted serial line was read I put a bpr on that so I would see what was happening to that string. I wont describe every step on how I did it because it's fairly easy. Instead I'll try to describe how it works:
Every two letters in '7E15AB3D1516D6' is in fact one byte. So first of all the string is transformed so it looks like this : 7E 15 AB 3D 15 16 D6 . 7 bytes that is. Now this string is Xor'ed against a four byte long string that was "5A 59 99 08". This string caught my curiosity because it didnt look like a hardcoded value and neither could I find it in the .EXE file but I continued nevertheless, not worring aout it. The strings was xor'ed like this:
| String from INI file: | 7E | 15 | AB | 3D | 15 | 16 | D6 |
| Four byte string: | 5A | 59 | 99 | 08 | 5A | 59 | 99 |
| Result after XOR: | 24 | 4C | 32 | 35 | 4F | 4F | 4F |
You see? The result is '$L25OOO'. Our entered serial string (somewhat transformed). The same procedure is done with the two other encrypted strings. If the decrypted username matches the username in plain text and if the decrypted ID matches the ID in plain text, then the program executes the registration check with the decrypted serial. The program will gladly accept it because we have patched the last check!
Ok, I sat down one night and coded this crack. It worked great on my computer but when I tried it on another computer it simply didnt work! Back to the drawing board again. It turned out that I was right when thinking that the 4 bytes xor string was strange. After some more examination I found out that this value was created from a special ID which is stored in the registry. The ID is created the first time brainsbreaker is installed and there is'nt much point in reversing the algorigthm for creating a BrainsBreaker ID becuase it uses the "TlsGetValue" function as source. The complete ID is about 50 bytes long but only 8 of these bytes are used to create the xor string (if you're really interested byte number 5,10,8,13,17,19,22,38 of the ID is used to make the xorstring). That's why my crack didnt work on the other machine - when I installed BrainsBreaker for the first time a different ID was created and thus also a different xorstring. So I sat down another night and re-coded the crack, this time for windows as we need to access the registry. This time the crack worked like a sharm on both machines! Oh joy oh joy!
Thoughts about BrainsBreaker
This is not important for the crack, but it's never the less very interesting.
I'm not sure about this but it looks like every puzzle is a stand-alone part
of the program. Every puzzle stores a number of things including the name
of the author of the puzzle, if the main program has been altered, wether
this puzzle is free/demo/registered and a number of other things. My guess
is that these values (or flags) are stored directly after the mainprogram
checks if it's registered or not. This way every puzzle can check if the main
program has been cracked. But we dont have to care about all of this because
the crack I presented above takes care of everything :). None of these flags
are stored directly in the .exe file, instead they are stored in encrypted
state. At startup these puzzles are decrypted using different keysources but
the most common seems to be "(c)J. Trujillo T." I managed to get this info
by stumbeling across a "xor [edi],al" function when the program was loading
the startup screen with all the puzzles. That of course cought my interest
and I started to examine it a bit more closer.
A small hint : It's a good idea to search the deadlisting for "MessageBoxA" functions as these can give you alot of usefull information sometimes. Fake a flag or something to make the program show the messagebox. For example I found out that every puzzle stores if the main program has been altered or not (if it has, a value of 12345 is stored in each of the puzzles) using this method.
But there are some things that remains a mystery for me still. I havnt been able to figure out how to bring up the registration-window yet and you can find a few very interesting functions if you look at the dead-listing:
Addr:00487ABC Ord: 14 (000Eh) Name: __DebuggerHookData Addr:004035BC Ord: 15 (000Fh) Name: __lockDebuggerData(void) Addr:004035E4 Ord: 16 (0010h) Name: __unlockDebuggerData(void)Antidebugging functions problaby but I havnt seen any marks of them. Pretty strange...
Conclusion - BrainsBreaker:
A somewhat complicated protection scheme, but nothing that we havnt seen before.
The hidden registraion window is a good idea but it's far to easy to find
it using a dead-listing approach.
标 题:破BrainsBreaker3.0[07b]! (9千字)
发信人:zest
时 间:2001-3-10 0:11:50
详细信息:
破BrainsBreaker3.0[07b]!
http://www.brainsbreaker.com/download.htm
非常感谢1212提供的Cruehead的优秀教程。
如有疑问,请参看此教程!
http://www.instinct.org/fravia/99solu/cruecom.htm
===========================================================
1、Key运算检测,最后保证[eax]为0,可BPM跟踪。
0167:00426D93 8BC1 MOV EAX,ECX
0167:00426D95 99 CDQ
0167:00426D96 F7FF IDIV EDI
0167:00426D98 8D041A LEA EAX,[EDX+EBX]
0167:00426D9B 8A1431 MOV DL,[ECX+ESI]
0167:00426D9E 3010 XOR [EAX],DL ******
0167:00426DA0 41 INC ECX
0167:00426DA1 3B4DF8 CMP ECX,[EBP-08]
0167:00426DA4 7CED JL 00426D93---->循环9次
改为:
0167:00426D93 8BC1 MOV EAX,ECX
0167:00426D95 99 CDQ
0167:00426D96 F7FF IDIV EDI
0167:00426D98 8D041A LEA EAX,[EDX+EBX]
0167:00426D9B 8A10 MOV DL,[EAX] ******
0167:00426D9D 90 NOP
0167:00426D9E 3010 XOR [EAX],DL ******we shall have a final value of zero
0167:00426DA0 41 INC ECX
0167:00426DA1 3B4DF8 CMP ECX,[EBP-08]
0167:00426DA4 7CED JL 00426D93
===========================================================
2、Pack、Name、Your ID运算检测,对比处可BPM跟踪。
0167:00427587 33C9 XOR ECX,ECX
0167:00427589 8BC1 MOV EAX,ECX
0167:0042758B 668B7D0C MOV DI,[EBP+0C]
0167:0042758F 99 CDQ
0167:00427590 F77DFC IDIV DWORD [EBP-04]
0167:00427593 8B45F8 MOV EAX,[EBP-08]
0167:00427596 03D0 ADD EDX,EAX
0167:00427598 663B7DE4 CMP DI,[EBP-1C]
0167:0042759C 8A02 MOV AL,[EDX]
0167:0042759E 7306 JNC 004275A6
0167:004275A0 8B7DE8 MOV EDI,[EBP-18]
0167:004275A3 32040F XOR AL,[EDI+ECX]
0167:004275A6 668B7D0C MOV DI,[EBP+0C]
0167:004275AA 663B7E0C CMP DI,[ESI+0C]
0167:004275AE 7306 JNC 004275B6
0167:004275B0 8B7E10 MOV EDI,[ESI+10]
0167:004275B3 32040F XOR AL,[EDI+ECX]
0167:004275B6 668B7D0C MOV DI,[EBP+0C]
0167:004275BA 663B7E14 CMP DI,[ESI+14]
0167:004275BE 7306 JNC 004275C6
0167:004275C0 8B7E18 MOV EDI,[ESI+18]
0167:004275C3 32040F XOR AL,[EDI+ECX]
0167:004275C6 FF450C INC DWORD [EBP+0C]
0167:004275C9 8802 MOV [EDX],AL
0167:004275CB 0FB74D0C MOVZX ECX,WORD [EBP+0C]
0167:004275CF 83F920 CMP ECX,BYTE +20
0167:004275D2 7CB5 JL 00427589---->循环20h次
0167:004275D4 FF75F4 PUSH DWORD [EBP-0C]
改为:(乱改程序会崩溃!)
0167:00427587 33C9 XOR ECX,ECX
0167:00427589 C745FC00000000 MOV DWORD [EBP-04],00 ******because zero bytes will be compared
0167:00427590 E93F000000 JMP 004275D4 ******
0167:00427595 F8 CLC
0167:00427596 03D0 ADD EDX,EAX
0167:00427598 663B7DE4 CMP DI,[EBP-1C]
0167:0042759C 8A02 MOV AL,[EDX]
0167:0042759E 7306 JNC 004275A6
0167:004275A0 8B7DE8 MOV EDI,[EBP-18]
0167:004275A3 32040F XOR AL,[EDI+ECX]
0167:004275A6 668B7D0C MOV DI,[EBP+0C]
0167:004275AA 663B7E0C CMP DI,[ESI+0C]
0167:004275AE 7306 JNC 004275B6
0167:004275B0 8B7E10 MOV EDI,[ESI+10]
0167:004275B3 32040F XOR AL,[EDI+ECX]
0167:004275B6 668B7D0C MOV DI,[EBP+0C]
0167:004275BA 663B7E14 CMP DI,[ESI+14]
0167:004275BE 7306 JNC 004275C6
0167:004275C0 8B7E18 MOV EDI,[ESI+18]
0167:004275C3 32040F XOR AL,[EDI+ECX]
0167:004275C6 FF450C INC DWORD [EBP+0C]
0167:004275C9 8802 MOV [EDX],AL
0167:004275CB 0FB74D0C MOVZX ECX,WORD [EBP+0C]
0167:004275CF 83F920 CMP ECX,BYTE +20
0167:004275D2 7CB5 JL 00427589
0167:004275D4 FF75F4 PUSH DWORD [EBP-0C]
===========================================================
3、程序注册检验对比处及是否被修改检验处如下:
* Referenced by a CALL at Addresses:
|:00405FC3 , :00420734 , :004213E0 , :004225A3 , :00426DAE
|:0042763A , :00427788 , :00459AF8 , :0046EBF0 , :00470C39
|:004800B5 , :00491CC4
|
:00495EC0 8B44240C mov eax, dword ptr [esp+0C]
:00495EC4 85C0 test eax, eax
:00495EC6 7444 je 00495F0C
:00495EC8 8B542404 mov edx, dword ptr [esp+04]
:00495ECC 56 push esi
:00495ECD 57 push edi
:00495ECE 8BF2 mov esi, edx
:00495ED0 8B7C2410 mov edi, dword ptr [esp+10]
:00495ED4 0BD7 or edx, edi
:00495ED6 83E203 and edx, 00000003
:00495ED9 7432 je 00495F0D
:00495EDB A901000000 test eax, 00000001
:00495EE0 740B je 00495EED
:00495EE2 8A0E mov cl, byte ptr [esi]
:00495EE4 3A0F cmp cl, byte ptr [edi]
:00495EE6 7552 jne 00495F3A
:00495EE8 46 inc esi
:00495EE9 47 inc edi
:00495EEA 48 dec eax
:00495EEB 741D je 00495F0A
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00495EE0(C), :00495F08(C)
|
:00495EED 8A0E mov cl, byte ptr [esi]
:00495EEF 8A17 mov dl, byte ptr [edi]
:00495EF1 38D1 cmp cl, dl
:00495EF3 7545 jne 00495F3A
:00495EF5 8A4E01 mov cl, byte ptr [esi+01]
:00495EF8 8A5701 mov dl, byte ptr [edi+01]
:00495EFB 38D1 cmp cl, dl
:00495EFD 753B jne 00495F3A
:00495EFF 83C702 add edi, 00000002
:00495F02 83C602 add esi, 00000002
:00495F05 83E802 sub eax, 00000002
:00495F08 75E3 jne 00495EED
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00495EEB(C), :00495F44(C)
|
:00495F0A 5F pop edi
:00495F0B 5E pop esi
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00495EC6(C)
|
:00495F0C C3 ret
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00495ED9(C)
|
:00495F0D 8BC8 mov ecx, eax
:00495F0F 83E003 and eax, 00000003
:00495F12 C1E902 shr ecx, 02
:00495F15 742B je 00495F42
:00495F17 F3 repz
:00495F18 A7 cmpsd
:00495F19 7427 je 00495F42
:00495F1B 8B4EFC mov ecx, dword ptr [esi-04]
:00495F1E 8B57FC mov edx, dword ptr [edi-04]
:00495F21 38D1 cmp cl, dl
:00495F23 7510 jne 00495F35
:00495F25 38F5 cmp ch, dh
:00495F27 750C jne 00495F35
:00495F29 C1E910 shr ecx, 10
:00495F2C C1EA10 shr edx, 10
:00495F2F 38D1 cmp cl, dl
:00495F31 7502 jne 00495F35
:00495F33 38F5 cmp ch, dh
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00495F23(C), :00495F27(C), :00495F31(C), :00495F4C(C), :00495F53(C)
|:00495F66(C)
|
:00495F35 B800000000 mov eax, 00000000
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00495EE6(C), :00495EF3(C), :00495EFD(C)
|
:00495F3A 1BC0 sbb eax, eax
:00495F3C 5F pop edi
:00495F3D 83D8FF sbb eax, FFFFFFFF
:00495F40 5E pop esi
:00495F41 C3 ret
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00495F15(C), :00495F19(C)
|
:00495F42 85C0 test eax, eax
:00495F44 74C4 je 00495F0A
:00495F46 8B16 mov edx, dword ptr [esi]
:00495F48 8B0F mov ecx, dword ptr [edi]
:00495F4A 38CA cmp dl, cl
:00495F4C 75E7 jne 00495F35
:00495F4E 48 dec eax
:00495F4F 7418 je 00495F69
:00495F51 38EE cmp dh, ch
:00495F53 75E0 jne 00495F35
:00495F55 48 dec eax
:00495F56 7411 je 00495F69
:00495F58 81E10000FF00 and ecx, 00FF0000
:00495F5E 81E20000FF00 and edx, 00FF0000
:00495F64 3BD1 cmp edx, ecx
:00495F66 75CD jne 00495F35
:00495F68 48 dec eax
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00495F4F(C), :00495F56(C)
|
:00495F69 5F pop edi
:00495F6A 5E pop esi
:00495F6B C3 ret
不能乱改,否则崩溃,程序其他部分还会调用此处,此乃程序高明之处。
===========================================================
4、程序被修改提示框的去除我用R!SC'sPatcher v1.4做PATCH,
非常简单,按1,2改。软件可在TOYE工具处下载。
我的bbrk32.rpp如下:
F=bbrk32.exe:
O=cr_bbrk32.exe:
P=426d9c/14,31/10,90:
P=427589/8b,c1,66,8b,7d,0c,99,f7,7d,fc,8b,45/c7,45,fc,00,00,00,00,e9,3f,00,00,00:
$
===========================================================
5、运行生成的cr_bbrk32.exe,
We have a fully functional REGISTERED copy of BrainsBreaker3.0[07b]!
===========================================================
/\zest/\2001.3.8