Llega el mes de marzo y queremos comenzarlo publicando la solución al reto de flash hacking realizado con motivo del pasado carnaval.
En esta ocasión, el gran Miguel nos ha facilitado en gran detalle el procedimiento que ha seguido, por lo que nos sirve como estupendo solucionario:
Solución al reto "Carnaval" de hackplayers.blogspot.com por Miguel
0. el reto estaba disponible aquí:
http://hackplayers.blogspot.com/2010/02/reto-llega-el-carnaval.html
1. me descargo la película
http://sites.google.com/site/h4ckpl4y3s/carnaval.swf
2. me descargo un descompilador gratuito (demo), en este caso el Trillix 4 de la casa Eltima (de Sothink no me fío después del troyano en el plugin para FF):
http://www.flash-decompiler.com/download/flash_decompiler.exe
3a. solución fácil:
abrir la película con el descompilador posicionarse en el fotograma 4:
-> Clave: samba10
3b. solución "guay" (o "pro" ;)
dado que el código actionscript está protegido (Amayeta?), y no puedo tener garantías de que la clave se altera de alguna manera durante la dinámica del juego, voy a intentar ganar "jugando".
veo que sí se puede tener acceso a ciertas variables, en concreto a una muy interesante llamada "score", donde, supongo, se almacena la puntuación obtenida durante la partida. Está inicializada a 0... qué pasará si la inicializo a un valor más "adecuado" como 990? Vamos a ello:
3b.1 - me bajo un descompresor flash (que no descompilador!) para descomprimir la película (de formato CWS a formato FWS) y poder así acceder directamente al contenido con un editor hexadecimal:
http://www.dcomsoft.com/download/compressor_decompressor.exe
3b.2 - en el Trillix, nos vamos al nodo "Scripts"->"Frame 1"->"Action Tag #1" donde vemos (en el modo "P/0h") el P-Code de inicialización de la variable "score", así como su equivalente en hexadecimal
3b.3 - abrimos la película descomprimida con un editor hexadecimal y localizamos dicha cadena, que procederemos a alterar para establecer nuestro valor deseado de 990. Aquí me encontré una sorpresa: esta variable es del subtipo 6, es decir, float, que es el tipo por defecto que asigna flash (supongo que por ser el más versátil) cuando una variable se inicializa a 0. De todo esto me enteré sobre la marcha, buscando en Internet. Acabé finalmente en:
http://www.opaque.net/~dave/swf5action.html
06 -> double -> 8 bytes -> 64 bits -> posible formato IEEE
lo siguiente fué localizar el formato de representación numérico de ese formato double, para saber "qué poner" en el fichero. Para eso me serví otra vez de Internet, y acabé aquí:
http://en.wikipedia.org/wiki/Double_precision -> que me llevó a...
http://www.binaryconvert.com/convert_double.html
bien, nuestro valor 990 se corresponde a:
http://www.binaryconvert.com/result_double.html?decimal=057057048
es decir: 0x408EF00000000000 que en flash se representa cómo 00 f0 8e 40 00 00 00 00 (invertidos e intercambiados)
hago la sustitución pertinente:
96 10 00 00 73 63 6F 72 65 00 06 00 00 00 00 00 00 00 00 por
96 10 00 00 73 63 6F 72 65 00 06 00 f0 8e 40 00 00 00 00
grabo el archivo editado
3b.4 - ejecuto la película y veo que mi hipótesis era cierta: la puntuación arranca en 990.
A continuación hago 10 puntitos y... ¡tachán! la clave es la misma, pero ahora con mayores garantías :)
3b.5 - si quieres ser "fino fino", puedes volver a comprimir la película, para que se parezca lo más posible a la original: carnaval_hacked.swf.
3b.v2 solución "guay" (o "pro") PERO sin tocar el binario después de haber comentado mi solución 3b. con vmotos, él me propuso que lo hiciera de otra manera: sin tocar el binario y accediendo directamente a memoria. Me entró la curiosidad y estuve buscando soluciones. Encontré una que parecía viable:
http://www.raymond.cc/blog/archives/2007/02/27/how-to-cheat-and-hack-flash-based-games/
lo que me llevó a http://cheatengine.org/
pero después de probar... no conseguía que funcionase.
seguí leyendo y el caso es que en el comentario 321 de la entrada original (si, más de 325 comentarios!!), se explica que eso no funciona y por qué: a partir de Flash 8, las variables son reposicionadas en memoria después de cada alteración, así que "Cheat Engine" NUNCA funcionaría.
pero entonces vmotos me dió una nueva clave: me habló de la herramienta que él tenía en mente para la solución: "Atlas". Fué al ver los archivos de configuración de "Atlas" cuando me di cuenta: ¡¡el control ActiveX de flash!!
Resulta que entre la lista de métodos públicos que ofrece el interfaz del control ActiveX del reproductor Shockwave-Flash, se encuentran dos que son justamente lo que andamos buscando: GetVariable() y SetVariable. Mediante estos métodos podemos obtener o establecer el contenido de cualquier variable dentro de la película que estemos manejando. Con este dato, y sabiendo de antemano el nombre de las variables (ver paso 3b.2), el resto fue coser y cantar: me creé una pequeña aplicación para la ocasión (en .NET C#) que importa el componente ActiveX de flash y que permite cargar una película y manejar sus variables. Sólo tienes que cargar "carnaval.swf", arrancar la
partida y ya puedes manipular las variables "score" y "time" a voluntad, tanto leerlas como escribirlas. Fácil, ¿verdad?
un apunte final: para esta solución, no hubiera sido estrictamente necesario descompilar la película para encontrar los nombres de las variables. Bastaría con descomprimirla (paso 3b.1) y buscar cadenas de texto en ella, con un editor o, mejor, con una herramienta tipo BinText (podéis encontrarla aquí: http://www.foundstone.com/us/resources/proddesc/bintext.htm), ya que sus nombres se almacenan tal cual y son legibles a simple vista; sería cuestión de un poco de habilidad y paciencia.
3c. Solución "ultrapro": ésta sería saltarse la protección de la película (creo que es la de Amayeta: http://www.amayeta.com/) y acceder a todo el código Actionscript.
Esta opción está fuera de mi alcance. Parece que hay una compañía de software capaz de saltarse esta protección (http://www.buraks.com/asv/), aunque la versión demo es demasiado antigua y la buena es de pago. También encontré a un programador que tiene un software (hecho en JAVA!) que parece funcionar, aunque la demo es "enrevesada" y está limitada (http://www.swf-reader.com). En cualquier caso, espero que no contemplases como opción el uso de software "conseguido ilegalmente"... (innecesario por otra parte ;)
4. Conclusiones
La primera versión del juego era demasiado fácil, al permitir el menú
contextual -> avanzar, avanzar, avanzar y listo :)
La segunda versión del juego, solucionado ese "agujero", sigue siendo bastante fácil igualmente, ya que la protección del código no enmascara ni oculta la clave.
Me he "autoampliado" la dificultad casi sin quererlo, de aquí la solución 3b.
En cualquier caso, ha sido entretenido y te agradezco el trabajo que supone.
PD: acabo de ver en la actualización de tu blog, que justamente buscabas la solución 3.b... jejeje.
PD2: gracias por hacerme recapacitar en la solución 3.b.v2, que aunque la conocía ya, no había reparado en ella.
Conclusiones finales por Hackplayers
Impresionante el análisis y la solución de Miguel, ¿verdad?. Nos deja poco más que hablar :) Simplemente, yéndonos al orígen, decir que el flash del reto se basaba en el tutorial en http://www.layoutgalaxy.com/html/htmnewletter47-page1.htm.
Descargando y modificando el recurso fla disponible, se creó una capa llamada ‘Superado’ y añadió el Fotograma clave 4
Posteriormente, se modificó un trigger para que cuando la puntuación alcanzara o superara los 1000 globos explotados fuera a ese frame, superando así el reto.
El resto fue modificar simplemente el 'look and feel' y añadir un nivel de protección básico con Amayeta.
Como veis, la sencillez en la elaboración del reto se traduce casi equitativamente en el número de posibilidades para solucionarlo.
Si bien y como comentaba primero Gryphus y luego Miguel, la primera versión del flash permitía solucionarlo directamente desde el navegador con el botón derecho y avanzando frames.
Para solventar esto, simplemente bastó con añadir en el primer frame "Stage.showMenu = false;" en lugar de "fscommand("showmenu",false);". La explicación la podéis encontrar en http://foros.cristalab.com/problemas-con-fscommandshowmenuboolean-t16109/.
Una vez solventado este ‘problema’, el reto siguió siendo relativamente sencillo:
1. es posible avanzar frames con otro reproductor
2. se puede decompilar el flash y obtener directamente la contraseña, o entretenernos un poco más obteniendo los nombres de las variables y modificarlas posteriormente con herramientas como el reproductor de Miguel o, más sencillo aún, poniéndolo directamente en el navegador como planteaba Arán: javascript:document.embeds[0].SetVariable("score","1000");
3. podemos también optar por no tocar ni siquiera el flash con herramientas como Atlas o Flash Variable Editor v1.8, que nos sacarán las variables que nos interesan a través de fuerza bruta y/o diccionario también con el método GetVariable (la variable del flash del reto es fácilmente adivinable: score) para modificarlas después con SetVariable.
Explotamos un globo más y…
En resumen podemos concluir que, sin utilizar el Cheat Engine, hemos visto y aprendido otras posibilidades de hacer trampas y ‘destripar’ un flash.
En un futuro volveremos a la carga con otro reto de flash hacking más complicado, por ejemplo intentando prohibir la ejecución del flash fuera del site, con un mayor nivel de ofuscación del Actionscript y con todo aquello ‘extra’ que se nos ocurra ;-) Pero eso será más adelante porque ya os anticipamos que el próximo reto será (si Alberto se anima) un crackme sencillito para sacar una clave 'hardcoded'.
Ganadores del reto
Finalmente, daros las gracias a todos los que habéis resuelto o intentado resolver el reto, especialmente a aquellos que nos habéis mandado vuestros comentarios y soluciones y, sobretodo y cómo no, a los ganadores del reto del carnaval, que han sido:
1. Miguel
2. Arán
3. Mario
A ellos lo único que podemos darles :-P, ¡nuestra admiración y más sincera enhorabuena!
En esta ocasión, el gran Miguel nos ha facilitado en gran detalle el procedimiento que ha seguido, por lo que nos sirve como estupendo solucionario:
Solución al reto "Carnaval" de hackplayers.blogspot.com por Miguel
0. el reto estaba disponible aquí:
http://hackplayers.blogspot.com/2010/02/reto-llega-el-carnaval.html
1. me descargo la película
http://sites.google.com/site/h4ckpl4y3s/carnaval.swf
2. me descargo un descompilador gratuito (demo), en este caso el Trillix 4 de la casa Eltima (de Sothink no me fío después del troyano en el plugin para FF):
http://www.flash-decompiler.com/download/flash_decompiler.exe
3a. solución fácil:
abrir la película con el descompilador posicionarse en el fotograma 4:
-> Clave: samba10
3b. solución "guay" (o "pro" ;)
dado que el código actionscript está protegido (Amayeta?), y no puedo tener garantías de que la clave se altera de alguna manera durante la dinámica del juego, voy a intentar ganar "jugando".
veo que sí se puede tener acceso a ciertas variables, en concreto a una muy interesante llamada "score", donde, supongo, se almacena la puntuación obtenida durante la partida. Está inicializada a 0... qué pasará si la inicializo a un valor más "adecuado" como 990? Vamos a ello:
3b.1 - me bajo un descompresor flash (que no descompilador!) para descomprimir la película (de formato CWS a formato FWS) y poder así acceder directamente al contenido con un editor hexadecimal:
http://www.dcomsoft.com/download/compressor_decompressor.exe
3b.2 - en el Trillix, nos vamos al nodo "Scripts"->"Frame 1"->"Action Tag #1" donde vemos (en el modo "P/0h") el P-Code de inicialización de la variable "score", así como su equivalente en hexadecimal
3b.3 - abrimos la película descomprimida con un editor hexadecimal y localizamos dicha cadena, que procederemos a alterar para establecer nuestro valor deseado de 990. Aquí me encontré una sorpresa: esta variable es del subtipo 6, es decir, float, que es el tipo por defecto que asigna flash (supongo que por ser el más versátil) cuando una variable se inicializa a 0. De todo esto me enteré sobre la marcha, buscando en Internet. Acabé finalmente en:
http://www.opaque.net/~dave/swf5action.html
06 -> double -> 8 bytes -> 64 bits -> posible formato IEEE
lo siguiente fué localizar el formato de representación numérico de ese formato double, para saber "qué poner" en el fichero. Para eso me serví otra vez de Internet, y acabé aquí:
http://en.wikipedia.org/wiki/Double_precision -> que me llevó a...
http://www.binaryconvert.com/convert_double.html
bien, nuestro valor 990 se corresponde a:
http://www.binaryconvert.com/result_double.html?decimal=057057048
es decir: 0x408EF00000000000 que en flash se representa cómo 00 f0 8e 40 00 00 00 00 (invertidos e intercambiados)
hago la sustitución pertinente:
96 10 00 00 73 63 6F 72 65 00 06 00 00 00 00 00 00 00 00 por
96 10 00 00 73 63 6F 72 65 00 06 00 f0 8e 40 00 00 00 00
grabo el archivo editado
3b.4 - ejecuto la película y veo que mi hipótesis era cierta: la puntuación arranca en 990.
A continuación hago 10 puntitos y... ¡tachán! la clave es la misma, pero ahora con mayores garantías :)
3b.5 - si quieres ser "fino fino", puedes volver a comprimir la película, para que se parezca lo más posible a la original: carnaval_hacked.swf.
3b.v2 solución "guay" (o "pro") PERO sin tocar el binario después de haber comentado mi solución 3b. con vmotos, él me propuso que lo hiciera de otra manera: sin tocar el binario y accediendo directamente a memoria. Me entró la curiosidad y estuve buscando soluciones. Encontré una que parecía viable:
http://www.raymond.cc/blog/archives/2007/02/27/how-to-cheat-and-hack-flash-based-games/
lo que me llevó a http://cheatengine.org/
pero después de probar... no conseguía que funcionase.
seguí leyendo y el caso es que en el comentario 321 de la entrada original (si, más de 325 comentarios!!), se explica que eso no funciona y por qué: a partir de Flash 8, las variables son reposicionadas en memoria después de cada alteración, así que "Cheat Engine" NUNCA funcionaría.
pero entonces vmotos me dió una nueva clave: me habló de la herramienta que él tenía en mente para la solución: "Atlas". Fué al ver los archivos de configuración de "Atlas" cuando me di cuenta: ¡¡el control ActiveX de flash!!
Resulta que entre la lista de métodos públicos que ofrece el interfaz del control ActiveX del reproductor Shockwave-Flash, se encuentran dos que son justamente lo que andamos buscando: GetVariable() y SetVariable. Mediante estos métodos podemos obtener o establecer el contenido de cualquier variable dentro de la película que estemos manejando. Con este dato, y sabiendo de antemano el nombre de las variables (ver paso 3b.2), el resto fue coser y cantar: me creé una pequeña aplicación para la ocasión (en .NET C#) que importa el componente ActiveX de flash y que permite cargar una película y manejar sus variables. Sólo tienes que cargar "carnaval.swf", arrancar la
partida y ya puedes manipular las variables "score" y "time" a voluntad, tanto leerlas como escribirlas. Fácil, ¿verdad?
un apunte final: para esta solución, no hubiera sido estrictamente necesario descompilar la película para encontrar los nombres de las variables. Bastaría con descomprimirla (paso 3b.1) y buscar cadenas de texto en ella, con un editor o, mejor, con una herramienta tipo BinText (podéis encontrarla aquí: http://www.foundstone.com/us/resources/proddesc/bintext.htm), ya que sus nombres se almacenan tal cual y son legibles a simple vista; sería cuestión de un poco de habilidad y paciencia.
3c. Solución "ultrapro": ésta sería saltarse la protección de la película (creo que es la de Amayeta: http://www.amayeta.com/) y acceder a todo el código Actionscript.
Esta opción está fuera de mi alcance. Parece que hay una compañía de software capaz de saltarse esta protección (http://www.buraks.com/asv/), aunque la versión demo es demasiado antigua y la buena es de pago. También encontré a un programador que tiene un software (hecho en JAVA!) que parece funcionar, aunque la demo es "enrevesada" y está limitada (http://www.swf-reader.com). En cualquier caso, espero que no contemplases como opción el uso de software "conseguido ilegalmente"... (innecesario por otra parte ;)
4. Conclusiones
La primera versión del juego era demasiado fácil, al permitir el menú
contextual -> avanzar, avanzar, avanzar y listo :)
La segunda versión del juego, solucionado ese "agujero", sigue siendo bastante fácil igualmente, ya que la protección del código no enmascara ni oculta la clave.
Me he "autoampliado" la dificultad casi sin quererlo, de aquí la solución 3b.
En cualquier caso, ha sido entretenido y te agradezco el trabajo que supone.
PD: acabo de ver en la actualización de tu blog, que justamente buscabas la solución 3.b... jejeje.
PD2: gracias por hacerme recapacitar en la solución 3.b.v2, que aunque la conocía ya, no había reparado en ella.
Conclusiones finales por Hackplayers
Impresionante el análisis y la solución de Miguel, ¿verdad?. Nos deja poco más que hablar :) Simplemente, yéndonos al orígen, decir que el flash del reto se basaba en el tutorial en http://www.layoutgalaxy.com/html/htmnewletter47-page1.htm.
Descargando y modificando el recurso fla disponible, se creó una capa llamada ‘Superado’ y añadió el Fotograma clave 4
Posteriormente, se modificó un trigger para que cuando la puntuación alcanzara o superara los 1000 globos explotados fuera a ese frame, superando así el reto.
El resto fue modificar simplemente el 'look and feel' y añadir un nivel de protección básico con Amayeta.
Como veis, la sencillez en la elaboración del reto se traduce casi equitativamente en el número de posibilidades para solucionarlo.
Si bien y como comentaba primero Gryphus y luego Miguel, la primera versión del flash permitía solucionarlo directamente desde el navegador con el botón derecho y avanzando frames.
Para solventar esto, simplemente bastó con añadir en el primer frame "Stage.showMenu = false;" en lugar de "fscommand("showmenu",false);". La explicación la podéis encontrar en http://foros.cristalab.com/problemas-con-fscommandshowmenuboolean-t16109/.
Una vez solventado este ‘problema’, el reto siguió siendo relativamente sencillo:
1. es posible avanzar frames con otro reproductor
2. se puede decompilar el flash y obtener directamente la contraseña, o entretenernos un poco más obteniendo los nombres de las variables y modificarlas posteriormente con herramientas como el reproductor de Miguel o, más sencillo aún, poniéndolo directamente en el navegador como planteaba Arán: javascript:document.embeds[0].SetVariable("score","1000");
3. podemos también optar por no tocar ni siquiera el flash con herramientas como Atlas o Flash Variable Editor v1.8, que nos sacarán las variables que nos interesan a través de fuerza bruta y/o diccionario también con el método GetVariable (la variable del flash del reto es fácilmente adivinable: score) para modificarlas después con SetVariable.
Explotamos un globo más y…
En resumen podemos concluir que, sin utilizar el Cheat Engine, hemos visto y aprendido otras posibilidades de hacer trampas y ‘destripar’ un flash.
En un futuro volveremos a la carga con otro reto de flash hacking más complicado, por ejemplo intentando prohibir la ejecución del flash fuera del site, con un mayor nivel de ofuscación del Actionscript y con todo aquello ‘extra’ que se nos ocurra ;-) Pero eso será más adelante porque ya os anticipamos que el próximo reto será (si Alberto se anima) un crackme sencillito para sacar una clave 'hardcoded'.
Ganadores del reto
Finalmente, daros las gracias a todos los que habéis resuelto o intentado resolver el reto, especialmente a aquellos que nos habéis mandado vuestros comentarios y soluciones y, sobretodo y cómo no, a los ganadores del reto del carnaval, que han sido:
1. Miguel
2. Arán
3. Mario
A ellos lo único que podemos darles :-P, ¡nuestra admiración y más sincera enhorabuena!
Comentarios
Publicar un comentario