| ESTUDIO COLECTIVO DE DESPROTECCIONES Última Actualizacion: 25/10/2001 |
Programa | TrickStyle | W95 / W98 / NT
Descripción | Juego futurista de carreras sobre aerotablas
Tipo | Protección comercial anticopia de CD's
Tipo de Tutorial | [X]Original, []Adaptación, []Aplicación, []Traducción
Url | NO DISPONIBLE
Protección | SECUROM
Dificultad | 1) Principiante, 2) Amateur, 3) Aficionado, 4) Profesional, 5) Especialista
Herramientas | SoftIce 4,Adump,ProcDump,IceDump 6.020,Hex WorkShop
Objetivo | Eliminar Securom
Cracker | Mr.Ocean [WkT!]
Grupo | http://www.whiskeykontekila.org
Fecha | 27 de Febrero de 2001
INTRODUCCION
Lo primero de todo qué es Securom: SecuROM es una protección anticopia para CD-ROM´s de Sony DADC que identifica el CD "original" por un mecanismo de autenticación especial. En el proceso se graba una huella digital electrónica que asigna un número único a cada título de CD-ROM. ¿Cómo detectarlo? Hasta la versión V4 en el directorio raíz del CD se hallan los archivos CMS16.DLL, CMS_95.DLL y CMS_NT.DLL. En las nuevas versiones (como el juego del presente tutorial) estos archivos se encuentran dentro del ejecutable principal. Si lo editas con un editor PE (ProcDump, PEditor) verás que hay dos secciones llamadas ".cms_t" y ".cms_d". Este no es un tutorial precisamente fácil. Yo asumiré que tú tienes unos conocimientos básicos sobre archivos PE, SoftIce, volcados de memoria, etc. También asumo que has leído antes los tutoriales de Securom de Pedro, R!SC y +Xoanon. De todas formas intentaré explicar las posibles dudas-problemas que vayan surgiendo.
AL ATAQUE
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
[ Entrada | Documentos Genéricos | WkT! Web Site ]
[ Todo el ECD | x Tipo de Protección | x Fecha de Publicación | x Orden Alfabético ]
(c) Whiskey Kon Tekila [WkT!] - The Original Spanish Reversers. Si necesitas contactar con nosotros , lee esto antes e infórmate de cómo puedes ayudarnos