Título: Llamar a una funcion de una DLL cargada dinamicamente Publicado por: PHREDA en 12 Julio 2021, 03:08 am Hola:
Estoy haciendo un interprete y necesito llamar a una funcion tomada de una dll cargada dinamicamente, esto es asi ya que quiero que el programa interpretado cargue la dll y no el interprete. Ademas necesito que los parametros se encuentren en un pila de enteros. aqui tengo un fragmento del codigo que estoy probando Código: HANDLE hStdout; la llamada comentada funciona ok ya que no lo esta haciendo por la direccion de la funcion (hFunc) pero quiero llamarla por esta direccion y le hago un cast para poder llamarla, aqui quiero aclara que necesito que todos los valores sean pasados int64, me imagina que la funcion a la que llame interpretara el valor segun le corresponda (esto no se como funciona) Alguien sabe como puedo hacer esto?, desde ya gracias. Título: Re: Llamar a una funcion de una DLL cargada dinamicamente Publicado por: Eternal Idol en 12 Julio 2021, 12:51 pm Las funciones que reciben cadenas como parametros en realidad terminan en A si son ANSI o en W si son widechar, asi que hasta ahora tu GetProcAddress devuelve 0 siempre. Con eso te deberia funcionar relativamente bien en x64 aunque no estas especificando la convencion de llamada que en este caso deberia ser stdcall.
No entiendo muy bien la razon de usar un entero de 64 bits con signo en lugar de un void * para hFunc (idem para los parametros, al menos que el entero sea sin signo y que sea de 4 bytes para codigo de 32 bits) y %x deberia ser %p para corresponderse con un puntero al usar printf. ¿hFunc es un puntero a funcion y despues se le asigna el valor de retorno de WriteConsoleA? En principio yo lo hubiera hecho asi: Código
O para generalizarlo y que funcione siempre con el tamaño de un puntero como parametro: Código
Como la funcion maneja los parametros depende de la convencion de llamada que especificara los registros y/o la pila para acceder a ellos. Título: Re: Llamar a una funcion de una DLL cargada dinamicamente Publicado por: PHREDA en 12 Julio 2021, 15:04 pm Ante todo, gracias por la respuesta.
efectivamente me da 0 el getprocaddress, pero parece que no existe la version A, en todo caso mas raro aun es que dentro del interprete parace estar funcionando ya que obtengo valores el codigo del interprete que ejecuta estas funciones: Código:
y el codigo de sys0 que es la llamada con tus indicaciones Código: int64_t sys0(int64_t fn) { return ((int64_t (__stdcall *)())fn)(); } estoy compilando esto en gcc-4.9.2 64 bits en dev-ccp el main de prueba es este Código: //////////////////////////////////////////////////////////////////////////// la salida del codigo en Código: Address=0000000000000000 coso ok? efectivamente sigue obteniedo 0 pero los numeros que aparecen despues de hola son los valores que obtiene dentro del interprete Seguire intentando alternativas. La razon por el que los parametros son todos interos es que en forth todos los parametros son pasados por una pila de numeros. recien me di cuenta, WriteConsole, da 0 el resto no.. seguire probando.. gracias compañero ! Lo encontre!, no estaba guardando los 64bits en la memoria que almacena las direcciones de las funciones... Título: Re: Llamar a una funcion de una DLL cargada dinamicamente Publicado por: Eternal Idol en 12 Julio 2021, 15:52 pm Código
Cita de: msdn A pointer to a buffer that contains characters to be written to the console screen buffer. This is expected to be an array of either char for WriteConsoleA or wchar_t for WriteConsoleW. https://docs.microsoft.com/en-us/windows/console/writeconsole Me alegro si conseguiste hacerlo funcionar :) Título: Re: Llamar a una funcion de una DLL cargada dinamicamente Publicado por: PHREDA en 12 Julio 2021, 15:57 pm habia entendido mal !
trataba de llamar a GetProcAddressA !!!! Título: Re: Llamar a una funcion de una DLL cargada dinamicamente Publicado por: Eternal Idol en 12 Julio 2021, 18:35 pm Ahh, claro, tiene su logica pero como solo se exportan las funciones en ANSI en un PE no hizo falta la pareja de GetProcAddressA/W ::)
Título: Re: Llamar a una funcion de una DLL cargada dinamicamente Publicado por: RayR en 13 Julio 2021, 04:00 am En general, no le deberías pasar a una función argumentos de tipos distintos a los que espera de la manera en que lo estás haciendo (o sea, mediante puntero a función con cast en los parámetros). Independientemente de cómo los interprete, el verdadero problema es que los tamaños podrían ser diferentes. Por ejemplo, el tercer parámetro de WriteConsole es de tipo DWORD, que ocupa 32 bits, pero al hacer el cast a int64_t le estarías pasando 64. En este caso imagino que funciona, pero es casi por casualidad. Estás compilando para 64 bits, por lo que los primeros 4 argumentos se van a pasar en registros. Como son independientes, no tienes problemas, pero si se pasaran en la pila, podría fallar. Esto pasaría si intentaras hacerlo en programas de 32 bits, o llamar funciones que reciban más parámetros. Por darte un ejemplo, no podrías llamar de manera confiable a CreateProcess, ni siquiera en 64 bits.
Imagino que lo estás haciendo para practicar, y está bien, pero obviamente, no sería buena idea hacer algo así en algo más "formal". Título: Re: Llamar a una funcion de una DLL cargada dinamicamente Publicado por: Eternal Idol en 13 Julio 2021, 11:32 am Efectivamente eso es lo que pasa con su ejemplo compilado en 32 bits, los parametros que la funcion necesita son de 4 y no 8 bytes pero asi como en Windows en modo protegido en 32 bits los parametros son todos de 4 bytes en Windows en modo largo en x64 los parametros son todos de 8 bytes. Por eso le dije que en principio usara los tipos de parametros de la funcion y de ultima usara PVOID que al menos es el tamaño de un puntero y este se debe poder pasar en un registro y pila "nativamente".
En realidad si podes llamar a CreateProcessA sin problemas, cada parametro en pila ocupa 64 bits de por si, aunque despues la funcion llamada solo lea los primeros 8, 16 o 32 bits. Si bien hay una sutil diferencia en el codigo generado en ambos casos cada parametro ocupa 8 bytes (notese como el quinto - 1 - y sexto parametros - 0x1230 - se mueven como DWORD o QWORD pero el siguiente parametro siempre esta a la misma distancia, 8 bytes): Código
Código
Si podria tener problemas con tipos de coma flotante que se pasan en otros registros pero no recuerdo ninguna API de Windows que los use. Y de cualquier manera si coincido en que es algo a evitar de ser posible. Título: Re: Llamar a una funcion de una DLL cargada dinamicamente Publicado por: PHREDA en 13 Julio 2021, 13:11 pm Gracias RayR por tus comentarios.
Se trata de un interprete, o sea, en tiempo de ejecucion va a cargar un dll y llamar a funciones, no es ningun ejemplo para practicar. Es cierto que no se que pasara cuando el parametro en punto flotante, veremos cuando use una dll para graficos 3d y como podria solucionar lo aca subi el proyecto porque ya funciona ! https://github.com/phreda4/r3evm (https://github.com/phreda4/r3evm) Bien por el codigo generadp por Eternal Idol, cuando construya el compilador voy a necesitar realizar esto automaticamente, aunque quizas tome el mismo camino que el interprete al inicio, una funcion por cada cantidad de parametros. El compilador de las versiones anteriores no usaba este mecanismo. Título: Re: Llamar a una funcion de una DLL cargada dinamicamente Publicado por: RayR en 13 Julio 2021, 16:16 pm Cierto, me olvidaba de que para x86-64 los parámetros en la pila se alinean a 64 bits.
|