1 - Introduccion

Bueno gente, aquí daré comienzo a este pequeño cursillo orientado a aquellas personas que tienen deseos de iniciarse en el mundo del crack , no pretende ser el tutorial de oro, pero si aclarar de forma sencilla ciertos aspectos que lograran clarificar la cuestión, y ayudarnos a entender de que se trata el tema.

Bueno lo primero que haré será hablar del lenguaje Assembler. Siempre que querramos crackear un programa lo ke deberemos hacer será desensamblarlo, existen varias herramientas para lograr este objetivo, como el famoso Softice o el OllyDBG (mi favorito ;) y en el que basaré este curso).

El Assembler (ASM de ahora en más) es un idioma de baja definición, es decir, que se halla , más cerca del lenguaje de las computadoras que el c/c++/VB y otros por ejemplo. Muchos se deberán estar preguntando a esta altura, si tienen ke estudiar tooooodo un lenguaje para poder crackear un simple programa, la respuesta es ke no (obviamente siempre es mejor acrecentar nuestros conocimientos ;) ) , pero lo cierto es ke solo es necesario usar un poko nuestro sentido común y conocer las instrucciones que nos interesan.

Entrando ya estrictamente en ASM, les recomiendo desensamblar algún programilla para ver el aspecto, haré una reseña y explicaré nada más las ordenes que pueden resultar de nuestro interés.Cuando desensamblemos el programa obtendremos algo como esto:

Aquí podemos ver todas las instrucciones que la máquina recibe por parte del programa.

Entre estas veremos algunas que son de suma importancia para nosotros que son las instrucciones CALL,JNZ,JE,TEST,CMP. Antes de especificarlas remarcaré que este programa se maneja en sistema hexagesimal de numeración.

  • CALL: Esta orden lo que hace es llamar a otra función la que realizará alguna operación, devolviendo posteriormente algún valor al programa.
  • TEST/CMP: Esta orden lo que realiza es una comparación entre dos valores, o de un valor con si mismo puede ser también, devolviendo un resultado a esta comparación 0 (FALSO) o 1 (VERDADERO).
  • JNZ: Esta orden realizará un salto hacia otra parte del programa en caso de que los valores chekeados sean distintos.
  • JNE: Esta orden realizará un salto hacia otra parte del programa en caso de que los valores chekeados sean iguales.
  • JMP: Esta orden aunque olvidé mencionarla arriba, es también importante, lo que hace es realizar un salto si o si, independientemente de que se compare un valor o no, o del resultado de una comparación.

    Básicamente esas serán las instrucciones que nos ocuparán y serán de nuestro interés, les recomiendo que lean el curso de ASM DESDE CERO de PABLO BARRON , que no es muy largo y es bastante completo y entendible respecto al tema, aunque si entendieron lo de arriba les bastará para comenzar.

    Les aclaré también que el OllyDBG es un debuger, es decir un debugeador, lo que hace aquí es hacer correr el programa para que podamos investigarlo mejor, igualmente entenderán mejor los que les quise decir si simplemente cogen el Olly , desensamblan algún programa y selecciones la opción Debug-->RUN, esto nos permitirá por decirlo de alguna manera, trabajar con el programa "en vivo" para poder ver como se comporta frente a ciertos estímulos que podamos ejercer.

    Bueno gente espero que les haya resultado interesante, y en la próxima entrega comenzaremos a trabajar sobre el Olly y sus funciones, éste ha sido un breve y relajado comienzo pero no se confien que ya tendrán que usar más adelante ese cerebro dentro de sus cabezas ;). Espero que les haya gustado.

2. Funcionamiento del OllyDBG

Bueno como había prometido, aquí comenzaremos a investigar el funcionamiento del OllyDBG, para llevar adelante nuestros fines. Como ya había explicado este programa es un desensamblador debugeador, que a mi gusto es de lo mejor por el sencillo interfaz intuitivo que tiene.

Como me imagino que ya habrás bajado el programa, y habrás probado lo que te dije el capítulo anterior, no???? jajaja, si que eres vago. Bueno ha llegado la hora asi que bájate el programa e instálalo de una vez ;). Bueno comenzaremos descargando algún programa, busquen algún crackme en lo posible, para empezar a experimentar. Incluiré ahora un gráfico para utilizarlo para tomar referencias, para explicar lo que estamos viendo.

