Llamadas a funciones de DLL desde C+ASM

20/04/2004 - 16:26 por Seth | Informe spam
Hola,

Tengo un problemilla, he de hacer una librería puente para llamar a una API
sobre la que no tengo control. A priori (en tiempo de diseño) no conozco el
número de argumentos ni el nombre de la función ni nada de nada...
únicamente algunos datos como que siempre devuelve un long y los tipos
estándar que acepta como entrada. En tiempo de ejecución me van a pasar un
string que tendré que parsear y con él obtendré el nombre de función y los
argumentos.

Visto lo visto, no puedo usar el típico GetProcAddress y hacer un cast con
el prototipo por lo que supongo que voy a tener que recurrir a assembler
dentro de una librería en C/C++ (uso Visual C++) para el paso y recogida por
la pila. Lo malo es que no lo he hecho nunca y, aunque se que se puede, no
se como... tampoco se si es posible verificar el número de argumentos para
que no me hagan ningun estropicio (me imagino que esto es imposible).
¿Alguien me puede hechar una mano o algun ejemplo?


Unos datos más: las funciones exportadas por la API son con el modelo
c_decl, siempre devuelven un long y por lo que me han comentado hasta ahora,
los argumentos de todas las funciones son punteros a tipos de datos
conocidos.


Saludos y muchas gracias,
Carlos

Preguntas similare

Leer las respuestas

#1 Cholo Lennon
20/04/2004 - 17:16 | Informe spam
LoadLibrary/GetProcAddress lo vas a tener que usar seguro!. Es la única
forma de obtener un puntero el punto de entrada de la función. La cuestión
es que argumentos colocas en la pila y donde la función retorna un resultado
(Esto, por lo general, para tipos enteros es en el registro EAX).
Como ayuda, puedes usar algun desensamblador para ver la forma de la función
en la DLL. Te recomiendo IDA Pro, es el mejor para este tipo de casos. Con
el podrás entre otras cosas identificar que valores puestos en la pila son
parámetros y cuales son variables locales.
Si tienes más información para ayudarte, será bienvenida (por ejemplo la DLL
misma).

Saludos
Cholo Lennon
Salta, ARG
Respuesta Responder a este mensaje
#2 Seth
20/04/2004 - 17:49 | Informe spam
Hola Cholo,

Sí claro, GetProcAddress lo voy a tener que usar, pero para pasar parámetros
me imagino que tendré que usar los push de asm y un call para llamar a la
función.

Te pongo un modelo de la función puente que quería implementar, en realidad
lo que necesito es un ejemplo de código en C que use asm para llamar a una
función, algo así:

typedef struct __stdArg {
DWORD tipo;
DWORD lpNombre
DWORD lpData;
} stdArg;

long APIBridge( const char * buf )
{
long lret = 0;
char * funcion;
stdArg ** args;
int numargs;
...
// Parsear string, obtener nombre de función y crear argumentos
...
DWORD lpFun = (DWORD) GetProcAddress( hLib, funcion );
if ( lpFun != NULL ) {


//PARTE A IMPLEMENTAR EN ASM
//llenar los argumentos ¿con push? todos los argumentos son punteros
a estructuras
//obtener el valor long devuelto y ponerlo en iret
//


} else {
lret = -1;
}

return lret;
}


las funciones a llamar tienen un aspecto así:

long FuncionEjemplo( DWORD arg1, DWORD arg2, ..., DWORD argN );

y como comentaba están exportadas con modelo c_decl.


De hecho creo que lo básico es saber como obtener desde ASM valores de
variables declaradas en C y como modificar una variable en C (tipo long)
desde ASM


Gracias de nuevo,
Carlos
Respuesta Responder a este mensaje
#3 Mario Ruiz
20/04/2004 - 18:37 | Informe spam
Otra posible solución es si puedes indicar al que hace la librería es que
los parámetros que le metes y / o devuelve la función sean del tipo LPVOID.
En ese caso, en tiempo de ejecución metes toda la información (p.e. Un
entero, un flotate, una cadena, etc..) en un array de char / byte y pasa el
puntero de esos datos la función interpreta el array de bytes en las
información que quiere


"Seth" escribió en el mensaje
news:c63bk7$7g335$
Hola,

Tengo un problemilla, he de hacer una librería puente para llamar a una


API
sobre la que no tengo control. A priori (en tiempo de diseño) no conozco


el
número de argumentos ni el nombre de la función ni nada de nada...
únicamente algunos datos como que siempre devuelve un long y los tipos
estándar que acepta como entrada. En tiempo de ejecución me van a pasar un
string que tendré que parsear y con él obtendré el nombre de función y los
argumentos.

Visto lo visto, no puedo usar el típico GetProcAddress y hacer un cast con
el prototipo por lo que supongo que voy a tener que recurrir a assembler
dentro de una librería en C/C++ (uso Visual C++) para el paso y recogida


por
la pila. Lo malo es que no lo he hecho nunca y, aunque se que se puede, no
se como... tampoco se si es posible verificar el número de argumentos para
que no me hagan ningun estropicio (me imagino que esto es imposible).
¿Alguien me puede hechar una mano o algun ejemplo?


Unos datos más: las funciones exportadas por la API son con el modelo
c_decl, siempre devuelven un long y por lo que me han comentado hasta


ahora,
los argumentos de todas las funciones son punteros a tipos de datos
conocidos.


Saludos y muchas gracias,
Carlos


Respuesta Responder a este mensaje
#4 Seth
20/04/2004 - 18:48 | Informe spam
Hola Mario,

Bueno, eso es una idea parecida a lo que intento hacer. De hecho el problema
es que no tenemos control sobre la API así que la opción queda descartada.

Gracias de todas formas,
Carlos
Respuesta Responder a este mensaje
#5 Cholo Lennon
20/04/2004 - 21:22 | Informe spam
Quizás no te haga falta trabajar con ensamblador, ya que puedes usar una
función con argumentos variables. Mira por ejemplo la siguiente función como
la declaro y obvserva tambien el código en ensamblador generado:

extern "C" {
// Función C
long Prueba(DWORD p1, ... ) {
return 0;
}
}

int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
/* el codigo asm para la instrucción siguiente es:
push 4
push 3
push 2
push 1
call Prueba ; llama a la funcion
add esp,10h ; ajusta el stack (convención C)
dword ptr [ebp-4],eax ; mueve el valor de retorno (eax) a
'retorno'
*/

long retorno;
retorno = Prueba(1,2,3,4);

return 0;
}

Como puedes ver simplemente tendrás que declarar un puntero a función con
argumentos variables. Luego simplemente mediante casting necesario lo cargas
con lo devuelto por GetProcAddress. La llamada luego la haces mediante una
simple función C. Lo que coloques en los argumentos ya corre por cuenta de
quien lo interprete, ya que pueden ser valores o direcciones.


Saludos
Cholo Lennon
Salta, ARG
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida