Pregunta

Estoy tratando de ejecutar un ataque de desbordamiento de búfer muy simple. Soy prácticamente un novato en esto. Entonces, si esta pregunta es estúpida, disculpe :-)

El código:

#include<stdio.h>
#include<stdlib.h>

int i, n;

void confused(int i) 
{
 printf("**Who called me? Why am I here?? *** %x\n ", i);
}

void shell_call(char *c) 
{
 printf(" ***Now calling \"%s\" shell command *** \n", c);
 system(c);
}

void victim_func()
{
 int a[4];
 printf("Enter n:  ");  scanf("%d",&n);
 printf("~~~~~~~~~~~~~ values and address of n locations ~~~~~~~~~~");
 for (i = 0;i <n ;i++) 
  printf ("\n a[%d] = %x, address = %x", i, a[i], &a[i]);
 printf("\nEnter %d HEX Values \n", n);

 // Buffer Overflow vulnerability HERE!

 for (i=0;i<n;i++)  scanf("%x",&a[i]);
   printf("Done reading junk numbers\n");
}

int main() 
{
 victim_func();
 printf(“\n done”);
 return 0; 
}

Cuando uso objdump para obtener las direcciones de la función, tengo lo siguiente:

main(): 0x804854d
Address of main() where printf() is called: 0x8048563
victim_func(): 0x8048455
confused(): 0x8048414

Ahora, lo que quiero es saltar a la función 'confundido ()' de victim_func () desbordando el búfer allí y sobrescribiendo la dirección de devolución a la dirección de confundido (). Y quiero volver de confundido () a la instrucción printf () en main, y salir normalmente. Entonces, proporciono la siguiente entrada

Enter n: 7
Enter 7 HEX values:
1
2
3
4
5
8048414 (This is to jump to confused)
8048563 (this is to jump to printf() in main)

Aunque el programa imprime "hecho" de esa declaración printf, está volviendo a vicim_func () e imprime "Ingrese n:"

¿Qué estoy haciendo mal? ¡Cualquier ayuda sería muy apreciada!

PD: No estoy seguro de si he hecho la pregunta correcta. Avíseme, si se necesita más información.

¿Fue útil?

Solución

Un ataque de desbordamiento de búfer es mucho más complejo que esto. En primer lugar, debe comprender el ensamblador para realizar esto. Después de desmontar el programa y la función, desea apuntar, necesita determinar el diseño de la pila cuando ejecuta esa función. Aquí hay una muestra de un desbordamiento de búfer, está usando Visual Studio, pero el principio es el mismo.

#include "stdafx.h"
#include <math.h>

volatile double  test;

double function3()
{
    test++;
    return exp(test);
}

double  function2()
{
    return log(test);
}

double  function1()
{
    int a[5] = {0};           
    a[7] = (int)&function3;
    return exp(function2());

}
int _tmain(int argc, _TCHAR* argv[])
{
    double a = function1();
    test = a;
    return a;
}

Gracias al desmontaje, sabemos que a la función1 se asigna antes, donde la función guardó el puntero del marco de la pila. El valor después de eso es la dirección de retorno donde la función1 debe ir si está finalizada.

00401090 55               push        ebp    <- we save the stack pointer
00401091 8B EC            mov         ebp,esp 
00401093 83 EC 1C         sub         esp,1Ch <- save space to allocate a[5]
00401096 B8 CC CC CC CC   mov         eax,0CCCCCCCCh 
0040109B 89 45 E4         mov         dword ptr [ebp-1Ch],eax  <- crt debug init a[5]  
0040109E 89 45 E8         mov         dword ptr [ebp-18h],eax 
004010A1 89 45 EC         mov         dword ptr [ebp-14h],eax 
004010A4 89 45 F0         mov         dword ptr [ebp-10h],eax 
004010A7 89 45 F4         mov         dword ptr [ebp-0Ch],eax 
004010AA 89 45 F8         mov         dword ptr [ebp-8],eax 
004010AD 89 45 FC         mov         dword ptr [ebp-4],eax 

A partir de esto, podemos concluir si sobrescribimos una [7] con una dirección diferente, la función no volverá a Main sino con cualquier dirección que escribamos en un [7].

Espero que esto ayude.

Otros consejos

Ahora, lo que quiero es saltar a la función 'confundido ()' de victim_func () desbordando el búfer allí y sobrescribiendo la dirección de devolución a la dirección de confundido () ...

En las plataformas modernas de Linux, también deberá asegurarse de que se desactivan dos características de seguridad para las pruebas. Primero en NX-Stacks, y el segundo es los protectores de pila.

Para apagar las pilas nx, use -Wl,z,execstack (Opuesto a -Wl,z,noexecstack). Para apagar los protectores de pila, use -fno-stack-protector (Opuesto a -fstack-protector o -fstack-protector-all).

Hay una tercera protección que es posible que necesite apagar. Esa protección es fortify_source. Fortify_source utiliza variantes "más seguras" de funciones de alto riesgo como memcpy y strcpy. El compilador utiliza las variantes más seguras cuando puede deducir el tamaño del búfer de destino. Si la copia excedería el tamaño del búfer de destino, entonces el programa llama abort(). Para deshabilitar fortify_source, compile el programa con -U_FORTIFY_SOURCE o -D_FORTIFY_SOURCE=0.

Las características de seguridad se activan de forma predeterminada porque ha habido muchos problemas en el pasado. En general, es algo bueno porque detiene muchos problemas (como el que estás experimentando).

En primer lugar, me parece que no debe ingresar el número 5 en su entrada de muestra. Su matriz se declara como [4], por lo tanto, tiene elementos indexados 0-3, por lo que su entrada de ataque me parece incorrecta.

También me parece que su programa asume varias cosas sobre la arquitectura:

  • Sizof (int) == sizeof (dirección de memoria)
  • La dirección del crecimiento y el mecanismo de la implementación de la pila de entornos

Si uno de estos supuestos es falso, nunca funcionará.

Esto parece una tarea de trabajo muy duro.

Hay ejemplos más fáciles de ataques de desbordamiento del búfer que cambiar el flujo de control del código. Por ejemplo, es posible que pueda sobrescribir otro datos que se supone que está protegido del usuario (como una configuración de seguridad)

No nos mostró la salida del programa con las direcciones de un [i]. Sospecho que el compilador está haciendo algo como alinear los datos en la pila a 16. Podría estar mucho más lejos en la dirección de devolución de lo que espera.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top