<< Texto nuevo >>Como podrán notar, si es que no se han quedado ciegos de pasar mucho tiempo delante de la PC ;) , he remarcado las diferentes areas del programa con distintos colores para poder distinguirlas y de esta manera poder explicar más sencillamente a qué hacen referencia.

ROJO: En este lugar podemos ver la dirección que se le ha asignado a la orden, esto nos servirá para poder orientarnos dentro del programa, y una vez ubicado el de nuestro interés, simplemente anotándolo no tener que repetir todo el proceso una y otra vez.

AZUL: Es el valor hexagesimal. Este es un sistema de numeración en base 16, que utiliza hasta el número 9 luego del cual comienza a utilizar letras hasta completar la escala, para que lo vean más claramente incluiré una tabla de conversión de los primeros valores para que lo vean: DEC-->1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ....... HEX-->1 2 3 4 5 6 7 8 9 A B C D E F 10 .......

VERDE: Aquí observaremos el area donde se hallan las órdenes en lenguaje ASM , como anteriormente he dicho para nuestros fines no será necesario conocerlas todas, aunque si muy útil para entender la rutina que realiza el programa, especialmente cuando nos avoquemos a obtener un serial.

NARANJA: Se verán los registros, para qué nos interesa eso?, a diferencia de otros lenguajes en ASM no se pueden definir variables indefinidas, si no que los valores se transpasan entre las que pueden ver en el gráfico, por lo tanto podremos ver allí el valor que toma, que como me imagino que ya habrán pensado en algún momento será nuestro objetivo el que se halle allí almacenado.
AMARILLO: Podremos ver la "Dump" o basura en castellano, he leído en repetidas ocasiones que es útil personalmente no me ha sido de gran ayuda hasta ahora, pero nunca se sabe por cierto.

Debemos saber que estos programas llaman a ciertas funciones que ya se hallan predefinidas en los módulos, para clarificar esto hagan lo siguiente en el programa que tienen debugeado en el OllyDBG, hagan click con el botón derecho del mouse y si posan sobre al opción VIEW, se desplegarán todos los modulos que se utilizan durante el programa. Para ver con mayor exactitud cuales son las funciones que se llaman (API para decirlo más concretamente), haremos de nuevo click con el botón derecho pero iremos a SEARCH FOR... , y una ves posados allí a NAME (LABEL) IN CURRENT MODULE, además de verlas se nos especificará la dirección la sección y el tipo que es si de importación o de exportación.

Otra opción que nos ocupará será SERCH FOR.... ---> All REFERENCES TEXT STING , que como imagino ya habrán descubierto por su nombre hace que se busquen todas las cadenas de texto existente dentro del módulo.

Si ampliamos la solapa DEBUG veremos varias opciones, a continuación lo que haré será, explicar qué opciones nos ocuparán y sus respectivos atajos para poder trabajar más cómodamente en nuestro ordenador, pudiendo independizarnos relativamente del mouse durante el manejo del programa para hacerlo de forma más agil, si bien al comienzo tomará más tiempo, con el acostumbramiento agilizará mucho el proceso. Estas son:

VIEW--->Breakpoint // DEBUG--->RUN // DEBUG--->Restart // DEBUG--->Step Intro // DEBUG--->Step Over //

Estas serán principalmente las opciones que nos ocuparán, existen otras útiles, pero las veremos más adelante cuando sean necesarias.

BREAKPOINT: Antes que nada explicaré lo que significa esto. Como el nombre lo indica es un punto de ruptura, es decir, cuando apliquemos un breakpoint a alguna parte del programa tendrá como resultado que la ejecución del mismo se detendrá allí. Existen varios tipos de breakpoint, utilizaremos el toogle cuya tecla de atajo en F2 , y lo que hace es poner un punto break fijo, a diferencia de otro caso como podría ser el breakpoint que se ejecuta solo una vez o de memory access, etc. Esta opción concretamente en sí, nos permitirá ver todos los breakpoint utilizados sobre el programa para poder visualizarlos más fácilmente y poder de esta manera manipularlos.

RUN: Como su nombre lo indica esto hará que corra el programa, su tecla de atajo es F9.

Restart: Esta opción limpiará la pantalla y desensamblará el programa de nuevo, su tecla de atajo es Ctrl+F2.

