Cracking SpeedBoat Attack
Ένα όχι και τόσο συνηθισμένο cd check ...
by human_thought
ΕΚΘΕΣΗ ΓΙΑ ΤΟ 1ο PROJECT
Στο προηγούμενο site της M.a.s.k. είχα γράψει ένα βοήθημα για το cd check αυτού του παιχνιδιού. Θα αναρωτιέστε ίσως γιατί γράφω πάλι για αυτό.Ο λόγος είναι απλός.Σε αυτό το βοήθημα θα εξηγήσω ΚΑΙ πως το πρόγραμμα ελέγχει για το CD εκτός από το απλώς να αφαιρέσω το cd check. Ακόμα,στο τέλος θα φτιάξουμε και έναν απλό patcher που θα patchαρει τα απαραίτητα κομμάτια του κώδικα ώστε να μην μας ζητάται πλέον το cd.Η έκθεση αυτή φυσικά γράφεται στο πλαίσιο του 1ου project της M.a.s.k. που αφορά τα cd checks.
Ξεκινώντας αυτό το βοήθημα θα έλεγα σε όλους τους crackers ότι ακόμα και αν δεν έχουν το παιχνίδι που περιγράφω εδώ,καλό θα ήταν να διαβάσουν την έκθεση,καθώς θα δούμε μαζί έναν λίγο πιο περίεργο τρόπο ελέγχου για το cd από το παιχνίδι.Επιπλέον θα γράψουμε έναν patcher σε Win32Asm.Ας ξεκινήσουμε λοιπόν: Το παιχνίδι αποτελείται από 2 εκτελέσιμα όπως θα έχετε προσέξει όσοι το έχετε.Το ένα εκτελέσιμο λέγεται "vsb.exe" ενώ το άλλο λέγεται "sboat.exe".Το πρώτο είναι ουσιαστικά ο loader του sboat.exe.Η αλήθεια είναι ότι δεν υπάρχει σοβαρός λόγος για την χρησιμοποίηση ενός loader,τουλάχιστον όχι κάτι που να έχω εντοπίσει προσωπικά καθώς το παιχνίδι τρέχει κανονικά και από τα δύο exe.Πάντως το exe του παιχνιδιού είναι το "sboat.exe",το οποίο και φορτώνουμε στον symbol loader για να δούμε πως το πρόγραμμα εξετάζει για την ύπαρξη του cd.Αρχικά βλέπουμε το API GetVersion το οποίο επιστρέφει πληροφορίες για την έκδοση των windows που έχουμε στον υπολογιστή μας,πιθανότατα για να ελέγξει αν έχουμε κάτι πιο καινούριο απο win9x ώστε να βγάλει κάποιο μήνυμα ασυμβατότητας,καθώς το παιχνίδι είναι σχετικά παλιό. Αμέσως μετά καλείται το GetCommandLineA,το οποίο επιστρέφει το path που βρίσκεται το executable και δέχεται κάποια μικρή επεξεργασία που δεν μας ενδιαφέρει.Το επόμενο Api είναι το GetStartupInfoA που επίσης δεν παίζει κανένα ρόλο στην προστασία φυσικά.Έπειτα όμως ακολουθεί το GetModuleHandleA,που επιστρέφει το module handle του εκτελέσιμου.Μπαίνοντας στο ακριβώς παρακάτω call στην διεύθυνση 4411F0,βλέπουμε τα εξής: (IDA Dump) .text:004411F0 push ebp
mov ebp, esp
sub esp, 1Ch
push ebx
push esi
push edi
call sub_441880
test eax, eax
jz loc_44120D
xor eax, eax
jmp loc_441483
loc_44120D:
mov eax, [ebp+lpszCmdLine] push eax
call sub_441B30
add esp, 4
loc_441219:
call sub_462000 <- Ένα call πριν το bad_guy msgbox.
test eax, eax <- Επέστρεψε με eax = 0 ?
jnz loc_441259 <- Τότε μην πηδάς,ακολουθεί bad_guy msgbox
push 15h <- Style of msgbox
mov eax, lpCaption
push eax <- "Speedboat Attack"
push offset aPleaseInsertSp <- 'Please, insert Speedboat Attack CD into CD drive.'
push 0 <- hWnd
call ds:MessageBoxA
Όπως βλέπετε εδώ υπάρχει ένα call σε μια διαδικασία και έπειτα ακολουθεί ο έλεγχος για το αν η επιστροφή της διαδικασίας ηταν μηδέν.Αν όντως ήταν τότε πηδάμε σε bad_guy messagebox. Αλλιώς όλα πήγαν καλά και το πρόγραμμα συνεχίζει την ροή του.Παρακάτω παραθέτω ένα κομμάτι της παλιότερης έκθεσης μου,όπου περιγράφω πως να παρακάμψουμε το check αυτό. Φυσικά υπάρχουν πάρα πολύ τρόποι,παρακάτω αναλύω έναν λίγο πιο περίεργο τρόπο:
Πριν να εκτελεστεί το messagebox,θα πρέπει να δοθούν αυτές οι πληροφορίες,φυσικά με ανάποδη σειρά.Μην ξεχνάτε την στοίβα.Ότι βάζουμε πρώτο,βγαίνει τελευταίο.Άρα,φυσιολογικά ο παρακάτω κώδικας κάνει τα εξής:
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
0044125E(U):
call 00462000 <-Πληροφορίες και διαδικασία τροφοδότησης του eax test eax, eax <-Ενδιαφέρον.Είναι ο eax μηδέν? jne 00441259 <-Όχι???Πήδα στο παιχνίδι και ξεπέρασε το messagebox push 00000015 <-Τύπος του Messagebox(RETRY/CANCEL) * Possible StringData Ref from Data Obj ->"Speedboat Attack" <-CAPTION
mov eax, dword ptr [00498CB4] <-Στην σχετική διεύθυνση 00498cb4 βρίσκεται το caption push eax <-Και μέσα στην στοίβα.Βρίσκεται πάνω-πάνω προς το παρόν.
* Possible StringData Ref from Data Obj ->"Please, insert Speedboat Attack CD into CD drive."
push 00498E60 <-Βάλε το μήνυμα στην στοίβα(μέσω της σχετικής διεύθυνσης) push 00000000 <-Βάλε και ένα μηδεν πάνω πάνω * Reference To: USER32.MessageBoxA, Ord:0195h
Call dword ptr [00707C08] <-ΚΑΙ ΚΑΛΕΣΕ ΤΟ MESSAGEBOX!!! mov dword ptr [006C7AFC], eax cmp dword ptr [006C7AFC], 00000002 jne 00441254 xor eax, eax jmp 00441483
Όπως καταλαβαίνετε,πολλά πράγματα μπορούν να περάσουν από το άρρωστο μυαλό μου :) Μπορούμε να αλλάξουμε αρχικά το είδος του messagebox.Πηγαίνετε στο Hiew,ας πούμε,στην διεύθυνση:
00441226 6A15 push 00000015
Και αλλάξτε το push 00000015 σε Push 00000013.Παρατηρείτε καμμιά διαφορά?Μπορείτε,επίσης,να αλλάξετε το caption ή το text του messagebox,επίσης πολύ εύκολα.Ο σκοπός,όμως είναι να βγάλουμε τελείως το messagebox,έτσι ώστε να μην μας ενοχλεί κάθε φορά που θα θέλουμε να παίξουμε το νόμιμα αγορασμένο παιχνίδι μας.Φαντάζομαι(και ελπίζω)να έχετε καταλάβει ήδη το πώς θα το κάνουμε αυτό.Με λίγη σκέψη,βλέπουμε ότι αν το πρόγραμμα συνεχίσει να εκτελείται μετά το αρχικό call,θα φτάσει στο messagebox και θα μας πετάξει.Άρα,πρέπει να ψάξουμε για διακλάδωση,που βρίσκεται φυσικά στο jne 00441259.Θέλουμε,λοιπόν,να γίνει διακλάδωση,άρα το αποτέλεσμα της προηγούμενης σύγκρισης να ΜΗΝ είναι μηδέν.Αν κάνετε,όμως break λίγο πριν τον κώδικα του messagebox,πάνω στο test,θα δείτε ότι ο eax έχει την τιμή μηδέν,πράγμα που δεν θέλουμε,φυσικά.Θα πρέπει η τιμή του να είναι διάφορη του μηδενός.Αυτό μπορούμε να το επιτύχουμε με πολλούς τρόπους,πιο εύκολα αλλάζοντας το jne σε je.Όμως,θα κάνουμε κάτι πιο πρωτότυπο!!! Θα μετατρέψουμε το test eax,eax σε xor eax,edx.Γιατί θα το κάνουμε αυτό???Για να αναλύσουμε λιγάκι:
Τι ακριβώς έκανε το test eax,eax,πριν το αλλάξουμε?
Η εντολή test εκτελούσε λογικό AND στον eax και περνούσε το αποτέλεσμα στην zero flag.Επειδή το αποτέλεσμα ήταν πάντα 0,το πρόγραμμα δεν διακλαδωνόταν.
Τι θα κάνει η xor eax,edx?
Την δεδομένη χρονική στιγμή που εκτελείται αυτός ο κώδικας,ο edx έχει τιμή διάφορη του μηδενός. Αυτό σημαίνει ότι και ο eax θα πάρει τιμή διάφορη του μηδενός μετά την εκτέλεση της εντολής αυτής.Μην ανησυχείτε για την τιμή του eax.Αργότερα στο πρόγραμμα,αλλάζει πριν να χρησιμοποιηθεί με οποιοδήποτε τρόπο,οπότε δεν υπάρχει πρόβλημα στο να αλλάξετε την εντολή αυτή.Ας κάνουμε,λοιπόν την αλλαγή.Πηγαίνετε στο Hiew,στην διεύθυνση 0044121E και αλλάξτε το test eax,eax σε xor eax,edx ,δίνοντας ως κώδικα μηχανής τον 31D0.Σώστε τις αλλαγές,βγείτε από το hiew και τρέξτε το παιχνίδι για να μπείτε στο main menu του...
Κάνοντας όσα περιγράφονται παραπάνω αφαιρούμε το πρώτο check του προγράμματος για το cd.Στην συνέχεια ακολουθεί άλλο ένα check όταν έχει ξεκινήσει το παιχνίδι,το οποίο θα εξετάσουμε αργότερα.Αυτό που δεν έχουμε δει ακόμα είναι ο τρόπος με τον οποίο το παιχνίδι εξετάζει αν έχουμε βάλει κάποιο cd ή όχι.Ας εξετάσουμε το "call 00462000" που είναι υπεύθυνο για την τροφοδότηση του eax και το τελικό αποτελέσμα της σύγκρισης για την ύπαρξη του cd.Ας δούμε τι κρύβεται μέσα σε αυτό: (IDA DUMP) sub esp, 80h
push ebx
push esi
push edi
call sub_462080
call ds:GetTickCount
lea esi, [eax+4]
lea ecx, [esp+8Ch+String1]
and esi, 7
mov eax, lpString2[esi*8]
push eax
push ecx
call ds:lstrcpyA
lea edi, [esp+8Ch+var_80]
xor eax, eax
mov ecx, 10h
repe stosd
lea ecx, [esp+8Ch+var_80]
lea eax, [esp+8Ch+String1]
push ecx
mov edx, dword_6FB0A0[esi*8]
push eax
push edx
call sub_4620B0
lea ecx, [esp+98h+var_80]
add esp, 0Ch
push ecx Ίσως σας κάνει εντύπωση που δεν έχω βάλει σχόλια στον παραπάνω κώδικα.Ο λόγος είναι ότι θα ήταν περιττό.Ο παραπάνω κώδικας απλώς αποκωδικοποιεί ένα string,συγκεκριμένα ένα path σε κάποιο αρχείο του cd,χωρίς το drive letter φυσικά,το οποίο θα εξετάσει παρακάτω.Ομολογώ πως αυτό το σημείο του κώδικα μου έκανε πολύ εντύπωση.Μέχρι τώρα δεν είχα συναντήσει ποτέ SMC code σε απλό cd check.Η αλήθεια είναι ότι η χρησιμοποίησή του είναι μια έξυπνη ιδέα,αφού εμποδίζει τον cracker από το να μάθει ποια αρχεία εξετάζει το πρόγραμμα για την ύπαρξή τους στο cd,μόνο και μόνο από το disassembly.Το πιο εντυπωσιακό,όμως είναι ότι ελέγχει κάθε φορά διαφορετικά αρχεία χρησιμοποιώντας το GetTickCount για να ψάχνει randomly για έναν συγκεκριμένο αριθμό από αυτά !!! Μετά από την αποκωδικοποίηση αυτή ακολουθεί το πλέον σημαντικό κομμάτι του κώδικα:
call sub_462110 <- Αυτό είναι το αποφασιστικό call
add esp, 4 <- Προσθέτει 4 στον esp για να φτιάξει την στοίβα
cmp eax, 1 <- Is eax = 1 ?
sbb eax, eax <- Αφαίρεση με την σήμανση υπολοίπου
neg eax <- To NOT του eax
pop edi <- Και διαδοχικά pops πριν την επιστροφή στον τελικό έλεγχο.
pop esi
pop ebx
add esp, 80h
retn
Ας εξετάσουμε τώρα το σημαντικό call που βγάζει το αποτέλεσμα: sub esp, 118h
push ebx
push esi
push edi
xor ebx, ebx
push ebp
mov edi, 1
mov esi, ds:wsprintfA
mov ebp, ds:GetDiskFreeSpaceA
loc_46212D:
lea eax, [edi+41h] <- Αρχικά EDI = 1.Δηλαδή τώρα EDI = 42h = Β !!!
lea ecx, [esp+128h+var_118]
push eax
push offset aC <- "%c:\\"
push ecx
call esi <- wsprintfA. Μετατρέπει το DRIVELETTER σε DRIVELETTER:\
lea ecx, [esp+118h+TotalNumberOfClusters]
lea edx, [esp+118h+NumberOfFreeClusters]
lea eax, [esp+118h+BytesPerSector]
add esp, 0Ch
push ecx <- lpTotalNumberOfClusters
push edx <- lpNumberOfFreeClusters
lea ecx, [esp+114h+SectorsPerCluster]
push eax <- lpBytesPerSector
lea edx, [esp+118h+RootPathName]
push ecx <- lpSectorsPerCluster
push edx <- lpRootPathName
call ebp <- GetDiskFreeSpaceA
test eax, eax <- Αν επέστρεψε μηδέν τότε δεν βρέθηκε δίσκος...
jz short loc_462167 <- Και πηδάει για νέα εξέταση
mov eax, [esp+10Ch+NumberOfFreeClusters] <- Αν βρέθηκε ο δίσκος πόσα free clusters έχει?
test eax, eax <- Κανένα?
jz short loc_46216F <- Τότε όλα καλά και πήδα...Το drive letter αντιστοιχεί σε CD-ROM !!!
loc_462167:
inc edi <- Αύξησε το μετρητή για να γίνεται διαδοχικά C,D,E,F,G...
cmp edi, 1Ah <- Εξέτασε μέχρι 26 δίσκους ...
jl short loc_46212D <- Check next letter
jmp short loc_462174 <- Αλλιώς τελείωσε με bad_guy...
loc_46216F:
mov ebx, 1 <- Θέσε και το good_guy για αυτό το stage...
loc_462174:
test ebx, ebx <- Είναι τελικά ο ebx = 1?
jnz short loc_462188 <- Ναι?Πήδα...
mov eax, 0FFFFFFFFh <- Αλλιώς ετοίμασε bad_guy...
pop ebp
pop edi
pop esi
pop ebx
add esp, 118h
retn
Βλέπετε ότι αυτό που γίνεται είναι πραγματικά έξυπνο.Υπάρχει ένα loopaki που φροντίζει να ελέγξει όλα τα drive letters ξεκινώντας από το B,καθώς το Α είναι το floppy.Μετά καλείται το wsprintfA που μετατρέπει το B σε Β:\ και το περνά ως παράμετρο στο GetDiskFreeSpaceA.Βεβαίως στο δικό μου υπολογιστή δεν υπάρχει τέτοιο drive letter,οπότε και η επιστροφή είναι 0 καθώς το API δεν επιστρέφει επιτυχώς.Μετά αυξάνεται το B σε C κα με το wsprintfa παίρνει πάλι την μορφή C:\ .Καλείται τότε το GetDiskFreeSpace και επιστρέφει επιτυχώς τώρα.Δεν φτάνει αυτό όμως. Ο σκληρός μου δίσκος έχει ελεύθερα clusters ενώ ένα cd rom όχι.Οπότε όταν εξετάζεται ο αριθμός των clusters αυτός είναι ΜΗ μηδενικός και πάμε σε bad_guy για το συγκεκριμένο drive letter,οπότε και αυξάνεται ο edi ώστε να γίνει πλέον D.Το ίδιο γίνεται και με τον E αφού έχω 3 partitions στον υπολογιστή μου :) Το F,όμως που είναι cd rom φέρει μεν επιτυχή επιστροφή στο GetDiskFreeSpace αλλά επιστρέφει μηδενικά free clusters,οπότε και αναγνωρίζεται ως cd rom drive letter και προχωράμε στο πρόγραμμα στην επόμενη εξέταση αφού ο ebx γίνει ένα,οπότε και φτάνουμε εδώ: mov eax, [esp+10Ch+arg_1C]
lea ecx, [esp+10Ch+RootPathName]
lea edx, [esp+10Ch+var_E4]
push eax
push ecx
push offset aSS <- "%s%s"
push edx
call esi <- wsprintfA Π.χ. Κάνει το F:\ και το Path => F:\Path
lea ecx, [esp+100h+PathName]
add esp, 10h
mov edi, ds:_lopen
nop
push 0 <- iRead
push ecx <- lpPathName
call edi <- lopen.Υπάρχει το αρχείο?
cmp eax, 0FFFFFFFFh <- Όχι?
jnz short loc_4621C9 <- Τότε μην πηδάς
mov eax, 0FFFFFFFFh <- bad_guy awaiting...
pop ebp
pop edi
pop esi
pop ebx
add esp, 118h
retn
loc_4621C9:
push eax <- hFile
mov esi, ds:_lclose
call esi <- lclose.Αν υπήρχε το αρχείο κλείσε το handle του
lea eax, [esp+0F0h+PathName]
push 1 <- iReadWrite !!!
push eax <- lpPathName
call edi <- lopen.Άνοιξε για READ - WRITE.OOPS,είναι CD ROM !!!
cmp eax, 0FFFFFFFFh <- Δεν υπήρξε καλή επιστροφή?
jnz short loc_4621ED <- Χαίρομαι.Έτσι έπρεπε να γίνει...:)
xor eax, eax <- Αυτό είναι good_guy.Εξηγώ παρακάτω γιατί.
pop ebp
pop edi
pop esi
pop ebx
add esp, 118h
retn
Φυσικά το ότι βρέθηκε το cd rom δεν μας αρκεί.Χρειάζεται να εξετάσουμε αν υπάρχουν κάποια συγκεκριμένα αρχεία σε αυτό,αλλιώς κάθε cd θα είναι valid.Θυμάστε το random string που σας έλεγα?Αυτό ανασύρεται εδώ και με το wsprinfA φτιάχνεται ένα path σαν και αυτό εδώ: F:\speedboat\levels\level0\swp.vie Έπειτα αυτό περνιέται ως παράμετρος στο _Lopen και με READ ACCESS επιστρέφει τιμή διάφορη του -1(0FFFFFFFFh) αν υπάρχει.Αν επιστραφεί FFFFFFFF στον eax,τότε το αρχείο δεν βρέθηκε και άρα δεν υπάρχει cd rom.Αρκεί να αλλάξουμε τον έλεγχο που ακολουθεί φυσικά.Το πιο έξυπνο κομμάτι όμως γίνεται παρακάτω.Καλείται ξανά το _Lopen,που ανοίγει ένα αρχείο και θέτει τον file pointer στην αρχή του.Προσδιορίζεται READ/WRITE ACCESS όμως.Όμως τα αρχεία σε ένα CD ROM είναι READ ONLY !!! Έτσι το _lopen αποτυγχάνει και αυτό ελέγχεται εδώ.Αν δεν αποτύχει το _lopen, τότε το αρχείο σίγουρα δεν βρίσκεται στο cd rom,οπότε και κάποιος μάλλον το έχει αντιγράψει στον δίσκο του.Θα έλεγα πως ειδικά αυτό το κομμάτι της προστασίας είναι αρκετά έξυπνο,αλλά σύντομα χάνει την αξία του,αφού υπάρχει το τελευταίο test eax,eax πριν το bad_guy messagebox,το οποίο είδατε παραπάνω πως το αλλάξαμε.Πλέον μπαίνουμε στο main menu του παιχνιδιού,αλλά όταν κάνουμε RACE,ξαναβγαίνει το ίδιο messagebox.Δεύτερο check ε?Θα έλεγα ευκολότερο από το πρώτο,πλέον.Ας δούμε πως ξεπερνιέται και αυτό,στο παρακάτω κομμάτι της πρώτης έκθεσής μου:
FIGHT:
Βγάλαμε,λοιπόν το πρώτο out of game check.Είμαστε στο main menu του παιχνιδιού και έτοιμοι να ξεκινήσουμε το παιχνίδι.Πατάμε "race",περιμένουμε λιγάκι και ΔΕΥΤΕΡΟ MESSAGEBOX !!!Και μάλιστα το ίδιο με το προηγούμενο.Μα πριν από λίγο δεν το βγάλαμε???Συγκεκριμένα αλλάξαμε ένα κομμάτι κώδικα για να μην εμφανίζεται το messagebox αλλά δεν το βγάλαμε από το πρόγραμμα.Για να καταλάβετε,το πρόγραμμα θα μπορούσε να έχει και 800 checks για το cd,μόνο που θα κούραζε τον χρήστη στο να αλλάζει menus και θα ήταν και χαζό εκ μέρους του προγραμματιστή.Ας βγάλουμε,λοιπόν και αυτό το check,που μάλλον είναι και πιο απλό από το προηγούμενο,έτσι κι αλλιώς.
Ελπίζω να καταλάβατε όλα όσα έχουμε κάνει μέχρι τώρα.Σημασία έχει το πώς σκεφτόμαστε και όχι το τι κάνουμε.Θα μπορούσαμε ακόμα και να φτιάξουμε ένα OK button-messagebox,με τα δικά μας λόγια και αφότου κλικάρουμε στο ok να ξεκινάει το παιχνίδι.Το καλό με αυτήν την προστασία είναι ότι είναι πολύ cracker-friendly και διασκεδαστική.Πιστεύω ότι τα δύο messageboxes είναι τουλάχιστον πολύ απλά για να τα βγάλει ένας cracker.
Το δεύτερο messagebox έχει μια σημαντική διαφορά από το πρώτο.Αν δεν έχουμε μέσα το CD,βγαίνει μόνο του,χωρίς να κλικάρουμε κάτι εκείνη την στιγμή.Αυτό σημαίνει ότι θα πρέπει να προσέξουμε αυτήν την λεπτομέρεια.Λοιπόν,καιρός να χρησιμοποιήσουμε το SoftIce.Μπείτε στο main menu του παιχνιδιού και πατήστε race.Τώρα,ανοίξτε το sice(ctrl-d) και θέστε breakpoint στο messagebox πληκτρολογώντας bpx messageboxa.Το πρόγραμμα θα σπάσει στο user32,καθώς δημιουργεί το messagebox.Πατήστε F11 και κλικάρετε στο επανάληψη του messagebox.Τώρα το softice θα σπάσει πάλι και θα δείτε τα εξής:
:0046222A FFD6 call esi :0046222C 83F804 cmp eax, 00000004 :0046222F A160B64900 mov eax, dword ptr [0049B660] :00462234 74D1 je 00462207
Στον παραπάνω κώδικα μας ενδιαφέρει μόνο το je.Όταν κλικάρουμε "επανάληψη",το je μας πάει πίσω στην διαδικασία checkαρίσματος για το αν θα βγει messagebox.Συγκεκριμένα μας βγάζει εδώ,αν εκτελέσουμε το je:
:00462207 E8F4FDFFFF call 00462000 <-Είμαστε εδώ :0046220C 8B0DB48C4900 mov ecx, dword ptr [00498CB4] :00462212 8B15300F7000 mov edx, dword ptr [00700F30] :00462218 A360B64900 mov dword ptr [0049B660], eax :0046221D 85C0 test eax, eax :0046221F 7515 jne 00462236 :00462221 6A15 push 00000015 :00462223 51 push ecx
Αν μπείτε λίγο στο Windasm και εξετάσετε αυτόν τον κώδικα,θα δείτε ότι αναφέρεται στο δεύτερο string του messagebox.Σας θυμίζει κάτι το test eax,eax???Είμαι σίγουρος.Μπορείτε να το αλλάξετε σε xor eax,edx όπως πριν και το παιχνίδι θα παίζει κανονικά.Μπείτε στο Hiew,λοιπόν και κάντε την αλλαγή όπως πριν.Και ξεκινήστε το παιχνίδι χωρίς cd φυσικά!!!
Ακριβώς το ίδιο check υπάρχει και εδώ.Πάλι καλείται το GetDiskFreeSpace και όλα τα υπόλοιπα ίδια APIs,όπως ακριβώς έγινε και πριν.Είδαμε,λοιπόν,μαζί ένα cd check,αρκετά πολύπλοκο αυτή τη φορά σε σχέση τουλάχιστον με τα περισσότερα που κυκλοφορούν.Ακόμα και στα παλιότερα παιχνίδια όπως αυτό που περιέγραψα εδώ,μπορεί κανείς να βρει κάποιες έξυπνες προστασίες όπως αυτή εδώ.Το μόνο κακό της ιστορίας είναι ο τελικός έλεγχος που είναι εξαιρετικά απλός και καταστρέφει όσα είχαν γίνει μέχρι τότε.Κάτι που μας διευκολύνει στο να γράψουμε και έναν απλό patcher για το εκτελέσιμο του παιχνιδιού,ώστε να "διορθώνει" το προβληματάκι αυτό και να παίζουμε χωρίς cd.Τον patcher τον έφτιαξα σε Win32Asm και μπορείτε να τον βρείτε στο συνοδευτικό αρχείο,εδώ.
ΠΡΟΣΟΧΗ Φυσικά δεν χρειάζεται καν να σας θυμίσω πως το βοήθημα αυτό είναι αυστηρά για εκπαιδευτικούς σκοπούς και για την οποιαδήποτε λάθος χρήση τους ο δημιουργός του δεν φέρει καμμία ευθύνη.Αν θέλετε έτοιμα cracks υπάρχουν πολλά άλλα μέρη στο internet,εδώ παρέχουμε μόνο γνώση.