An overview of Safedisc versions

by ArthaXerXès

Published by +Tsehp June 2001

Mise au point

(taken from Safedisc® User Guide)
Can the SafeDisc technology be hacked?
The developers of SafeDisc, Ç-Dilla Labs, has investigated all known methods and tools used by hackers to compromise the encryption or the authentication code. SafeDisc will disrupt any attempt to use disassemblers and debuggers to isolate or patch any of the SafeDisc code. Many other techniques are used in order to increase the time, expense, and expertise required to compromise a SafeDisc protected title. These substantial disincentives will assure that the commercial value of the title has been fully exploited before any risk of compromising the security arises.

Macrovision has maintained the effectiveness of its home video copy-protection technology to the satisfaction of the major Hollywood studios for the last 15 years. Our unique experience in the copy-protection business and our technical expertise will assure that the quality and effectiveness of the SafeDisc technology will be constantly improved in order to maintain its effectiveness against piracy.
The truth :
  1. The Safedisc technology does not prevent piracy since the CDs can be copied by someone with a DAO RAW capable CDR and who is able to operate a CD recording software.
  2. We have totally reversed the "encryption" and "authentication code", we have even developped easy-to-use software to automatically remove Safedisc from any program.
  3. The great majority of software is pirated and distributed unprotected in their full version the day it hits the stores (sometimes even before !).
  4. Macrovision home video copy-protection can be defeated either by a cheap electronic device or by a program for those who have a computer with video-in.
Spare your money, do not buy protections schemes. There are cheaper and more efficient ways to fight piracy.


Although I have noted a decreased use of CD protection (most of them are defeated by a kid with CloneCD), they are still strongly present (and strongly annoying).

Safedisc is probably the most used, thanks to an agressive marketing and a clever price policy, and also the fact it is easy of use and (almost) transparent to the end user. However, from a technical point of view the protection is disappointing. In my humble opinion, it is just a collection of hacks, nothing really clever or outstanding. The code is dirty and inefficient, somehow I wonder how the makers are able to maintain it (and understand why there is no real improvement since the first version).

In this short essay, I will review the various Safedisc versions, from 1.6.0 to 2.05.30. Consider this essay as a mise en bouche for a forthcoming essay that will be a detailed reverse engineering of Safedisc 2, something much more advanced than my previous essay on Safedisc.

If you find this document to be inaccurate or incomplete, feel free to inform me. I would also like to thank Black Check, Booo, dec0de12, Icydee, Knulla, Lord Crass, Moelch, Portia, r!sc and many other Fravias I forgot (or wish to remain anonymous) who kindly and selflessly shared their insights.

How to determine the Safedisc version

In order to determine the Safedisc version, you have to search for this string in the executable (icd for 1.x.x, exe for 2.x.x) : "BoG_ *90.0&!! Yy>". Just after there should be three unsigned longs, that are respectively the version, subversion and revision numbers. Safedisc 2 executables can be recognized by the presence of sections named "stxt???" (where ? is any figure), dll placed in the temp directory during execution and appended data at the end of the executable.

Revision history

Note that I do not consider anti-debugging features here, I am only writing about unwrapping. Anti-debugging becomes heavier and heavier with each new version, you should be very careful with your breakpoints and carefully monitor the secdrv.sys device driver under NT.

And by no mean this should be considered as an introduction to Safedisc. You need to have a minimum of experience with the protection, and a real experience of reverse engineering under Windows. I am neither going to explain the technical terms nor detailing the PE format (for example).
The first released version. Sections are ciphered using the TEA algorithm with a 128 bits key in the form aaaa where a is a 32 bits number. The key is red from the CD or computed from hidden data in the loader if this is impossible (CD reader failure). The imports are simply mixed using a Monte Carlo algorithm, you need to demangle them with the TEA key and then update the first thunk. Note that only kernel32.dll and user32.dll imports are modified.

