===========================================
	          cd-check-removal tutor fr halflife
	          done by the_matrix [winkillerz]
=========================================== 

dieses tutuorial richtiet sich an anfnger, die aber schon ein bischen erfahrung beim spiele-cracken haben
(also wenn ihr nicht wisst, was ein getdrivetpyea macht, dann lest euch mal das cd-remove-tu von wkz_daedalus durch!)

1)   was brauchen wir?
	windasm
	hiew
	softice (nicht unbedingt, aber wer es selber lsen will erspart sich damit viele jmps!)
	
also die bliche strategie: hl.exe disassembeln und in die string refs geschaut....ach sowas, keine referenz
 (ok, ich gebe zu, dass ich gar nicht erst geguckt habe, da es eh keine msgbox im spiel gibt...)
 iss aber egal, die hilft uns eh nicht weiter!
 
  also gleich in den imports nachgesehen... GetDrivetypeA aha, 2 mal vorhanden. das sieht ja schon relativ einfach aus.
 hinter dem getdrivetype wird mit 00000005 verglichen, entspricht dem cdrom...aha, beim 2. das gleiche! schn, also
 nopen wir die jumps aus...und als htte ich es geahnt...die fehlermeldung kommt wieder...
 ....wenn ihr die hl.exe schon gepatcht habt macht es nicht rckgngig, die jmps zu patchen war der erste schritt....
 
 
 also analysieren wir erstmal die cd-check-routine:
 

* Reference To: KERNEL32.GetDriveTypeA, Ord:00DEh -----> erster getdrivetypea
                                  |
:0043A8CD FF15988B4E00            Call dword ptr [004E8B98]
:0043A8D3 83F805                  cmp eax, 00000005
:0043A8D6 740C                    je 0043A8E4 -------> sehr verdchtig!!
:0043A8D8 8BC6                    mov eax, esi
:0043A8DA 5F                      pop edi
:0043A8DB 5E                      pop esi
:0043A8DC 5B                      pop ebx
:0043A8DD 81C420020000            add esp, 00000220
:0043A8E3 C3                      ret ------> kehre an den ausgangspunkt zurck, nimm keine werte aus der funtion mit (-> fehlermeldng: cd feht)

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0043A8D6(C)
|
:0043A8E4 8D7C240C                lea edi, dword ptr [esp+0C] --------> hier gehts nach dem je weiter
........
blah, blah, blah
........

:0043A92C 53                      push ebx

* Reference To: KERNEL32.GetVolumeInformationA, Ord:014Eh -----> da will doch jemand den namen von der cd wisssen 
                                  |					    (die ja nicht eingelegt ist!)
:0043A92D FF159C8B4E00            Call dword ptr [004E8B9C]
........
nochmal blah, blah, blah
........

:0043A94F 53                      push ebx

* Reference To: KERNEL32.GetDiskFreeSpaceA, Ord:00DAh -----> und den freien platz auf der cd will er auch wissen? wieso?!
                                  | 				             na auf einer cd ist immer null platz nach dem brennen (auch bei 
:0043A950 FF15948B4E00            Call dword ptr [004E8B94]         multisession, windows iss bloss zu bld dazu das rauszukriegen)
:0043A956 837C241000              cmp dword ptr [esp+10], 00000000
:0043A95B 740F                    je 0043A96C -----> noch verdchtiger!
:0043A95D B801000000              mov eax, 00000001 -------> wird noch sehr hufig auftauchen, allerdings ist die kopierte zahl wohl mehr
:0043A962 5F                      pop edi			     zum debuggen verwendet worden, denn nach jeder stufe der protection wird sie 
:0043A963 5E                      pop esi			     um eins grer, am ende ist sie jedoch meist 7 oder A
.....
:0043A96B C3                      ret

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0043A95B(C)
|
:0043A96C 8B4C2414                mov ecx, dword ptr [esp+14]
:0043A970 0FAF4C2418              imul ecx, dword ptr [esp+18]
:0043A975 0FAF4C241C              imul ecx, dword ptr [esp+1C]
:0043A97A 3B8C2434020000          cmp ecx, dword ptr [esp+00000234]
:0043A981 730F                    jnb 0043A992 ------> und die nchste stufe
:0043A983 B80A000000              mov eax, 0000000A
:0043A988 5F                      pop edi
:0043A989 5E                      pop esi
:0043A98A 5B                      pop ebx
:0043A98B 81C420020000            add esp, 00000220
:0043A991 C3                      ret