Step Over: Esta opción avanzará paso por paso dentro de las ordenes de ejecución del programa, nos servirá para realizar lo que se llama proceso de traceado o simplemente "tracear". Cuando traceamos lo que estamos haciendo es seguir paso por paso la ejecución del programa pero no simplemente para visualizarlo, si no por ejemplo si el programa realiza una comparación y luego hay un salto lo que hará es según el resultado tomar el salto o no y en caso de tomarlo arrojarnos a la zona del programa hacia donde estaba orientado dicho salto. Su tecla de Atajo es F8.

Step Into: Esta es similar a la anterior con la diferencia de que con esta ingresaremos en las llamadas (CALL), es decir podremos ver el proceso que realiza esta. Por ejemplo en un call se da la generación de una frase, si seguimos con F8 (recordemos, se los acabo de decir ;) , que es para Step Over) , pasaremos al siguiente paso viendo el resultado, sin entrar en la llamada, en cambio con F7 (tecla de atajo de Step Into) , ingresaremos al proceso que se realiza dentro de la llamada. Debemos ser muy cuidadosos cuando utilizamos esta opción al treacear, ya que algunas llamadas nos llevan a otro módulos (recordemos las API) , lo que podría despistar completamente al nuevo usuario.

Conjuntamente con esta herramiento aprovecharé la oportunidad para referirme al W32Dasm. Esta herramienta es a mi entender un desensablador pero tiene la paticularidad que pondrá las cosas más claras para poder realizar una mejor lectura del funcionamiento del programa, ya que dentro del mismo desensamblado se hace la referencia a desde que lugares son llamadas las funciones y por ejemplo en ciertos programas las referencias a las cadenas de texto son visibles desde este y no desde el olly por ejemplo. Les recomiendo simplemente que se lo descarguen y le echen una ojeada , con lo explicado para el OllyDBG no tendrán el menor problema para entender el funcionamiento del mismo.

3. El primer programa

 Bueno gente, siendo consciente de la impaciencia que los ocupa, y a riesgo de aburrirnos comenzaremos en este capítulo a acercarnos al primer programa :) .El objetivo será un crackme V1.0 de cruehead que obtuve con el curso de Ricardo Narvaja (muy recomendado para aquellos que se decidan por el Softice en lugar del OllyDBG), creo que el autor no se molestará, ya que este curso es con fines educativos y siempre es bueno aprender ;).

Lo primero que haremos será, claro está, registrarnos, al menos que seas de esas personas que se ganan la lotería me imagino que es altamente probable que te salte el siguiente mensaje "No Luck there,mate!". Entonces tomaremos lápiz y papel y anotaremos este mensaje que es el que nos dá el programa cuando nos registramos incorrectamente. Ahora pensemos lo siguiente, hemos ingresado un serial y nos ha retornado un mensaje donde nos dice que el serial es incorrecto, momento... cómo diablos lo sabía?, luego de pensarlo un rato llegamos a la conclusión lógica, nuestro serial en algún momento ha tenido que ser comparado con el primero para que el crackme llegue a saber que no era válido. Entonces nos queda después de pensar un poco más el siguiente esquema:

El programa captura nuestro serial--->lo compara con el original--->llego a la conclusión que no es igual--->Salta a la zona del Mensaje de error.

Escribo este esquema en mi hoja justo debajo del mensaje de error y en mi hoja miro toda la información que junte y me queda algo como lo siguiente:

Nombre del Programa: CrackMe v1.0 Autor:Cruehead Msg de Error: "No Luck there,mate! El programa captura nuestro serial--->lo compara con el original--->llego a la conclusión que no es igual--->Salta a la zona del Mensaje de error.

Me quedo un rato mirando la hoja mientras fumo un cigarrillo, y se me enciende la lamparita ;), qué pasaría si pudiese evitar que el programa luego de comparar los serial saltara a la zona de error... mmmmm, entro al Wdasm y lo desensamblo y luego de borrar el salto que hay después de la comparación...BUUUUUUUUUUUUUUUUUU, lo único que he conseguido es que el programa se me cuelgue al intentar registrarme, evidentemente la cosa es por ahí pero esa no es la solución. Pienso un poco más y digo, y si cambio el salto para que salte si son iguales, por lo tanto si son diferentes saltaría a la parte del programa donde estaremos registrados, interesante , interesante....

