Safedisc
Safedisc
by ArthaXerXès
Version 1.0, 25th January 2000
Copyright
2000
c ArthaXerXès and all the contributors to “The Twilight of Safedisc”. All rights
reserved.
This document is provided “as is” without express or implied warranty, including, but not
restricted to, the merchantability and the fitness for a particular purpose.
ArthaXerXès and the contributors to this document assume no liability for direct or indirect
damages resulting from its use, even if the damage results from errors in the document and even if
one or several authors have been advised of the possibility of such damage.
As well, illegal uses of this document are your entire responsibility. We do not condone
piracy, this document has been written for educational purposes.
You can distribute this document freely in any way, as long as it is kept in its original form. Should
you wish to quote this document, do not forget to precise the title, the author and the version.
1 Introduction 1
1.1 A note from the author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 What is in this essay . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3 The requisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.4 Software used . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.5 Some due credits and thanks . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.6 Contacting the author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2 Copying the CD 4
2.1 Full copy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1.1 RAW Copy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1.2 Recording . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.3 The limits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
4 Conclusion 29
4.1 Safedisc is no more . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.2 The future . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.3 Reliable CD protection does not exist . . . . . . . . . . . . . . . . . . . . . . 30
Introduction
Not all these programs are free of use. Keep this in mind please, and act in consequence. I
shall explain in due time why we need all these programs, for now ensure that you installed
them on your computer.
Black Check for the papers he wrote, and also for the additional information he was
willing to give to provide.
R!SC also for the papers he wrote about the Safedisc protection.
Tola he also wrote some good papers about Safedisc.
Pedro for the hint on the dr7 check. (even if it was a long time ago, and for a complete
different matter)
Fravia+ for the marvellous web site he created (which is unfortunately no more), from
which I learnt a lot.
The Prestige team for their patience, their lack of arrogance (very rare in the scene),
and also for being my method testers.
Some close friends which I will obviously not name, that helped me a lot in providing
me software and also in testing my work.
Copying the CD
The software is obviously not a problem. Most of the programs allow RAW writing, the
most famous is of course Clone CD, but Discjuggler also works fine for example.
However, if your CD recorder does not support DAO RAW there is little to do. Perhaps
that hacking the firmware may give good results (DAO RAW is generally only disabled in
the firmware), but this is not an easy hack.
To determine if your hardware supports DAO RAW, you may either check your
documentation or look in the supported functions menu command that most software have.
It should inform you if DAO RAW is supported. (TAO RAW will not work for obvious
reasons)
2.1.2 Recording
The process is very simple. I recommend to follow these steps :
1. Know that reading speed and recording speed may affect the quality of the copy. For
optimal results 1:1 copy is advised. However, with good hardware and good software,
higher speeds should not affect the quality.
2. Do not try to make an on-the-fly copy ! This will not work.
3. At first, you need to create an image of the Safedisc CD. To obtain a correct image,
you must ensure that errors are ignored, that RAW mode is enabled and that the
CD reader with which you are making the image supports RAW reading. The whole
reading process is a bit lengthy, so be patient.
4. Once the image is done, the only thing left to do is to launch recording. Again, check
that RAW mode is enabled and that errors will be written uncorrected (i.e.
ignored).
You certainly wonder why I fully reversed safedisc if copying it is so easy. The explained
method has got some limits that you certainly noticed.
Safedisc use several ways to detect a debugger, therefore you have to camouflage Softice.
There are a lot of documents that explain how to do it, it is very easy (there are even
programs doing it for you). I do not advise to use Frogsice, it is an excellent detection tool,
but it is better to modify Softice directly.
There is a lot of data to dump before we actually start cracking. As you already know, the
ICD contains three parts that are ciphered :
Furthermore, the .data section is modified during the execution of the ICD after it has
been unwrapped, this is why we can dump the .data section only during a limited period :
after it has been decoded and before the execution of the program starts.
The best way is probably to put a breakpoint on FreeLibrary. The lengths of all the
sections and their respective start addresses can be determined with the help of Procdump.
Simply open the file rayman2.icd, and choose ‘‘PE Editor’’. You also need to write
down the entry point of the executable of course.
With my method, we also need to hack dplayerx.dll and rayman2.exe. Both files have
ciphered .txt sections, we have to dump them too.
Time for dumping !
1. Make sure Softice is loaded, hit CTRL-D and type the commands : bc * ; bpx
FreeLibrary ; bd * ; g (; stands for ENTER).
2. Run rayman2.exe with either the original or a DAO RAW copy of the Rayman 2 CD.
3. Wait for the logo to disappear, hit CTRL-D and enable the breakpoint (be *).
4. You should find yourself in Softice few seconds after the breakpoint has been
activated. Hit F11 (or type g @ss:esp) to return to the caller (which should be
within dplayerx).
5. Disassemble the entry point of rayman2.icd, in typing u 45fcc0. You should see this
code :
push ebp
mov ebp , esp
push ffffffffh
push 0049 c9d0h
push 0045 f f 9 0 h
mov eax , dword ptr fs : [ 0 0 0 0 0 0 0 0 ]
push eax
...
If you do not, this means the .text section is not deciphered yet. Hit g and wait for
the debugger to break again.
Once you have done this with all files, you can copy them to the main installation directory
or Rayman 2. It is of course advised to back up the original files in another directory before
doing so.
You probably noticed, that the program crashes if you put breakpoint in it. This
is because it performs checksums on its sections, and it uses the value of these
checksum to decode the .txt one. Once the program will be deprotected, you will
see that you can put breakpoint wherever you wish.
If you try to run the hacked rayman2.exe now it will crash, since it tries to decode sections
that are already decoded. It is time to disassemble rayman2.exe and dplayerx.dll with
IDA. Choose 686 for the processor. The whole disassembling process takes few minutes,
depending on the speed of your computer.
Once done, enable faults (faults on) in Softice, and run the executable. You should be
within rayman2, this is what we want. Put a breakpoint on the first memory address of the
.txt section (bpm 401000 R). Run the program again. You will be in this copy memory
routine :
...
mov ecx , [ esp+8+a r g 8 ] ; how many to copy
mov e s i , [ eax +4]
mov e d i , [ esp+8+a r g 4 ]
mov eax , ecx
add esi , edi ; copy from
mov e d i , [ esp+8+arg C ] ; copy to
shr ecx , 2 ; how many to copy d i v 4
repe movsd ; <− t h i s i s p r o b a b l y where you w i l l break
mov ecx , eax
mov ax , 1
and ecx , 3 ; how many to copy mod 4
repe movsb
pop edi
pop esi
retn
It is now wise to put a breakpoint on edi-4 (bpm edi-4). You may now type g. You will
break again, but in a different place, which looks like a checksum routine.
...
mov eax , [ ebp +8]
mov ecx , [ eax ]
mov [ ebp+v a r 8 ] , ecx ; <− you w i l l certainly b r e a k here
mov edx , [ ebp +8]
mov eax , [ edx +4]
mov [ ebp+var C ] , eax
mov ecx , ds : dword 42F010
mov [ ebp+v a r 1 0 ] , ecx
...
You probably noticed that there are a lot of useless jumps. All these jumps are here to
make tracing and disassembling more difficult, they are totally useless.
This is where IDA comes useful, remember, IDA stands for Advanced
Interactive Disassembler. Interactive : this is the important keyword. I really
hope that you know how to use IDA, because I am not going to teach you this :
it would take too much time. Read your IDA manuals or some tutorials on the
matter if you feel lost.
I also strongly advise you to rename the functions, labels and variables to
explicit names, it makes reversing much easier.
Of course, the checksum routine in which we ended is located in the .txt2 section. Since
the entry point of the executable is in the .text section, we can assume that the function
that does the whole decoding of the .txt section is called in the .text section.
We have two alternative : we can trace from the entry point and monitor if changes are
performed on the .txt section, or we can use cross reference to find what is the main
function. The later method is the one I used, but you can use the other one if you prefer,
however, in my opinion it is less reliable in this case.
In IDA go at the top of the “checksum” function in which you ended. Rename it
“checksum 0”. Go to the caller, and rename it “checksum 1”, and so on until you find
yourself into a function which is called from the .text section.
note : it is highly probable that some functions are not detected by IDA. If
that is the case, you have to scroll up until you find this sequence :
push ebp
mov ebp , esp
push ...
This marks the beginning of the function. Rebuild it from here (hit P) or use
the menu.
Also, IDA can be confused by the following code :
...
jmp short near ptr l o c w h a t e v e r +1
...
loc whatever :
wrong d i s a s s e m b l e d code
...
The whole process may take some time, and you will probably want to test within softice if
you found the right caller. Eventually, you should find the “big” call at location 00410a94,
the function is 004270ad. You probably noticed that the program uses a checksum
performed on the .txt2 section to decode the .txt section. Removing the call to the
function will therefore solve two problems.
...
loc 4 1 0 A9 4 : ; CODE XREF: . t e x t :00410 A90
call checksum 6
add esp , 4
...
Removing this call will solve our little problem. Use WinHex, search for the string e8 14
66 (you will see that it is unique) and replace it with eb 03. We did most of the hard job
concerning rayman2.exe, but there are still one or two things to do.
If you try to run now the executable, you will see (with FileMonitor for example) that it
loads dplayerx.dll and rayman2.icd from the CD. What it does is checking the files, and
if they were modified, it loads them from the CD instead.
This protection is easy to find and to remove. To find it, put a breakpoint on
GetFileAttributesA, and wait until it is called with dplayerx.dll or rayman2.icd as
parameters. GetFileAttributesA is called by the shell and by clokspl.exe before it is
called by rayman2.exe.
You should break in this code :
...
mov e s i , [ ebp+a r g 4 ]
mov e d i , ds : G e t F i l e A t t r i b u t e s A
push e s i ; <− e s i p o i n t s to t h e name of t h e file to check
call edi ; checking the f i l e . . .
cmp eax , 0 FFFFFFFFh
...
If you analyse the function carefully, you will see it is easy to crack. This code does the
check :
...
l o c 4 0 5 2 E 0 : ; CODE XREF: c h e c k f i l e +96
cmp word ptr [ ecx ] , 0
jnz l o c 4 0 5 4 1 F ; here we jump i f t h e l o c a l file i s ok
...
Therefore, we merely have to make the jump unconditional. You will see that we shall jump
to a location in which eax is set to 1 (true). The string to search is 0f 85 35 01, the string
to put is e9 36 01 00 00. Now the locals file are loaded.
More checksums
There are still checksums performed, and it is a good idea to remove them, isn’t it ? As
usual, if you put a breakpoint on 401000, you will find them.
The easier to remove is the one that is called from “clean code” (i.e. without 1031337 jumps
around). Just after the call, eax is tested. Unless you are completly stupid, you probably
guessed that this can be easily removed in modifying the called function.
...
loc 4028FD : ; CODE XREF: C D i l l a c h e c k 2 +AC
push 2
call checksum 2 5 ; t h e n a s t y checksum
add esp , 4
test ax , ax ; eax == 0 −> no soup f o r you !
jnz short l o c 4 0 2 9 4 F
...
...
t h e c h e c k s : ; CODE XREF: . t e x t :004115 C9
mov eax , [ ebp−18h ]
Here my choice was to “jump over” the two calls. Search for 02 EB 0B EB FC D7 E1 4A
76 BA 98 05 A5 0D 8B and replace 02 with 53. The checksums are now annihilated !
There is a first CD protection layer, that allows Safedisc to quickly detects if the wrong CD
or no CD at all is inserted. If you put a breakpoint on GetDriveTypeA you will find it at
once. It is better to remove this protection if you want to make a “no CD crack”. If you do
not remove it, you will need a perfect copy of the CD, and you will not be allowed to have
the crack on the CD.
sub esp , 1 0 4 h
lea eax , [ esp +104h+v a r 1 0 4 ]
push 104 h
push eax
push 0
call ds : GetModuleFileNameA
lea ecx , [ esp +104h+v a r 1 0 4 ]
push ecx
call ds : GetDriveTypeA
cmp eax , 5
jnz short CD drive found
mov edx , [ esp +104h+a r g 0 ]
lea eax , [ esp +104h+v a r 1 0 4 ]
push edx
push eax
call sub 412780
add esp , 8
add esp , 1 0 4 h
retn
This protection is mundane. To remove it, you just need to replace the string 81 EC 04 01
00 00 8D 44 with 33 c0 40 c3 or b8 01 00 00 00 c3.
Now, we have to remove the real CD check. Locating it is very easy, since it is so slow you
just have to trace until you have some long CD operation performed. If you narrow your
search, you will quickly find the routine, which is 4064d0. This function is called twice,
from the same function (4055b0). Here is the code corresponding to the calls :
...
push e s i ; see , t h e argument ?
push o f f s e t b y t e 4 3 6 1 0 0 ; and t h i s one ?
mov ecx , [ ebp+a r g 1 4 ]
sub esp , 0 Ch
mov edx , esp
mov [ edx ] , eax
mov eax , [ ebp+a r g 1 8 ]
mov [ edx + 4 ] , ecx
mov [ edx + 8 ] , eax
call near ptr s a f e d i s c C D c h e c k ; <−− c a l l e d here
add esp , 1 4 h
mov ebx , eax ; t h e r e s u l t of t h e f u n c t i o n i s in eax
mov [ ebp+var C ] , e d i
jmp loc 40581A
Use the technique we used many times : make the function always return 1. For this, you
have to search for the string 55 8b ec 53 56 57 bb and replace with 33 c0 40 c3 or b8
01 00 00 00 c3. There is no more CD protection in rayman2.exe, congratulations
reverser !
note : you will notice that the LED of your CD drive lights, this is because
there is still some CD check performed around 405628 (the result does not
matter since the protection is cracked). It is not required to modify anything for
the protection to be fully removed, but you can remove the access if you wish.
It is easier that what we did, is not it ?
As I told you, the protection checks for the content of the debug register dr2 in our
example. It is not necessary to remove this check since I think there is a bug in it. :-)
However, I perfectly remember that other Safedisc versions used a similar protection, but
instead of checking dr2, dr7 was checked. The dr7 check is very disturbing since you
cannot use any breakpoint. Future protection may use the dr7 check again, therefore I
think it is relevant to explain how to remove it.
The eight debug registers control the debug operation of the processor. These
registers can be written to and read using the move to or from debug register
form of the mov instruction. A debug register may be the source or destination
operand for one of these instructions. The debug registers are privileged
resources; a mov instruction that accesses these registers can only be executed in
real-address mode, in smm, or in protected mode at a cpl of 0. An attempt to
read or write the debug registers from any other privilege level generates a
general-protection exception (#GP).
Since the program runs in ring 3, and there is no VXD, the programmers used a very clever
(yes, sometimes protection makers are clever !) trick to switch to ring 0 : they change the
division by 0 handler and perform a division by 0. When they are within the handler, they
are running in ring 0, enabling them to check the debug registers...
We now have to locate the debug register access, and this is very easy ! As explained in the
later quotation, the debug registers can only be acceded with the help of a mov instruction.
And a mov r32, dr0-dr7 instruction is always assembled as 0F 21 xx. Look at the tables
to determine the value of xx.
7 6 5 4 3 2 1 0
Opcode structure
1 1 y y y z z z
register y y y register z z z
dr0 0 0 0 eax 0 0 0
dr1 0 0 1 ecx 0 0 1
dr2 0 1 0 edx 0 1 0
dr3 0 1 1 ebx 0 1 1
dr4 1 0 0 esp 1 0 0
dr5 1 0 1 ebp 1 0 1
dr6 1 1 0 esi 1 1 0
dr7 1 1 1 edi 1 1 1
Table 3.1: Third opcode format for mov to/from debug registers
In our example, mov eax, dr2 is assembled 0f 21 d0 (d0 = 11010000). If you search for
this short string in rayman2.exe, you will find it only once. Replace 0f with CC and
redirect the int 3 to Softice (i3here on or bpint 3). This way you will break in the dr2
check routine.
...
pusha
mov [ ebp+var 1C ] , cs
sidt [ ebp+v a r 1 4 ]
mov eax , dword ptr [ ebp+v a r 1 4 +2]
mov e s i , [ eax +4]
mov s i , [ eax ]
mov edi , [ esi ]
mov [ ebp+v a r 4 ] , e d i
mov e d i , [ e s i +4]
mov [ ebp+v a r 8 ] , e d i
mov dword ptr [ e s i + 1 ] , 0 CF530E58h
mov byte ptr [ e s i ] , 58 h
lea ebx , d i v 0 h a n d l e r ; see , we change t h e h a n d l e r . . .
xor eax , eax
div eax ; d i v i s i o n by z e r o . . .
Of course, dr2 should contain 0, and it does, even when using it within Softice (type cpu to
know the value of the registers). This is why I consider this protection has got a bug !
Unless I misunderstood something. . . If you encounter a dr7 check instead of a dr2 check,
the expected value for dr7 is 400, not 0.
Important : if ever you encounter a dr7 check, this is the first protection you
should remove.
There is no need to remove the dr2 check in our case since the function that calls it has
been either modified or not called at all thanks to our previous modifications. However, to
do it you would have to search for the string 8b 4d e8 89 and replace it with c7 00 00 00
00 00 33 c0 40.
Now rayman2.exe is fully deprotected, and I think it is time for us to take a break. What
about a game of Unreal Tournament ? Very relaxing. Perhaps you would prefer to eat
something or to have a drink ? Your brain probably needs glucose now (especially if
English is not your natural language), therefore a fruit juice or some biscuits may be a good
idea. I do not recommend alcoholic beverage, for contrary to what you feel, your capacities
are decreased. You can also stop for now, and resume reading another day.
Of course, if you master the very ancient art of meditation, the moment is ideal.
If you prefer, you can continue to read this document, but I really advise you to take a
break so as to take fully advantage of what you just learnt.
This is the last thing we have to do, once performed, Safedisc protection will be no more.
dplayerx.dll takes care of deciphering the ICD file with the help of the key extracted from
the CD (actually bad sectors). It also interfaces the modified .rdata with the system.
Indeed, instead of directly accessing the system function, the program goes through
dplayerx.dll which redirects it to the right location.
This is why, in other tutorials you had to rebuild the .rdata section manually, which was
sometimes producing unreliable cracks. The whole point of my method is here, we modify
dplayerx.dll, so that it still interfaces the system functions, even if there is no CD at all
in the drive.
However, you remember that we rebuilt the ICD file. Why ? Simply because decoding the
ICD is slow. We shall therefore modify dplayerx.dll so that it does not deciphers the ICD
anymore.
You can proceed the same way that we did for rayman2.exe, since this is the same type of
routines, except that they are located in dplayerx.dll.txt2 this time. All that you have
to do, is to follow the same procedure and you will eventually find this call :
...
mov [ eax + 4 ] , edx
mov ecx , [ ebp+a r g 8 ]
mov [ eax + 8 ] , ecx
call near ptr a w checksum 3 ; here we decode . . .
add esp , 2 8 h
jmp short l o c 8 F 9 5 6 4
...
Removing this is mundane (but finding it was not, was it ? ;-)). Search for e8 90 00 00
and replace with eb 03.
Debug registers
There is the exact same routine that checks the content of dr2 in dplayerx.dll. As I said,
do not waste your time with it : it is inefficient. However, should you face a dr7 check, you
must act as explained previously in that case.
To speed up loading, we built an ICD file with decoded .data and .text sections. Of
course, dplayerx.dll will try to decipher them anyway, therefore when executing
rayman2.icd, you will not have the clear code anymore.
What you have to do, is to remove the call to the function that takes care of the whole
decoding process. An easy task, for to detect it you just need to trace from the entry point
of the dll, and monitor the content of rayman2.icd.text. You will quickly find this piece
of code to be interesting :
...
call ds : G e t C u r r e n t P r o c e s s
push o f f s e t dword 905030
mov dword 909740 , eax
call sub 8F8BBA
add esp , 4
mov dword 909744 , eax
push 1
push o f f s e t dword 909740
call d e c i p h e r ; t h i s f u n c t i o n does t h e whole t h i n g
...
Step into decipher, you will finally reach this piece of code :
...
mov eax , esp
mov [ eax ] , ecx
mov ecx , dword 908980
mov [ eax + 4 ] , edx
mov [ eax + 8 ] , ecx
You will see later, when we shall study how to crack without the CD, that the heart of
Safedisc lies deep in this function. For now, however, all we need to do is to remove the
call. What we shall do is jump over the code, but where to ? If you jump just after it will
crash since we are within a loop.
But do we know where the whole .rdata process takes place ? No we do not. Run
rayman2.exe with faults enabled (faults on), you will quickly find yourself in
dplayerx.dll, near this code :
...
loc 8F1AF9 : ; CODE XREF: c r e a t e a p i i n t e r f a c e +738
mov ecx , [ ebp+key ] ; s t o r e t h e key in ecx
mov edx , [ ebp+r d a t a v a l u e ] ; edx c o n t a i n s a v a l u e
; from . r d a t a
xor edx , [ ecx ]
The problem is that ecx should contain the key extracted from the original CD (actually
“computed” is a more accurate term), since we hacked the protection, the memory contains
garbage instead of the correct key, therefore the program access an invalid memory
emplacement.
How to guess the correct key value ? Well, this is very simple, you do not guess it, you steal
it. Note that the key is stored in 909473. If you put a breakpoint on this value and run the
program again (bpm 909473 W), you will eventually break here :
a r g 0 = dword ptr 8
a r g 4 = word ptr 0 Ch
push ebp
mov ebp , esp
mov eax , [ ebp+a r g 0 ]
mov ecx , [ eax ]
mov key backup , ecx ; here we copy to 909473
mov dx , [ ebp+a r g 4 ]
mov word 909477 , dx
pop ebp
retn
s t o r e k e y endp
This is perfect. All you have to do is to disable all breakpoints but the one on 909473, move
the hacked files (rayman2.exe, dplayerx.dll and rayman2.icd) elsewhere and restore the
original files. Insert the original CD, wait for the program to break and smile, for the
correct value of the key should be in ecx. In our case, the value is c15cf2e5.
Change the code so that c15cf2e5 is always stored in 909473, will bypass the check. To do
so, simply search for 8B 45 08 8B 08 89 0D and replace with b9 e5 f2 5c c1. Now the
program does not crash anymore within dplayerx.dll, but within rayman2.icd.
We know why : this is because we have not removed the call to the function that decodes
the .text and .data sections. We also know where this function is called, at the location
8f40b0. All we have to do is to jump just before the call to the function that maps the API.
Within IDA, if you scroll down from 8f40b0, you will find this piece of code to be attractive :
...
loc 8F48E3 : ; CODE XREF: w h o l e I C D s t u f f +28B4
mov ecx , [ ebp +8]
push ecx
push o f f s e t key 1
call r d a t a c h k s ; we c a l l t h i s f u n c t i o n once t h e
; ICD i s d e c i p h e r e d .
; I t w i l l t a k e care of t h e whole . r d a t a remapping s t u f f . . .
add esp , 8
...
Well, do I really have to tell you what to do ? Instead of calling the function, we shall
directly jump to 8f48e3. To do this, search for E8 EB 0D 00 and replace with 83 c4 0c e9
2b 08 00 00.
Ready for the test ? Remove the original CD from the drive, ensure that the hacked version
of rayman2.exe, dplayerx.dll and rayman2.icd are in the main directory, and run
rayman2.exe. . .
. . . congratulations, it works. You just cracked Safedisc.
Of course, the program still asks you for the CD, this is not the Safedisc
protection which is in cause but the game itself. If you insert a copy of the CD,
it will work fine, for the checks are mundane.
Removing the non-safedisc protection of Rayman 2 is trivial matter, and I shall
not discuss it here.
3.1.6 Generalization
We annihilated Safedisc, did not we ? What is best, is that we do not have to take care of
.rdata, since it will be rebuilt as if the original CD were present !
If you try this method on a different Safedisc game, you will notice that dplayerx.dll and
the main executable have got the same size (if not, this certainly means it is a different
version of safedisc). You will also notice that the protection functions are located at the
same position. Cracking should not take more than 10 minutes.
If you encounter a different version of Safedisc, what you learnt here should prove useful,
since chances are the protection is much alike. If you follow this method, you should be
able to defeat any future Safedisc releases.
What you know, is that it inspects the CD and searches for the bad sectors. Afterward,
with the help of the sectors found, it computes a key, which will be used to decode the
sections of rayman2.icd. We also noticed that the .rdata section is still dependant of
dplayerx.dll after the operation, this is to make cracking harder.
We need to reverse the ciphering algorithm, and we also need to create a brute force
cracker. Afterward, we shall extract the decoded section to obtain the same ICD than before
(you will see that it is a slow process, therefore it is better to have the sections deciphered)
You may follow the same steps to build a working a rayman2.exe. Dump the .txt section,
rebuild the exe and remove the protections. If you already have a hacked rayman2.exe,
there is nothing to do.
...
mov eax , esp
mov [ eax ] , ecx
mov ecx , dword 908980
mov [ eax + 4 ] , edx
mov [ eax + 8 ] , ecx
As I told you, the heart of Safedisc lies deep within. After a lot of tracing and code
analysis, you will discover that the sections are decode per 4096bytes-sized blocks, and that
each block is decoded per 8bytes-sized blocks. Here is the decryption algorithm :
d e c o d e 8 b y t e s proc near
; CODE XREF: d e c o d i n g i t r e a l +27 d e c o d i n g i t r e a l +8B . . .
t o d e c o d e = dword ptr 8
key = dword ptr 0Ch
push ebp ; t h i s r o u t i n e s de c o d e s 8 b y t e s
mov ebp , esp
mov eax , ds : r d a t a 0 ; t h e f i r s t 4 b y t e s of d p l a y e r x . d l l . r d a t a
push ebx
push esi
loc 8F800A :
mov esi , [ ebp+t o d e c o d e ]
push edi
mov edi , ds : r d a t a 4 ; t h e 4−8 th b y t e s of d p l a y e r x . d l l . r d a t a
mov edx , [ esi ]
mov ecx , [ e s i +4]
shl eax , 5
[ garbage ]
mov ebx , e d i
dec edi
test ebx , ebx
jbe end routine
mov e s i , [ ebp+key ]
inc edi
mov [ ebp+key ] , e d i
shl edi , 4
add edi , ebx
mov ebx , edx
shr ebx , 5
add ebx , [ e s i +0Ch]
xor edi , ebx
lea ebx , [ eax+edx ]
xor edi , ebx
sub ecx , edi
[ garbage ]
[ garbage ]
sub eax , ds : r d a t a 0
[ garbage ]
mov e d i , [ ebp+key ]
dec edi
mov [ ebp+key ] , e d i
jnz short s t a r t l o o p
mov e s i , [ ebp+t o d e c o d e ]
[ garbage ]
[ garbage ]
pop edi
pop esi
pop ebx
pop ebp
retn
d e c o d e 8 b y t e s endp
The algorithm is not unknown anymore. We have ciphered data, we know the algorithm,
but we ignore the key and do not have clear data. To brute force the algorithm we need to
guess clear data, and we can do it.
At the end of the .data section you should see this pattern CD DE 58 A2 75 01 7F to be
repeated a lot of time. It does not require a lot of PE knowledge to know that .data
sections end with 0, for alignment purposes. Therefore, we know that CD DE 58 A2 75 01
7F corresponds to 00 00 00 00 00 00 00 00.
We have the algorithm, clear text and coded text. We can easily determine the key now.
But there is still a problem, trying from 00000000h to FFFFFFFFh will take some time.
Fortunately we have a way to narrow our search. You certainly remember that the .rdata
section is handled in a different manner, and that the algorithm is very different. Here it is :
...
loc 8F1AF9 : ; CODE XREF: c r e a t e a p i i n t e r f a c e +738
mov ecx , [ ebp+key ] ; s t o r e t h e key in ecx
mov edx , [ ebp+r d a t a v a l u e ] ; ( 1 ) edx c o n t a i n s a v a l u e
; from . r d a t a
xor edx , [ ecx ]
If you are careful, you will see that at the point (1), edx always contains something like c1
xx xx xx. Since this result is xored with the value of the key, and since there is no way
that the result of the operation can be greater than FFFFFFh, we know that the two first
bytes of the key are c1 (because a ⊕ a = 0). We divided the number of possibilities by 256,
this imply cracking will be 256 times faster !
You have to program something that will try to find the correct key. Here is some source
code to help you :
mov eax , s t a r t v a l u e
; put c1000000 − 1 in s t a r t v a l u e
mov e s i , addr
bl loop :
inc eax
jz bl end
push eax
push esi
or ecx , edx
jnz bl loop
bl end :
ret
b r u t e l o o p endp
mov eax , r d a t a v a l
; put t h e 4 f i r s t b y t e s of d p l a y e r x . d l l . r d a t a here
shl eax , 5
mov e s i , key
s t a r t l o o p : ; we l o o p 20 h time s
mov ebx , e s i ; key +8
mov e d i , edx
shl edi , 4
add e d i , ebx
mov ebx , edx
shr ebx , 5
add ebx , e s i ; key +C
xor e d i , ebx
lea ebx , [ eax+edx ]
xor e d i , ebx
sub ecx , e d i
sub eax , r d a t a v a l
dec ebp
jnz start loop
end routine :
ret
d e c o d e 8 b y t e s endp
You have of course to add more to obtain a full program, but the hardest part is explained
here. I suppose that you understood that the algorithm uses a 32 bytes long key, but that
this key is actually 4 times the same 8 bytes long key.
After a short period, if your program works fine, you should find the same key than before :
c15cf2e5.
You can follow the very same steps for hacking dplayerx.dll, except that you should not
remove the ICD deciphering. It is now needed to alter the key before this function is called.
A very easy task, all that you have to do, is to put a breakpoint on 8F40B0 (bpx 8f40b0
when you are within dplayerx.dll). When you will break, put these bytes starting at 908988
: e5 2f 55 c1 e5 2f 55 c1 e5 2f 55 c1 e5 2f 55 c1 (ed ds:908988
c15cf2e5,c15cf2e5,c15cf2e5,c15cf2e5, afterward check with db ds:908988 that bytes
are in the reversed order.)
Once the memory has been modified, step over the call, both sections are now decoded.
You may dump them and rebuild the ICD file. Once this is done, all you have to do is to
hack dplayerx.dll so that the .rdata section get deciphered correctly.
The final result should be the same than the one we obtained with the original CD. Test
it. . .
. . . congratulations, you just cracked Safedisc without the original CD.
You learnt how to crack without the CD. What are the files you need for cracking ? Here is
the list :
1. rayman2.exe
2. dplayerx.dll
3. rayman2.icd
note : if you are working on IRC, for an ISO release for example (thou knave !),
you only need these three files. However, if the provider can dump the sections
for you, it is of course better.
The Prestige’s fellows told me that the whole ISO was transmitted through ftp
to the cracked. Try my method. . .
Conclusion
Right now, I have Unreal Tournament to play with, it uses an even more recent version of
Safedisc. Future versions of this essay will include the results of my inverstigations ! (as
well as corrections I suppose :-)).
However, I doubt that major changes will occur, therefore if you master the techniques
described, you should also be able to crack future versions of Safedisc.
What I expect to change :
• Some changes in the deciphering algorithm. (find the new one and reverse it)
• New anti-debug tricks. (use Frogsice and your brain, remember the debug registers)
• More checksums. (bpm is your friend)
• Some reorganizations within the code. (just analyse the code with IDA)
As you can see, they can not really catch you by surprise. . .