puntero a funcion

Iniciado por xiruko, 3 Septiembre 2012, 21:55 PM

0 Miembros y 5 Visitantes están viendo este tema.

xiruko

buenas a todos,

ando investigando el tema de los punteros a funciones y sus utilidades, y una que me ha llamado la atencion es la de cambiar el codigo en tiempo de ejecucion, sin tener que volver a compilar. estaba haciendo un pequeño ejemplo sacado de una web, y no se por que me da error de segmentation fault. el code es el siguiente:


#include <stdio.h>

int main() {

int (*pfn)();
char codigo[]={0x55,0x48,0x89,0xe5,0xb8,0x01,0x00,0x00,0x00,0xc9,0xc3};

pfn=&codigo[0];
printf("Valor inicial: %d\n", pfn());
codigo[5]=0x05;
printf("Valor cambiado: %d\n", pfn());

return 0;
}


la cadena "codigo" la he hecho escribiendo la siguiente funcion:


int funcion() {
return 0x01;
}


en un archivo a parte, creando luego el archivo objeto con: gcc -c funcion.c, y luego viendo su codigo binario en la terminal con una utilidad en mac llamada otool semejante a objdump.

el tema es que escribo el mismo programa que el de la web y no se por que a mi me falla... la web es esta:

http://usuarios.multimania.es/rllopis/mainMutante.html

alguien sabe que puede pasar? este es un tema completamente nuevo para mi, y con un par de buenos links de ayuda para leer ya estaria mas que satisfecho. llevo un par de horas dando vueltas por google y sigo casi como he empezado...

gracias y un saludo!

soyloqbuskas

#1
¡Buenas xiruko!

La verdad es que a ese codigo no le veo mucho sentido....no termino de entender que es lo que se pretende....pero echate un vistazo a este enlace que tiene ejemplos de punteros a funciones:

http://copstone.com/2010/01/punteros-a-funciones/

De todas formas si te da un Segment Fault (fallo de segmentacion) esto se debe a tu programa esta intentado a acceder a posiciones de memoria no permitidas. Y probablemente el fallo este en estas 2 lineas:


pfn=&codigo[0];
printf("Valor inicial: %d\n", pfn());


Al puntero pfn le estas asginado el puntero que apunta a codigo[0] (y esta posicion no esta apuntando a ninguna funcion probablemente). Por eso cuando haces el printf() y se va a ejecutar la funcion, lo que hace el programa es irse a la posicion que le has asignado al puntero (que vete a saber cual es) y resulta que alli no hay ninguna funcion y encima puede que estes accediendo a una posicion fuera del mapa de memoria asignado a tu programa.....

De hecho al compilarlo me ha dado un warning...(yo en mi caso he metido el main y la funcion en el mismo fichero...)
Citar####@%%%%:/home/%%%%%/Escritorio# gcc -Wall prueba.c -o prueba
prueba.c: In function 'main':
prueba.c:13:5: warning: assignment from incompatible pointer type [enabled by default]
Creo que ese codigo no esta bien....

Un saludo.
"Si tienes 1 manzana y yo tengo otra manzana...
y las intercambiamos, ambos seguiremos teniendo 1 manzana.
Pero...si tu tienes 1 idea y yo tengo otra idea...
y las intercambiamos, ambos tendremos 2 ideas."


George Bernard Shaw

xiruko

#2
gracias por el link, lo he mirado por encima y mas o menos eso ya es lo que habia visto, aunque ahora le dedicare un rato a leerlo bien e intentare entenderlo del todo, ya que por los comentarios parece buen material.

pero el tema es, figura que en "codigo" esta la funcion funcion() (tendria que haber cogido otro nombre...) en codigo maquina, y por lo tanto al hacer pfn=&codigo[0] lo que en teoria se esta haciendo y que ademas parece logico segun lo que hacen en la web, es decirle que el puntero a funcion apunte a donde comienza la funcion funcion(), y seguira avanzando por ahi hasta que se encuentre el return no? no se si me he liado escribiendo... pero bueno eso es lo que me gustaria realmente aprender, por eso si tienes algun link que hable sobre codigos mutantes aunque sea en ingles estaria muy agradecido.

un saludo!

edito: bueno... que no esta bien esta claro si da un segmentation fault... xD

Citarencima puede que estes accediendo a una posicion fuera del mapa de memoria asignado a tu programa.....