Desensamblo mi objetivo con el Wdasm y busca las referencias de cadenas de texto (el botón de la derecha de todo al lado del de print, "String Data References") y veo algo así:

O por dios! si está allí ni más ni menos que el mensaje de error que salta al ingresar un serial falso, mmmm... haremos doble click sobre él a ver donde está y me arroja a la posición de la memoria 004013B4, así que aquí está la zona de "mal chico". Apuntamos está dirección en nuestra hoja como más nos guste llamarla, yo por ejemplo puse, Posición de Msg de Error 004013B4. Ahora a continuar... comienzo a mirar para arriba para ver desde donde han llamado al mensaje de error, paso por el lugar que hace referencia a una string que dice "No Luck!", me huele que busca despiertarno, seguiremos con lo que tenemos hasta ahora, seguimos subiendo un poco más y veremos algo así:

Referenced by a (U)nconditional or (C)onditional Jump at address : 0040138B (C)

Esto quiere decir que la zona de error fue llamada desde esa dirección, así que como con todo descubrimiento, a la hojita. Inmediatamente iremos a esa dirección a ver que diablos ocurre por esos lados. Vamos en las opciones del Wdasm a goto--->Goto code location o tocamos Shift+F12 e iremos a esa dirección. Nos deposita allí y estamos sobre una orden que dice Jb , y la zona de la memoria de donde venimos . Bueno este Jb ( no no, no está hablando de la marca de whisky, significa Jump if Below), es muy bonito pero no lo queremos dentro de nuestro programa ya que nos está llevando donde no queremos ir. Ahora que tenemos la dirección cerramos el Wdasm y nos vamos al OllyDBG y desensamblamos el Crackme. Hacemos click sobre la pantalla ya vamos a GO TO--->Expression, e ingresamos a la dirección de la memoria que queremos ir. Pero que le haremos a este pobre JB , lo modificaremos para que salte si los serial son iguales por lo tanto si son diferentes....ejemmm , pensemos que pasará. Nos situamos sobre el salto y hacemos un click con el botón derecho del mouse y vamos a la opción assemble.

Aquí modificamos el JB por un JE (Las modificaciones realizadas en ollyDBG son provisorias, más adelante veremos como hacerlas permanentes), asi saltará si son iguales y vamos a Debug--->RUN e intentamos registrarnos Y........BUUUUUUUUUUU.... agua, no ha pasado nada ese tedioso mensaje sigue en el mismo lugar, pero por más pesada que sea la piedra siempre hay una forma de moverla ;), así que volvemos al Wdasm y volvemos a las cadenas de texto y vemos el mensaje de error, hacemos doble clic y estamos en la misma zona de la memoria de siempre, si le damos otro doble click sobre el mensaje.... O DIABLOS, está en otra parte también el mensaje o sea que el programa solo buscaba despistarme....maldito, caí en la trampa pero te he pillado igual. Esta vez caemos sobre 401370, asi que a la hoja y lo anotamos y escribimos que lo anterior era un engaño para recordarlo. Y ahora igual que antes nos interesa ver desde donde se llama esta posición y vemos que es llamada desde 401245, así que anotamos y allá nos vamos. A ver que hoy, justo encima de esa posición vemos un JE siguiendo a una comparación, demasiado sospechoso para mi gusto jeje. Así que anotamos la posición del JE 401243 y me posiciono encima del salto y lo sigo con el botón Jump To a ver a donde nos lleva. Si alguien se molestó en mirar bien y no se dedica unicamente a hacer lo que aquí les digo ;) habrá notado que en las referencias de cadenas había un mensaje que decía "Great Work,mate!" , y si alguno milagrosamente por curiodad le hizo doble click y ya por gracia divina miró desde donde era llamado.... BINGOOOOOOOOOOOO estamos en el mismo lugar o sea que ESE es nuestro salto muchachos.

Ahora entonces nos vamos a toda velocidad al OllyDBG y nos posicionamos sobre el salto y en assemble lo cambiamos por un JNE , para que salten si no son iguales y le damos RUN (F9) e intentamos registrarnos y lo tenemos nos sale un mensaje de felicitaciones :). Lo hemos logrado. Bueno espero que se hayan divertido, ha sido un capítulo bastante fructifero, ya hemos crackeado nuestro primer programa. Escríbanme para decirles si les ha gustado, cualquier duda o sugerencia.

