Publicidad
Publicidad

RSS Ingeniería de Software

¿Cómo funciona el memory breakpoint en un depurador de C/C++? (breakpoints part III)

Comentar
¿Cómo funciona el memory breakpoint en un depurador de C/C++? (breakpoints part III)
Desensamblador y Depurador IDA corriendo en Windows

En el último artículo de la serie vimos lo útiles que pueden llegar a ser los hardware breakpoints para depurar aplicaciones que por ejemplo hacen comprobaciones de CRC y no pueden ser depuradas modificando sus datos en memoria.

Hoy vamos a ver como podemos utilizar memory breakpoints para sobrepasar los límites impuestos por los hardware breakpoints y poder entre otras cosas controlar el acceso a grandes partes de la memoria.

Leer más »

¿Cómo funciona el hardware breakpoint en un depurador de C/C++? (breakpoints part II)

Comentar
¿Cómo funciona el hardware breakpoint en un depurador de C/C++? (breakpoints part II)

Ayer vimos como el depurador reemplaza el primer byte de un opcode en una dirección de memoria específica donde, previamente, hemos fijado un breakpoint y donde colocamos el opcode 0xcc o lo que es lo mismo la instrucción int 3 que le indica al procesador que se detenga y lance un evento de depurado que es capturado por el depurador.

También vimos que en este proceso, al sobreescribir parte de la memoria del proceso en depuración se modifica el CRC del mismo y algunas aplicaciones (como la mayoría del malware) comparan el CRC contra un checksum válido y si han habido modificaciones el proceso se mata a sí mismo para no permitir la depuración. En esos casos es necesario echar mano de los hardware breakpoints.

Leer más »
Publicidad

¿Cómo funciona el breakpoint en un depurador de C/C++?

1 Comentario
¿Cómo funciona el breakpoint en un depurador de C/C++?

addEventListener('load', function (event) { prettyPrint() }, false);

Y llegamos al punto caliente de nuestra serie sobre el funcionamiento de los depuradores de C y C++. Ya sabemos como funciona la CPU y la pila de la memoria. También sabemos que son los eventos de depurado y que el sistema operativo ofrece una interfaz para atraparlos.

Hoy vamos a hablar en profundidad sobre los puntos de interrupción o "breakpoints" que son sin duda la parte fundamental de cualquier depurador. Hoy vamos a aprender como fijarlos y como son utilizados por el depurador de forma interna para ayudarnos a depurar nuestros procesos.

Leer más »

¿Cómo funciona un depurador de C/C++? (Parte III)

Comentar
¿Cómo funciona un depurador de C/C++? (Parte III)

En esta serie ya hemos hablado sobre los registros de carácter general del procesador en arquitectura x86 y de como funciona la pila o stack. Ambos conceptos son completamente necesarios para lograr entender en profundidad como funciona un depurador.

Hoy vamos a hablar sobre los eventos de depurado. De forma abstracta, un depurador no es más que un bucle sin fin que espera a que sucedan eventos de depurado. Cuando sucede un evento, el bucle se rompe, y se invoca a un manejador o handler de eventos cualificado para procesarlo.

Leer más »

¿Cómo funciona un depurador de C/C++? (Parte II)

3 Comentarios
¿Cómo funciona un depurador de C/C++? (Parte II)

addEventListener('load', function (event) { prettyPrint() }, false);

Ayer hablábamos sobre la CPU y los registros de propósito general para entender como procesa a bajo nivel el hardware de nuestro sistema el código compilado al interpretar los opcodes que generan los compiladores.

Hoy vamos a ver muy brevemente como funciona la memoria y más específicamente la pila en la arquitectura x86. De esta forma todos estos conceptos no nos serán arcanos cuando entremos en detalles de ¿cómo funciona un depurador de C/C++?.

La pila es una estructura que es necesario e importante comprender cuando se desarrolla un depurador. La pila almacena información acerca de como una función es invocada, los parámetros que recibe (aunque en la arquitectura x86_64 esto no es del todo cierto) y como y a donde debe volver cuando finaliza la ejecución de la misma.

