es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo dibujar el marco de la pila para una función en C.

1a: Examina el código a continuación y dibuja los marcos de pila cuando la función1, función2 y función3 son llamadas por el programa principal en un sistema de 32 bits. Usa objdumb y el depurador GDB para analizar el código ensamblador de las funciones. Dibuja el marco de pila después de analizar el código ensamblador. La Figura 2 muestra un marco de pila de ejemplo. El requisito de esta parte es producir tres marcos de pila correspondientes a las tres funciones del código. Las direcciones y el contenido correspondiente de la pila (según el código ensamblador de las funciones) deben incluirse de acuerdo con el formato mostrado en la Figura 2. También se debe incluir una captura de pantalla del código ensamblador de las funciones.

1b: Identifica una vulnerabilidad de software en el código. Explota la vulnerabilidad y ejecuta la función4 en lugar de la función3. Es importante tener en cuenta que la función4 nunca es llamada por la función principal. Tu tarea es inyectar un argumento de línea de comandos para que se llame a la función4 en lugar de la función3. Incluye capturas de pantalla de todo el proceso y explica el procedimiento de explotación de la pila.

int function1(int x, int y, int z)
{
    int result_func1;
    result_func1 = x + y + z;
    return result_func1
}

int function2(int x, int y, char* input_string)
{
    int result_func2;
    char buffer[20];
    strcpy(buffer, input_string);
    printf("tu cadena de entrada %s se copia en el búfer \n", input_string);
    result_func2= x - y;
    return result_func2
}

void function3(int result1, int result2)
{
    printf("El resultado de la función 1 es %d\n", result1);
    printf("El resultado de la función 1 es %d\n", result1);
}

void function4(void)
{
    printf("La función nunca es llamada \n");
    exit(-1);
}
int main(int argc, char* argv[])
{
    int result1;
    int result2;
    result1 = function1(5, 10, 15);
    result2 = function2(20, 8, argv[1]);
    function3(result1, result_func1);
}

Marco de pila de la función1

Apreciaría mucho si alguien pudiera ayudarme.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    1a: Para dibujar los marcos de la pila, es necesario analizar el código ensamblador de cada función utilizando objdump y el depurador GDB. Esto te ayudará a identificar el tamaño del marco de la pila, las direcciones de memoria de las variables locales y la dirección de retorno. Luego, puedes dibujar el marco de la pila de acuerdo al formato mostrado en la Figura 2, incluyendo la dirección y contenido de la pila.

    Por ejemplo, para la función1:

    int function1(int x, int y, int z)
    {
        int result_func1;
        result_func1 = x + y + z;
        return result_func1;
    }
    

    El código ensamblador se puede obtener mediante el comando:

    $ objdump -d -M intel a.out
    

    Debes identificar las instrucciones que asignan espacio para las variables locales y empujan la dirección de retorno a la pila. Por ejemplo:

    08048608 <function1>:
     8048608:      55                      push   ebp
     8048609:      89 e5                   mov    ebp,esp
     804860b:      83 ec 18                sub    esp,0x18
     804860e:      8b 45 08                mov    eax,DWORD PTR [ebp+0x8]
     8048611:      03 45 0c                add    eax,DWORD PTR [ebp+0xc]
     8048614:      03 45 10                add    eax,DWORD PTR [ebp+0x10]
     8048617:      89 45 f4                mov    DWORD PTR [ebp-0xc],eax
     804861a:      8b 45 f4                mov    eax,DWORD PTR [ebp-0xc]
     804861d:      c9                      leave
     804861e:      c3                      ret
    

    Puedes ver que la función comienza empujando el puntero base (ebp) a la pila y moviendo el puntero de pila (esp) al puntero base. Luego asigna 0x18 bytes de espacio en la pila para las variables locales restando 0x18 del puntero de pila. Finalmente, mueve los parámetros (x, y, z) a registros, realiza la suma y guarda el resultado en la variable local result_func1. Antes de retornar, mueve el resultado al registro eax, desempuja el puntero base y retorna desempujando la dirección de retorno de la pila.

    Utilizando esta información, puedes dibujar el marco de la pila para la función1, incluyendo la dirección y contenido de la pila.

    1b: Para aprovechar la vulnerabilidad en el código, necesitas utilizar un desbordamiento de búfer para sobrescribir la dirección de retorno en la pila y redirigir la ejecución del código a la función4 en lugar de la función3. Esto se puede hacer proporcionando una cadena de entrada que sea más larga que el tamaño del búfer (20 bytes) en la función2.

    Por ejemplo:

    int main(int argc, char* argv[])
    {
        int result1;
        int result2;
        result1 = function1(5, 10, 15);
        result2 = function2(20, 8, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB" "\x80\x85\x04\x08");
        function3(result1, result2);
    }
    

    En este ejemplo, la cadena de entrada es “AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB” seguida de la dirección de function4 (0x08048580) en formato little-endian. Esto sobrescribirá la dirección de retorno en la pila con la dirección de function4 y redirigirá la ejecución del código a esa función en lugar de la función3.

    Puedes utilizar el depurador GDB para verificar que el desbordamiento de búfer funcione como se espera y se llame a la función4 en lugar de la función3. Asegúrate de incluir capturas de pantalla de todo el proceso, incluyendo la cadena de entrada, el marco de la pila antes y después del desbordamiento de búfer y la salida del programa.

Comments are closed.