Tal como se lee puede parecer algo un tanto extraño. Todo el mundo que programa usa las variables para leer o introducir datos en ellas (aunque a veces lo que se esta haciendo por debajo es realmente llamar a una función). El caso es que el C, y por extensión el C++ (ignoro si el C# tiene esta caracteristica) puede crear punteros a funciones. Estos punteros, como el resto, son una variable que contiene una dirección de memoria; sin embargo, su uso normal es asignarle el nombre de una función en vez de una variable, tal que así:
1 2 3 4 |
typedef unsigned int (*funcion)(const char *); funcion pepe; pepe=strlen; printf("Longitud de hola:%d\n",pepe("hola")); |
Pero que pasaría si en vez de asignarle una función le asignamos una variable? Pues
que el contenido de esa variable lo ejecutaría. Por supuesto, la variable no puede tener cualquier contenido; los bytes que contendría deberían ser codigo maquina. Por ejemplo el siguiente código en ensamblador:
1 2 |
MOV EAX,9 RET |
traducido a codigo máquina del intel x86 sería:
B8 09 00 00 00
C3
Por lo que si ejecutamos las siguientes lineas:
1 2 3 4 5 |
typedef unsigned int (*funcion)(void); funcion pepe; unsigned char juan[]={0xb8,9,0,0,0,0xc3}; pepe=(unsigned int (*)(void))(void*)juan; printf("Es un 9?:%d\n",pepe()); |
Lo que hemos hecho es llamar a una dirección de memoria que contenia una ristra de bytes, los cuales son significativos para el microprocesador. En el ejemplo hemos asignado al registro EAX (registro que almacena siempre lo que devuelve una función) el número 9 y a continuación ejecutamos un RET para retornar de la llamada de la función. Así hemos simulado una llamada a una función tal y como lo habría hecho el compilador, pudiendo incluso modificar el código (el contenido de la variable) en tiempo de ejecución sin problemas de violaciones de memoria o similares. Este código funciona tanto en Linux como en Windows siempre que sea un micro intel x86, aunque se puede usar en un motorola, power pc, o lo que querais siempre que conozcais el
lenguaje maquina del micro.
Este artículo dará pie a otro mucho más avanzado sobre como lograr que un programa original pueda acceder a un web service sin que otros se aprovechen de esa información (si usar contraseñas ni nada parecido).
Los punteros a funciones en C# son los llamados delegados. Aunque supongo que no podran apuntar a una variable cualquiera como en c/c++
Ummm, parece que se puede retomar los punteros del C y C++.
Muy interesante tu weblog. Lo he descubierto y hay algunos posts realmente brillantes (como el de cargar un diskete de boot con un menú chorra), y la mayoría son muy amenos.
Sigue así!
Dosdedos
http://www.dosdedos.tk
Muchas gracias, intentaré seguir así, aunque no siempre es fácil buscar cosas que cumplan esos criterios 😉