Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: xiruko en 3 Septiembre 2012, 21:55 pm



Título: puntero a funcion
Publicado por: xiruko en 3 Septiembre 2012, 21:55 pm
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:

Código
  1. #include <stdio.h>
  2.  
  3. int main() {
  4.  
  5. int (*pfn)();
  6. char codigo[]={0x55,0x48,0x89,0xe5,0xb8,0x01,0x00,0x00,0x00,0xc9,0xc3};
  7.  
  8. pfn=&codigo[0];
  9. printf("Valor inicial: %d\n", pfn());
  10. codigo[5]=0x05;
  11. printf("Valor cambiado: %d\n", pfn());
  12.  
  13. return 0;
  14. }

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

Código
  1. int funcion() {
  2. return 0x01;
  3. }

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 (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!


Título: Re: puntero a funcion
Publicado por: soyloqbuskas en 3 Septiembre 2012, 22:47 pm
¡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/ (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:

Código
  1. pfn=&codigo[0];
  2. printf("Valor inicial: %d\n", pfn());
  3.  

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.


Título: Re: puntero a funcion
Publicado por: xiruko en 3 Septiembre 2012, 22:58 pm
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

Citar
encima 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.


Título: Re: puntero a funcion
Publicado por: 0xDani en 3 Septiembre 2012, 23:44 pm
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.


Título: Re: puntero a funcion
Publicado por: xiruko en 4 Septiembre 2012, 00:06 am
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


Título: Re: puntero a funcion
Publicado por: avesudra en 4 Septiembre 2012, 01:29 am
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.
Código:
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.


Título: Re: puntero a funcion
Publicado por: xiruko en 4 Septiembre 2012, 01:49 am
 :o

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

Citar
Guao yo no había tocado este tema en C

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


Título: Re: puntero a funcion
Publicado por: avesudra en 4 Septiembre 2012, 01:52 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.

           
Código
  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5.    //Declaro una variable de tipo puntero a función:
  6.    int (*pfn)();
  7.  
  8.    /* Escribo el código máquina de la función:
  9.  
  10.         int mutante()
  11.         {
  12.             return 0x01;
  13.         }
  14.  
  15.         NOTA IMPORTANTE:
  16.  
  17.         Para obtener el código máquina de una función hacemos lo siguiente:
  18.  
  19.             1.Escribir un archivo fuente con el código C de la funcion.
  20.  
  21.             2.Compilar el archivo fuente para obtener el archivo objeto:
  22.               ($ es el prompt del sistema)
  23.  
  24.                $ cc -c mutante.c -o mutante.o
  25.  
  26.             3.Una vez tenemos el archivo objeto,vemos su codigo binario:
  27.  
  28.                $ objdump -s mutante.o
  29.  
  30.             4.Y ya está; sólo falta copiar la salida del comando anterior y
  31.               ponerlo en un array de chars.
  32.  
  33.     */
  34.  
  35.    //código máquina equivalente de la función anterior:
  36.    char codigo[]={
  37.        0x55,//0
  38.        0x89,//1
  39.        0xe5,//2
  40.        0xb8,//3
  41.  
  42.        0x01,//4 <-- esto lo voy a mutar después (es el entero que retorna pfn).
  43.        0x00,//5
  44.        0x00,//6
  45.        0x00,//7
  46.  
  47.        0x5d,//8
  48.        0xc3,//9
  49.        0x90,//10
  50.        0x90,//11
  51.  
  52.        0x90,//12
  53.        0x90,//13
  54.        0x90,//14
  55.        0x90 //15
  56.    };
  57.  
  58.    //ahora hago que el puntero a función apunte al primer elemento del array:
  59.    pfn = &codigo[0];
  60.  
  61.    //comprobemos que efectivamente muta:
  62.    printf("Valor retornado por f antes de mutar   ... f() = %d\n",pfn());
  63.  
  64.    //Mutar el código.Para ello,cambio el valor que retorna pfn en el array de código:
  65.    codigo[4] = 0x8;
  66.  
  67.    printf("Valor retornado por f despues de mutar ... f() = %d\n",pfn());
  68.  
  69.    return 0;
  70. }
  71.  


Título: Re: puntero a funcion
Publicado por: xiruko en 4 Septiembre 2012, 01:56 am
pues a mi me da segmentation fault...  :huh:


Título: Re: puntero a funcion
Publicado por: avesudra en 4 Septiembre 2012, 01:59 am
pues a mi me da segmentation fault...  :huh:
Mira lo que he puesto en el post de antes , lo he modificado.


Título: Re: puntero a funcion
Publicado por: xiruko en 4 Septiembre 2012, 02:04 am
acabo de buscar lo que era cygwin ya que no tenia ni idea. bueno yo estoy con mac os 64bit y con gcc. puede ser que ese programa sea para 32bits, lastima que no tenga ni idea de que es lo que cambia de una a otra a parte de un poco de teoria xD

en fin, al menos se que funcionar funciona, voy a buscar por ahi a ver que encuentro.


Título: Re: puntero a funcion
Publicado por: avesudra en 4 Septiembre 2012, 02:07 am
acabo de buscar lo que era cygwin ya que no tenia ni idea. bueno yo estoy con mac os 64bit y con gcc. puede ser que ese programa sea para 32bits, lastima que no tenga ni idea de que es lo que cambia de una a otra a parte de un poco de teoria xD

en fin, al menos se que funcionar funciona, voy a buscar por ahi a ver que encuentro.
Nah ni yo tengo cygwin lo he utilizado algunas veces para tutoriales de compilar librerías y eso pero bah, puedes ser pero lo que me parece muy muy extraño es que me funcione tanto tu código como el de la web, porque tienen valores diferentes.


Título: Re: puntero a funcion
Publicado por: xiruko en 4 Septiembre 2012, 02:15 am
entonces el mio te funciona?? es bueno saberlo, aunque si que es raro raro que te funcionen los dos codigos. yo me habia hecho el mio ya que al ser diferente plataforma preferi hacermelo antes que usar el suyo. pero si te funcionan los dos... pff no tengo ni idea de nada la verdad xD

a ver si se pasa alguien y nos puede iluminar un poco.


Título: Re: puntero a funcion
Publicado por: avesudra en 4 Septiembre 2012, 02:28 am
Si mira la salida la tienes abajo, yo creo que me estoy metiendo demasiado sin saber , pero lo mismo no es que sea un segmentation fault , si no que no tiene permisos de ejecución en esa zona de memoria... Cógete un debugger, y analiza el código(El ida por ejemplo en http://www.hex-rays.com/products/ida/support/download_freeware.shtml) o el gdb es un debugger en ASM , así puedes ver por donde va.
Código:
Valor inicial: 1
Valor cambiado: 5

Process returned 0 (0x0)   execution time : 0.011 s
Press any key to continue.


Título: Re: puntero a funcion
Publicado por: xiruko en 4 Septiembre 2012, 02:38 am
ya lo hice antes, pero la verdad no se que buscar. quiero decir que si, veo que el programa peta en el momento de: pfn=&codigo[0], y dice que no tiene acceso a esa zona de memoria (vamos, lo que es un seg fault). eso si declaro la variable local dentro del main. en cambio, si la declaro global el error que me da es bus error.

la verdad que ni idea... estoy buscando informacion pero cada nueva web que miro, todo es nuevo para mi y me pierdo al momento. pero bueno, ya tenia ganas de aprender algo nuevo en c que me llamara la atencion asi que a ello voy... algun dia volvere con la respuesta. espero no tardar mucho :D


Título: Re: puntero a funcion
Publicado por: avesudra en 4 Septiembre 2012, 02:46 am
ya lo hice antes, pero la verdad no se que buscar. quiero decir que si, veo que el programa peta en el momento de: pfn=&codigo[0], y dice que no tiene acceso a esa zona de memoria (vamos, lo que es un seg fault). eso si declaro la variable local dentro del main. en cambio, si la declaro global el error que me da es bus error.

la verdad que ni idea... estoy buscando informacion pero cada nueva web que miro, todo es nuevo para mi y me pierdo al momento. pero bueno, ya tenia ganas de aprender algo nuevo en c que me llamara la atencion asi que a ello voy... algun dia volvere con la respuesta. espero no tardar mucho :D
Ya ya pero con uno en assembler puedes ver en que instrucción peta, bueno a ver si vienen algunos expertos por este post jajaja, te dejo las capturas en asm del OllyDbg de tu código:
Zona de printfs:
(http://img225.imageshack.us/img225/5411/mutablecodeprintfs.png)
Primera llamada:
(http://img829.imageshack.us/img829/3552/primerallamadaafuncion.png)
Segunda llamada:
(http://img801.imageshack.us/img801/7708/segundallamadaafuncion.png)


Título: Re: puntero a funcion
Publicado por: fary en 4 Septiembre 2012, 11:40 am
Ya ya pero con uno en assembler puedes ver en que instrucción peta, bueno a ver si vienen algunos expertos por este post jajaja, te dejo las capturas en asm del OllyDbg de tu código:
Zona de printfs:
(http://img225.imageshack.us/img225/5411/mutablecodeprintfs.png)
Primera llamada:
(http://img829.imageshack.us/img829/3552/primerallamadaafuncion.png)
Segunda llamada:
(http://img801.imageshack.us/img801/7708/segundallamadaafuncion.png)


El problema es que el está en mac, para windows creo que sobraría con dar permisos PAGE_EXECUTE_READWRITE Con la API VirtualProtect a la parte de memoría que queremos modificar en tiempo de ejecución.

saludos.


Título: Re: puntero a funcion
Publicado por: avesudra en 4 Septiembre 2012, 13:25 pm
El problema es que el está en mac, para windows creo que sobraría con dar permisos PAGE_EXECUTE_READWRITE Con la API VirtualProtect a la parte de memoría que queremos modificar en tiempo de ejecución.

saludos.
Lo sé pero el caso es que a mí me funciona perfectamente, es curioso , es que esa parte de memoria es solo para ser leída y escribida nada más ¿no mDrinky? y no ejecutada.


Título: Re: puntero a funcion
Publicado por: fary en 4 Septiembre 2012, 14:42 pm
Lo sé pero el caso es que a mí me funciona perfectamente, es curioso , es que esa parte de memoria es solo para ser leída y escribida nada más ¿no mDrinky? y no ejecutada.
    No, esa parte es de ejecucion. Pero para poder modificarla tienes que tener derecho de escritura. 


Título: Re: puntero a funcion
Publicado por: avesudra en 4 Septiembre 2012, 14:50 pm
    No, esa parte es de ejecucion. Pero para poder modificarla tienes que tener derecho de escritura. 
Pero si es un array de char , ¿que menos que pueda ser modificado no?No lo entiendo :xD además si a mi me funciona , me deberia echar para atras por no poder escribir ¿no? Es curioso...


Título: Re: puntero a funcion
Publicado por: fary en 4 Septiembre 2012, 17:53 pm
Pero si es un array de char , ¿que menos que pueda ser modificado no?No lo entiendo :xD además si a mi me funciona , me deberia echar para atras por no poder escribir ¿no? Es curioso...

Tambien depende de como compile y en que sección se pongan las variables... estamos entrando ya en el formato PE.

saludos.


Título: Re: puntero a funcion
Publicado por: avesudra en 4 Septiembre 2012, 23:32 pm
Tambien depende de como compile y en que sección se pongan las variables... estamos entrando ya en el formato PE.

saludos.
Entiendo entiendo , ya no tengo ni idea del formato PE , así que no sé.

¡Un saludo!


Título: Re: puntero a funcion
Publicado por: roilivethelife en 5 Septiembre 2012, 22:50 pm
Parece un tema interesante, se podria utilizar en un crypter para ocultar funciones, pero lo veo chungo de aplicar...


Título: Re: puntero a funcion
Publicado por: Fire544 en 11 Septiembre 2012, 04:02 am
Son punteros de funciones que apuntan a codigo en ejecucion no a datos, como los punteros de tipos, claro se pueden hacer cosas interesantes, porque creen que los grandes del lenguaje como Dennis R. Dice "La  potencia del lenguaje esta en el uso de punteros".


Título: Re: puntero a funcion
Publicado por: avesudra en 11 Septiembre 2012, 04:03 am
Son punteros de funciones que apuntan a codigo no a datos, como los punteros de tipos, claro se pueden hacer cosas interesantes, porque creen que los grandes del lenguaje como Dennis R. Dice "La  potencia del lenguaje esta en el uso de punteros".
Lamentablemente , no dice , decía.


Título: Re: puntero a funcion
Publicado por: Fire544 en 11 Septiembre 2012, 04:04 am
xDDD, si claro, mira a ver o sea se puede alterar el flujo de datos en cualquier software de cualquier magnitud en ejecucion, y tener control total de este, sin tener que trabajar con la Programacion tediosa en ASM !!


Título: Re: puntero a funcion
Publicado por: X3R4CK3R en 13 Septiembre 2012, 06:41 am
Corroboro que es bastante interesante y útil, una pena que por lo visto no sea tan fácil en C++. Alguien podría dejar alguna info para hacer lo equivalente en C++?

Saludos


Título: Re: puntero a funcion
Publicado por: fary en 13 Septiembre 2012, 14:38 pm
Corroboro que es bastante interesante y útil, una pena que por lo visto no sea tan fácil en C++. Alguien podría dejar alguna info para hacer lo equivalente en C++?

Saludos

En C++ es exactamente igual. Solo que funciones estandart usas las de C++ envez de las de C.

saludos.


Título: Re: puntero a funcion
Publicado por: systemfirst97 en 28 Enero 2014, 21:31 pm
¡Buenas xiruko!

La verdad es que a ese codigo no le veo mucho sentido....no termino de entender que es lo que se pretende

estoy de  acuerdo con el e checado el codigo deteniada mente y al termino no e encontrado un sentido a este codigo ya que el autor solo juega con las localidades de memoria y para mostrar el valor modificado solo cambia el valor de la posicion inicia,

o al menos no e comprendido la finalidad de ese codigo si algunos  la comprendido favor de comentar para que los demas  podamos veririficar el codigo


Título: Re: puntero a funcion
Publicado por: xiruko en 28 Enero 2014, 23:14 pm
La gracia de esta idea de código mutante es poder modificar el código en tiempo de ejecución. El código que pone el autor es solo un ejemplo básico para mostrar esta idea. En él, se usar un array de char para almacenar el código máquina de esa función simple que solo retorna un número. Y la gracia es cambiar ese número de retorno cuando corres el programa.

Uno de los casos prácticos para aplicar esto sería por ejemplo un virus que cuando se ejecutase o autoreplicase, lo hiciera siempre con una nueva versión del código sin que estos cambios afectaran a las funciones principales del virus. O sino un sistema de cifrado que trabajara en tiempo de ejecución conforme se necesiten las funciones cifradas para después de usarlas volverlas a cifrar, en lugar de descifrar todo el código al inicio de la ejecución y dejarlo visible mientras corra el programa.

Las aplicaciones de esto son muy atractivas, aunque como puedes imaginarte nada triviales.

Un saludo.