solucionar segmentation error dumped como c buffer-overflow shellcode

c - segmentation - Intento de aplastamiento de pila dando segfault



segmentation fault(core dumped) c error (5)

Estoy tratando de hacer un ejemplo de Smashing the Stack para Fun and Profit in C, pero estoy algo atrapado en un punto, el siguiente es el código (tengo una máquina de 64 bits con Ubuntu de 64 bits):

int main() { int x; x = 0; func(1,2,3); x = 1; printf("x is : %d/n", x); } void func(int a, int b, int c) { char buffer[1]; int *ret; ret = buffer + 17; (*ret) += 7; }

El código anterior funciona bien y al devolver la línea x=1 no se ejecuta, pero no puedo entender la lógica detrás de ret = buffer + 17; , ¿no debería ser ret = buffer + 16; es decir, 8 bytes para el buffer y 8 para el puntero base guardado en la pila.

En segundo lugar, entiendo que el char buffer[1] está tomando 8 bytes (debido al arco de 64 bits) y si aumento este búfer para decir buffer[2] , aún el mismo código debería funcionar bien, PERO esto no está sucediendo y comienza a dar falla seg.

Saludos, Numan


Además de (o mejor aún, además de) ejecutar un depurador, también puede usar la construcción printf "% p" para imprimir las direcciones de sus variables, por ejemplo:

printf("buf: %p/n", buffer); //&buffer[0] works too; &buffer works for an array printf("ret: %p/n", &ret): printf("a: %p/n", &a);

Imprimir las direcciones de varias cosas puede dar una gran idea de cómo su compilador / implementación está organizando cosas en segundo plano. ¡Y también puedes hacerlo directamente desde el código C!


Con mucha de esta pila de cosas sensacionales, tu mejor amigo es gdb . Ya que estás segfaulting ya estás escribiendo memoria que no deberías ser (una buena señal). Una forma más efectiva de hacerlo bien es cambiar la dirección del remitente a otro lugar que sea una dirección válida (por ejemplo, a la dirección de la función o a algún shellcode que tenga). Un gran recurso que recomendaría es el Manual del Shellcoder , pero como tiene una arquitectura de 64 bits, muchos de los ejemplos necesitan un poco de trabajo para comenzar.



Paso a paso por el desmontaje en gdb (disassemble, stepi, nexti) y observe los registros en cada paso (registros de información).

Aquí cómo puede pasar por el desmontaje:

gdb ./myprogram break main run display/4i $eip stepi stepi ... info registers ...

También debería saber (probablemente ya lo hace dado que consiguió que funcione) que en muchas distribuciones, el protector de pila está habilitado por defecto en gcc. Puedes desactivarlo manualmente con -fno-stack-protector .


''char'' en cada arquitectura que he usado tiene 8 bits de ancho, independientemente de si se trata de un micro de 8 bits, un micro de 16 bits, un PC de 32 bits o un PC nuevo de 64 bits. Int, por otro lado, tiende a ser el tamaño de la palabra.

El orden en que los locales se colocan en la pila puede ser específico de la implementación. Supongo que tu compilador está poniendo "int * ret" en la pila antes de "char buffer 1 ". Entonces, para llegar a la dirección de retorno, tenemos que pasar por "char buffer 1 " (1 byte), "int * ret" (8 bytes) y el puntero base guardado (8 bytes) para un total de 17 bytes.

Aquí hay una descripción del marco de la pila en x86 de 64 bits: http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-035-computer-language-engineering-spring-2010/projects / x86-64