4. Cómo crackear el mismo Crackme

En este capítulo veremos como crackear el mismo Crackme, pero si no pudiésemos ver las string references, es decir, imagínense que cuando lo desensamblamos con el wdasm o miramos las referencias de texto en el OllyDBG y no encontramos nada, qué hacemos?. Bueno para resolver esta preguntra, aclararemos lo siguiente, además de poder situar lo Breakpoint en ciertos lugares del programa como hemos hecho en el capítulo anterior, existen las llamadas funciones API, que son funciones que existen en Windows y el programa utiliza para no escribir funciones que ya puede utilizar tomándolas de otro lado.

La idea será utilizar estas funciones para que nos guíen a la zona deseada, para poder encontrar el salto condicional que deseamos cambiar. En este caso la función API que utilizaremos es una llamada MESSAGEBOXA , que es la que dibuja las ventanitas con mensajes, así que pensaremos que si podemos ubicar cuando el programa llama a esta función para dibujarnos la ventanita de NO LUCK THERE MATE, podremos ubicar desde donde se realiza la comparación, ya que antes de dibujarla checkeará si nuestro serial es correcto.

Dicho esto, ponemos manos a la obra. Como siempre lo primero que haremos será irnos a nuestro querido OllyDBG, y desensamblaremos el Crackme. Hecho esto le daremos a F9 (para que corra el debugeador y se ejecute el programa), y luego haremos click derecho sobre el programa desensamblado e iremos a SEARCH FOR--->Name (label) in current module, o simplemente pulsaremos CTRL+N, lo que es equivalente y obtendremos algo como lo siguiente.

Bueno aquí estamos delante de los módulos que se utilizan. Lo que haremos será localizar el que nos interesa MESSAGEBOXA. Aquí veremos una diferencia, mientras que con el Softice bastará poner BPX MESSAGEBOXA, para poner un breakpoint en la función, aquí lo que haremos será seguirla para ver desde donde se utiliza, ya que con un Breakpoint no llegaremos a nada :) .

Entonces lo siguiente, ubicada la función nos situaremos sobre ella y le daremos al botón derecho del mouse, y lo que nos ocupa a nosotros es ver desde qué lugares es llamada, así que iremos a la opción FIND REFERENCES TO IMPORT y allí nos salen 4 direcciones 40135C, 401378, 4013BC, 40143A .

Si hacemos doble click sobre la primera (para que nos lleve al programa desensamblado, a la posición desde donde se llama) veremos que se trata de la ventana de que hemos ingresado el serial correcto, es claro que esta no nos interesa, ya que si ingresamos el serial incorrecto no utilizará dicho mensaje :p .

Así que seguimos, si hacemos doble click sobre el segundo y el tercero, veremos que ambos hacen referencia a la ventanita de error, mmmmm... por aquí debe ser el asunto. Pero miro y digo "son dos", algo no está bien, y es allí donde usando la memoria me acuerdo que ya en el capítulo anterior, el programa me había engañado llevándome por un camino falso, así que procederé con cautela.

Hago doble click sobre la que se llama desde 401378 y debajo de la posición en la que me arroja, hay un RETN (return, es decir que utiliza la función y me devuelve mediante esa orden, debajo de la posición desde la cual fue llamada para dibujar la ventana), así que pondremos con F2 un Breakpoint en ese RETN, he intento registrarme, esta vez lo hemos pillado, ya que el programa nos arroja el error inmediatamente luego de intentar registrarnos, lo que nos está diciendo que nuestro Breakpoint no ha detenido el programa, por lo que el programa no utiliza la zona donde pusimos con F2 el Break, por lo tanto este es el mensaje de error que nos había engañado en el capítulo pasado.

Así que sabiendo esto hacemos doble click sobre 4013BC, e igual que con el anterior vemos que debajo de donde nos arroja, hay un RETN, al que le pondremos un Breakpoint , y luego intentaremos registrarnos.