und in dieser manier geht es weiter: je wenn rckgabewert von der gecallten function ok ist, wenn nicht kein jmp, der
eax bekommt einen sinnlosen wert und dann schgleilich ein ret. er checkt nochmal ein paar dateien auf vorhandensein,
versucht dateien auf der cd zu lschen, holt sich noch allerhand infos ber die cd und macht nochmal einen getdrivetypea.
da geht es weiter:


* Referenced by a CALL at Address:
|:0043ACB2   
|
:0043ABA0 81EC04010000            sub esp, 00000104


.........viel, viel weiter unten: (aber noch in der selben funktion!)


* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0043AC19(C), :0043AC28(C), :0043AC38(C) -----> anfang: ziel von vielen jmps
|
:0043ABFC 803F00                  cmp byte ptr [edi], 00
:0043ABFF 745D                    je 0043AC5E
:0043AC01 6A00                    push 00000000
:0043AC03 57                      push edi
:0043AC04 E8E7D30300              call 00477FF0
:0043AC09 83C408                  add esp, 00000008
:0043AC0C 8D7801                  lea edi, dword ptr [eax+01]
:0043AC0F 57                      push edi

* Reference To: KERNEL32.GetDriveTypeA, Ord:00DEh -----> die gesuchte funktion
                                  |
:0043AC10 FF15988B4E00            Call dword ptr [004E8B98]
:0043AC16 83F805                  cmp eax, 00000005 ------> vergleich mit 5 (cdrom)
:0043AC19 75E1                    jne 0043ABFC --------> wenn nicht 5 dann wieder an den anfang
:0043AC1B 55                      push ebp
:0043AC1C 57                      push edi
:0043AC1D E83EFCFFFF              call 0043A860 ------>funktion die, datein testet, lscht usw...(siehe oben)
:0043AC22 83C408                  add esp, 00000008
:0043AC25 83F807                  cmp eax, 00000007 ----------> vergleich des eax mit 7, wenn nicht 7, dann springe an den anfang
:0043AC28 75D2                    jne 0043ABFC		     jede funktions-stufe gibt einen anderen wert zurck, bei der letzten stufe
:0043AC2A 55                      push ebp			     (wenn alles ok ist) gibt es eine 7 im eax
:0043AC2B 56                      push esi
:0043AC2C 57                      push edi
:0043AC2D E84EFEFFFF              call 0043AA80 ---------> noch ein call, der sowas hnliches macht wie der davor
:0043AC32 83C40C                  add esp, 0000000C
:0043AC35 83F807                  cmp eax, 00000007 ----------> wieder vergleich mit 7
:0043AC38 75C2                    jne 0043ABFC ---------> wenn nicht 7 dann springe zum anfang
:0043AC3A B9FFFFFFFF              mov ecx, FFFFFFFF
.......
:0043AC70 81C404010000            add esp, 00000104
:0043AC76 C3                      ret


sooo, jetzt wisst ihr schon in etwa worum es geht!

zum vergleich nochmal die jmps die du umkehrst (dann geht es aber nicht mehr mit der original-cd!) oder besser mit hiew ausnopst:

hier gleich noch die offsets um in hiew dahin zu kommen:

0043A8D6	39cd6 ---> 2 x 90
0043AC19	3a019 ---> 2 x 90
0043AC28	3a028 ---> 2 x 90
0043AC38	3a038 ---> 2 x 90

soo, das ganze in hiew gendert.....exe gestartet....und auf new game ----> hard oder so klicken.....und.....da iss ja wieder diese nervige
message!!!!!!

tja, jetzt bist du gefragt, denn so sieht das eigentlich generell aus beim cracken, der kopierschutz oder der cd-check funzt auch noch
nachdem man ihn halb verstmmelt hat.....

ich geb euch nen kleinen tip: suckt mal eine funktion, die valve.ico checkt, da gibt es die lsung (zumindest den weg dahin,
die lsung selbst steht ein bischen weiter oben....)








wenn du noch nicht soweit bist, oder es aufgegeben hast, dann lese weiter:







hier also die funktion, die valve.ico checkt:


* Referenced by a CALL at Addresses:
|:0041CC5E   , :0041CC9D   -------> wo kommen die denn her?
|
:0043AC80 B818120000              mov eax, 00001218
:0043AC85 E866C20300              call 00476EF0
:0043AC8A C744240407000000        mov [esp+04], 00000007
:0043AC92 53                      push ebx
:0043AC93 56                      push esi
:0043AC94 57                      push edi
:0043AC95 55                      push ebp
:0043AC96 E8B5020000              call 0043AF50
:0043AC9B 8D442410                lea eax, dword ptr [esp+10]
:0043AC9F 6866120000              push 00001266
:0043ACA4 C744241400000000        mov [esp+14], 00000000

* Possible StringData Ref from Data Obj ->"valve.ico" ------> der gesuchte string
                                  |
:0043ACAC 68B8E84B00              push 004BE8B8
:0043ACB1 50                      push eax
:0043ACB2 E8E9FEFFFF              call 0043ABA0 ------> callt die 2. funciton mit getdrivetypea
.........


ich glaube ihr habt es schon: die ganze funktion wird gecallt von 0041CC5E und 0041CC9D und da springen wir einfach mal hin!


* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0041CBE9(C), :0041CBF1(C), :0041CC22(C), :0041CC26(C)
|
:0041CC3F C70558CB4B0000000000    mov dword ptr [004BCB58], 00000000
:0041CC49 85F6                    test esi, esi
:0041CC4B 0F84A8000000            je 0041CCF9
:0041CC51 833D00EE4B0000          cmp dword ptr [004BEE00], 00000000
:0041CC58 0F859B000000            jne 0041CCF9
:0041CC5E E81DE00100              call 0043AC80 ----->von hier wird sie gecallt......
:0041CC63 85C0                    test eax, eax --------> aha, der eax wird gecheckt....schaut mal in  die funktion rein mit valve.ico, dort
:0041CC65 7572                    jne 0041CCD9	      wird vor dem letzten ret der eax nicht mit xor eax,eax gelscht, sondern auf 1 gesetzt,
:0041CC67 68027F0000              push 00007F02	      also: den jne in jmps verndern

* Reference To: USER32.LoadCursorA, Ord:0172h
                                  |
:0041CC6C 8B1D448E4E00            mov ebx, dword ptr [004E8E44]
:0041CC72 6A00                    push 00000000
:0041CC74 FFD3                    call ebx
:0041CC76 89442414                mov dword ptr [esp+14], eax
:0041CC7A 68007F0000              push 00007F00
:0041CC7F 6A00                    push 00000000
:0041CC81 FFD3                    call ebx
:0041CC83 8BE8                    mov ebp, eax
:0041CC85 33DB                    xor ebx, ebx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0041CCCE(C)
|
:0041CC87 55                      push ebp

* Reference To: USER32.SetCursor, Ord:01EBh
                                  |
:0041CC88 FF15F88D4E00            Call dword ptr [004E8DF8]
:0041CC8E 6854010000              push 00000154
:0041CC93 6A00                    push 00000000
:0041CC95 E8162C0500              call 0046F8B0
:0041CC9A 83C408                  add esp, 00000008
:0041CC9D E8DEDF0100              call 0043AC80 -------> .......und von hier
:0041CCA2 85C0                    test eax, eax	             bekannt? also wieder den jne in jmps umndern
:0041CCA4 752A                    jne 0041CCD0
:0041CCA6 833D90044D0000          cmp dword ptr [004D0490], 00000000
:0041CCAD 7405                    je 0041CCB4



tja, und nachdem du den kram gepatcht hast, hast du einen relativ kompilzierten aber sehr logisch aufgebauten cd-check ausgehebelt.....
gratulation!! nun noch schnell einen patch basteln mit patchfx oder ultrapatcher32 (oder mit der eigenen crackengine!?) und releasen!!!!

ps: fr die besseren cracker: ich weis, es gibt noch viele andere wege um hl.exe zu cracken, man knnte zb. die ganzen je in den
funktionen in jmps patchen, so dass er am ende den richtigen wert von selbst setzt oder beim ersten ret einfach den wert mit mov eax, 0000007
selbst zu setzen, aber ich wollte die logik in der routine zeigen, und wie einfach es ist bei solchen funktionen die protection zu knacken.


ok, das wars fr heute, jetzt setzt euch an ein anderes game ran und no-cd-crackt es!!!!!!!!!

greetz:

	winkillerz [esp. wkz_daedalus]
	laxity
	+orc
	sn00pe
	gonzo
	blackcheck
	r!sc
	duellist
	xCrk

WIR OSSIS MSSEN ZUSAMMENHALTEN !!!!!!