02/08/2011

Diablo II part 2

Introduction

Après mon post sur la fabrication de serial pour diablo II, je ne pouvais pas en rester là.
Il fallait que je joue avec Securom afin de me fabriquer un no-cd avec mes petits doigts.
Bab00n a écrit un excellent article sur la création d'un no-cd pour Diablo II Lord Of Destruction (l'extension du jeu).

Securom v4

Ici pour diablo II original (Version 1.03), nous avons affaire à du securom v4, il faut savoir que nous sommes en présence de 2 éxécutables à la base.

   > hexdump -C Game.exe | grep -i "AddD"
   0003b940  00 00 00 00 41 64 64 44  00 00 00 00 35 39 4a 50  |....AddD....59JP|
   0003b960  00 00 00 00 46 57 53 00  41 64 64 44 00 00 00 00  |....FWS.AddD....|
   0003b970  41 64 64 44 00 00 00 00  5c 00 00 00 1a 27 1a 12  |AddD....\....'..|
   00048000  41 64 64 44 03 00 00 00  34 2e 30 37 2e 30 30 00  |AddD....4.07.00.|

Ici nous avons affaire à du securom version 4.07.00, protection ID aurait pu très bien faire l'affaire :

diablo2_protid

Find OEP

La première étape est de trouver l'oep, 2 solutions s'offrent à nous :


    004169A6  |> |58                    /POP EAX
    004169A7  |. |FFE0                  |JMP EAX

Nous arrivons enfin sur l'enty point :

00402120  /.  55            PUSH EBP

Reconstruction des calls redirigés

Securom met en place un système pour rédiriger les calls vers les différentes API dont il a besoin.
C'est en recherchant des renseignements sur securom, que j'ai commencé à me demander si j'allais etre en présence de call [Securom] / call Securom.
Securom étant la section dans notre cas "cms_t".
Donc je décide d'écrire un script Olly :

//log "Loggin all call [Securom]"
//next:
//findop eip, #FF15#
//mov eip, $RESULT
//log eip
//add eip, 6
//cmp $RESULT, 0
//jne next
//pause

var dest
log "Loggin all call Securom"
next:
findop eip, #E8????????#
mov eip, $RESULT
mov dest, [eip + 1]
add dest, eip
cmp dest, 40F000
jbe not_log
log "-- Maybe new ?"
log dest
log eip
not_log:
add eip, 5
cmp $RESULT, 0
jne next
pause

La première parti commenté du script sert à loguer les call [Securom], alors que l'autre sert à loguer les call Securom.
Résultat nous sommes en présence de seulement de call [Securom], dont voici un exemple :

00402146    FF15 F0024200   CALL DWORD PTR DS:[4202F0]               ; Game.0040FBD0

La routine en 0x0040FBD0, va calculer l'api à apeler puis mettre le résultat dans eax, et ansi jmp eax, afin de l'apeler.
N'étant pas sur de moi, j'ai tout fait à la mano ('Non je ne suis pas fou, je voulais pas faire de la race c'est tout').
Donc j'ai écrit un script Olly pour loguer tout ca et remplacer correctement les call [Securom] par call [API].

Voici un bout de la routine intéressant :

0041035E    8B06            MOV EAX,DWORD PTR DS:[ESI]
00410360    5F              POP EDI
00410361    5E              POP ESI
00410362    5B              POP EBX
00410363    8BE5            MOV ESP,EBP
00410365    5D              POP EBP
00410366    FFE0            JMP EAX

Le but va etre de bp en 0x0041035E, loguer esi, et loguer d'ou nous avons été apelé.

var rez
bp 0041035E
cnt:
eob Break
eoe handler
run

handler:
ret

Break:
log esi
mov rez, [esp - 4]
sub rez, 6
log rez
log [esi]
jmp cnt

Arrivé à l'entry point, j'exec le script et la failed :

diablo2_error

Pourtant le script partait bien :

diablo2_log

En fait bêtement dans cette routine, ils font appel à timeGetTime :

00410264    FF15 F8164400   CALL DWORD PTR DS:[4416F8]               ; WINMM.timeGetTime

Je m'emmerde pas, je nop un saut conditionnel en 0x004100F0.
Et la le jeu se lance, nous avons été en mesure de tout loguer.
Il suffit de remplacer à la mano les call [Securom], par call [API], ou alors il suffit juste de modifier le script :].
Vous n'aurez plus qu'a dump le processus, un coup d'importRec et le tour est joué !

Hmmm par contre il reste un CD-Check dans storm.dll (0x00357CA4) ;)

Have Fun :]
On se revoit pour une version 5 de securom ou du safedisc.