FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
|
Herramientas | Buscar en Tema | Desplegado |
|
#1
|
|||
|
|||
Escritura de la rutina a inyectar
Hola,
En vista de que nadie se interesó, había abandonado este hilo; pero, he recibido una petición personal para continuarlo, así quea quí hay más detalles: Ya hemos visto la idea central y analizado un poco el punto de arranque, o sea la definición de los datos. pasemos al punto 2, la escritura de nuestra rutina: También sabemos que la rutina a escribir tiene un solo parámetro que es un apuntador a una estructura tipo Record. Nuestro proceso luce entonces algo como:
Ahora bien, lo crítico aquí es entender que como esta rutina se ejecuta en el espacio de direcciones de otro proceso, cualquier dato no local (o sea, difererente a variables locales de la rutina, al parámetro, u otras rutinas a llamar) tiene que estar en el espacio de direcciones del otro proceso. Así pués, que pasa si por ejemplo quisieramos llamar a la rutina GetCommandLine de Windows ? Si intentáramos algo como esto:
El resultado sería un total desastre. Con lo dicho, es claro que al compilar la dirección de StrPas queda con respecto a nuestro espacio de direcciones, no el del otro proceso, y lo mismo aplica para GetCommandLine. Y entonces como se hace ?. La manera de proceder es pasar, como campos de la estructura RemoteStruct, las direcciones, dentro del espacio del otro proceso, de las rutinas que necesitemos llamar. Esto, de todas formas es muy restringido porque solo aplica para ciertas rutinas de Windows, como explicaremos más adelante. Por ahora, concentremonos en como quedaría la rutina;
El cambio de String a PChar es porque, según lo expuesto, no podemos llamar a StrPas, tenemos por tanto que limitarnos al uso de Windows, o sea al PChar. Observese que se está llamando una Variable, correspondiente a un campo de dwEntryPoint, que debe ser del tipo Function. Por tanto, la definición de RemoteStruct debe tener en cuenta eso. Quedaría algo así:
Para ser más claro, he incluído otra función de Windows, SendMessage, resaltando que se debe definir el prototipo completo de la función, incluyendo los parámetros de la misma Según esta lógica, es claro que se debe llenar DGetCommandLine en nuestro proceso con la dirección que dicha rutina tenga en el otro proceso. Como obtemo esa dirección ? Lo veremos en la próxima entrega. |
#2
|
|||
|
|||
creo que la información que estas posteando es muy interesante y valiosa.
Creo que si la gente no contesta es porque no es una cosa muy usual lo que explicas. Y no todo el mundo puede seguir estos temas (incluido yo mismo), aunque tengo interes en este tema. Por lo que te animo a continuar e incluso pienso que este tema es para hacer un tutorial extenso. Gracias por ser generoso y compartir tus conocimientos. Un saludo.... |
#3
|
|||
|
|||
Cita:
Gracias por el comentario. Ciertamente, comparto tús apreciaciones. Quiero disculparme con los que estén interesados en el tema. Sí tengo la intención de terminarlo; pero, un exceso de trabajo me ha impedido elaborar el siguiente punto. Espero hacerlo a mediados de la semana de Diciembre |
#4
|
||||
|
||||
Bueno, cuando alguien se propone publicar tutoriales o explicaciones sobre temas complejos o poco comunes, siempre espera un poco de apoyo. No puedo leer tu hilo sin demostrarte explícitamente mi interés.
Aunque yo programo en C fundamentalmente y apenas domino el delphi, te sigo perfectamente. Veo que te centras, de momento, en la inyección con la API CreateRemoteThread. ¿Has pensado en otras técnicas?. Digo esto porque numerosos antivirus y cortafuegos tienen un Hook a esa API y bloquean la inyección. Y no es que el objetivo sea burlar un antivirus, que de hecho muchos de ellos son burlados inyectando así, sino por curiosidad técnica... Que conste que no pretendo desviar tu exposición. El tema de inyectar sin dll es más complejo que si lo hacemos con dll recibe mi apoyo por atreverte decidirte en abordar este tema. Saludos. Última edición por escafandra fecha: 01-12-2008 a las 00:24:03. |
#5
|
||||
|
||||
Hola amigos.
Rolando, acabo de enterarme de la existencia de este interesante hilo. Y pensar que vienes planteando esto desde mayo. He leído por completo el planteamiento hecho aquí y en el otro hilo que refieres al principio. Francamente desconocía que existiese algo como la función CreateRemoteThread, aunque ahora que lo pienso, quizá ella es una de las claves de cómo funcionan los depuradores. Ya leí la ayuda de ésta en el archivo de oro Win32.hlp que viene con todo Delphi. Y también encontré esto en Google Code Search. Es un ejemplo muy bien explicado, del cual me llamó la atención esta parte: Cita:
Por un lado pienso, "ah, pues entonces sólo con DLLs nativas se puede", pero la pregunta que inmediatamente me salta es: ¿Cómo le hace Windows cuando llamamos a una función de su API que recibe una rutina de retrollamada (call back) como parámetro, puesto que solemos usar un simple "@Rutina"? Y mientras terminaba de escribir esta tonta pregunta ya me respondía a mí mismo: Ah, pues ahí no hay problema porque cuando llamamos a esa función de la API, su DLL fue previamente cargada en el espacio de nuestro propio proceso, así que la dirección dada por el arroba es perfectamente válida. Pero entonces me queda la inquietud: ¿realmente puede instalarse una rutina de un proceso en ejecución dentro del espacio y contexto de otro proceso? ¿O en la práctica esto de la inyección de código máquina sólo es posible definiendo la rutina en una DLL y haciendo que un LoadLibrary inyectado con CreateRemoteThread cargue esa DLL en el proceso ajeno? Que interesante tema, en verdad. Estaré pendiente de los avances, esperemos llegar a un feliz desenlace. Y bueno, me despido por unas horas, porque si no mi chica me enviará a un lugar muy muy remoto. Un abrazo inyectado. Al González. P.D. Una duda más: ¿cómo es posible que el proceso remoto pueda usar el parámetro "C:\\HookTool.dll", si al compilarse el programa esa constante quedaría en el espacio de memoria del proceso inyector? |
#6
|
||||
|
||||
Pues creo que la intención de rolandoj es injectar código sin dll. Si que se puede...
Para poder colocar "algo" en el espacio de direcciones ajeno, tenemos varias API que lo permiten: OpenProcess // Abre un proceso; VirtualAllocEx // Reserva memoria en un proceso WriteProcessMemory // Escribe en la memoria de un proceso reservada por VirtualAllocEx VirtualFree // Libera la memoria reservada por VirtualAllocEx Las DLL nativas se cargan siempre en el mismo espacio relativo de cada proceso, no así las demás dlls. Saludos. |
#7
|
||||
|
||||
Hola de nuevo.
Indagando encontré respuestas a las dudas que me surgieron en el mensaje anterior. 1. El código que cité arriba más bien era seudocódigo, el real conlleva complejidades adicionales pero por lo visto superables. 2. Efectivamente, el parámetro lpParameter dado a la función CreateRemoteThread, debe ser una dirección de memoria válida para el proceso remoto. El truco para esto es obtener ésta con la función VirtualAllocEx y escribir en ella el argumento con la función WriteProcessMemory. ¡Por lo visto podemos escribir datos directamente en la memoria de otros procesos! 3. El ejemplo de Rezmond que enlacé arriba es sólo el segundo de al menos dos maneras que él plantea para lograr la inyección. El método 1 no necesita que sea cargada ninguna DLL (aunque por otras razones sí emplea DLLs en el ejemplo que expone). 4. Sí es posible inyectar una rutina de nuestro programa en el espacio de memoria de otro proceso. Como puede apreciarse en el ejemplo del método 1, el truco es, también, utilizar las funciones VirtualAllocEx y WriteProcessMemory para copiar el código máquina de nuestra rutina en la memoria del proceso remoto, y luego usar CreateRemoteThread para crear un hilo dentro de tal proceso, empezando su ejecución en la dirección base del bloque de memoria donde fue copiado el código. 5. En ambos casos, Rezmond ejecuta inicialmente otra función de su autoría, llamada GetDebugPrivs, la cual llama a otro par de funciones de la API de Windows para darle al programa algo así como permisos de depuración. Desconozco en qué punto de sus ejemplos son necesarios tales permisos, pero parece ser algo importante para que aquellos funcionen. Ahora sólo me quedaría la pregunta, ¿cómo saber cuántos bytes ocupa el código máquina de una función? En uno de los ejemplos vemos que se utilizó un valor de 1000 bytes (cómo diciendo más vale que sobre a que falte), pero ¿podría, por ejemplo, servirnos la ventana CPU del depurador (Ctrl+Alt+C) para calcular el tamaño de una rutina? Espero con esto haber contribuido en algo para que Rolando encuentre solución al problema que plantea. No quiere decir que me despido del tema, solo que esperaré sus comentarios para ver por dónde podemos seguir ayudando. Saludos. Al González. P.D. Ahora veo que Escafandra hizo un adelanto sobre esto que comenté. Interesante el uso de esas funciones. Última edición por Al González fecha: 01-12-2008 a las 09:18:28. |
#8
|
||||
|
||||
Cita:
El problema aparece cuando Func1 llama a su vez a otras funciones que no sean APIs, pues ese tamaño habrá que calcularlo para reservar memoria y "subirlas" a su vez, con lo que en realidad lo que interesa es "subir" no una función sino todo el código que se valla a ejecutar en el nuevo espacio de direcciones. En el caso de hacerlo con dll es el S.O. el que se encarga de todo, pero en nuestro caso debe hacerse manualmente. Saludos. |
|
|
Temas Similares | ||||
Tema | Autor | Foro | Respuestas | Último mensaje |
Thread y servidor DCOM externo al proceso ( EXE ) | Aldo | OOP | 1 | 15-09-2006 17:39:47 |
Como utilizar un componente externo? | Sergei | OOP | 2 | 24-01-2006 19:12:24 |
Inyectar proceso | conde | API de Windows | 4 | 10-09-2005 15:52:17 |
Como se puede programar directamente??? | Antuan | Varios | 10 | 04-08-2005 08:04:38 |
Como correr un archivo externo? | fayala | Firebird e Interbase | 3 | 07-04-2005 03:56:00 |
|