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 ? :-)