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.
- Diablo II.exe : Qui fait un CreateProcess('Game.exe' ... ).
- Game.exe : Notre éxécutable protégé par securom.
> 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 :
Find OEP
La première étape est de trouver l'oep, 2 solutions s'offrent à nous :
- Bp sur WriteProcessMemory, compter le nombre de break avant que le jeu se lance, une fois ce nombre calculé, s'arreter sur le dernier appel, retourner dans le user code, et chercher un jmp EAX.
- Bp sur GetDriveTypeA, retourner en code user, et scroller jusqu'à trouver le jmp EAX.
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 :
Pourtant le script partait bien :
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.