Leer más »

¿Cómo funciona un depurador de C/C++? (Parte I)

23 Comentarios
¿Cómo funciona un depurador de C/C++? (Parte I)

addEventListener('load', function (event) { prettyPrint() }, false);

Todos aquellos programadores que hayan programado en C o C++ conocen los típicos depuradores de código disponibles para el código máquina generado por el compilador de dichos lenguajes.

Dependiendo del sistema operativo estaremos acostumbrados a gdb y sus amigos (ddd, kgdb, etc, etc), LLDB, WinDbg, OllyDbg, etc. No vamos a entrar en cual de estos depuradores es mejor sino que vamos a hacer un pequeño recorrido por su funcionamiento interno.

Para entender el funcionamiento de un depurador, primero debemos entender el funcionamiento del procesador y de la memoria.

Leer más »
Publicidad

Ecosistema ALM en .NET. Breve introducción a metodologías de desarrollo

6 Comentarios
Ecosistema ALM en .NET. Breve introducción a metodologías de desarrollo

La construcción de un software es un ejercicio de trabajo y tiempo considerable, de gran complejidad incluso en sus formas más simples y que debe permanecer activo en el tiempo con una importancia cada vez más grande en la sociedad actual.

Por ello la generación de aplicaciones informáticas por la metodología de ASM (A Salto de Mata) no solamente es negativa sino que implica riesgos inasumibles para las empresas que se dedican al desarrollo. Aunque demasiadas de ellas aún no le dan la importancia que tiene.

Así, al menos desde la década de los años 70 del siglo pasado, ha ido evolucionando la idea de ALM. Que son las fases que todo proyecto deberá superar para intentar conseguir ese objetivo tan resbaladizo como es el éxito.

En esta serie que empiezo, voy a desgranar el ecosistema que tenemos en .Net para gestionar las necesidades de cualquier metodología que utilicemos para gestionar el ALM de nuestras aplicaciones, pero desde el punto de vista del desarrollador. Y con un importante componente de la filosofía Agile en los artículos.

Leer más »

Optimizando al máximo: Bitvectores

58 Comentarios
Optimizando al máximo: Bitvectores

addEventListener('load', function (event) { prettyPrint() }, false);



Cuando programamos cualquier tipo de aplicación, es común la necesidad de almacenar estados o valores de tipo boleano para nuestras estructuras de datos. Si por ejemplo programamos en C99 podemos hacer uso del tipo _Bool que ocupa un byte de longitud, también ocupa un byte el tipo bool de C++.

Sin embargo, utilizar un byte para un valor que puede ser representado por un único bit es un gasto del 88% más de recursos de los estríctamente necesarios si partimos de la base de que un byte puede almacenar ocho bits y representar 256 valores diferentes.

Si en nuestra aplicación necesitamos guardar estados o flags sobre nuestras estructuras de datos, podemos utilizar un tipo de dato para almacenar estados mucho más eficiente que un array de elementos de un byte de longitud o que propiedades de tipo booleano. Podemos usar Bitvectores.

Leer más »

¿Por qué es importante definir y validar casos de uso?

14 Comentarios
¿Por qué es importante definir y validar casos de uso?

Anteriormente hemos hablado sobre la importancia de saber valorar y definir nuestros recursos y lo que cuesta nuestro tiempo a la hora de acometer cualquier proyecto de autoempleo. También hemos hablado sobre la importancia de las metodologías en el trabajo autoempleado. Pero aún no hemos hablado de ¿Por qué es importante definir y validar casos de uso?.

En mayor o menor medida, todos conocemos lo que es un caso de uso y para que se utiliza. Muchos profesionales ven la tarea de definir casos de uso como algo tedioso y aburrido que al final, no vale para nada. No voy a entrar a valorar la magnitud del error que creo que comete ese tipo de profesional con ese tipo de aseveración. Definir un documento de especificación funcional es tarea fundamental a la hora de defender nuestros proyectos y legitimar los cambios facturables a los mismos.

Leer más »
Publicidad

Ver más artículos