En esta ocasión el programa se ha detenido ;), así que le daremos a F8 para que nos devuelva, y nos arroja sobre la posición 401232, hasta aquí vamos bien pero, mmmm.... este lugar me resulta familiar,aaaaaa....como no? si no es más ni menos que donde la otra vez habíamos hallado el salto a modificar la última vez jajaja ;), si miramos 5 y 6 órdenes hacia abajo respectivamente veremos la comparación y el salto, modificaremos el salto igual que la vez anterior posicionándonos sobre él , le damos a la barra espaciadora, para que nos lleve a la opción Assemble y allí modificamos el salto JE por un JNE, y ... BINGO , lo hemos logrado una vez más y no hemos precisado las referencias de texto ;).

5. Repaso General

Bueno hasta ahora nos venimos divirtiendo después de dos capítulos de ejercitación, pero llegó la hora de hacer un repaso general ;).

Cap 1: En este capítulo hemos aprendido los conceptos generales sobre el lenguaje Assembler, CALL,JNZ,JE,TEST,CMP. Aprendiendo la principal diferencia entre Jnz y Je, para identificar saltos que nos llevan a la zona del programa a la que no queremos que nos arroje

Cap 2: Manejo del OllyDBG, e instrucciones básicas para su funcionamiento.

Cap 3: Manipulación y crackeo de nuestro primer programa.

Cap 4: Forma alternativa de capturación del salto, que nos llevaba a la zona no deseada del programa.

Refrescado el contenido anterior, comenzaremos este capítulo. Como primer paso lo que haré es recordarles que en el capítulo anterior la forma alternativa (en realidad es mejor acostumbrarse a esta para prescindir de las String References), consistía en ubicar un Breakpoint en MessageBoxA, donde se generaba el cartel de error; a continuación les haré un listado de otros lugares donde pueden situar los breakpoint en las API, para encontrar el salto no deseado para poder modificarlo.

"MessageBox" ; MessageBoxExA ; MessageBeep ; "SendMessage" ; DialogBoxParamA ; CreateWindow ; CreateWindowEx ; ShowWindow ; UpdateWindow; GetDlgItemText ; "GetDlgItemInt" ; GetWindowText ; GetWindowWord ; GetWindowInt ;

Para programas con vencimiento de tiempo: GetLocalTime ; GetFileTime ; GetSystemtime

Como habrán notado, en la lista anterior, hay tres que he resaltado con comillas, esto se debe a que son a nivel personal las que generalmente más funcionan, lo que no quiere decir que siempre sea así. Visto esto daremos inicio al temario que ocupa al Cap 5.
Lo que haremos será el tradicional método visto en el cap 3, con un nuevo Crackme, del mismo autor y obtenido del mismo lugar que el anterior. Pero no es igual al anterior, si no que al ejecutarlo nos pide solamente un password. La intención de este Capítulo, es tomar práctica.
Cogeremos el Crackme v2.0 y lo primero que haremos será obviamente ejecutarlo, e intentar registrarnos para que nos salga el mensaje de error. "NO LUCK THERE, MATE!", claro este que anotaremos el mensaje en nuestra hoja de descubrimiento (recordemos que SIEMPRE debemos anotar lo que vayamos descubriendo, ya que hay programas, que llevan días para entender correctamente el funcionamiento y realizar los cambios necesarios, y sería ilógico todos los días empezar de 0 ;) ). Ahora lo desensablamos con el Wdasm y vamos a las straing references, una vez allí ubicamos el cartel de error y le damos doble click y nos arroja sobre la zona 00401357, pero como somos muy listos nos acordamos que anteriormente nos habían pillado con un doble mensaje, asi que le hago doble click de nuevo....esta vez nos arroja sobre el mismo lugar, es decir, no hay otro, nadie intenta engañarnos, pero bueno mejor prevenir que curar dice el dicho ;).

Una vez allí subimos y buscamos para ver desde donde ha sido llamado el salto y vemos que se hace desde 00401243. Justo encima de este vemos el salto 00401241 que contiene el JE que nos lleva a la zona que no queremos llegar, anotamos esta dirección y nos vamos al OllyDBG y vamos a esa dirección y como se ha enseñado en lecciones anteriores modificaremos por un JNE , e intentamos registrarnos, y.....BINGO estamos adentro. Si queremos utilizar el método sin las References String, no tenemos mas que ir a los módulos y localizar el MessageBoxA, si hacemos doble click nos arrojará, justo debajo del salto :) .
Bueno allí fue nuestro segundo programa, espero que les haya agradado.

Bueno Este tutorial fue de uso Educativo por BH-SATAN-X