######## Cdilla Safedisc Tutorial by Black Check   #########



Intro
-------
O.k,o.k weil's so viele wollten,gibts mein tut nun auch in Deutsch.
Seit dem ersten Essay hat CDilla ihren Kopier'schutz' etwas 
gendert.Auch wenn die Neuerungen lachhaft sind (Safedisc filez
werden nicht mehr ins Verzeichniss kopiert,rdata) gibts ein neues
tut.Unser Opfer ist Legacy of Kain:Soul Reaver (Deutsch).Ich gehe
natrlich davon aus,dass du das erste tut (gibts auch in Deutsch)
gelesen und verstanden hast.


Tools
-------

-Soul Reaver original CD
-Softice
-Adump 1.0
-Procdump 1.5
-Frogsice 0.31
-Hex Workshop 32 


#####################
1. Anti Sice        #
#####################

Tja..Cdilla war echt faul und hat an dem Anti Sice garnix 
gendert.Ich bin echt entuscht Jungs.Naja,vielleicht ein anderes
mal.Fr uns heist das Frogsice 0.31 laden und es funkt.Sogar meine 
alte Methode die dll und die exe zu patchen funkt noch(brauchen wir
aber nicht mit v0.31).



#####################
2. Let's dump       #
#####################


Na dann dumpen wir den Scheiss mal...

Der entrypoint der icd ist 4c11e0.R!SC hat einen netten 
Ansatzpunkt gefunden:bpx Freelibrary.Also Frogsice an
bpx gesetzt und los gehts.Wiederhole F5 und u 4c11e0,bis
das baby entschlsselt ist.Jetzt F12 und a,jmp eip um das
Teil anzuhalten.Mit Procdump (1.5!) machen wir jetzt einen
full dump und einen partial dump.Der full dump wird unsere
gefixte exe,und aus dem Anderen rippen wir uns die rdata section.
Achtung!Die rdata section ist im part.dump um 1800h bytes 
verschoben.Aber wenn du das drinn' hast erkennst du sie auf
Anhieb.Speicher sie als rdata.dat. 




######################
3. Fixing the .rdata #
######################

Na wenigstens haben sie ihr Api Call System ein bisschen
verndert.Auch wenns mich echt nicht umhaut funktioniert 
meine alte Methode nicht mehr.

x:       pushad
         push 00000000   | Function number
         push 00000000   | Dll   number  
         call[x+21]
         add esp,8
         popad
         jmp[x+13]

x+1b:    dd ApiAddress  (=f700c0)
x+1f:    dw ???
x+21:    dd ApiFuckUpCallAddress
x+25:    pushad
         push 00000001
         push 00000000
         call[...]
         .
         .
         .
            

In der alten version hat der call die Adressen in
eax und ecx zurckgegeben.Dieser peinliche Fehler
wurde ausgebessert(ich bin stolz auf euch!).Dummerweise
wird die richtige Adresse aber immernoch ins Codesegment
geschrieben.Es gibt mehrere Methoden um das zu nutzen,
ich hab mich aber fr folgendes entschieden:
Den ganzen Scheiss ins Codeseg schreiben lassen,alles
dumpen und dann ein kleines Prog schreiben,dass uns
eine richtige rdata section bastelt.Wir haben 4ah
Kernel und 20h User imports.


3.1 Den Safedisc call missbrauchen
-----------------------------------

Starte jetzt Adump.Merk dir deine dump Adresse gut...
Jetzt setzen wir einen Bp auf den Entrypoint und starten.
Wenn Safedisc sich bequemt hat die icd zu entschlsseln
Fangen wir an zu coden:

:a

4c11e0: push ebx       | EBX von Hand auf null setzen !!!
        push 00000000  | Spter ndern..
        call f700c0    | Der CDilla Apicall
        inc  ebx
        cmp  ebx,4a    | number of Kernel imports
        jnz 4c11e0
        jmp eip


Nachdem wir es laufen lassen haben ndern wir den push zu 1
und dem cmp zu cmp ebx,20 und lassen es nochmal laufen.Jetzt
haben wir alle Adressen im Code =).



3.2 Den Scheiss dumpen
--------------------------------

Jetzt mssen wir erstmal den Anfang finden.Step in den
ersten Api CAll (Getversion meistens) und scroll nach
oben:

F94540:  pushad
         push 0000000
         push 0000000    | Kernel
         call [...]


Schreib dir die Adresse vom ersten pushad auf.Mit dem
'u' Befehl in Sice kannst du dir das Zeugs richtig anzeigen
lassen.Nun scrollen wir munter weiter nach unten,bis zum
ersten User Eintrag:



F95004: pushad
        push 00000000
        push 00000001    | User
        call[...]


