Vamos a lío !!!!!
Si leíste el tutorial de Pedro puedes ver cómo él pone breakpoints
en WriteProcessmemory, GetDriveTypeA, etc...pero Sony ha mejorado
Securom y ahora es capaz de detectar estos breakpoints. Hiuston !!!!!
Tenemos un problema !!!!
Bueno lo primero que vamos a hacer es recopilar información
del ejecutable (TS_D3D.exe):

Entry Point --> 00553E90 (situado en la sección
".cms_t")
Como podréis comprobar el código de Securom ahora se encuentra
dentro del ejecutable principal, en las secciones
".cms_t" (cms_text) y ".cms_d" (cms_data).
Tenemos que hallar el punto de entrada original del ejecutable (el
que tenía antes de pasar por Securom)
Cómo +Xoanon explica en su tute, tenemos que buscar el "JMP
EAX" que nos lleva al Entry Point original. Oppsss !!!! pero no
podemos tracear ni poner breakpoints en WriteProcessMemory o
GetDriveTypeA.
Bueno es el momento de ver algo de teoría:
Para establecer un breakpoint con SoftIce (y cualquier otro debugger)
lo que hace éste es cambiar el primer byte del código donde hemos
puesto el punto de ruptura por CCh, que es el opcode de Int 3 (que hace
saltar al debugger). Lo que pasa que éste es un proceso transparente
para el cracker ya que el SoftIce en pantalla muestra el byte original y
no "CC". Y es aquí dónde se basa Securom (y muchas otras
protecciones) para detectar los breakpoints. Haced lo siguiente:
u GetDriveTypeA
KERNEL32!GetDriveTypeA
016F:BFF678EF 57
PUSH EDI <--- Securom
comprueba el breakpoint aquí
016F:BFF678F0 6A21
PUSH 21 <---
Qué tal si lo ponemos aquí? ;)
016F:BFF678F2 2BD2
SUB EDX,EDX
El SoftIce parcheará el byte siguiente a GetDriveTypeA y Securom no
nos detectará el breakpoint.
Mucha gente me preguntó si no es más fácil poner un BPM? Quizás sí,
pero el Securom no nos permite tener BPM´s, se niega a correr cuando se
encuentra con alguno, entre otras cosas porque como veréis un poco más
abajo el propio Securom maneja sus propios BPM´s.
BPX getdrivetypea+1
F12 y aparecemos aquí:
016F:00551E21 51
PUSH ECX
016F:00551E22 FF151C505700
CALL [KERNEL32!GetDriveTypeA]
016F:00551E28 83F805
CMP EAX,05
016F:00551E2B 7421
JZ 00551E4E
Ahora tendríamos que trazar hasta encontrar el Entry Point original,
pero si pulsas F8 o F10 simplemente no pasa nada...nos han mutilado el
SoftIce!!! Cómo se lo han montado? Aquí tenéis la solución "by Ni2":
"El F8 no funciona (o parece q no funciona) porque el SECUROM
pone un breakpoint por hardware (BPM en DR0) en la dirección donde no
funciona el F8. Como estamos bajo el SICE, no se produce excepción tras
una INT 1 (la INT 1 la genera el BPM que ha puesto el SECUROM). El
SECUROM, lo que hace es instalar un SEH que se encarga de manejar la
excepcion (INT 1) tras el breakpoint que ha puesto"
Encontrar y jugar con las SEH que instala Securom puede llevar mucho
tiempo y requeriría un estudio mucho más a fondo de la protección
(jeje, como si no nos la hubiésemos estudiado para el UnSecurom ;) Hi Ni2!
Hi SkUaTeR!) Habrá que buscar pues otra solución. Es ésta:
Pulsa 'Control+Av.Pág' hasta encontrar el siguiente código:
016F:00553054 58
POP EAX
016F:00553055 FFE0
JMP EAX
016F:00553057 A3286E5700 MOV
[00576E28],EAX
Y haz lo siguiente:
- BPX 553055
- Borra (o desactiva) el breakpoint de Getdrivetypea
- Pulsa F5 y espera que salte el SoftIce
Aparecemos en :00553055, miramos el valor de EAX y vemos que es
004EBBA4. Bien este es el punto de entrada original sin Securom. Pero
todavía no es el momento de cantar victoria, tan sólo hemos ganado la
primera batalla.....si volcamos el archivo y lo ejecutamos nos peta en
las narices porque las llamadas a las APIS todavía dependen de
Securom. Vamos a ver que hacemos para subsanar este problemilla:
016F:004EBBA4 55
PUSH EBP
<-- Entry Point original
016F:004EBBA5 8BEC
MOV EBP,ESP
016F:004EBBA7 6AFF
PUSH FF
016F:004EBBA9 6808AF5000
PUSH 0050AF08
016F:004EBBAE 68A8114F00
PUSH 004F11A8
016F:004EBBB3 64A100000000
MOV EAX,FS:[00000000]
016F:004EBBB9 50
PUSH EAX
016F:004EBBBA 64892500000000 MOV
FS:[00000000],ESP
016F:004EBBC1 83EC58
SUB ESP,58
016F:004EBBC4 53
PUSH EBX
016F:004EBBC5 56
PUSH ESI
016F:004EBBC6 57
PUSH EDI
016F:004EBBC7 8965E8
MOV [EBP-18],ESP
016F:004EBBCA FF1528C25500
CALL [0055C228] <--
Llama a la rutina de Securom encargada
016F:004EBBD0 33D2
XOR EDX,EDX
de las APIS
Bueno al menos ahora podemos tracear con F8 y F10. Nos
aprovechamos de eso y trazamos esa llamada con F8. Aparecemos aquí:
016F:0054D040 55
PUSH EBP
016F:0054D041 8BEC MOV
EBP,ESP
016F:0054D043 83EC28 SUB ESP,28
De nuevo con 'Control+Av.Pág' vemos que lo que hace la
rutina es sacar de una tabla la llamada correcta a la API, almacena el
valor correcto en EAX y salta a ella. Busca el siguiente código:
016F:0054D5B7 5D
POP EBP
016F:0054D5B8 FFE0 JMP EAX
016F:0054D5BA 5F
POP EDI
Pon un breakpoint en 0054D5B8. Le damos al F5 y
esperamos que salte el Sice. Ahora poned:
:what eax
|
The value BFF833FD is (a) KERNEL32!GetVersion
|
Osea que ese 'JMP EAX' en realidad es el salto a la
llamada correcta. Podríamos codificar un pequeño programilla que nos
arreglase las llamadas a las APIS tal que:
:0054D5B7 Aquí EAX
contiene la llamada correcta
:0054D5B8 JMP a Nuestra rutina
:mi rutina Cambia
CALL [0055C228] a CALL valor de EAX
Si lo hacemos, funciona perfectamente, pero sólo lo haría
en nuestro sistema operativo (en mi caso WindowsME). La solución está
en hacer una llamada directa a la tabla de importación. Buscamos 'BFF833FD'
en la memoria y:
:s 400000 l ffffffff FD 33 F8 BF
|
Pattern found at 0030:004FB0CC (000FB0CC)
|
Si en 004EBBCA
cambiamos
CALL [0055C228]
por
CALL [004FB0CC]
vemos que llamamos a GetVersion
sin pasar por la rutina de Securom, prueba superada !!!
Si estudiamos un poco más la
rutina que devuelve la llamada correcta, vemos que Securom coge la
dirección desde donde ha sido llamada y en función de eso saca de una
tabla la correcta. Pero todo esto nos supondría un trabajo enorme si
tuviésemos que corregir a mano todas llamadas a las APIS. Por eso
codificaremos en SoftIce un programilla como éste que nos haga la faena
sucia:
; Securom Call FiXeR
; Ejecuta Adump. Ejecuta el comando "r" , STARTOFFS es la
dirección ADUMP
; en 0054D5B8 cambia
; JMP EAX
; a
; JMP dirección ADUMP;
; Y en la dirección ADUMP ensambla esto:
mov ebx,eax
; Guardamos en EBX la API llamada
pop eax
; Obtenemos la dirección de retorno después de
la llamada
mov edx, ebx
; Guardamos EBX en EDX como precaución
mov ecx,004FB000h ;
004FB000=Inico sección ".rdata"
BUSCAIAT:
cmp dword ptr[ecx],ebx ;
Busca la API en la sección ".rdata"
jnz SIGUEBUSCANDO1
mov dword ptr[eax-4],ecx ;
Modifica "CALL [0055C228]" por "CALL [API correcta]"
mov ecx,00401000
; 00401000= inicio de la sección
".text"
BUSCALLAMADA:
cmp
word ptr [ecx],15FFh
; Busca la siguiente llamada a Securom en la sección
".text"
jnz SIGUEBUSCANDO2
; FF 15 28 C2 55 00 son los bytes de
cmp dword ptr [ecx+2], 0055C228h
; CALL [0055C228] y cambian en función
jnz SIGUEBUSCANDO2
; del juego que estés crackeando
jmp ecx ;
Salta a la llamada siguiente para que Securom nos devuelva la correcta
SIGUEBUSCANDO1:
inc ecx
cmp
ecx,0050D000h ;
Es fin de sección ".rdata"???
jnz BUSCAIAT
; Si no lo es, sigue buscando
int 3
; Si algo va mal romperemos aquí
SIGUEBUSCANDO2:
inc ecx
cmp ecx,004F9000h ; Es
fin de sección ".text"??
jnz BUSCALLAMADA
; Si no lo es, sigue buscando
int 3
; Cuando todas las llamadas estén corregidas
romperemos aquí
Ahora pon "BPINT 3", desactiva todos los
breakpoints, cruza los dedos y pulsa F5. Arrrrrrgggggghhhh!!!!
Falla!!! Puto Securom de los....tranquilos no os desaniméis. Esto
sucede porque Securom comprueba el CRC de su rutina. Si el CRC llama
a una API errónea y peta. Pero....cómo nos enfrentamos a un CRC si los
BPM´s están inutilizados? Pues gracias a este magnífico programilla
de EliCZ: "SuperBPM". Pero no
podemos cargarlo desde el principio, porque sino el Securom se niega a
correr. Debemos ejecutar el juego y cuando rompamos en el verdadero
Entry Point, parar el proceso y ya sí, cargar el SuperBPM. Jeje qué
lioso, no? Con el SuperBPM, un poco de vista e intuición
(jeje y algo más quizás, SkUaTeR y Ni2 ya saben a lo que me refiero ;)
) unas páginas más arriba del JMP EAX encontramos el siguiente código:
:0054D28A 8B0A mov ecx, dword ptr
[edx]
:0054D28C 3B08 cmp ecx, dword ptr [eax] <---
Comprueba el "checksum"
:0054D28E 7409 jz 0054D299
<--- Hay
que hacer incondicional este salto
Sí, si forzamos ese salto diremos adiós a las caídas
de sistema. Para mentes retorcidas: Os podéis imaginar lo cabrón que
podía haber sido el Securom si hubiese utilizado directamente el
CRC para desencriptar las APIS? Pues ésto (y más) lo podréis
comprobar en el tute de LaserLok.
Bueno, cuando todas las llamadas estén corregidas
vuelca la sección ".text". Divide "TS_D3D.exe" en
secciones y reconstruye el fichero con la nueva sección
".text". Con un editor PE cambia el Entry Point por el nuevo.
En teoría ya tenemos finalizado nuestro crack, pero si ejecutamos el
juego provocamos un bonito fallo de protección general. ¿A qué es
debido? Pues a que Securom todavía no ha dicho la última palabra. La
dirección a la que apunta la tabla de importación en la cabecera
PE no es la correcta (esta técnica es usada por muchos otros
protectores). Pero... ¿cómo podemos encontrar la verdadera tabla
de importación? Muy sencillo. Con un editor hexadecimal (para esta
tarea os recomiendo Hex WorkShop) buscamos la cadena 'Kernel32.dll' (que
es la primera importación). La encontramos en el offset 10C11C,
invertimos bytes y nos queda 1CC110. Buscamos (generalmente hacía
arriba) '1CC110', encontramos lo siguiente:

IMAGE IMPORT DESCRIPTOR:
-1- |
-2- |
-3- |
-4- |
-5- |
Original First Thunk |
TimeDateStamp |
ForwardChain |
Name |
First Thunk |
E4BD
1000 |
0000
0000 |
0000
0000 |
1CC1
1000 |
5CB0
0F00 |
Estamos indudablemente en el inicio de
nuestra tabla de importación. Vamos a nuestro editor PE y en
'Directory' cambiamos el RVA de 'Import Table' a 0010BC98. Ejecutamos el
juego y....funciooonaaaaa!!!!!! Este juego no tiene CD-Check secundario,
por tanto ya tenemos TrickStyle 100% crackeado. Tampoco tiene videos o músicas
que poder ripear. Queda por tanto pendiente para un futuro tute, enseñaros
el arte de ripear.
VARIANTES
DE SECUROM
Durante el desarrollo del UnSecurom nos topamos con dos
pequeñas variantes de esta versión:
- La primera en juegos como el ShadowMan, Revolt y Rally
Championship. El proceso de crackeo es algo más sencillo. Sólo debéis
llegar al verdadero EntryPoint y volcar la sección ".text".
En esta variante las APIS no están redirigidas con lo cual nos
olvidamos de la parte más engorrosa de Securom. Y con editor PE veréis
que el ejecutable tiene 2 secciones ".idata", la primera es la
buena. Así pues, una vez reconstruido el fichero tenéis que corregir
la IAT al inicio de esa sección.
- La segunda me la encontré en el FreeStyleBMX. También
tiene 2 secciones ".idata", pero aquí sí que están
redirigidas las APIS. No existe copia de la tabla de importación en la
sección ".rdata" y la rutina de corrección de APIS tiene que
buscar en la primera ".idata". La IAT también es el inicio de
la primera ".idata".
PALABRAS
FINALES
Salvo que Sony dé un gran giro
(y hace mucho que no lo da) en su protección no deberíais tener ningún
problema al crackear cualquier nueva versión. De echo la única gran
dificultad de esta versión en realidad es corregir las llamadas a las
API'S. Pero ahora el problema ya está resuelto, no?
Saludos y agradecimientos:
- A SkUaTeR y Ni2. Qué locos que
estamos!!!
- A AlCaLiNo y GAMESPACK, por su amistad y soporte técnico
- A Alexia y a Sir_Death por los buenos ratos en el chat
- A R!sc, +Xoanon y Pedro por sus tutoriales (y en general a todos los
que crackean juegos)
- A Karpoff simplemente por TODO
- Y a toda la gente de BCN y Cádiz que me dejo :)
Dudas, erratas y demás a:
mrocean@whiskeykontekila.org
|