There is an additional step to perform prior to reorder the imports, you have to decrypt the ASCIIs, the algorithm is actually quite simple, you also have to remove the "hint".
Here is the algorithm used to decipher the ASCII (taken from Safedisc annihilator) :

// key is the 128 bits TEA key
ascii_key = (unsigned char)((key >> 24) ^ 0xAB); // will be needed to decipher the ASCII

for(k = 2, cur_ascii_key = ascii_key; ; k++)
  buffer = ascii_pointer[k];
  ascii_pointer[k] ^= cur_ascii_key; // xor character using key
  cur_ascii_key = buffer; // key is unxored character

  if (ascii_pointer[k] == 0)

} // end ascii deciphering

Safedisc now supports Windows NT, it will automatically install/uninstall a NT driver called secdrv.sys.

Now the imports' RVAs are xored using the lower 32 bits of the TEA key, this helps you to quickly find the TEA key (an idea of Black Check). Why ? Simply because there are imports stored in loader.exe (you will find 4 dwords in the loader in this form a a b b just after a 0x00000000) and instead 0x00000000 is stored in the icd. If we xor the ciphered 0x00000000 with one of the dword found in the loader, we will obtain the TEA key (well the lowest 32 bits dword, but since the key is of the form aaaa, you can extrapolate the full key most easily) ! All you have to do is to try for each import dword.

Things are becoming more complicate here. Now the calls (well, a certain kind of call only, Ç-dilla did not implement a disassembler in Safedisc) are modified and need to be fixed. Here is the solution r!sc found and that I also used (this is actually a mimic of Safedisc) :
  1. Look for 0xff15 in the code section(s)
  2. Compute a remainder (the way it is computed will change in other version). This remainder is the way Ç-dilla found to apply their algorithm only on calls. Pretty lame I must say.
  3. If the remainder is equal to a certain value (again this changes), then proceed with "deciphering".
  4. Deciphering pseudo code :
    1. determine if this is a call to user32 or kernel32
    2. call_pointer -= api_thunk_start
    3. call_pointer += (current_section_offset + key) % number_of_apis
    4. call_pointer = (call_pointer + number_of_apis) % number_of_apis
    5. call_pointer = (call_pointer << 2) + api_thunk_start + pe_image_base

The only change here is that the calls remainder is computed in a different fashion.

Macromedia Director Files can be protected using Safedisc.

Things changed here. To me, it sounds like Ç-dilla found out about our generic unwrappers. ;-) Well they did two things to counter us (but it did not work of course).

Problems :
  1. They fixed the TEA key weakness (the fact that it is 4 times the same dword), the key is now a real 128 bits number (do not worry we found a way around).
  2. To prevent automatic unwrapping, they use code inside dplayerx.dll for the modified calls. This code changes with every protected program, and thus you cannot write a generic algorithm (again, we found a way around :-).

Solutions :
  1. Well, I do not like to despise other programmer's work, but this move was pretty worthless. At first we were a little bit concerned by this, but eventually someone (I think it is r!sc) discovered that the 128 bits key is actually computed from various values we can easily retrieve (instead of reading 128 bits from the CD, which would have been more secure...).

    Using our magic 32 bits value :

    inc_entry_point = entry_point + 0x2d8; // entry_point is the icd entry point

    x_val = ((TEA_key1 - inc_entry_point) ^ checksum) ^ raw_key[0];
    full_TEAkey[0] = TEA_key1;
    full_TEAkey[1] = (x_val ^ raw_key[1]) + inc_entry_point;
    full_TEAkey[2] = (x_val ^ raw_key[2]) + inc_entry_point;
    full_TEAkey[3] = (x_val ^ raw_key[3]) + inc_entry_point;

    The raw key is stored in loader.exe, look for "DECRPE\0\0". In future version they added an offset, but it is still located in the same place.

    Another result of this feature is that we started to wonder if there was actually any data red off the CD. I knew there was some data actually red from the CD (this was partially correct), but later I learnt that this data is also present in the loader (to make the protection work on poor CD readers), which means that you can generate the full key without any brute forcing and without the original CD.
  2. Well, this was a more clever move. I had to implement a dplayerx.dll loader (and also had to fight against some nasty problems under 2k), get the pointer to the magic routines and apply them. Note that the call deciphering routine is still the same (logical), this is the way used to determine if a call must be fixed or not that changed. It is not a remainder any more, we apply an eax modifier (a routine that modifies the value of the eax register) stolen from dplayerx.dll. This is the only reasonable way, since the eax modifier changes with each different dplayerx.dll.