fuera del mapa? pero si estoy accediento a la posicion de la variable "codigo" la cual forma parte de mi programa, entonces no estoy yendo fuera no? lo de que no se encuentra ninguna funcion alli si que puede ser, aunque seguro que debe haber alguna manera de hacer algo parecido.

0xDani

Viendo el link que has puesto, es reseñable el hecho de que en el ejemplo del citado link se modifica la posicion 4 del array, no la 5.

Saludos.
I keep searching for something that I never seem to find, but maybe I won't, because I left it all behind!

I code for $$$
Hago trabajos en C/C++
Contactar por PM

xiruko

en mi caso el valor de retorno esta en la posicion 5 y en la suya el 4. aunque eso es lo de menos, he quitado la parte del codigo que cambia el numero quedandome solo con la asignacion del puntero y el primer printf, y sigue dando error.

el caso es, si declaro la variable "codigo" como local dentro del main, el error es de seg fault; en cambio si la declaro global, el error es bus error. sigo investigando y al menos he encontrado algo que puede arrojar algo de luz sobre el asunto. si consigo algo ya posteare, un saludo

avesudra

#5
Guao yo no había tocado este tema en C , te dejo esto para que lo mires: http://publications.gbdirect.co.uk/c_book/chapter5/function_pointers.html , en C++ hay problemas con los cast de tipos a (void*)() , y es un coñazo, os dejo la salida y  confirmo que funciona, por cierto que modifique el código en la posición del array no importa , pues el valor de retorno son los 4 bytes esos, lo que pasa es que les hace un cast a int.
Valor retornado por f antes de mutar   ... f() = 1
Valor retornado por f despues de mutar ... f() = 8

Process returned 0 (0x0)   execution time : 0.009 s
Press any key to continue.
Regístrate en

xiruko

#6
 :o

el que funciona?? el codigo de la web? y como lo has hecho? xD

CitarGuao yo no había tocado este tema en C

ni yo, y es una pasada lo que se puede llegar a hacer ;-)

avesudra

#7
Cita de: xiruko en  4 Septiembre 2012, 01:49 AM
:o

el que funciona?? el codigo de la web? y como lo has hecho? xD
No he hecho nada xD , qué compilador estais usando ? yo el gcc (mingw para ser exactos y bajo windows 7), esto es lo que he puesto:
CUIDADIN:
Mirad lo que pone encima de la pagina web :
CODIGO C AUTOMUTANTE.
           
            COMPILADO CON GNU GCC SOBRE CYGWIN PARA WINDOWS-98.

           
#include <stdio.h>

int main()
{
   //Declaro una variable de tipo puntero a función:
   int (*pfn)();

   /* Escribo el código máquina de la función:

       int mutante()
       {
           return 0x01;
       }

       NOTA IMPORTANTE:

       Para obtener el código máquina de una función hacemos lo siguiente:

           1.Escribir un archivo fuente con el código C de la funcion.

           2.Compilar el archivo fuente para obtener el archivo objeto:
             ($ es el prompt del sistema)

              $ cc -c mutante.c -o mutante.o

           3.Una vez tenemos el archivo objeto,vemos su codigo binario:

              $ objdump -s mutante.o

           4.Y ya está; sólo falta copiar la salida del comando anterior y
             ponerlo en un array de chars.

   */

   //código máquina equivalente de la función anterior:
   char codigo[]={
       0x55,//0
       0x89,//1
       0xe5,//2
       0xb8,//3

       0x01,//4 <-- esto lo voy a mutar después (es el entero que retorna pfn).
       0x00,//5
       0x00,//6
       0x00,//7

       0x5d,//8
       0xc3,//9
       0x90,//10
       0x90,//11

       0x90,//12
       0x90,//13
       0x90,//14
       0x90 //15
   };

   //ahora hago que el puntero a función apunte al primer elemento del array:
   pfn = &codigo[0];

   //comprobemos que efectivamente muta:
   printf("Valor retornado por f antes de mutar   ... f() = %d\n",pfn());

   //Mutar el código.Para ello,cambio el valor que retorna pfn en el array de código:
   codigo[4] = 0x8;

   printf("Valor retornado por f despues de mutar ... f() = %d\n",pfn());

   return 0;
}
Regístrate en

xiruko

pues a mi me da segmentation fault...  :huh:

avesudra

Cita de: xiruko en  4 Septiembre 2012, 01:56 AM
pues a mi me da segmentation fault...  :huh:
Mira lo que he puesto en el post de antes , lo he modificado.
Regístrate en