Adresse aufschreiben (Nebenbei: Du solltest dir alle Bltter
aufheben die so beim cracken entstehen.Es ist echt witzig
wenn du Bltter die schon ein paar Jahre alt sind wieder in
die Finger kriegst.Pass nur auf,dass kein Anderer sie liest.Er
knnte dich fr absolut Geisteskrank halten ...=)Zurck zum
Thema:Wenn du ein Bisschen hochscrollst siehts du auch wie
viele Kernel imports es gibt.Scroll jetzt ganz runter bis
zu den NULL bytes und schreib dir die Adresse auf. 

Komischerweise mssen wir in zwei Teilen dumpen:

m F94540 l ac4 828de000
m F95004 l 49f 828df000
              (Adump mem)

Speicher in Adump und nenn die files Kernel.dat und
User.dat.


3.3 Unser ApiCall Fixup
----------------------

Jetzt brauchen wir nur noch ein kleines Programm,dass die
richtigen imports aus dem Code Seg nimmt und eine richtige
rdata zusammenflickt.Cdillafx.exe braucht
drei files:

Kernel.dat
User.dat
Rdata.dat

und erstellt rdata.fix.Ich hab das in etwa 15 minuten
geschrieben,drum musst du fr andere games die Werte
von Hand ndern...



################# CDillafx.c ################################


#include <stdio.h>
#include <io.h>
#include <alloc.h>
#include <fcntl.h>
#include <process.h>
#include <sys\stat.h>

typedef unsigned char byte;
typedef unsigned long u32;

byte *Kernel,*User,*Rdata;

u32  KernelOff=0xf94540; // we wrote this down before
u32  UserOff  =0xf95004;
u32  Offset=0;
u32  GoodAdr,BadAdr;
int  Temp,k=0,u=0;
int  KernelSize=2756;   // size of our files
int  UserSize=1183;
int  RdataSize=14336;

void Load_File(byte*File,byte*Buf,unsigned l)
{
   int handle, bytes;

    if ( (handle=open(File, O_RDONLY | O_BINARY,
		 S_IWRITE | S_IREAD)) == -1)
   {
      printf("Error opening file.. ");
      exit(1);
   }

   if (read(handle,Buf,l) == -1)
   {
      printf("Read failed.\n");
      exit(1);
   }
 close(handle);
}

int Change_Entry(u32 Good,u32 Bad)
 {
  u32 Entry,o;

  for(o=0;o<RdataSize;o++)
   {
    memmove(&Entry,Rdata+o,4);

    if(Entry==Bad)
     {
      memmove(Rdata+o,&Good,4);
      return 0;
     }
  }
 printf("\nFixup failed for %x",Bad);
 return 1;
}

void Write_File(void)
 {
  int handle;

  if ( (handle=open("Rdata.fix", O_RDWR | O_BINARY | O_CREAT,
		 S_IWRITE | S_IREAD)) == -1)
   {
      printf("Error opening file.. ");
      exit(1);
   }

   if (write(handle,Rdata,RdataSize) == -1)
   {
      printf("Write failed.\n");
      exit(1);
   }
 close(handle);
}


void main(void)
 {
  Kernel=(byte*) malloc(10000);
  User  =(byte*) malloc(10000); // you may want to change this
  Rdata =(byte*) malloc(20000);

  Load_File("Kernel.dat",Kernel,KernelSize);
  Load_File("User.dat",User,UserSize);
  Load_File("Rdata.dat",Rdata,RdataSize);

  for(;;)
   {
    memmove(&Temp,Kernel,2);
    if(Temp!=0x6860) break;             // are we finished?
    memmove(&GoodAdr,Kernel+0x1b,4);    // Get Import Address
    Change_Entry(GoodAdr,KernelOff);    // And replace it
    KernelOff+=0x25;                    // Entries are 25h bytes long 
    Kernel+=0x25;
    k++;
   }

  for(;;)
   {
    memmove(&Temp,User,2);
    if(Temp!=0x6860) break;             // are we finished?
    memmove(&GoodAdr,User+0x1b,4);
    Change_Entry(GoodAdr,UserOff);
    UserOff+=0x25;
    User+=0x25;
    u++;
   }
   Write_File();

   printf("\n%x Kernel imports fixed",k);
   printf("\n%x User imports fixed\n",u);

   printf("\nCheckmate Cdilla!");

 }





Mit irgendeinem Dos C compiler bersetzen und starten.
Rdata.fix in den full dump pasten und es Funkt!

Mit Procdump kann man wie im ersten tut die exe W9x 
kompatibel machen...


################
4. The end     #
################


Wenn Cdilla mal den Arsch hochkriegt und ihren lcherlichen
Kopierschutz ernsthaft verbessert gibts ein neues tut
inclusive einer Liste mit allen Safedisc games und Versionsnummern
aber nicht jetzt...

This tut is dedicated to White Tiger who sits in jail...


Interresting stuff goes to black_check@yahoo.de