One big new feature here, a second layer of encryption is applied on the ICD using a mundane algorithm. Also the address for the dplayerx.dll routines changed. The second layer of encryption has to be removed before brute forcing of course. And yes, the second layer uses a routine from dplayerx.dll. Here is the algorithm for a block of data :

bool __fastcall icd_rebuilding::new_decipher_block(void *p, unsigned long size)

  unsigned long done, i_size;
  unsigned long buf1, buf2;
  unsigned long *ptr;

  done = 0;

  i_size = size >> 2;

  ptr = (unsigned long *)p;

  while(done < i_size)
    buf2 = (done << 0x18) | (done << 0x10) | (done << 0x08) | done;
    buf1 = ptr[done] ^ buf2;
    buf1 = m_dplayerx->execute_eax_modifier(0x65be, buf1) ^ buf2;
    ptr[done++] = m_dplayerx->execute_eax_modifier(0x65be + 0x63, buf1);

  return true;


The real news are (taken from SafeDisc® Release Notes) :
  1. SafeDisc API
    The SafeDisc API provides extra security features. These are implemented by inserting macros, from the SafeDisc API, into the product code. After the product has been protected with SafeDisc, the macros enable SafeDisc security routines to be performed whilst the protected product is being run.
  2. Protection of DLLs
    SafeDisc can be used to protect DLLs as well as EXEs.

But really, what changed ? From the outside, many things have changed since everything seems to be held in one executable file.
Internally ? Almost nothing.

2.05.30 from an unwrapping point of view is strictly 1.50.20. What is boring though is the heavier anti-debugging features payload. Also, as I said above, everything is now packed in one executable. You need to extract the data from this executable. It is appended at the end of the executable (not even stored in a section...).

Since I have not really worked a lot on Safedisc 2, I cannot tell you the exact nature of the algorithms, but I suspect them to be quite simple. Portia posted about them on my message board, but I have discarded the message (I told you I was not a god ! :-).

To unwrap 2.05.30 you will probably have to do the following :
  1. extract dplayerx.dll and the "loader" from the main executable.
  2. extract the "icd" from the main executable.
  3. Unwrap the icd.
  4. fix the entry point (it points to Safedisc code) of the icd. The original entry point is hidden "under" the main SD2 routine, it is very easy to find with IDA. Also fix the data directory (for the imports).

I have not yet performed an in-depth reversing of the Safedisc API, but I suspect it can be fully and automatically disabled quite easily. The key is probably to find and disable the hub that all protected functions use. One could either reverse the hub to restore the functions, or modify the hub to unconditionally operate.


There are also more recent version of Safedisc 2 available, but I have stopped working on Safedisc since 2.05.30 (other projects to attend), and I am just getting back to it. If you have additional information to share, please be my guest. Ihope that you found that document useful.

If you find information about Safedisc hard to come by, this is because of the bad spirit of competition in the warez scene. Most of the "big" groups have unsafedisc-like programs and really do not want other groups to have them, therefore they keep secret what they know about the protection. I do not think they realize that everybody would benefit from cooperation.

"He who controls the unwrapping controls the warez". ;-)

And before you ask me : yes, there is a version of Safedisc Annihilator to support Safedisc 2 in the works, and no, I do not know when it will be released (I have many other tasks that require my attention).

ArthaXerXès -- 06/16/2001