jueves, 4 de octubre de 2012
Gray Hat Python: Programación en Python para hacking e ingeniería inversa
Python se está convirtiendo en el lenguaje de programación elegido por muchos que se dedican al hacking, a la ingeniería inversa y a probar software. La razón principal es que es fácil y rápido de escribir, soporta bajo nivel y tiene bibliotecas que nos hacen felices.
Ya no tendremos que buscar siempre en foros y manuales, Gray Hat Python muestra el uso de Python para una amplia variedad de tareas de hacking. Este libro explica los conceptos detrás de las herramientas de hacking y las técnicas con depuradores, troyanos, fuzzers y emuladores. Pero el autor, Justin Seitz, va más allá de la teoría mostrando cómo aprovechar las herramientas existentes de seguridad basadas en Python - y cómo construir las tuyas propias cuando lo necesites.
Leyendo este libro aprenderas a:
* Automatizar las tediosas tareas de ingeniería inversa y seguridad
* Diseñar y programar tu propio depurador
* Fuzzear drivers de Windows y a crear potentes fuzzers desde el principio
* Divertirte con la inyección de código y librerías, técnicas de soft y hard hooking y otros trucos con software
* Esnifar tráfico seguro de sesión web cifrada
* Usar PyDBG, Immunity Debugger, Sulley, IDAPython, PyEMU y más
Idioma: Ingles
DESCARGA
Ingenieria Inversa de Troyanos III
Desde ahora empezaremos a practicar… y como su profesor dejo pendiente una explicación de cierta rutina, en cierto stub, aprovechara la clase para explicarla y enseñarles a hacer su propia rutina…
Lo que veremos hoy es conocido como “manual packing” o empaquetamiento manual, en el que lo que haremos será encriptar nuestro ejecutable favorito nosotros mismos directamente con el olly. Pero antes de entrar en el tema explicare la rutina del stub…
Y como seria muy tonto explicar una rutina de un ejecutable sin que los alumnos puedan “sentir que trabajan con el ejecutable” se los adjunto… (Los que entraron al Chat “por obligación” se sentirán algo molestos, pero no se preocupen que casi nadie pasa por este subforo –y probablemente sean recompensados-)
Antes de empezar, veamos un par de APIs que se utilizan aquí y que no se han explicado:
GetModuleHandleA
Obtiene el Handle o manejador de un modulo, siempre y cuando este se encuentre cargado en la memoria.
Returns
La función devolverá el handle del modulo si tiene éxito, de lo contrario devolverá cero
GetProcAddress
Obtiene la dirección de memoria de una función exportada del modulo especificado, siempre y cuando el modulo esté cargado.
Returns
La función devolverá la dirección de memoria de la función. De fallar devolverá cero.
Bien, empecemos… apenas abrimos el ejecutable con el olly caemos en un Pushad
Podríamos explicar la rutina así, pero para hacer las cosas más sencillas utilizaremos el plugin del Olly AnalizeThis! (Si no lo tienen lo encontraran adjunto al final)
Vemos que ha cambiado un poco, pero gracias a ese cambio podemos ver una tabla de texto… si miramos bien podemos deducir que esta obteniendo las direcciones de memoria de las APIs que se mencionan en el cuadro de texto, y guarda esas direcciones en otro lado, y si nos fijamos bien, esos saltos que están abajo apuntan a hacia donde se guardaron esa direcciones de memoria. Es decir que es como una mini-IAT.
Ahí esta dividido por partes ese código.
En la parte 1 si, se darán cuenta que lo que hace es obtener el Handle o manejador del modulo “Kernel32.dll”
En la parte 2, mete el handle en el stack, pasa al siguiente elemento del cuadro de texto que se ve claramente en la imagen, y si son muy despistados (:ja:), es el que esta marcado con el numero 4. Compara si ese elemento es ultimo de la tabla (6179 son los bytes invertidos de “ya” en ASCII,) y si no lo es, entonces mete el handle de la dll (kernel32) en el stack y mete también, el elemento de la tabla al que apunta EBP para llamar a GetProcAddress, y hacer la mini-IAT.
Luego de eso, chequea el Bit de IsDebuggerPresent.
Y si esta a 1, nos lanzara afuera con un salto condicional que se ve que va directo a ExitProcess. Ahora ustedes dirán: como puede Chequear el Bit de IsDebuggerPresent si no llama a esa API? Pues la respuesta es sencilla, si en el olly oprimen Ctrl. + G y ponen ahí “IsDebuggerPresent” (con sus respectivas mayúsculas, o no funcionara) verán que en el lugar en el que caen, están las mismas primeras tres instrucciones que en la imagen que esta arriba de este párrafo (a excepción del pushad), pero si tenemos suerte, o mejor dicho, algún plugin que modifique ese bit (o lo modifican ustedes mismos), se hará una llamada a GetVersion, a la cual se le machacaran los datos que retorna con un popad y nos iremos en un vertiginoso salto hacia el inicio de la rutina de desencriptado (Al fin!!!)
Ahí vemos otro pushad, y vemos también que empezara a desencriptar desde 401020, que al parecer desencriptara el exe por bloques de 179h bytes y que cada tres bytes los encripta de forma distinta. Al llegar ECX a cero saltara hacia la call que esta abajo del salto incondicional, hacia el inicio del bucle encriptador, veamos que hay dentro de ese call…
Pues, resumiré diciendo que es una rutina basura, en la cual se llama 100 veces a GetModuleHandleA pidiendo el handle o manejador de una dll Inexistente (lolazo.dll para ser mas exactos) y repite el bucle anidado ahí 300 veces (bucle que hace solo push EAX/pop EAX)
Al retornar vemos que se hace una comparación entre lo que hay en EAX y 4075BD, si no es igual nos manda a seguir desencriptando. Con esto sabemos que va a desencriptar hasta esa dirección, pero luego de eso hay un salto que va hacia abajo… veamos que nos depara la rutina por esos lares…
Este trozo de código, lo veremos en dos partes…
Ahí vemos que incrementa en uno el byte almacenado en 4090F5 y lo compara con 91, básicamente es para verificar si se ejecutara la primera parte del código a analizar o la segunda. Primero se ejecutara esta parte, en la que vemos que mueve ciertos valores hacia la rutina de desencriptado, así que lo mejor será ejecutarlo hasta el pushad.
Una vez llegado aquí nos vamos hacia donde empieza la rutina para ver que cambios hizo…
Ahí nos fijamos que ha cambiado las operaciones de la rutina, el antiguo ADD ahora es un XOR, el antiguo ROR ahora es un ROL, y el antiguo XOR ahora es un ADD…
Siguiendo donde estábamos, hay un PUSH 5000 y una llamada a “Sleep”, esta API lo que hace es parar la ejecución del programa el tiempo que se le diga, que en este caso son 5000h milisegundos (5000h = 20480d) y se nos manda al inicio de la rutina de desencriptado de nuevo.
Al llegar a desencriptar el byte de la dirección 4075BD vuelve a hacia la rutina que estamos analizando, y el salto decide que se ejecute la segunda parte…
Ahí vemos que cambia de nuevo la rutina, así que ejecutamos para ver que cambios se hacen…
Ahora solo hay dos cambios, el primero es que el antiguo ADD se convirtió en un SUB y el salto que estaba al final de la rutina de desencriptado que nos mandaba al último código analizado, ahora nos manda a 4074ED. Que ciertamente es nuestro entripoint.
Listo… un poco larga la explicación, pero a más de uno le servirá para entender muchas cosas (o eso creo). Ahora pasemos a algo más interesante…
Haciendo Manual-Packing
Yo explicare como hacerlo con el Stub del Bifrost (versión 1.21 desempacada), ustedes pueden hacerlo con el stub que prefieran… (los enlaces de las herramientas utilizadas están al final)
Para no estar trasteando con ningún editor de recursos lo que vamos a hacer es sacar el stub dándole a builder… no importa la configuración que le den, solo denle al botón build que esta abajo a la derecha y les saldrá un mensaje, lo dejaran en el aire, es decir no lo toquen… abran la carpeta donde tienen el bif y copian el ejecutable que se llama Server.exe y lo ponen en otra carpeta, este será el que utilizaremos… ya pueden darle aceptar al cartel y cerrar el cliente y si quieren borrar el Server.exe que esta al lado del cliente (sobra decir que si utilizas otro stub tendrán que sacarlo con el editor de recursos)
Lo que tenemos que hacer ahora es agregar una nueva sección, para esto yo utilizare el Stud_pe, ustedes utilicen el PE Editor que prefieran.
Los que me siguen con el Stud_pe: arrastramos el Stub que acabamos de sacar y nos vamos a la pestaña sections, hacemos click secundario > New Section, y el cuadro que aparece ponemos RAW SIZE: 200 y VIRTUAL SIZE: 1000 (esto es por que en RAW SIZE solo se pueden Poner Múltiplos de 200 y en VIRTUAL SIZE múltiplos de 1000) ahora seleccionamos “fill section with NULL bytes”
Ahora le damos al botón “ADD” y ya tenemos lista la nueva sección, así que abrimos el stub con el olly y nos vamos a donde pusimos la nueva sección.
Para obtener el valor en memoria de la nueva sección lo que tenemos que hacer es sumar el IMAGEBASE y el VIRTUAL OFFSET (normalmente el IMAGEBASE tiene un valor de 400000 en los ejecutables) y la dirección resultante es la que pondremos en el olly. Otra forma de llegar a la dirección virtual de la sección es con el plugin OllyAdvanced en el que se marcara la casilla “enable Advaced Ctrl. + G” y al hacer presionar esa combinación marcamos donde dice offset en el cuadro que nos aparece y ponemos la dirección que nos aparece en RAW OFFSET.
Una vez llegados acá, podremos empezar a escribir código para encriptar, pero deberemos tener en cuenta algo antes de encriptar y eso es la IAT y el IMPORT DESCRIPTOR.
La IAT la hallamos buscando algún call hacia cualquier API, cuando encontremos una miramos la dirección que esta entre corchetes ([]) y nos dirigimos hacia allá en el dump, y nos fijamos donde empieza y donde termina, en este caso empieza en 401000 y termina en 401020 (por eso empezaba a desencriptar desde ahí en la rutina explicada arriba)
Ahora le toca el turno al IMPORT DESCRIPTOR, pero hay dos caminos a recorrer, el primero es que cuando terminemos de encriptar, dumpeemos, con lo cual el plugin OllyDump pondrá un IMPORT DESCRIPTOR en una nueva sección y no habrá que preocuparse por el, pero esto nos aumentara el tamaño (el original es de 23Kb y lo dejara de 41Kb) y el otro camino es hacer “copy to executable” con lo cual mantendremos el tamaño, pero deberemos preocuparnos por el IMPORT DESCRIPTOR así que elijan su camino.
Camino del “Copy to executable”: deberemos hallar el IMPORT DESCRIPTOR y para ello nos ayudara el Stud_pe, en la primera pestaña hay una parte que dice “Import table” y tiene su dirección en RVA (Relative Virtual Address), RAW y el tamaño.
Esas direcciones son las del IMPORT DESCRIPTOR y como dije antes, para obtener su dirección virtual, se suma el RVA al IMAGEBASE. Y el resultado es el que se pone en el olly y para nuestra suerte, no hay nada después del IMPORT DESCRIPTOR, así que hasta ahí encriptaremos.
Aquí los caminos se unen…
La encriptación que haremos será una súper básica, pero que como vimos en la rutina explicada al principio, puede mejorarse.
Movemos hacia algún registro de uso general la dirección desde la que empezamos a encriptar…
Encriptamos el byte de la dirección a la que apunta el registro de uso general con cualquier operación matemática o lógica…
Incrementamos el valor del registro en uno.
Comparamos si se ha llegado hasta donde queremos encriptar (4075f4 si vamos a hacer “copy to executable”, hasta el final de la sección si vamos a dumpear)
Hacemos que si no es igual, siga encriptando.
Y por ultimo hacemos que salte al entri point cuando termine de encriptar.
Ahora para que de verdad quede encriptado, vamos a hacer lo siguiente, nos paramos donde esta la instrucción MOV hacemos click Secundario y hacemos click en “New origin here” o lo que es lo mismo Ctrl. + *, Ponemos un breakPoint en el salto hacia el entri point y corremos con F9 al parar deberemos tomar la decisión, dumpeamos o no…
Si dumpean, hagan click secundario > “dump debugged process” y solo pongan como entripoint la dirección del MOV (Sin el IMAGEBASE) y guarden con el nombre que prefieran y listo.
Si no dumpean, seleccionen el código recién escrito, hagan click secundario > Copy to executable > selection, para volver al CPU (a ventana donde estábamos trabajando) hacemos click en el botón “C” de la barra de botones, luego vallan a 401000, hagan click normal en la primera instrucción para que se marque y vallan hacia el inicio del IMPORT DESCRIPTOR (4075f4) y presionando shift hacen click ahí donde aparecieron. Ahora de nuevo click secundario > Copy to executable > selection y ahí damos de nuevo click secundario > save file, Guardemos y con el Stud_pe cambiamos el entri point la dirección del MOV (sin el IMAGEBASE) y listo.
ahora despues de guardado lo abrimos de nuevo para que desencripte, es decir lo que tenemos que hacer es cambiar el sub por un add y hacer copy to executable, fin
Bifrost publico desempacado
plugin analizethis
plugin ollyDump
Stud_pe
stub de la explicacion
By: bloodday
Lo que veremos hoy es conocido como “manual packing” o empaquetamiento manual, en el que lo que haremos será encriptar nuestro ejecutable favorito nosotros mismos directamente con el olly. Pero antes de entrar en el tema explicare la rutina del stub…
Y como seria muy tonto explicar una rutina de un ejecutable sin que los alumnos puedan “sentir que trabajan con el ejecutable” se los adjunto… (Los que entraron al Chat “por obligación” se sentirán algo molestos, pero no se preocupen que casi nadie pasa por este subforo –y probablemente sean recompensados-)
Antes de empezar, veamos un par de APIs que se utilizan aquí y que no se han explicado:
GetModuleHandleA
Obtiene el Handle o manejador de un modulo, siempre y cuando este se encuentre cargado en la memoria.
Push @offset nombre del modulo Call GetModuleHandleA
Returns
La función devolverá el handle del modulo si tiene éxito, de lo contrario devolverá cero
GetProcAddress
Obtiene la dirección de memoria de una función exportada del modulo especificado, siempre y cuando el modulo esté cargado.
Push @offset nombre o ordinal de la función Push Handle del modulo.
Returns
La función devolverá la dirección de memoria de la función. De fallar devolverá cero.
Bien, empecemos… apenas abrimos el ejecutable con el olly caemos en un Pushad
Podríamos explicar la rutina así, pero para hacer las cosas más sencillas utilizaremos el plugin del Olly AnalizeThis! (Si no lo tienen lo encontraran adjunto al final)
Vemos que ha cambiado un poco, pero gracias a ese cambio podemos ver una tabla de texto… si miramos bien podemos deducir que esta obteniendo las direcciones de memoria de las APIs que se mencionan en el cuadro de texto, y guarda esas direcciones en otro lado, y si nos fijamos bien, esos saltos que están abajo apuntan a hacia donde se guardaron esa direcciones de memoria. Es decir que es como una mini-IAT.
Ahí esta dividido por partes ese código.
En la parte 1 si, se darán cuenta que lo que hace es obtener el Handle o manejador del modulo “Kernel32.dll”
En la parte 2, mete el handle en el stack, pasa al siguiente elemento del cuadro de texto que se ve claramente en la imagen, y si son muy despistados (:ja:), es el que esta marcado con el numero 4. Compara si ese elemento es ultimo de la tabla (6179 son los bytes invertidos de “ya” en ASCII,) y si no lo es, entonces mete el handle de la dll (kernel32) en el stack y mete también, el elemento de la tabla al que apunta EBP para llamar a GetProcAddress, y hacer la mini-IAT.
Luego de eso, chequea el Bit de IsDebuggerPresent.
Y si esta a 1, nos lanzara afuera con un salto condicional que se ve que va directo a ExitProcess. Ahora ustedes dirán: como puede Chequear el Bit de IsDebuggerPresent si no llama a esa API? Pues la respuesta es sencilla, si en el olly oprimen Ctrl. + G y ponen ahí “IsDebuggerPresent” (con sus respectivas mayúsculas, o no funcionara) verán que en el lugar en el que caen, están las mismas primeras tres instrucciones que en la imagen que esta arriba de este párrafo (a excepción del pushad), pero si tenemos suerte, o mejor dicho, algún plugin que modifique ese bit (o lo modifican ustedes mismos), se hará una llamada a GetVersion, a la cual se le machacaran los datos que retorna con un popad y nos iremos en un vertiginoso salto hacia el inicio de la rutina de desencriptado (Al fin!!!)
Ahí vemos otro pushad, y vemos también que empezara a desencriptar desde 401020, que al parecer desencriptara el exe por bloques de 179h bytes y que cada tres bytes los encripta de forma distinta. Al llegar ECX a cero saltara hacia la call que esta abajo del salto incondicional, hacia el inicio del bucle encriptador, veamos que hay dentro de ese call…
Pues, resumiré diciendo que es una rutina basura, en la cual se llama 100 veces a GetModuleHandleA pidiendo el handle o manejador de una dll Inexistente (lolazo.dll para ser mas exactos) y repite el bucle anidado ahí 300 veces (bucle que hace solo push EAX/pop EAX)
Al retornar vemos que se hace una comparación entre lo que hay en EAX y 4075BD, si no es igual nos manda a seguir desencriptando. Con esto sabemos que va a desencriptar hasta esa dirección, pero luego de eso hay un salto que va hacia abajo… veamos que nos depara la rutina por esos lares…
Este trozo de código, lo veremos en dos partes…
Ahí vemos que incrementa en uno el byte almacenado en 4090F5 y lo compara con 91, básicamente es para verificar si se ejecutara la primera parte del código a analizar o la segunda. Primero se ejecutara esta parte, en la que vemos que mueve ciertos valores hacia la rutina de desencriptado, así que lo mejor será ejecutarlo hasta el pushad.
Una vez llegado aquí nos vamos hacia donde empieza la rutina para ver que cambios hizo…
Ahí nos fijamos que ha cambiado las operaciones de la rutina, el antiguo ADD ahora es un XOR, el antiguo ROR ahora es un ROL, y el antiguo XOR ahora es un ADD…
Siguiendo donde estábamos, hay un PUSH 5000 y una llamada a “Sleep”, esta API lo que hace es parar la ejecución del programa el tiempo que se le diga, que en este caso son 5000h milisegundos (5000h = 20480d) y se nos manda al inicio de la rutina de desencriptado de nuevo.
Al llegar a desencriptar el byte de la dirección 4075BD vuelve a hacia la rutina que estamos analizando, y el salto decide que se ejecute la segunda parte…
Ahí vemos que cambia de nuevo la rutina, así que ejecutamos para ver que cambios se hacen…
Ahora solo hay dos cambios, el primero es que el antiguo ADD se convirtió en un SUB y el salto que estaba al final de la rutina de desencriptado que nos mandaba al último código analizado, ahora nos manda a 4074ED. Que ciertamente es nuestro entripoint.
Listo… un poco larga la explicación, pero a más de uno le servirá para entender muchas cosas (o eso creo). Ahora pasemos a algo más interesante…
Haciendo Manual-Packing
Yo explicare como hacerlo con el Stub del Bifrost (versión 1.21 desempacada), ustedes pueden hacerlo con el stub que prefieran… (los enlaces de las herramientas utilizadas están al final)
Para no estar trasteando con ningún editor de recursos lo que vamos a hacer es sacar el stub dándole a builder… no importa la configuración que le den, solo denle al botón build que esta abajo a la derecha y les saldrá un mensaje, lo dejaran en el aire, es decir no lo toquen… abran la carpeta donde tienen el bif y copian el ejecutable que se llama Server.exe y lo ponen en otra carpeta, este será el que utilizaremos… ya pueden darle aceptar al cartel y cerrar el cliente y si quieren borrar el Server.exe que esta al lado del cliente (sobra decir que si utilizas otro stub tendrán que sacarlo con el editor de recursos)
Lo que tenemos que hacer ahora es agregar una nueva sección, para esto yo utilizare el Stud_pe, ustedes utilicen el PE Editor que prefieran.
Los que me siguen con el Stud_pe: arrastramos el Stub que acabamos de sacar y nos vamos a la pestaña sections, hacemos click secundario > New Section, y el cuadro que aparece ponemos RAW SIZE: 200 y VIRTUAL SIZE: 1000 (esto es por que en RAW SIZE solo se pueden Poner Múltiplos de 200 y en VIRTUAL SIZE múltiplos de 1000) ahora seleccionamos “fill section with NULL bytes”
Ahora le damos al botón “ADD” y ya tenemos lista la nueva sección, así que abrimos el stub con el olly y nos vamos a donde pusimos la nueva sección.
Para obtener el valor en memoria de la nueva sección lo que tenemos que hacer es sumar el IMAGEBASE y el VIRTUAL OFFSET (normalmente el IMAGEBASE tiene un valor de 400000 en los ejecutables) y la dirección resultante es la que pondremos en el olly. Otra forma de llegar a la dirección virtual de la sección es con el plugin OllyAdvanced en el que se marcara la casilla “enable Advaced Ctrl. + G” y al hacer presionar esa combinación marcamos donde dice offset en el cuadro que nos aparece y ponemos la dirección que nos aparece en RAW OFFSET.
Una vez llegados acá, podremos empezar a escribir código para encriptar, pero deberemos tener en cuenta algo antes de encriptar y eso es la IAT y el IMPORT DESCRIPTOR.
La IAT la hallamos buscando algún call hacia cualquier API, cuando encontremos una miramos la dirección que esta entre corchetes ([]) y nos dirigimos hacia allá en el dump, y nos fijamos donde empieza y donde termina, en este caso empieza en 401000 y termina en 401020 (por eso empezaba a desencriptar desde ahí en la rutina explicada arriba)
Ahora le toca el turno al IMPORT DESCRIPTOR, pero hay dos caminos a recorrer, el primero es que cuando terminemos de encriptar, dumpeemos, con lo cual el plugin OllyDump pondrá un IMPORT DESCRIPTOR en una nueva sección y no habrá que preocuparse por el, pero esto nos aumentara el tamaño (el original es de 23Kb y lo dejara de 41Kb) y el otro camino es hacer “copy to executable” con lo cual mantendremos el tamaño, pero deberemos preocuparnos por el IMPORT DESCRIPTOR así que elijan su camino.
Camino del “Copy to executable”: deberemos hallar el IMPORT DESCRIPTOR y para ello nos ayudara el Stud_pe, en la primera pestaña hay una parte que dice “Import table” y tiene su dirección en RVA (Relative Virtual Address), RAW y el tamaño.
Esas direcciones son las del IMPORT DESCRIPTOR y como dije antes, para obtener su dirección virtual, se suma el RVA al IMAGEBASE. Y el resultado es el que se pone en el olly y para nuestra suerte, no hay nada después del IMPORT DESCRIPTOR, así que hasta ahí encriptaremos.
Aquí los caminos se unen…
La encriptación que haremos será una súper básica, pero que como vimos en la rutina explicada al principio, puede mejorarse.
Movemos hacia algún registro de uso general la dirección desde la que empezamos a encriptar…
MOV EAX,401020
Encriptamos el byte de la dirección a la que apunta el registro de uso general con cualquier operación matemática o lógica…
MOV EAX,401020 SUB BYTE PTR DS:[EAX],51
Incrementamos el valor del registro en uno.
MOV EAX,401020 SUB BYTE PTR DS:[EAX],51 INC EAX
Comparamos si se ha llegado hasta donde queremos encriptar (4075f4 si vamos a hacer “copy to executable”, hasta el final de la sección si vamos a dumpear)
MOV EAX,401020 SUB BYTE PTR DS:[EAX],51 INC EAX CMP EAX, XXXXX // ustedes ponen el valor
Hacemos que si no es igual, siga encriptando.
MOV EAX,401020 SUB BYTE PTR DS:[EAX],51 INC EAX CMP EAX, XXXXX // ustedes ponen el valor JNE @dirección donde esta el SUB
Y por ultimo hacemos que salte al entri point cuando termine de encriptar.
MOV EAX,401020 SUB BYTE PTR DS:[EAX],51 INC EAX CMP EAX, XXXXX // ustedes ponen el valor JNE @dirección donde esta el SUB JMP 4074ED
Ahora para que de verdad quede encriptado, vamos a hacer lo siguiente, nos paramos donde esta la instrucción MOV hacemos click Secundario y hacemos click en “New origin here” o lo que es lo mismo Ctrl. + *, Ponemos un breakPoint en el salto hacia el entri point y corremos con F9 al parar deberemos tomar la decisión, dumpeamos o no…
Si dumpean, hagan click secundario > “dump debugged process” y solo pongan como entripoint la dirección del MOV (Sin el IMAGEBASE) y guarden con el nombre que prefieran y listo.
Si no dumpean, seleccionen el código recién escrito, hagan click secundario > Copy to executable > selection, para volver al CPU (a ventana donde estábamos trabajando) hacemos click en el botón “C” de la barra de botones, luego vallan a 401000, hagan click normal en la primera instrucción para que se marque y vallan hacia el inicio del IMPORT DESCRIPTOR (4075f4) y presionando shift hacen click ahí donde aparecieron. Ahora de nuevo click secundario > Copy to executable > selection y ahí damos de nuevo click secundario > save file, Guardemos y con el Stud_pe cambiamos el entri point la dirección del MOV (sin el IMAGEBASE) y listo.
ahora despues de guardado lo abrimos de nuevo para que desencripte, es decir lo que tenemos que hacer es cambiar el sub por un add y hacer copy to executable, fin
Bifrost publico desempacado
plugin analizethis
plugin ollyDump
Stud_pe
stub de la explicacion
By: bloodday
Ingenieria Inversa de Troyanos II
Bueno para empezar en la clase anterior quedamos pendientes con los saltos, así que será lo primero que veamos (salten esta parte los que se leyeron “ASM por CaoS ReptantE”), luego veremos algunas APIs de Windows y empezaremos a ver de refilón el debugger.
Instrucciones de salto
El listado de un programa consiste en una sucesión de instrucciones. Sin embargo a la hora de ejecutarlo, la ejecución del mismo no sigue el orden del listado, sino que, de acuerdo con distintas circunstancias y mediante las instrucciones de salto, se interrumpe la ejecución lineal del programa para continuar dicha ejecución en otro lugar del código.
Las instrucciones de salto son básicamente de dos tipos: de salto condicional y de salto incondicional. En el primer tipo, la instrucción de salto suele ponerse después de una comparación y el programa decide si se efectúa o no el salto, según el estado de los flags (excepto en un caso, en el que el salto se efectúa si el valor del registro ECX o CX es cero). En el segundo, el salto se efectúa siempre.
Tipos de salto
Según la distancia a la que se efectúe el salto, estos se dividen en tres tipos: corto, cercano y lejano. También se dividen en absolutos o relativos, según como se exprese en la instrucción la dirección de destino del salto. Como veremos, los saltos cortos y cercanos son relativos, y los largos absolutos. En el salto corto, la dirección de destino se expresa mediante un byte, que va a continuación del código de la instrucción. Este byte contiene un número con signo que, sumado a la dirección de la instrucción siguiente a la del salto, nos da la dirección de destino del mismo. Como este número es con signo, podemos deducir que un salto corto sólo puede efectuarse a una distancia hacia adelante de 127 bytes y hacia atrás de 128. Veamos dos ejemplos de salto corto:
En el primer salto, la dirección de destino es la suma de la dirección de la instrucción siguiente y el desplazamiento: 4011EA+5=4011EF. En el segundo caso, E2 es un número negativo, por lo que la dirección de destino es la de la instrucción siguiente menos la equivalencia en positivo de E2 (1E): 4011F4-1E=4011D6. Estos cálculos, por supuesto, no los hace el programador, que simplemente dirige el salto a una etiqueta para que luego el compilador coloque los códigos correspondientes, pero me ha parecido que valía la pena explicarlo aquí.
- y aquí interrumpo yo de nuevo, nosotros NO trabajaremos desde un compilador, así que no pondremos saltos a etiquetas si no a direcciones de memoria, pero no se preocupen que tampoco tendremos que hacer “cálculos de salto”
El salto cercano es básicamente lo mismo que el salto corto. La diferencia está en que la distancia a que se efectúa es mayor, y no se puede expresar en un byte, por lo que se dispone de cuatro bytes (en programas de 16 bits) que permiten saltos de 32767 bytes hacia adelante y 32768 hacia atrás o de ocho bytes (en programas de 32 bits) que permiten vertiginosos saltos de 2147483647 bytes hacia adelante y 21474836478 bytes hacia atrás.
En la primera instrucción, la dirección de destino es: 401955+96= 4019EB. En la segunda la dirección es: 4019D1-9A= 401937. Fijaos en que los bytes que indican el desplazamiento están escritos al revés y que 9A es la equivalencia en positivo de FFFFFF66.
Los saltos largos se utilizan cuando la instrucción de destino está en un segmento distinto al de la instrucción de salto.
Saltos Condicionales
Las instrucciones de salto condicional sólo admiten los formatos de salto corto y salto cercano, por lo que su código está formado por el código de la instrucción más un byte (cb), un Word (cw) o un doubleword (cd) que determinan el desplazamiento del salto.
Aquí tenéis una relación de las instrucciones de salto condicional, desglosadas según el tipo de salto, en la que pueden apreciarse las equivalencias entre instrucciones de nombre distinto pero idéntica función.
Salto incondicional
Es un salto que no está sujeto a ninguna condición, es decir, que se efectúa siempre. Hay una sola instrucción: jmp. Esta instrucción admite los tres tipos de salto: corto, cercano y lejano. Creo que con unos ejemplos será suficiente:
Ahora que hemos visto todos los saltos habidos y por haber pasemos a otro tema, las API.
Como se dijo en la clase 1, son instrucciones preprogramadas que le facilitan la vida al programador, pero para poder utilizarlas, se debe indicar en el ejecutable cuales son las que van a utilizar, y en que librería se encuentran (aunque no lo crean, hay apis repetidas en Kernel32.dll y Ntdll.dll), pero además de esto también hay que pasarle unos parámetros o argumentos, para que la función sepa lo que va a hacer.
La forma de pasarle estos argumentos a las APIs es metiéndolos en la pila (push) antes de llamar a la API.
Como pueden ver en este ejemplo, se introducen los argumentos a la pila antes de la llamada a la API, los “punteros” son las direcciones que contienen los verdaderos argumentos.
Para cada API los argumentos son diferentes. Y aquí les dejo algunas APIs, lo que hacen y los argumentos que necesitan
MessageBoxA
Crea, despliega, y maneja una caja de mensaje. La caja de mensaje contiene un mensaje definido por el programa y un título, más cualquier combinación de iconos y botones predefinida.
Returns
El valor de retorno es cero si no hay bastante memoria para crear la caja de mensaje. Si la función tiene éxito, el valor del retorno es uno de lo siguiente valores devueltos por la caja de diálogo:
IDABORT, IDCANCEL, IDIGNORE, IDNO, IDOK, IDRETRY, IDYES
Si una caja de mensaje tiene un botón de Cancelación, la función devuelve el valor IDCANCEL si la tecla ESC es apretada o si de botón de Cancelación es seleccionado. Si la caja de mensaje no tiene ningún botón de Cancelación, apretar ESC no tiene efecto.
CreateFileA
La función CreateFile crea, abre, o trunca un archivo, pipe (*), fuente de comunicaciones, dispositivo de disco, o consola. Devuelve un manipulador que puede usarse para acceder al objeto. También puede abrir y puede devolver un manipulador para un directorio.
Returns
Si la función tiene éxito, el valor del retorno es un manipulador abierto del archivo especificado. Si el archivo especificado existe antes de función llamada y dwCreationDistribution es CREATE_ALWAYS u OPEN_ALWAYS, una llamada a GetLastError devuelve ERROR_ALREADY_EXISTS (aunque la función ha tenido éxito). Si el archivo no existe antes de la llamada, GetLastError devuelve cero.
ReadFileA
La función de ReadFile lee datos de un archivo, comienza en la posición indicada por el indicador del archivo. Después de que la operación de lectura se ha completado, el indicador del archivo es ajustado realmente por el número de bytes leídos, a menos que el manipulador de archivos sea creado con el atributo superpuesto. Si el manipulador de archivos es creado para entrada y salida superpuesta (I/O), la aplicación debe ajustar la posición del indicador del archivo después de la operación de lectura.
Returns
Si la función tiene éxito, el valor del retorno es TRUE. Si el valor de retorno es que TRUE y el número de lectura de los bytes es cero, el indicador del archivo estaba más allá del extremo actual del archivo en el momento de la operación de lectura.
Si la función falla, el valor de retorno es FALSE. Para conseguir información extendida del error, llama a GetLastError.
WriteFile
La función WriteFile escribe datos a un archivo y está diseñado para la operación sincrónica y asíncrona. La función comienza escribiendo datos al archivo en la posición indicado por el indicador del archivo. Después de que la operación de escritura se ha completado, el indicador del archivo es ajustado realmente por el número de bytes escritos, excepto cuando el archivo es abierto con FILE_FLAG_OVERLAPPED. Si el manipulador de archivos se creara para la entrada y salida solapada (I/O), la aplicación debe ajustar la posición del indicador del archivo después de que la operación de escritura es terminada.
Returns
Si la función tiene éxito, el valor de retorno es TRUE.
Si la función falla, el valor del retorno es FALSE. Para conseguir información extendida del error, llama a GetLastError.
RegCreateKeyExA
La función RegCreateKeyEx crea la clave especificada. Si la clave ya existe en el registro, la función lo abre.
Returns
Si la función tiene éxito, el valor de retorno es ERROR_SUCCESS.
Si la función falla, el valor de retorno es un valor de error.
(la forma de llamar a estas apis en ASM es hacer push a los parámetros, poniendo los que están de últimos, de primeros –por ejemplo, el parámetro lpdwDispsition de la ultima API explicada, es al que primero se debe hacer push-)
Eso es todo en cuanto a APIs por hoy, ahora pasaremos al debugger que será en lo que nos enfoquemos de aquí en adelante…
Empecemos con las partes del mismo, pero una imagen vale más que mil palabras
Ahora vamos a ver que función tiene cada parte…
En el desensamblado, es donde trabajaremos la mayor parte del tiempo y es donde se nos muestran las instrucciones a ejecutar.
La barra de información, es donde se nos muestra la información acerca de cada instrucción (valores con los que trabaja, desde donde es llamada X subrutina, etc.)
El dump, es donde se nos muestra los valores hexa de los segmentos de la memoria
La pila o Stack, es eso la pila, es donde se guardan datos provisionalmente, y donde se pasan los parámetros a las API.
Los registros nos muestran el valor de los mismos, con posibilidad de modificarlos
Los botones de ventanas, nos muestran las distintas ventanas al presionarlos:
- los conceptos no explicados, serán vistos sobre la marcha en esta u otras clases.
El botón “L” nos muestra el Log, que si lo vemos apenas al cargar cualquier ejecutable, veremos que nos dice que cargo los plugins y el ejecutable de forma satisfactoria, esta ventana nos será de especial atención, pues será aquí donde se nos muestre los parámetros que se le pasan a las API cuando son llamadas, de esta forma sabremos todo lo que hace nuestra victima (esto después de haber hecho ciertas cosillas que veremos en las próximas clases)
El botón “E” nos muestra los módulos que se han cargado en memoria, es decir el ejecutables, las dll, los ocx y cualquier otro modulo que necesite para funcionar (pudiendo llegar a ser otro ejecutable, pues aunque no lo crean, los ejecutables también pueden exportar funciones, siendo así otros ejecutables necesitaran cargar este ejecutable a la memoria para poder utilizar sus funciones exportadas)
El Botón “M” nos muestra la memoria, es decir los módulos cargados, sus secciones, trozos de memoria reservados a ciertos módulos por la llamada a la función VirtualAlloc, etc.
El botón “T” nos muestra los threads o hilos creados, permitiéndonos “matarlos”, suspenderlos, etc.
El botón “W” nos muestra las ventanas creadas por nuestro ejecutable.
El botón “H” nos muestra los handles o manejadores.
El botón “C” nos muestra la “CPU” es decir la ventana que esta en la imagen donde esta la pila, el dump, etc.
El botón “/” nos muestra los parches o cambios hechos a mano, (o debería, pero yo nunca he visto nada en esa ventana)
El botón “K” nos muestra el “Call Stack” es decir las subrutinas en las que hemos entrado, o mejor dicho las subrutinas en las que estamos dentro.
El Botón “B” nos muestra los breackpoints que hemos puesto, y el estado de los mismos.
El botón “R” nos muestra las referencias, pero para que nos muestre algo debemos primero buscarlas, en esta ventana se nos muestran las referencias a la instrucción que especifiquemos, las referencias de texto dentro del ejecutable, las llamadas intermodulares, etc.
El botón “…” nos muestra el “run trace” es decir, aquí quedan logueadas las instrucciones ejecutadas cuando se tracea. Para esto debemos “abrir el run trace” esto se hace en el menú DEBUG > Open or Clear Run Trace.
Y el botón “S” al poner el Mouse encima de el nos dice “Show Source” que en español será algo así como “mostrar fuente”, pero nunca he sabido para que es esta ventana…
Los botones de acción, los explicare según el orden en el que aparezcan en la imagen (por ejemplo “el tercer botón hace esto, esto y lo otro) así que estad atentos con la imagen.
El primer botón, es el que tiene la forma de un botón de play (?) y lo que hace es correr el programa, y su tecla de acceso rápido es F9.
El segundo botón, es el botón de pause (??) y hace lo que es obvio pausa o detiene la ejecución del programa..
El tercer botón, de forma de flecha doblada a la derecha, ( algo parecido a esto ) es el botón “step into” y lo que hace es que ejecuta instrucción por instrucción, entrando en las calls (se entenderá mejor en la practica) su tecla de acceso rápido es F7.
El cuarto botón, es una flecha que medio se asoma por arriba, (este si no se como expresarlo T_T) es el botón “step over” y hace lo mismo que el anterior, ejecuta instrucción por instrucción, pero con la diferencia de que con este no entramos a los calls, si no que se ejecutan las subrutinas completas. Su tecla de acceso rápido el F8.
El quinto botón, es una flecha zigzagueante, es el botón trace into. Lo que hace es eso tracear (ejecutar instrucción por instrucción, pero continuamente, es decir sin parar, al “abrir el Run trace” quedara logueado ahí, cada instrucción ejecutada. Cuando nosotros ejecutaos paso a paso con F8 o F7 también se le llama tracear) entrando en las calls. Su combinación de acceso rápido es Ctrl. + F7.
El sexto botón, es el botón de “trace over” que hace lo mismo que el anterior, pero sin entrar en las calls. Su combinación de acceso rápido es Ctrl. +F8.
Y el séptimo botón, es el botón es el botón “till return” y lo que haces es ayudarnos a salir de una subrutina, es decir, que ejecuta las instrucciones hasta encontrar una instrucción RETN y ahí para. Su combinación de acceso rápido es Ctrl. + F9.
Bueno, esto es todo por ahora… disculpen (de nuevo) lo largo del post, se que deben estar MUY fastidiados después de leer todo esto (si me pagaran por hacer post largos, me haría millonario con esta serie de clases), pero ahora ya están listos para la practica, que empezaremos desde la próxima clase.
By: bloodday
Instrucciones de salto
El listado de un programa consiste en una sucesión de instrucciones. Sin embargo a la hora de ejecutarlo, la ejecución del mismo no sigue el orden del listado, sino que, de acuerdo con distintas circunstancias y mediante las instrucciones de salto, se interrumpe la ejecución lineal del programa para continuar dicha ejecución en otro lugar del código.
Las instrucciones de salto son básicamente de dos tipos: de salto condicional y de salto incondicional. En el primer tipo, la instrucción de salto suele ponerse después de una comparación y el programa decide si se efectúa o no el salto, según el estado de los flags (excepto en un caso, en el que el salto se efectúa si el valor del registro ECX o CX es cero). En el segundo, el salto se efectúa siempre.
Tipos de salto
Según la distancia a la que se efectúe el salto, estos se dividen en tres tipos: corto, cercano y lejano. También se dividen en absolutos o relativos, según como se exprese en la instrucción la dirección de destino del salto. Como veremos, los saltos cortos y cercanos son relativos, y los largos absolutos. En el salto corto, la dirección de destino se expresa mediante un byte, que va a continuación del código de la instrucción. Este byte contiene un número con signo que, sumado a la dirección de la instrucción siguiente a la del salto, nos da la dirección de destino del mismo. Como este número es con signo, podemos deducir que un salto corto sólo puede efectuarse a una distancia hacia adelante de 127 bytes y hacia atrás de 128. Veamos dos ejemplos de salto corto:
:004011E5 83FB05 cmp ebx, 00000005[br] :004011E8 7505 jne 004011EF[br] :004011EA C645002D mov [ebp+00], 2D[br] ...[br] :004011EF 83FB09 cmp ebx, 00000009[br] :004011F2 72E2 jb 004011D6[br] :004011F4 58 pop eax
En el primer salto, la dirección de destino es la suma de la dirección de la instrucción siguiente y el desplazamiento: 4011EA+5=4011EF. En el segundo caso, E2 es un número negativo, por lo que la dirección de destino es la de la instrucción siguiente menos la equivalencia en positivo de E2 (1E): 4011F4-1E=4011D6. Estos cálculos, por supuesto, no los hace el programador, que simplemente dirige el salto a una etiqueta para que luego el compilador coloque los códigos correspondientes, pero me ha parecido que valía la pena explicarlo aquí.
- y aquí interrumpo yo de nuevo, nosotros NO trabajaremos desde un compilador, así que no pondremos saltos a etiquetas si no a direcciones de memoria, pero no se preocupen que tampoco tendremos que hacer “cálculos de salto”
El salto cercano es básicamente lo mismo que el salto corto. La diferencia está en que la distancia a que se efectúa es mayor, y no se puede expresar en un byte, por lo que se dispone de cuatro bytes (en programas de 16 bits) que permiten saltos de 32767 bytes hacia adelante y 32768 hacia atrás o de ocho bytes (en programas de 32 bits) que permiten vertiginosos saltos de 2147483647 bytes hacia adelante y 21474836478 bytes hacia atrás.
:0040194F 0F8E96000000 jle 004019EB[br] :00401955 8D4C2404 lea ecx, dword ptr [esp+04][br] ...[br] :004019CB 0F8566FFFFFF jne 00401937[br] :004019D1 8D4C240C lea ecx, dword ptr [esp+0C]
En la primera instrucción, la dirección de destino es: 401955+96= 4019EB. En la segunda la dirección es: 4019D1-9A= 401937. Fijaos en que los bytes que indican el desplazamiento están escritos al revés y que 9A es la equivalencia en positivo de FFFFFF66.
Los saltos largos se utilizan cuando la instrucción de destino está en un segmento distinto al de la instrucción de salto.
:0003.0C28 2EFFA72D0C jmp word ptr cs:[bx+0C2D]
Saltos Condicionales
Las instrucciones de salto condicional sólo admiten los formatos de salto corto y salto cercano, por lo que su código está formado por el código de la instrucción más un byte (cb), un Word (cw) o un doubleword (cd) que determinan el desplazamiento del salto.
Aquí tenéis una relación de las instrucciones de salto condicional, desglosadas según el tipo de salto, en la que pueden apreciarse las equivalencias entre instrucciones de nombre distinto pero idéntica función.
JA Si es superior (CF=0 y ZF=0) JNBE Si no es inferior o igual (CF=0 y ZF=0) JAE Si es superior o igual (CF=0) JNB Si no es inferior (CF=0) JNC Si no hay acarreo (CF=0) JNA Si no es superior (CF=1 o ZF=1) JBE es inferior o igual (CF=1 o ZF=1) JNAE Si no es superior o igual (CF=1) JB Si es inferior (CF=1) JC Si hay acarreo (CF=1) JG Si es mayor (ZF=0 y SF=OF) JNLE Si no es menor o igual (ZF=0 y SF=OF) JGE Si es mayor o igual (SF=OF) JNL Si no es menor (SF=OF) JNG Si no es mayor (ZF=1 o SF<>OF) JLE Si es menor o igual (ZF=1 o SF<>OF) JNGE Si no es mayor o igual (SF<>OF) JL Si es menor (SF<>OF) JE Si es igual (ZF=1) JZ Si es cero (ZF=1) JNE Si no es igual (ZF=0) JNZ Si no es cero (ZF=0) JO Si hay desbordamiento (OF=1) JNO Si no hay desbordamiento (OF=0) JP Si hay paridad (PF=1) JPE Si es paridad par (PF=1) JNP Si no hay paridad (PF=0) JPO Si es paridad impar (PF=0) JS Si es signo negativo (SF=1) JNS Si no es signo negativo (SF=0) JCXZ Si CX=0 //esta instrucción solo es interpretada JECXZ Si ECX=0 //por procesadores INTEL
Salto incondicional
Es un salto que no está sujeto a ninguna condición, es decir, que se efectúa siempre. Hay una sola instrucción: jmp. Esta instrucción admite los tres tipos de salto: corto, cercano y lejano. Creo que con unos ejemplos será suficiente:
:004011DA EB30 jmp 0040120C :00402B35 E9F8000000 jmp 00402C32 :0001.02B4 E94D01 jmp 0404 :0003.0C28 2EFFA72D0C jmp word ptr cs:[bx+0C2D]
Ahora que hemos visto todos los saltos habidos y por haber pasemos a otro tema, las API.
Como se dijo en la clase 1, son instrucciones preprogramadas que le facilitan la vida al programador, pero para poder utilizarlas, se debe indicar en el ejecutable cuales son las que van a utilizar, y en que librería se encuentran (aunque no lo crean, hay apis repetidas en Kernel32.dll y Ntdll.dll), pero además de esto también hay que pasarle unos parámetros o argumentos, para que la función sepa lo que va a hacer.
La forma de pasarle estos argumentos a las APIs es metiéndolos en la pila (push) antes de llamar a la API.
Push 40 //tipo de MessageBox Push 402000 //puntero del titulo del MessageBox Push 402010 //puntero del texto del MessageBox Push 0 //manejador del MessageBox Call MessageBoxA
Como pueden ver en este ejemplo, se introducen los argumentos a la pila antes de la llamada a la API, los “punteros” son las direcciones que contienen los verdaderos argumentos.
Para cada API los argumentos son diferentes. Y aquí les dejo algunas APIs, lo que hacen y los argumentos que necesitan
MessageBoxA
Crea, despliega, y maneja una caja de mensaje. La caja de mensaje contiene un mensaje definido por el programa y un título, más cualquier combinación de iconos y botones predefinida.
Int MessageBox( HWND hWnd, // el manipulador de ventana padre LPCTSTR lpText, // la dirección del texto dentro de la caja de mensaje LPCTSTR lpCaption, // la dirección del título de la caja de mensaje UINT uType // el estilo de caja de mensaje );
Returns
El valor de retorno es cero si no hay bastante memoria para crear la caja de mensaje. Si la función tiene éxito, el valor del retorno es uno de lo siguiente valores devueltos por la caja de diálogo:
IDABORT, IDCANCEL, IDIGNORE, IDNO, IDOK, IDRETRY, IDYES
Si una caja de mensaje tiene un botón de Cancelación, la función devuelve el valor IDCANCEL si la tecla ESC es apretada o si de botón de Cancelación es seleccionado. Si la caja de mensaje no tiene ningún botón de Cancelación, apretar ESC no tiene efecto.
CreateFileA
La función CreateFile crea, abre, o trunca un archivo, pipe (*), fuente de comunicaciones, dispositivo de disco, o consola. Devuelve un manipulador que puede usarse para acceder al objeto. También puede abrir y puede devolver un manipulador para un directorio.
HANDLE CreateFile( LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDistribution, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile );
Returns
Si la función tiene éxito, el valor del retorno es un manipulador abierto del archivo especificado. Si el archivo especificado existe antes de función llamada y dwCreationDistribution es CREATE_ALWAYS u OPEN_ALWAYS, una llamada a GetLastError devuelve ERROR_ALREADY_EXISTS (aunque la función ha tenido éxito). Si el archivo no existe antes de la llamada, GetLastError devuelve cero.
ReadFileA
La función de ReadFile lee datos de un archivo, comienza en la posición indicada por el indicador del archivo. Después de que la operación de lectura se ha completado, el indicador del archivo es ajustado realmente por el número de bytes leídos, a menos que el manipulador de archivos sea creado con el atributo superpuesto. Si el manipulador de archivos es creado para entrada y salida superpuesta (I/O), la aplicación debe ajustar la posición del indicador del archivo después de la operación de lectura.
BOOL ReadFile( HANDLE hFile, // el manipulador de archivo para leer LPVOID lpBuffer, // la dirección de buffer que recibe los datos DWORD nNumberOfBytesToRead, // el número de bytes para leer LPDWORD lpNumberOfBytesRead, // la direc de número de lectura de los bytes LPOVERLAPPED lpOverlapped // la dirección de estructura para el dato );
Returns
Si la función tiene éxito, el valor del retorno es TRUE. Si el valor de retorno es que TRUE y el número de lectura de los bytes es cero, el indicador del archivo estaba más allá del extremo actual del archivo en el momento de la operación de lectura.
Si la función falla, el valor de retorno es FALSE. Para conseguir información extendida del error, llama a GetLastError.
WriteFile
La función WriteFile escribe datos a un archivo y está diseñado para la operación sincrónica y asíncrona. La función comienza escribiendo datos al archivo en la posición indicado por el indicador del archivo. Después de que la operación de escritura se ha completado, el indicador del archivo es ajustado realmente por el número de bytes escritos, excepto cuando el archivo es abierto con FILE_FLAG_OVERLAPPED. Si el manipulador de archivos se creara para la entrada y salida solapada (I/O), la aplicación debe ajustar la posición del indicador del archivo después de que la operación de escritura es terminada.
BOOL WriteFile( HANDLE hFile, // el manipulador de archivo para escribir LPCVOID lpBuffer, // la dirección de datos para escribir al archivo DWORD nNumberOfBytesToWrite, // el número de bytes a escribir LPDWORD lpNumberOfBytesWritten, // la dirección del número de bytes escritos LPOVERLAPPED lpOverlapped // la direc. D estructura nece para I/O solapada );
Returns
Si la función tiene éxito, el valor de retorno es TRUE.
Si la función falla, el valor del retorno es FALSE. Para conseguir información extendida del error, llama a GetLastError.
RegCreateKeyExA
La función RegCreateKeyEx crea la clave especificada. Si la clave ya existe en el registro, la función lo abre.
LONG RegCreateKeyEx ( HKEY hKey, // el manipulador de una clave abierta LPCTSTR lpszSubKey, // la dirección del nombre de subclave DWORD dwReserved, // reservado LPTSTR lpszClass, // la dirección de clase de string DWORD fdwOptions, // las opciones especiales de flag REGSAM samDesired, // acceso de seguridad deseado LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition );
Returns
Si la función tiene éxito, el valor de retorno es ERROR_SUCCESS.
Si la función falla, el valor de retorno es un valor de error.
(la forma de llamar a estas apis en ASM es hacer push a los parámetros, poniendo los que están de últimos, de primeros –por ejemplo, el parámetro lpdwDispsition de la ultima API explicada, es al que primero se debe hacer push-)
Eso es todo en cuanto a APIs por hoy, ahora pasaremos al debugger que será en lo que nos enfoquemos de aquí en adelante…
Empecemos con las partes del mismo, pero una imagen vale más que mil palabras
Ahora vamos a ver que función tiene cada parte…
En el desensamblado, es donde trabajaremos la mayor parte del tiempo y es donde se nos muestran las instrucciones a ejecutar.
La barra de información, es donde se nos muestra la información acerca de cada instrucción (valores con los que trabaja, desde donde es llamada X subrutina, etc.)
El dump, es donde se nos muestra los valores hexa de los segmentos de la memoria
La pila o Stack, es eso la pila, es donde se guardan datos provisionalmente, y donde se pasan los parámetros a las API.
Los registros nos muestran el valor de los mismos, con posibilidad de modificarlos
Los botones de ventanas, nos muestran las distintas ventanas al presionarlos:
- los conceptos no explicados, serán vistos sobre la marcha en esta u otras clases.
El botón “L” nos muestra el Log, que si lo vemos apenas al cargar cualquier ejecutable, veremos que nos dice que cargo los plugins y el ejecutable de forma satisfactoria, esta ventana nos será de especial atención, pues será aquí donde se nos muestre los parámetros que se le pasan a las API cuando son llamadas, de esta forma sabremos todo lo que hace nuestra victima (esto después de haber hecho ciertas cosillas que veremos en las próximas clases)
El botón “E” nos muestra los módulos que se han cargado en memoria, es decir el ejecutables, las dll, los ocx y cualquier otro modulo que necesite para funcionar (pudiendo llegar a ser otro ejecutable, pues aunque no lo crean, los ejecutables también pueden exportar funciones, siendo así otros ejecutables necesitaran cargar este ejecutable a la memoria para poder utilizar sus funciones exportadas)
El Botón “M” nos muestra la memoria, es decir los módulos cargados, sus secciones, trozos de memoria reservados a ciertos módulos por la llamada a la función VirtualAlloc, etc.
El botón “T” nos muestra los threads o hilos creados, permitiéndonos “matarlos”, suspenderlos, etc.
El botón “W” nos muestra las ventanas creadas por nuestro ejecutable.
El botón “H” nos muestra los handles o manejadores.
El botón “C” nos muestra la “CPU” es decir la ventana que esta en la imagen donde esta la pila, el dump, etc.
El botón “/” nos muestra los parches o cambios hechos a mano, (o debería, pero yo nunca he visto nada en esa ventana)
El botón “K” nos muestra el “Call Stack” es decir las subrutinas en las que hemos entrado, o mejor dicho las subrutinas en las que estamos dentro.
El Botón “B” nos muestra los breackpoints que hemos puesto, y el estado de los mismos.
El botón “R” nos muestra las referencias, pero para que nos muestre algo debemos primero buscarlas, en esta ventana se nos muestran las referencias a la instrucción que especifiquemos, las referencias de texto dentro del ejecutable, las llamadas intermodulares, etc.
El botón “…” nos muestra el “run trace” es decir, aquí quedan logueadas las instrucciones ejecutadas cuando se tracea. Para esto debemos “abrir el run trace” esto se hace en el menú DEBUG > Open or Clear Run Trace.
Y el botón “S” al poner el Mouse encima de el nos dice “Show Source” que en español será algo así como “mostrar fuente”, pero nunca he sabido para que es esta ventana…
Los botones de acción, los explicare según el orden en el que aparezcan en la imagen (por ejemplo “el tercer botón hace esto, esto y lo otro) así que estad atentos con la imagen.
El primer botón, es el que tiene la forma de un botón de play (?) y lo que hace es correr el programa, y su tecla de acceso rápido es F9.
El segundo botón, es el botón de pause (??) y hace lo que es obvio pausa o detiene la ejecución del programa..
El tercer botón, de forma de flecha doblada a la derecha, ( algo parecido a esto ) es el botón “step into” y lo que hace es que ejecuta instrucción por instrucción, entrando en las calls (se entenderá mejor en la practica) su tecla de acceso rápido es F7.
El cuarto botón, es una flecha que medio se asoma por arriba, (este si no se como expresarlo T_T) es el botón “step over” y hace lo mismo que el anterior, ejecuta instrucción por instrucción, pero con la diferencia de que con este no entramos a los calls, si no que se ejecutan las subrutinas completas. Su tecla de acceso rápido el F8.
El quinto botón, es una flecha zigzagueante, es el botón trace into. Lo que hace es eso tracear (ejecutar instrucción por instrucción, pero continuamente, es decir sin parar, al “abrir el Run trace” quedara logueado ahí, cada instrucción ejecutada. Cuando nosotros ejecutaos paso a paso con F8 o F7 también se le llama tracear) entrando en las calls. Su combinación de acceso rápido es Ctrl. + F7.
El sexto botón, es el botón de “trace over” que hace lo mismo que el anterior, pero sin entrar en las calls. Su combinación de acceso rápido es Ctrl. +F8.
Y el séptimo botón, es el botón es el botón “till return” y lo que haces es ayudarnos a salir de una subrutina, es decir, que ejecuta las instrucciones hasta encontrar una instrucción RETN y ahí para. Su combinación de acceso rápido es Ctrl. + F9.
Bueno, esto es todo por ahora… disculpen (de nuevo) lo largo del post, se que deben estar MUY fastidiados después de leer todo esto (si me pagaran por hacer post largos, me haría millonario con esta serie de clases), pero ahora ya están listos para la practica, que empezaremos desde la próxima clase.
By: bloodday
Ingenieria Inversa De Troyanos I
En nuestras primeras clases... empezaremos con algunas definiciones,
veremos lo que hacen las instrucciones de ensamblador, y algunas APIs de
Windows, les diría que se leyeran el "Windows API for programmers" pero
hay algunas APIs que no esta ahí (por ejemplo busquen
DebugActiveProcessStop y no les aparecerá) así que para las APIs que no
sepamos que hacen, usaremos el Puto google (con esto también me incluyo
por que hay muchas APIs que no se que hacen...)
Empecemos con las definiciones...
Registros: los registros, son algo así como "variables" que usa el procesador, y hay varios de ellos, y cada uno tiene una tarea especifica... nosotros nos concentraremos en los que nos muestra el ollydbg, que son EAX, EBX, ECX, EDX, EBP, ESP, ESI, EDI y EIP. Pero que carajos significa eso?
Pues bien, la “E” significa EXTENDIDO, pero por que extendido? Pues sencillo, antes se trabajaba con 16 bits y los registros eran AX, BX, CX, DX, BP, SP, SI, DI e IP, y para poder trabajar con 32 bits se “inventaron” estos registros extendidos.
Bueno, para dar una explicación sencilla diremos que los registros que terminan en “X” (EAX, EBX, ECX y EDX) son registros de uso general, pero además de ello también tienen una tarea específica que cumplir. Los registros que terminan en “P” (EIP, EBP y ESP) son registros que llevan un Puntero (Pointer en ingles) es por eso que terminan en “P” y Finalmente los dos registros que terminan en “I” (ESI y EDI) son registros de Índice.
Como ya hemos dicho, cada registro tiene una función específica, y la segunda letra de su nombre nos indica la función asignada a cada registro, de esta manera la “A” de EAX, quiere decir que es el registro Acumulador, por ser aquí donde se guarden los resultados de ciertas operaciones (div y mul por ejemplo) y donde la mayoría de las APIs retornen algún valor.
La “B” de EBX, y EBP nos indica que son registros de Base, en el caso de EBX además de su uso como registro general, suele utilizarse para direccionar el acceso a datos situados en la memoria. Y EBP es utilizado para direccionar el acceso a datos situados dentro del espacio ocupado por la pila, aunque también puede ser de uso general.
La “C” de ECX, nos indica que es el registro Contador (Counter en ingles) y es así, por que es el registro utilizado para hacer bucles, además de ser un registro de uso general.
La “D” de EDX nos indica que es un registro de Datos, y es así por ser utilizado en instrucciones de entrada y salida, pero además de esto, también es utilizado en conjunto con EAX para formar números de mas de 32 bits en operaciones como multiplicar (mul) o dividir (div)
La “S” de ESP viene dada por que como ya se dijo lleva un puntero, y este es el de la Pila (Stack en ingles) es decir que apunta hacia el primer valor de ésta.
La “I” de EIP significa Instrucción, es decir que este registro nos dice el Puntero o la dirección de la siguiente instrucción a ejecutar.
Y por ultimo los registros de Índice ESI y EDI, pues estos registros son utilizados por ciertas operaciones como origen (ESI) y destino (EDI) por ejemplo para copiar un bloque de bytes.
API: Las APIs (Application Programming Interface) son rutinas "prefabricadas" destinadas a facilitar la labor del Programador y al mismo tiempo a reducir la extensión de los programas, porque no hace falta incluir estas Rutinas en el ejecutable, ya que están incluidas en librerías de Windows.
Flags: son Bits que se ponen a uno o cero según la instrucción que ejecutemos, y hay instrucciones que hacen una cosa u otra según el estado de alguno de ellos (saltos condicionales por ejemplo)
Instrucciones del lenguaje ASM (sacadas de “ASM por Caos Reptante” por que me parece que mejor explicadas no podrían estar)
Vamos a ver la mayoría, pero no todas, he dejado de lado las que me han parecido menos importantes.
And El resultado es 1 si los dos operandos son 1, y 0 en cualquier otro caso.
1 and 1 = 1
1 and 0 = 0
0 and 1 = 0
0 and 0 = 0
Ejemplo: 1011 and 0110 = 0010
Or El resultado es 1 si uno o los dos operandos es 1, y 0 en cualquier otro caso.
1 or 1 = 1
1 or 0 = 1
0 or 1 = 1
0 or 0 = 0
Ejemplo: 1011 or 0110 = 1111
Xor El resultado es 1 si uno y sólo uno de los dos operandos es 1, y 0 en cualquier otro caso
1 xor 1 = 0
1 xor 0 = 1
0 xor 1 = 1
0 xor 0 = 0
Ejemplo: 1011 xor 0110 = 1101
Not Simplemente invierte el valor del único operando de esta función
Not 1 = 0
Not 0 = 1
Ejemplo: not 0110 = 1001
Estos ejemplos los hemos visto con números binarios. Como estas operaciones se hacen bit a bit, si quisiéramos hacer una operación entre números en formato hexadecimal, que es lo más corriente, deberíamos pasarlos antes a binario. O bien utilizar la calculadora de Windows en formato científico.
Nop (No Operation)
Esta instrucción es de gran utilidad: no hace nada. Su verdadera utilidad reside en rellenar los huecos provocados por la eliminación de instrucciones o su substitución por instrucciones de menor longitud. Su nombre da origen al verbo "nopear" que tan a menudo utilizan los chicos malos ;-) Hay corrientes filosóficas dentro del cracking que sostienen que poner nops es una cochinada.
-y aquí tengo que hacer una pausa para reseñar que la instrucción NOP NO EXISTE pues si vemos su opcode (bytes de la instrucción) es 90, y este opcode pertenece a la instrucción XCHG EAX,EAX pero como es obvio que esto no modifica nada, los debuggers y desensambladotes usan este “convencionalismo”
Push (Push Word or Doubleword Onto the Stack)
Esta instrucción resta del registro ESP, la longitud de su único operando que puede ser de tipo Word o doubleword (4 u 8 bytes), y a continuación lo coloca en la pila. (en pocas palabras pone lo que le indiques de primero en la pila)
Pop (Pop a Value from the Stack)
Es la inversa de la anterior, es decir que incrementa el registro ESP y retira el valor disponible de la pila y lo coloca donde indica el operando.
Pushad (Push All General-Purpose Registers)
Estas instrucciones guardan el contenido de los registros en la pila en un orden determinado. Así pues, pushad equivale a: push EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI.
Popad (Pop All General-Purpose Registers)
Estas instrucciones efectúan la función inversa de las anteriores, es decir, restituyen a los registros los valores recuperados de la pila en el orden inverso al que se guardaron. Así popad equivale a: pop EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX.
Pushfd (Push EFLAGS Register onto the Stack)
Popfd (Pop Stack into EFLAGS Register)
Estas parejas de instrucciones colocan y retiran de la pila el registro de flags.
mov (Move)
Esta instrucción tiene dos operandos. Copia el contenido del operando de origen (representado en segundo lugar) en el de destino (en primer lugar), y según el tipo de estos operandos adopta formatos distintos. He aquí unos ejemplos:
movsx (Move with Sign-Extension)
Copia el contenido del segundo operando, que puede ser un registro o una posición de memoria, en el primero (de doble longitud que el segundo), rellenándose los bits sobrantes por la izquierda con el valor del bit más significativo del segundo operando. Aquí tenemos un par de ejemplos:
Vemos como en el primer ejemplo los espacios vacíos se rellenan con ceros y en el segundo con unos.
movzx (Move with Zero-Extend)
Igual a movsx, pero en este caso, los espacios sobrantes se rellenan siempre con ceros. Veamos como el segundo ejemplo de la instrucción anterior da un resultado distinto:
ea (Load Effective Address)
Similar a la instrucción mov, pero el primer operando es un registro de uso general y el segundo una dirección de memoria. Esta instrucción es útil sobre todo cuando esta dirección de memoria responde a un cálculo previo.
xchg (Exchange Register/Memory with Register)
Esta instrucción intercambia los contenidos de los dos operandos.
En el primer ejemplo, el contenido del registro ECX, se copia en el registro EDX, y el contenido anterior de EDX, se copia en ECX. Se obtendría el mismo resultado con:
La instrucción pop ecx toma el valor que hay en la pila y lo coloca en el registro ECX, pero como podemos ver por la instrucción anterior push edx, este valor, procedía del registro EDX. Luego se coloca en EDX el valor procedente de ECX.
bswap (Byte Swap)
Esta instrucción es para empleo exclusivo con registros de 32 bits como único parámetro. Intercambia los bits 0 a 7 con los bits 24 a 31, y los bits 16 a 23 con los bit 8 a 15.
Inc (Increment by 1) / dec (Decrement by 1)
Estas dos instrucciones incrementan y decrementan respectivamente el valor indicado en su único operando.
En los dos primeros ejemplos, se incrementaría y decrementaría el valor contenido en los cuatro bytes situados a partir de la dirección 513424.
add (Add)
Esta instrucción suma los contenidos de sus dos operandos y coloca el resultado en el operando representado en primer lugar.
En el tercer ejemplo, como el resultado se coloca siempre en el primer operando, no sería aceptada por el compilador una instrucción como add 00000008, dword ptr [ebp-1C]
adc (Add with Carry)
Esta instrucción es similar a la anterior, con la diferencia de que se suma también el valor del flag de acarreo. Se utiliza para sumar valores mayores de 32 bits. Supongamos que queremos sumar al contenido de los registros EDX:EAX (EDX=00000021h y EAX=87AE43F5), un valor de más de 32 bits (3ED671A23). Veamos como se hace:
sub (Subtract)
Esta instrucción resta el contenido del segundo operando del primero, colocando el resultado en el primer operando.
sbb (Integer Subtraction with Borrow)
Esta instrucción es una resta en la que se tiene en cuenta el valor del flag de acarreo. Supongamos que del contenido de los registros EDX:EAX después del ejecutado el ejemplo de la instrucción adc (EDX=00000025h y EAX=75155E18), queremos restar el valor 3ED671A23. El resultado es el valor que tenían inicialmente los dos registros en el ejemplo citado:
mul (Unsigned Multiply) / imul (Signed Multiply)
Estas dos instrucciones se utilizan para multiplicar dos valores. La diferencia más importante entre las dos, es que en la primera no se tiene en cuenta el signo de los factores, mientras que en la segunda sí. Como veremos en algunos ejemplos, esta diferencia se refleja en los valores de los flags.
En la instrucción mul, hay un solo operando. Si es un valor de tamaño byte, se multiplica este valor por el contenido de AL y el resultado se guarda en EAX, si el valor es de tamaño word (2 bytes), se multiplica por AX, y el resultado se guarda en EAX y finalmente, si el valor es de tamaño dword (4bytes), se multiplica por EAX y el resultado se guarda en EDX:EAX. O sea, que el espacio destinado al resultado siempre es de tamaño doble al de los operandos.
En la instrucción imul, hay también una mayor variedad en el origen de sus factores. Además de la utilización de los registros EAX y EDX, así como de sus subdivisiones, pueden especificarse otros orígenes y destinos de datos y puede haber hasta tres operandos. El primero, es el lugar donde se va a guardar el resultado, que debe ser siempre un registro, el segundo y el tercero son los dos valores a multiplicar. En estos ejemplos vemos como estas instrucciones con dos o tres operandos, tienen el mismo
espacio para el resultado que para cada uno de los factores:
Veamos finalmente la diferencia entre la multiplicación con signo y sin él:
Esta vez, en el primer caso, el resultado ha sido correcto, porque 2147483647d multiplicado por dos ha dado 4294967294d, por tanto, no se ha activado ningún flag. Pero en el segundo caso, teniendo en cuenta el signo, hemos multiplicado 2147483647d por dos y nos ha dado como resultado -2. Ahora si se han activado los flags.
div (Unsigned Divide) / idiv (Signed Divide)
El caso de la división es muy parecido al de la multiplicación. Hay dos instrucciones: div para números en los que no se considere el signo e idiv para números que se consideren con signo. El dividendo está formado por una pareja de registros y el divisor es el único operando. He aquí varios ejemplos de una y otra instrucción:
Ahora, como hemos hecho con la multiplicación, vamos a ver el diferente resultado que se obtiene empleando una u otra instrucción:
En el primer caso, al no considerar el signo de los números, se ha dividido 1 por 65535, que ha dado un cociente de 0 y un resto de 1. En el segundo caso, se ha dividido -1 por 1, lo que ha dado un cociente de -1 y un resto de 0. No ha habido overflow ni acarreo en ninguno de los dos casos.
xadd (Exchange and Add)
Intercambia los valores de los dos operandos y los suma, colocando el resultado en el primer operando. El primer operando puede ser un registro o una posición de memoria, pero el segundo sólo puede ser un registro.
En la dirección indicada por EBX tendremos el valor CD AB 34 12. Vemos el valor que hemos puesto en la memoria invertido, porque el paso del valor de un registro a la
memoria y viceversa se hace empezando por el último byte y terminando por el primero.
EAX contiene el valor 12AB4701 (12AB34CD+1234) y ECX el valor 12AB34CD.
La dirección indicada por EBX contiene el valor 01 BE 34 12 (1234ABCD+1234) y el registro ECX el valor 1234ABCD.
neg (Two's Complement Negation)
Esta instrucción tiene la finalidad de cambiar de signo el número representado por su único operando, mediante una operación de complemento a dos.
CMP (Compare Two Operands)
La comparación entre dos valores es en realidad una resta entre ambos. Según cual sea el resultado, podemos saber si los valores son iguales y en caso contrario, cual de ellos es el mayor. Así, se podría utilizar la instrucción sub ecx, ebx para comparar el resultado de estos dos registros, sin embargo el hacerlo así tiene el problema de que el resultado de la resta se colocaría en el registro ECX, cuyo valor anterior desaparecería. Para evitar este problema el programador dispone de la instrucción cmp.
Esta instrucción resta el segundo operando del primero. El resultado no se guarda en ningún sitio, pero según cual sea este resultado, pueden modificarse los valores de los flags CF, OF, SF, ZF, AF y PF. Es en base al estado de estos flags, que se efectúa o no el salto condicional que suele acompañar a esta instrucción. Veremos esta instrucción en los ejemplos de saltos condicionales.
Bueno, eso es todo por esta clase, si tienen preguntas, háganlas por acá o por el Chat, para la próxima veremos algunas APIs, y nos introduciremos en el Olly para aprender a utilizarlo y ver las posibilidades que nos da.
Para los que quieran leer el documento “ASM por Caos Reptante” se los dejo adjunto.
http://www.mediafire.com/?mz9zxnvwztn
PD: disculpen lo largo, y faltaron los saltos, pero será para la próxima clase
By: bloodday
Empecemos con las definiciones...
Registros: los registros, son algo así como "variables" que usa el procesador, y hay varios de ellos, y cada uno tiene una tarea especifica... nosotros nos concentraremos en los que nos muestra el ollydbg, que son EAX, EBX, ECX, EDX, EBP, ESP, ESI, EDI y EIP. Pero que carajos significa eso?
Pues bien, la “E” significa EXTENDIDO, pero por que extendido? Pues sencillo, antes se trabajaba con 16 bits y los registros eran AX, BX, CX, DX, BP, SP, SI, DI e IP, y para poder trabajar con 32 bits se “inventaron” estos registros extendidos.
Bueno, para dar una explicación sencilla diremos que los registros que terminan en “X” (EAX, EBX, ECX y EDX) son registros de uso general, pero además de ello también tienen una tarea específica que cumplir. Los registros que terminan en “P” (EIP, EBP y ESP) son registros que llevan un Puntero (Pointer en ingles) es por eso que terminan en “P” y Finalmente los dos registros que terminan en “I” (ESI y EDI) son registros de Índice.
Como ya hemos dicho, cada registro tiene una función específica, y la segunda letra de su nombre nos indica la función asignada a cada registro, de esta manera la “A” de EAX, quiere decir que es el registro Acumulador, por ser aquí donde se guarden los resultados de ciertas operaciones (div y mul por ejemplo) y donde la mayoría de las APIs retornen algún valor.
La “B” de EBX, y EBP nos indica que son registros de Base, en el caso de EBX además de su uso como registro general, suele utilizarse para direccionar el acceso a datos situados en la memoria. Y EBP es utilizado para direccionar el acceso a datos situados dentro del espacio ocupado por la pila, aunque también puede ser de uso general.
La “C” de ECX, nos indica que es el registro Contador (Counter en ingles) y es así, por que es el registro utilizado para hacer bucles, además de ser un registro de uso general.
La “D” de EDX nos indica que es un registro de Datos, y es así por ser utilizado en instrucciones de entrada y salida, pero además de esto, también es utilizado en conjunto con EAX para formar números de mas de 32 bits en operaciones como multiplicar (mul) o dividir (div)
La “S” de ESP viene dada por que como ya se dijo lleva un puntero, y este es el de la Pila (Stack en ingles) es decir que apunta hacia el primer valor de ésta.
La “I” de EIP significa Instrucción, es decir que este registro nos dice el Puntero o la dirección de la siguiente instrucción a ejecutar.
Y por ultimo los registros de Índice ESI y EDI, pues estos registros son utilizados por ciertas operaciones como origen (ESI) y destino (EDI) por ejemplo para copiar un bloque de bytes.
API: Las APIs (Application Programming Interface) son rutinas "prefabricadas" destinadas a facilitar la labor del Programador y al mismo tiempo a reducir la extensión de los programas, porque no hace falta incluir estas Rutinas en el ejecutable, ya que están incluidas en librerías de Windows.
Flags: son Bits que se ponen a uno o cero según la instrucción que ejecutemos, y hay instrucciones que hacen una cosa u otra según el estado de alguno de ellos (saltos condicionales por ejemplo)
Instrucciones del lenguaje ASM (sacadas de “ASM por Caos Reptante” por que me parece que mejor explicadas no podrían estar)
Vamos a ver la mayoría, pero no todas, he dejado de lado las que me han parecido menos importantes.
And El resultado es 1 si los dos operandos son 1, y 0 en cualquier otro caso.
1 and 1 = 1
1 and 0 = 0
0 and 1 = 0
0 and 0 = 0
Ejemplo: 1011 and 0110 = 0010
Or El resultado es 1 si uno o los dos operandos es 1, y 0 en cualquier otro caso.
1 or 1 = 1
1 or 0 = 1
0 or 1 = 1
0 or 0 = 0
Ejemplo: 1011 or 0110 = 1111
Xor El resultado es 1 si uno y sólo uno de los dos operandos es 1, y 0 en cualquier otro caso
1 xor 1 = 0
1 xor 0 = 1
0 xor 1 = 1
0 xor 0 = 0
Ejemplo: 1011 xor 0110 = 1101
Not Simplemente invierte el valor del único operando de esta función
Not 1 = 0
Not 0 = 1
Ejemplo: not 0110 = 1001
Estos ejemplos los hemos visto con números binarios. Como estas operaciones se hacen bit a bit, si quisiéramos hacer una operación entre números en formato hexadecimal, que es lo más corriente, deberíamos pasarlos antes a binario. O bien utilizar la calculadora de Windows en formato científico.
Nop (No Operation)
Esta instrucción es de gran utilidad: no hace nada. Su verdadera utilidad reside en rellenar los huecos provocados por la eliminación de instrucciones o su substitución por instrucciones de menor longitud. Su nombre da origen al verbo "nopear" que tan a menudo utilizan los chicos malos ;-) Hay corrientes filosóficas dentro del cracking que sostienen que poner nops es una cochinada.
-y aquí tengo que hacer una pausa para reseñar que la instrucción NOP NO EXISTE pues si vemos su opcode (bytes de la instrucción) es 90, y este opcode pertenece a la instrucción XCHG EAX,EAX pero como es obvio que esto no modifica nada, los debuggers y desensambladotes usan este “convencionalismo”
Push (Push Word or Doubleword Onto the Stack)
Esta instrucción resta del registro ESP, la longitud de su único operando que puede ser de tipo Word o doubleword (4 u 8 bytes), y a continuación lo coloca en la pila. (en pocas palabras pone lo que le indiques de primero en la pila)
Pop (Pop a Value from the Stack)
Es la inversa de la anterior, es decir que incrementa el registro ESP y retira el valor disponible de la pila y lo coloca donde indica el operando.
Pushad (Push All General-Purpose Registers)
Estas instrucciones guardan el contenido de los registros en la pila en un orden determinado. Así pues, pushad equivale a: push EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI.
Popad (Pop All General-Purpose Registers)
Estas instrucciones efectúan la función inversa de las anteriores, es decir, restituyen a los registros los valores recuperados de la pila en el orden inverso al que se guardaron. Así popad equivale a: pop EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX.
Pushfd (Push EFLAGS Register onto the Stack)
Popfd (Pop Stack into EFLAGS Register)
Estas parejas de instrucciones colocan y retiran de la pila el registro de flags.
mov (Move)
Esta instrucción tiene dos operandos. Copia el contenido del operando de origen (representado en segundo lugar) en el de destino (en primer lugar), y según el tipo de estos operandos adopta formatos distintos. He aquí unos ejemplos:
6689C8 mov ax, cx[br] 8BC3 mov eax, ebx[br] 8B5BDC mov ebx, dword ptr [ebx-24][br] 893438 mov dword ptr [eax+edi], esi
movsx (Move with Sign-Extension)
Copia el contenido del segundo operando, que puede ser un registro o una posición de memoria, en el primero (de doble longitud que el segundo), rellenándose los bits sobrantes por la izquierda con el valor del bit más significativo del segundo operando. Aquí tenemos un par de ejemplos:
33C0 xor eax, eax[br] BB78563412 mov ebx, 12345678[br] 0FBFC3 movsx eax, bx EAX=00005678[br] 33C0 xor eax, eax[br] BBCDAB3412 mov ebx, 1234ABCD[br] 0FBFC3 movsx eax, bx EAX=FFFFABCD
Vemos como en el primer ejemplo los espacios vacíos se rellenan con ceros y en el segundo con unos.
movzx (Move with Zero-Extend)
Igual a movsx, pero en este caso, los espacios sobrantes se rellenan siempre con ceros. Veamos como el segundo ejemplo de la instrucción anterior da un resultado distinto:
33C0 xor eax, eax[br] BBCDAB3412 mov ebx, 1234ABCD[br] 0FB7C3 movzx eax, bx EAX=0000ABCD
ea (Load Effective Address)
Similar a la instrucción mov, pero el primer operando es un registro de uso general y el segundo una dirección de memoria. Esta instrucción es útil sobre todo cuando esta dirección de memoria responde a un cálculo previo.
8D4638 lea eax, dword ptr [esi+38]
xchg (Exchange Register/Memory with Register)
Esta instrucción intercambia los contenidos de los dos operandos.
87CA xchg edx, ecx[br] 870538305100 xchg dword ptr [00513038], eax[br] 8710 xchg dword ptr [eax], edx
En el primer ejemplo, el contenido del registro ECX, se copia en el registro EDX, y el contenido anterior de EDX, se copia en ECX. Se obtendría el mismo resultado con:
51 push ecx[br] 52 push edx[br] 59 pop ecx[br] 5A pop edx
La instrucción pop ecx toma el valor que hay en la pila y lo coloca en el registro ECX, pero como podemos ver por la instrucción anterior push edx, este valor, procedía del registro EDX. Luego se coloca en EDX el valor procedente de ECX.
bswap (Byte Swap)
Esta instrucción es para empleo exclusivo con registros de 32 bits como único parámetro. Intercambia los bits 0 a 7 con los bits 24 a 31, y los bits 16 a 23 con los bit 8 a 15.
B8CD34AB12 mov eax, 12AB34CD EAX=12AB34CD[br] 0FC8 bswap eax EAX=CD34AB12
Inc (Increment by 1) / dec (Decrement by 1)
Estas dos instrucciones incrementan y decrementan respectivamente el valor indicado en su único operando.
FF0524345100 Inc dword ptr [00513424][br] FF0D24345100 dec dword ptr [00513424][br] 40 inc eax[br] 4B dec ebx
En los dos primeros ejemplos, se incrementaría y decrementaría el valor contenido en los cuatro bytes situados a partir de la dirección 513424.
add (Add)
Esta instrucción suma los contenidos de sus dos operandos y coloca el resultado en el operando representado en primer lugar.
02C1 add al, cl AL + CL -> AL[br] 01C2 add edx, eax EDX + EAX -> EDX[br] 8345E408 add dword ptr [ebp-1C], 0000008 dword ptr [EBP-1C]+ 8 > [EBP-1C]
En el tercer ejemplo, como el resultado se coloca siempre en el primer operando, no sería aceptada por el compilador una instrucción como add 00000008, dword ptr [ebp-1C]
adc (Add with Carry)
Esta instrucción es similar a la anterior, con la diferencia de que se suma también el valor del flag de acarreo. Se utiliza para sumar valores mayores de 32 bits. Supongamos que queremos sumar al contenido de los registros EDX:EAX (EDX=00000021h y EAX=87AE43F5), un valor de más de 32 bits (3ED671A23). Veamos como se hace:
Add eax, ED671A23 EAX=75155E18 (87AE43F5+ED671A23) CF=1[br] adc edx, 0000003 EDX=25h (21h+3+1)
sub (Subtract)
Esta instrucción resta el contenido del segundo operando del primero, colocando el resultado en el primer operando.
83EA16 sub edx, 00000016 EDX - 16 -> EDX[br] 29C8 sub eax, ecx EAX - ECX -> EAX[br] 2B2B sub ebp, dword ptr [ebx] EBP - dword ptr [EBX] -> EBP
sbb (Integer Subtraction with Borrow)
Esta instrucción es una resta en la que se tiene en cuenta el valor del flag de acarreo. Supongamos que del contenido de los registros EDX:EAX después del ejecutado el ejemplo de la instrucción adc (EDX=00000025h y EAX=75155E18), queremos restar el valor 3ED671A23. El resultado es el valor que tenían inicialmente los dos registros en el ejemplo citado:
Sub eax, ED671A23 EAX=87AE43F5 (75155E18-ED671A23) CF=1[br] sbb edx, 0000003 EDX=21h (25h-3-1)
mul (Unsigned Multiply) / imul (Signed Multiply)
Estas dos instrucciones se utilizan para multiplicar dos valores. La diferencia más importante entre las dos, es que en la primera no se tiene en cuenta el signo de los factores, mientras que en la segunda sí. Como veremos en algunos ejemplos, esta diferencia se refleja en los valores de los flags.
En la instrucción mul, hay un solo operando. Si es un valor de tamaño byte, se multiplica este valor por el contenido de AL y el resultado se guarda en EAX, si el valor es de tamaño word (2 bytes), se multiplica por AX, y el resultado se guarda en EAX y finalmente, si el valor es de tamaño dword (4bytes), se multiplica por EAX y el resultado se guarda en EDX:EAX. O sea, que el espacio destinado al resultado siempre es de tamaño doble al de los operandos.
F7E1 mul ecx EAX*ECX -> EDX:EAX[br] F72424 mul dword ptr [esp] EAX*[ESP] -> EDX:EAX
En la instrucción imul, hay también una mayor variedad en el origen de sus factores. Además de la utilización de los registros EAX y EDX, así como de sus subdivisiones, pueden especificarse otros orígenes y destinos de datos y puede haber hasta tres operandos. El primero, es el lugar donde se va a guardar el resultado, que debe ser siempre un registro, el segundo y el tercero son los dos valores a multiplicar. En estos ejemplos vemos como estas instrucciones con dos o tres operandos, tienen el mismo
espacio para el resultado que para cada uno de los factores:
F7EB imul ebx EAX x EBX -> EDX:EAX[br] 696E74020080FF imul ebp, dword ptr [esi+74], FF800002 [ESI+74] x FF800002 -> EBP[br] 0FAF55E8 imul edx, dword ptr [ebp-18] EDX x [EBP-18] -> EDX
Veamos finalmente la diferencia entre la multiplicación con signo y sin él:
En la primera operación, como se consideran los números sin signo, se ha multiplicado 65535d por 65535d y el resultado ha sido 1. Debido a este resultado "anómalo", se han activado los flags OF y CF. En cambio, en la segunda operación, en la que se toma en cuenta el signo, se ha multiplicado -1 por -1 y el resultado ha sido 1. En este caso no se ha activado ningún flag. Otro ejemplo:66B8FFFF mov ax, FFFF AX=FFFF[br] 66BBFFFF mov bx, FFFF[br] 66F7E3 mul bx AX=0001 OF=1 CF=1[br] 66B8FFFF mov ax, FFFF[br] 66F7EB imul bx AX=0001 OF=0 CF=0
B8FFFFFF7F mov eax, 7FFFFFFF[br] BB02000000 mov ebx, 00000002[br] F7E3 mul ebx EAX=FFFFFFFE OF=0 CF=0[br] B8FFFFFF7F mov eax, 7FFFFFFF[br] F7EB imul ebx EAX=FFFFFFFE OF=1 CF=1
Esta vez, en el primer caso, el resultado ha sido correcto, porque 2147483647d multiplicado por dos ha dado 4294967294d, por tanto, no se ha activado ningún flag. Pero en el segundo caso, teniendo en cuenta el signo, hemos multiplicado 2147483647d por dos y nos ha dado como resultado -2. Ahora si se han activado los flags.
div (Unsigned Divide) / idiv (Signed Divide)
El caso de la división es muy parecido al de la multiplicación. Hay dos instrucciones: div para números en los que no se considere el signo e idiv para números que se consideren con signo. El dividendo está formado por una pareja de registros y el divisor es el único operando. He aquí varios ejemplos de una y otra instrucción:
66F7F3 div bx DX:AX : BX -> AX resto -> DX[br] F7F3 div ebx EDX:EAX : EBX -> EAX resto -> EDX[br] F77308 div dword ptr [ebx+08] EDX:EAX : [EBX+8] -> EAX resto -> EDX[br] F7F9 idiv ecx EDX:EAX : ECX -> EAX resto -> EDX
Ahora, como hemos hecho con la multiplicación, vamos a ver el diferente resultado que se obtiene empleando una u otra instrucción:
33D2 xor edx, edx[br] 66B80100 mov ax, 0001[br] 66BBFFFF mov bx, FFFF[br] 66F7F3 div bx AX=0000 DX=0001[br] 33D2 xor edx, edx[br] 66B80100 mov ax, 0001[br] 66F7FB idiv bx AX=FFFF DX=0000
En el primer caso, al no considerar el signo de los números, se ha dividido 1 por 65535, que ha dado un cociente de 0 y un resto de 1. En el segundo caso, se ha dividido -1 por 1, lo que ha dado un cociente de -1 y un resto de 0. No ha habido overflow ni acarreo en ninguno de los dos casos.
xadd (Exchange and Add)
Intercambia los valores de los dos operandos y los suma, colocando el resultado en el primer operando. El primer operando puede ser un registro o una posición de memoria, pero el segundo sólo puede ser un registro.
C703CDAB3412 mov dword ptr [ebx], 1234ABCD
En la dirección indicada por EBX tendremos el valor CD AB 34 12. Vemos el valor que hemos puesto en la memoria invertido, porque el paso del valor de un registro a la
memoria y viceversa se hace empezando por el último byte y terminando por el primero.
B8CD34AB12 mov eax, 12AB34CD[br] B934120000 mov ecx, 00001234[br] 0FC1C8 xadd eax, ecx
EAX contiene el valor 12AB4701 (12AB34CD+1234) y ECX el valor 12AB34CD.
B934120000 mov ecx, 00001234[br] 0FC10B xadd dword ptr [ebx], ecx
La dirección indicada por EBX contiene el valor 01 BE 34 12 (1234ABCD+1234) y el registro ECX el valor 1234ABCD.
neg (Two's Complement Negation)
Esta instrucción tiene la finalidad de cambiar de signo el número representado por su único operando, mediante una operación de complemento a dos.
B81C325100 mov eax, 0051321C[br] F7D8 neg eax EAX=FFAECDE4[br] neg 0000 0000 0101 0001 0011 0010 0001 1100 = 0051321C[br] 1111 1111 1010 1110 1100 1101 1110 0011[br] + 1[br] 1111 1111 1010 1110 1100 1101 1110 0100 = FFAECDE4
CMP (Compare Two Operands)
La comparación entre dos valores es en realidad una resta entre ambos. Según cual sea el resultado, podemos saber si los valores son iguales y en caso contrario, cual de ellos es el mayor. Así, se podría utilizar la instrucción sub ecx, ebx para comparar el resultado de estos dos registros, sin embargo el hacerlo así tiene el problema de que el resultado de la resta se colocaría en el registro ECX, cuyo valor anterior desaparecería. Para evitar este problema el programador dispone de la instrucción cmp.
Esta instrucción resta el segundo operando del primero. El resultado no se guarda en ningún sitio, pero según cual sea este resultado, pueden modificarse los valores de los flags CF, OF, SF, ZF, AF y PF. Es en base al estado de estos flags, que se efectúa o no el salto condicional que suele acompañar a esta instrucción. Veremos esta instrucción en los ejemplos de saltos condicionales.
Bueno, eso es todo por esta clase, si tienen preguntas, háganlas por acá o por el Chat, para la próxima veremos algunas APIs, y nos introduciremos en el Olly para aprender a utilizarlo y ver las posibilidades que nos da.
Para los que quieran leer el documento “ASM por Caos Reptante” se los dejo adjunto.
http://www.mediafire.com/?mz9zxnvwztn
PD: disculpen lo largo, y faltaron los saltos, pero será para la próxima clase
By: bloodday
Olly DBG (Diferentes tipos de olly)
Les dejo diferentes tipo de olly para que se bajen el que quieran.
OllyDbg-flyODBG
RapidShare: 1-CLICK Web hosting - Easy Filehosting
ollydbg ? ricardo nar.
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg_SLV edition
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg -Arabic
RapidShare: 1-CLICK Web hosting - Easy Filehosting
Ollydbg ? xp
RapidShare: 1-CLICK Web hosting - Easy Filehosting
Ollydbg ? greenstyle
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg ? armadillo
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg ? xp+ dct
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg ? ADO
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg ? SND
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg -D2K2
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg ? DeFixed
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg ? DeFixed v2 (foff)
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg ? ExeCryptor
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg 1.10 - Official
http://www.ollydbg.de/odbg110.zip
OllyDbg 2.0 - Official (Ultima versi?n)
http://www.ollydbg.de/odbg200j.zip
OllyDbg-flyODBG
RapidShare: 1-CLICK Web hosting - Easy Filehosting
ollydbg ? ricardo nar.
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg_SLV edition
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg -Arabic
RapidShare: 1-CLICK Web hosting - Easy Filehosting
Ollydbg ? xp
RapidShare: 1-CLICK Web hosting - Easy Filehosting
Ollydbg ? greenstyle
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg ? armadillo
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg ? xp+ dct
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg ? ADO
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg ? SND
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg -D2K2
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg ? DeFixed
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg ? DeFixed v2 (foff)
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg ? ExeCryptor
RapidShare: 1-CLICK Web hosting - Easy Filehosting
OllyDbg 1.10 - Official
http://www.ollydbg.de/odbg110.zip
OllyDbg 2.0 - Official (Ultima versi?n)
http://www.ollydbg.de/odbg200j.zip
Metodo crackeo del Fly Crypter v2.4+ AUSG 0.8
Aqui les dejo el metodo para crackear el Fly Crypter v2.4+ AUSG 0.8 ya
que esta generando mucho revuelo entre comunidades de hacking que se
haya conseguido crackear su proteccion por hardware pero nadie cuenta
como lo ha hecho.
Fuente: http://forums.hacking.org.il/
Since i want to see you realy want to learn and not to use this
forum in a bad manner this is written in english on purpose and
also it holds all information you will need to crack it your self
The tut/guide
==============
with PEiD you can see that this application is written in VB6 P-Code
Since this is P-Code you will need to use the following tools:
VB Decompiler
=============
Lite edition: http://vb-decompiler.org/download.htm
WKT VB P-Code Debugger
=======================
http://www.woodmann.com/collaborative/tools/index.php/Whiskey_Kon_Tequilla_VB_P-Code_Debugger
- This application have a very good help file so don't tell me you don't know how to use it!
- for the VB P-Code Debugger to work you will need to go to the location you seleted to install
the VB P-Code Debugger and copy the WKTVBDE.dll to your windows/system32 dir.
moreover, you will need to copy from windows/system32 the following files:
msvbvm50.dll
msvbvm60.dll
in the place that Fly Crypter v2.4 + USG 0.8 Private folder is located
open Fly Crypter v2.4.exe with VB Decompiler
=============================================
choose sub_main:
in 46FDB4 you will see that it starts an "IF"
from this if you can see that if the condition
is not apply then a message box will appear.
the text in the message box is encrypted in a
stupid way but we don't care about this because
all we want is to patch the code so it will not
go to the message box but will continue to our
application.
open VB P-Code Debugger and open: Fly Crypter v2.4.exe
========================================================
1. set a break-point on: 46FDB4
2. now execute the application through the debugger.
3. when the debugger breaks you will need to trace trace down a bit
(about 8 lines) with F10, you will see that this is the IF branch commnad.
4. you will need to patch this branch command
Branch that jumps are usually 1C or 1D byte code
so you will need to patch it accurdanly:
- if its 1D change to 1C and opposite.
*just do the same thing to AUSG 0.8.exe
*(ofcorse in his address's)
Fuente: http://forums.hacking.org.il/
martes, 2 de octubre de 2012
Concepto de Ing. Inversa o Cracking
Ingerieria Inversa
El objetivo de la ingeniería inversa es obtener información o
un diseño a partir de un producto accesible al público, con el fin de
determinar de qué está hecho, qué lo hace funcionar y cómo fue
fabricado.
Hoy en día (principios del siglo XXI), los productos más comúnmente sometidos a ingeniería inversa son los programas de computadoras y los componentes electrónicos, pero, en realidad, cualquier producto puede ser objeto de un análisis de Ingeniería Inversa.
El método se denomina así porque avanza en dirección opuesta a las tareas habituales de ingeniería,
que consisten en utilizar datos técnicos para elaborar un producto
determinado. En general, si el producto u otro material que fue sometido
a la ingeniería inversa fue obtenido en forma apropiada, entonces el
proceso es legítimo y legal. De la misma forma, pueden fabricarse y
distribuirse, legalmente, los productos genéricos creados a partir de la
información obtenida de la ingeniería inversa, como es el caso de
algunos proyectos de Software libre ampliamente conocidos.
El programa Samba es un claro ejemplo de ingeniería inversa, dado que permite a sistemas operativos UNIX compartir archivos con sistemas Microsoft Windows.
El proyecto Samba tuvo que investigar información confidencial (no
liberada al público en general por Microsoft) sobre los aspectos
técnicos relacionados con el sistema de archivos Windows. Lo mismo realiza el proyecto WINE para el conjunto de API de Windows y OpenOffice.org con los formatos propios de Microsoft Office, o se hace para entender la estructura del sistema de archivos NTFS y así poder desarrollar drivers para la lectura-escritura sobre el mismo (principalmente para sistemas basados en GNU/Linux).
La ingeniería inversa es un método de resolución. Aplicar ingeniería
inversa a algo supone profundizar en el estudio de su funcionamiento,
hasta el punto de que podamos llegar a entender, modificar y mejorar
dicho modo de funcionamiento.
Pero este término no sólo se aplica al software, sino que también se
considera ingeniería inversa el estudio de todo tipo de elementos (por
ejemplo, equipos electrónicos, microcontroladores, u objeto fabril de
cualquier clase). Diríamos, más bien, que la ingeniería inversa antecede
al nacimiento del software, tratándose de una posibilidad a disposición
de las empresas para la producción de bienes mediante copiado desde el mismo surgimiento de la ingeniería.
En el caso concreto del software,
se conoce por ingeniería inversa a la actividad que se ocupa de
descubrir cómo funciona un programa, función o característica de cuyo
código fuente no se dispone, hasta el punto de poder modificar ese
código o generar código propio que cumpla las mismas funciones. La gran
mayoría del software de pago
incluye en su licencia una prohibición expresa de aplicar ingeniería
inversa a su código, con el intento de evitar que se pueda modificar su
código y que así los usuarios tengan que pagar si quieren usarlo.
¿Que es un Cracker?
El término cracker (del inglés crack, romper) se utiliza para referirse a las personas que rompen algún sistema de seguridad. Los crackers pueden estar motivados por una multitud de razones, incluyendo fines de lucro, protesta, o por el desafío.
Cracker es una persona que mediante ingenieria inversa realiza: seriales, keygens y cracks.
Un cracker es alguien que viola la seguridad de un sistema informatico
de forma similar a como lo haria un hacker, a lo que a diferencia de
este ultimo, el cracker realiza la intrusion con fines de beneficio
personal o para hacer daño.
El termino deriva de la expresion "criminal hacker", y fue creado alrededor de 1985 por contraposicion al termino hacker, en defensa de estos ultimos por el uso incorrecto del termino.
Se considera que la actividad de esta clase de cracker es dañina e ilegal.
Tambien se denomina cracker a quien diseña o programa cracks informaticos, que sirven para modificar el comportamiento o ampliar la funcionalidad del software o hardware original al que se aplican, sin que en absoluto pretenda ser dañino para el usuario del mismo.
No puede considerarse que la actividad de esta clase de cracker sea ilegal si ha obtenido el software o hardware legitimamente, aunque la distribucion de los cracks pudiera serlo.
El termino deriva de la expresion "criminal hacker", y fue creado alrededor de 1985 por contraposicion al termino hacker, en defensa de estos ultimos por el uso incorrecto del termino.
Se considera que la actividad de esta clase de cracker es dañina e ilegal.
Tambien se denomina cracker a quien diseña o programa cracks informaticos, que sirven para modificar el comportamiento o ampliar la funcionalidad del software o hardware original al que se aplican, sin que en absoluto pretenda ser dañino para el usuario del mismo.
No puede considerarse que la actividad de esta clase de cracker sea ilegal si ha obtenido el software o hardware legitimamente, aunque la distribucion de los cracks pudiera serlo.
Asimismo, un
cracker tambien es aquel que practica el cracking (accion de modificar
el codigo fuente a un programa). Esta actividad estan prohibida a
menos que el programa al que se le aplica sea de Software libre, y por
lo general requiere muchos conocimientos sobre hacking.
Debido a la confusion de terminos que he visto en cuanto al termino "crackear" he decidido
hacer unas pequeñas lineas para aclarar el termino que vagamente se maneja a nivel de usuario mas no a nivel de cracker, para eso definiria como se maneja el termino de las dos formas.
A nivel de usuario: Hay gente que llama crackear al simple manejo de un crack o de un patch, yo
no lo llamaria crackear ya que es simplemente usar un programa que permite tener cierto beneficio
de una aplicaciones comerciales.
A nivel de cracker: Las cosas son diferentes ya que aqui se crackea(rompe) una proteccion ya sea
decifrando el algoritmo que no permite la utilizacion de un 100 % de una aplicacion, o editando
instrucciones en el ejecutable.
A nivel de usuario: Parchar significa que vas a substituir el ejecutable original con uno previamente
editado con la finalidad de que burle el mismo su propia proteccion.
A nivel de cracker: Parchar significa editar, añadir o eliminar instrucciones de un ejecutable para
burlar o saltar la proteccion de un ejecutable.
hacer unas pequeñas lineas para aclarar el termino que vagamente se maneja a nivel de usuario mas no a nivel de cracker, para eso definiria como se maneja el termino de las dos formas.
¿Que es crackear?
A nivel de usuario: Hay gente que llama crackear al simple manejo de un crack o de un patch, yo
no lo llamaria crackear ya que es simplemente usar un programa que permite tener cierto beneficio
de una aplicaciones comerciales.
A nivel de cracker: Las cosas son diferentes ya que aqui se crackea(rompe) una proteccion ya sea
decifrando el algoritmo que no permite la utilizacion de un 100 % de una aplicacion, o editando
instrucciones en el ejecutable.
¿Que es parchar?
A nivel de usuario: Parchar significa que vas a substituir el ejecutable original con uno previamente
editado con la finalidad de que burle el mismo su propia proteccion.
A nivel de cracker: Parchar significa editar, añadir o eliminar instrucciones de un ejecutable para
burlar o saltar la proteccion de un ejecutable.
INGENIERIA INVERSA BASICA I ("Aprediendo sobre los programas")
INGENIERIA INVERSA BASICA I
"Aprediendo sobre los programas"
Bueno, me eh tomado la libertad de empezar con esta serie de tutos en los q dare algunas nociones sobre la ingenieria inversa orientandome a la explicacion de las herramientas q utilizaremos. Pero antes de empezar con un grupo de herramientas en especifico, me gustaria tratar de explicar de una forma clara y secilla, que sucede cuando un programa es compilado y que sucede cuando se ejecuta.
-¿Que sucede cuando un programa es compilado?
simple, el programa se traduce a un lenguaje universal para los procesadores. Un compilador es como un traductor el cual convierte lo que nosotros escribimos, en algo que el procesador pueda entender, osea ceros y unos xD, pero estos ceros y unos pueden ser representados en un sistema mas entendible, el hexadecimal, y este lo mas lejos que puede llegar a ser representado es a codificacion ansi, o unicode, es por esto que cuando abrimos un exe, dll o ocx con bloc de notas, vemos una serie de caracteres ksi incomprensible para algien q no sea un genio o q pueda reconocer algo mas q un "MZ" al inicio y una que otra cadena de texto, ya que lo q se ve es la codificacion ansi del codigo binario del programa, q el procesador si puede entender. Este principio es base para el cracking, ya que tenemos q tomar en cuenta que si un programa qiere ser ejecutado por el procesador, debe estar en un lenguaje universal para los procesadores, el binario, esto es lo q permite q exista el concepto de ingenieria inversa o cracking, ya q este conciste en modificar un programa a gusto, esto es posible ya q como todos los programas tienen un solo lenguaje. Uno de los requisitos para ser cracker es saber por lo menos a un nivel basico este lenguaje, el assembler, tambien llamado: codigo de maquina, asm, ensamblador, entre otros. Asi prueben cambiar una "A" por una "a" en un exe en bloc de notas, veran que cuando guardan y ejecutan, el programa ya no trabajara igual q el original, asi el truco esta en saber, exactamente donde y que modificar, para q aga lo que qeremos, para esto existen programas (herramientas) q nos ponen las cosas mas faciles, nos covierten el codigo ansi que vemos con el bloc de notas, en mnemonicos (comandos de ensamblador) aciendo el codigo interpretable para el cracker. Estos son los desensambladores los cuales estudiaremos mas adelante.
Un "editor hexadecimal" es un programa q nos permite ver un programa especifico a nivel hexa y en ansi, y ademas nos permite modificarlo, entre otras cosas.
-¿Que sucede cuando un programa es ejecutado?
weno basikmente cuando un programa se ejecuta, se dice que "se carga en memoria", esto qiere decir q el codigo del programa se guarda en la memoria ram. La memoria ram se secciona de manera q cuando un programa se carga, sus instrucciones son cargadas en un rango de memoria de un segmento especifico, por ejemplo de 004010000-0040232A en el segmento indicado, una instruccion por cada offset. Asi el procesador puede tener un acceso a estos datos para procesarlos.
Existen herramientas q nos permiten ejecutar un programa instruccion por instruccion, ademas de monitorear los valores almacenados en los registros y el desensamblado del programa cargado. Estos son los "depuradores" o "debuggers", algunos de estos tambien nos permiten modificar las instrucciones en ejecucion y editar el programa cargado. Algo q tenemos q tomar en cuenta es q muchos programas utilizan modulos, por esto cuando usemos programas para ver los procesos en ejecucion, asi como el pupe y el procdump, veremos q al seleccionar un proceso este tiene varios subprocesos de los cuales depende, stos subprocesos tambien son usados por otros programas.
El termino "volcar memoria" se refiere a coger un rango especifico de memoria y copiar el codigo contenido dentro de ese espacio en un nuevo archivo. Este proceso es usado mayormente cuando estamos frente a un programa empacado o protegido, y no tenemos el desempacador especifico. El problema cuando tenemos un programa empacado o protegido es q a la ora de desensamblarlo, nos encontraremos con una rutina de descompresion y no con el programa, esto aria q cualqier intento d crackeo sea inutil mientras no tengamos el codigo nativo del programa. Algunos tutos despues estudiaremos como "bajarnos" un programa de la memoria.
Algunos puntos importantes a resaltar en este 1er tuto son:
-Algo impresindible para aprender a crackear es tener conocimientos basicos de asm.
-Todos los progamas procesados por el procesador estan un mismo lenguaje, el lenguaje de maquina.
-Un "editor hexadecimal" es un programa q nos permite ver un programa especifico a nivel hexa y en ansi, y ademas nos permite modificarlo.
-Cuando un programa se ejecuta, el codigo de este se guarda en la memoria ram.
-La mayoria de los programas dependen de modulos.
Algunos consejos para los newbis:
-Te ira mucho mejor crackeando, si ya tienes experiencia programando.
-Los crackers deben tener una mente abierta a un mundo de posibilidades.
-La paciencia es un virtud de los crackers.
-La ingenieria inversa es como la medicina o como cualqier otra rama del hacking, si no te actualizas, te qedas obsoleto.
Auto: Cronux
"Aprediendo sobre los programas"
Bueno, me eh tomado la libertad de empezar con esta serie de tutos en los q dare algunas nociones sobre la ingenieria inversa orientandome a la explicacion de las herramientas q utilizaremos. Pero antes de empezar con un grupo de herramientas en especifico, me gustaria tratar de explicar de una forma clara y secilla, que sucede cuando un programa es compilado y que sucede cuando se ejecuta.
-¿Que sucede cuando un programa es compilado?
simple, el programa se traduce a un lenguaje universal para los procesadores. Un compilador es como un traductor el cual convierte lo que nosotros escribimos, en algo que el procesador pueda entender, osea ceros y unos xD, pero estos ceros y unos pueden ser representados en un sistema mas entendible, el hexadecimal, y este lo mas lejos que puede llegar a ser representado es a codificacion ansi, o unicode, es por esto que cuando abrimos un exe, dll o ocx con bloc de notas, vemos una serie de caracteres ksi incomprensible para algien q no sea un genio o q pueda reconocer algo mas q un "MZ" al inicio y una que otra cadena de texto, ya que lo q se ve es la codificacion ansi del codigo binario del programa, q el procesador si puede entender. Este principio es base para el cracking, ya que tenemos q tomar en cuenta que si un programa qiere ser ejecutado por el procesador, debe estar en un lenguaje universal para los procesadores, el binario, esto es lo q permite q exista el concepto de ingenieria inversa o cracking, ya q este conciste en modificar un programa a gusto, esto es posible ya q como todos los programas tienen un solo lenguaje. Uno de los requisitos para ser cracker es saber por lo menos a un nivel basico este lenguaje, el assembler, tambien llamado: codigo de maquina, asm, ensamblador, entre otros. Asi prueben cambiar una "A" por una "a" en un exe en bloc de notas, veran que cuando guardan y ejecutan, el programa ya no trabajara igual q el original, asi el truco esta en saber, exactamente donde y que modificar, para q aga lo que qeremos, para esto existen programas (herramientas) q nos ponen las cosas mas faciles, nos covierten el codigo ansi que vemos con el bloc de notas, en mnemonicos (comandos de ensamblador) aciendo el codigo interpretable para el cracker. Estos son los desensambladores los cuales estudiaremos mas adelante.
Un "editor hexadecimal" es un programa q nos permite ver un programa especifico a nivel hexa y en ansi, y ademas nos permite modificarlo, entre otras cosas.
-¿Que sucede cuando un programa es ejecutado?
weno basikmente cuando un programa se ejecuta, se dice que "se carga en memoria", esto qiere decir q el codigo del programa se guarda en la memoria ram. La memoria ram se secciona de manera q cuando un programa se carga, sus instrucciones son cargadas en un rango de memoria de un segmento especifico, por ejemplo de 004010000-0040232A en el segmento indicado, una instruccion por cada offset. Asi el procesador puede tener un acceso a estos datos para procesarlos.
Existen herramientas q nos permiten ejecutar un programa instruccion por instruccion, ademas de monitorear los valores almacenados en los registros y el desensamblado del programa cargado. Estos son los "depuradores" o "debuggers", algunos de estos tambien nos permiten modificar las instrucciones en ejecucion y editar el programa cargado. Algo q tenemos q tomar en cuenta es q muchos programas utilizan modulos, por esto cuando usemos programas para ver los procesos en ejecucion, asi como el pupe y el procdump, veremos q al seleccionar un proceso este tiene varios subprocesos de los cuales depende, stos subprocesos tambien son usados por otros programas.
El termino "volcar memoria" se refiere a coger un rango especifico de memoria y copiar el codigo contenido dentro de ese espacio en un nuevo archivo. Este proceso es usado mayormente cuando estamos frente a un programa empacado o protegido, y no tenemos el desempacador especifico. El problema cuando tenemos un programa empacado o protegido es q a la ora de desensamblarlo, nos encontraremos con una rutina de descompresion y no con el programa, esto aria q cualqier intento d crackeo sea inutil mientras no tengamos el codigo nativo del programa. Algunos tutos despues estudiaremos como "bajarnos" un programa de la memoria.
Algunos puntos importantes a resaltar en este 1er tuto son:
-Algo impresindible para aprender a crackear es tener conocimientos basicos de asm.
-Todos los progamas procesados por el procesador estan un mismo lenguaje, el lenguaje de maquina.
-Un "editor hexadecimal" es un programa q nos permite ver un programa especifico a nivel hexa y en ansi, y ademas nos permite modificarlo.
-Cuando un programa se ejecuta, el codigo de este se guarda en la memoria ram.
-La mayoria de los programas dependen de modulos.
Algunos consejos para los newbis:
-Te ira mucho mejor crackeando, si ya tienes experiencia programando.
-Los crackers deben tener una mente abierta a un mundo de posibilidades.
-La paciencia es un virtud de los crackers.
-La ingenieria inversa es como la medicina o como cualqier otra rama del hacking, si no te actualizas, te qedas obsoleto.
Auto: Cronux
Ingeniería Inversa: Definición
(Reverse Engineering).
La ingeniería inversa es el proceso de descubrir los principios
tecnológicos de un dispositivo, objeto o sistema, a través de
razonamiento abductivo de su estructura, función y operación.
La ingeniería inversa se trata de tomar algo, (un dispositivo mecánico o electrónico, un software de computadora, etc.) para analizar su funcionamiento en detalle, generalmente para intentar crear un dispositivo o programa que haga la misma o similar tarea sin copiar la original.
Usos de la ingeniería inversa
Ingeniería Inversa Del Software:
Tipo de ingeniería inversa dedicada a las aplicaciones.
En software, la ingeniería inversa puede llevarse a cabo empleando algunos de los siguientes métodos:
La ingeniería inversa se trata de tomar algo, (un dispositivo mecánico o electrónico, un software de computadora, etc.) para analizar su funcionamiento en detalle, generalmente para intentar crear un dispositivo o programa que haga la misma o similar tarea sin copiar la original.
Usos de la ingeniería inversa
- La ingeniería inversa suele ser empleada por empresas, para analizar si el producto de su competencia infringe patentes de sus propios productos.
- Muchas veces, la ingeniería inversa es utilizada en el área militar para investigar (y copiar) las tecnologías de otras naciones, sin obtener planos ni detalles de su construcción o desarrollo.
- En el software y en el hardware, la ingeniería inversa, muchas veces es empleada para desarrollar productos que sean compatibles con otros productos, sin conocer detalles de desarrollo de éstos últimos. En otras palabras, quien desarrolla los nuevos productos, no puede acceder a los detalles de fabricación de los productos de los que intenta ser compatibles.
- La ingeniería inversa también es empleada para comprobar la seguridad de un producto, generar keygens de aplicaciones, reparación de productos, etc.
Ingeniería Inversa Del Software:
Tipo de ingeniería inversa dedicada a las aplicaciones.
En software, la ingeniería inversa puede llevarse a cabo empleando algunos de los siguientes métodos:
- Desensamblar una aplicación empleando un desensamblador.
- Descompilar una aplicación empleando un descompilador: proceso que intenta recrear el código fuente en un lenguaje de alto nivel de un programa compilado.
- Análisis a través de la observación del intercambio de información, especialmente usado en la ingeniería inversa de protocolos y de controladores de dispositivos.
Suscribirse a:
Entradas (Atom)