Viruses Like Activities 


TSR's - terminate but stay resident programs - from their name appear to be strangers belonging to strange lands. In fact Microsoft wanted them to be so treated because officially it never accepted that TSR's were possible. For quite some time TSR's was indeed a closely guarded secret . But it was only Microsoft who blew it up...by developing a DOS utility called PRINT.COM. This utility helps carrying out the printing in the background whereas you do some other work in the foreground.

And once hackers burnt their midnight oil to get to the root of the PRINT.COM, Microsoft's secret became public knowledge. And overnight, number of TSR's were born. The more popular amongst the herd were Sidekick and Prokey. But even today most of the programmers hold an awe for TSR's. Through a series of programs I intend to bring TSR's down to earth. Let us understand the basis of TSR's first.

When we work with any program like say dBASE, it is loaded into memory on top of COMMAND.COM and when we quit from dBASE it is erased from the memory so that the next program may be loaded on top of COMMAND.COM. With TSR the rules are slightly different. Once loaded in memory it remains on top of COMMAND.COM. And now if we load say Wordstar it will be loaded on top of TSR and not on top of COMMAND.COM. So both TSR and Wordstar coexist. Now all that needs to be done is to activate the TSR through some trigger. This trigger is usually the hot-keys. For example the hot-keys for Sidekick are Ctrl and Alt. From this it is clear that while writing a TSR care should be exercised to make it resident in memory. Turbo C allows you to do this through a function called keep( ). Look at the following program :

#include "dos.h" 

main( ) 

printf ( "Before calling keep\n" ) ; 

keep ( 0 , 500 ) ; 

printf ( "After calling keep" ) ; 

}

Once executed you will find that only the first message is displayed. keep( ) makes your program TSR i.e. keeps it in memory and terminates its execution. That is the reason why the output of the second printf( ) doesn't go to the screen. The arguments of keep( ) helps DOS in finding out how much memory to set aside for storing your program in memory.

Although we can now make our program resident in memory, there is no way that it will ever become active. If it is to be activated it is necessary to capture interrupts. But how? Well, at the low end of memory there exists an Interrupt Vector Table ( IVT ). It contains addresses of routines stored in ROM-BIOS... routines which carry out important tasks like reading from disk or keyboard, writing to screen, etc. When we hit a key, an interrupt occurs and then the address of the routine corresponding to this interrupt is picked up from IVT and the control is passed to this routine. While capturing interrupts we have to change the address in IVT so that it contains the address of our TSR. After doing this whenever an interrupt occurs then from IVT address of our TSR is picked up and the control reaches our TSR. Once the control reaches the TSR, we can do something on the screen or on the printer or at any other place and finally handover the control to the ROM-BIOS routine. Turbo C provides functions getvect( ) and setvect( ) to facilitate capturing of interrupts. An important thing that one has to remember is the interrupt numbers associated with various devices. For example, interrupt number 8 is associated with timer, 9 with keyboard, 19 with disk, 23 with printer and so on. Once these details are mastered C makes available raw power at your fingertips


 Dancing Dolls

This program displays an activity similar to that of a virus called Dancing Dolls. Whenever you press a key all the characters on the screen which are in uppercase get converted to lower case and that those in lower case turn to upper case. Compile the program given below to create an EXE file and then quit out of Turbo C and execute this program. After that load Wordstar or dbase or even Turbo C and watch the dance !

#include "dos.h" 

void interrupt newroutine( ) ; 

void interrupt ( *oldroutine )( ) ; 

char far *s = ( char far * ) 0xB8000000 ; int i ; 

main( )  

oldroutine = getvect ( 9 ) ; 

setvect  ( 9, newroutine ) ; 

keep ( 0 , 1000 ) ; 

void interrupt newroutine( )  

for ( i = 0 ; i <= 3999 ; i+= 2 )   

if ( *( s + i ) >= 65 &&  *( s + i ) <= 90 ) 

* ( s + i ) += 32 ; 

else 

if ( *( s + i ) >= 97 &&  *( s + i ) <= 122 ) 

* ( s + i ) -= 32 ; 

( *oldroutine )( ) ; 

}

When our( )gets called from main( ), first time through the for loop all capitals on the screen are changed to small case and vice versa. The indefinite while loop ensures that this effect is immediately reversed thereby making characters small case one moment and capitals the next. This change takes place so fast that it gives an illusion of the characters dancing on the screen (to your tune).
 

 Caps Locked

How about a TSR which will permanently keep the Caps Lock on? For this we will have to steal interrupt number 9, and then have a routine called which puts on the Caps Lock after the normal keyboard ROM-BIOS routine has done its job. Here is the program.

#include "dos.h" 

 

void interrupt ( *prev )( ) ; 

void interrupt our( ) ; 

char far *kb = ( char far * ) 0x417 ; 

 

main( ) 

prev = getvect ( 9 ) ; 

setvect ( 9, our ) ; 

keep ( 0, 500 ) ; 

 

void interrupt our( ) 

( *prev )( ) ; 

*kb = *kb | 64 ; 

To understand our( ), note down the following points.

  • The status of Caps Lock is stored in the sixth bit of byte 417h. A 1 in the sixth bit indicates that the Caps Lock is on and a 0 indicates that it is off. 

  • The interrupt number 9 is generated once when we hit a key and once when we release it. 

  • When the Caps Lock key is pressed the ROM-BIOS routine toggles the sixth bit in 417h, whereas when the Caps Lock key is released the bit remains unchanged. The function our( ) uses this knowledge to ensure that the Caps Lock remains permanently on. Whenever we press a key, instead of the keyboard routine in ROM-BIOS being executed, the our( ) function is executed. This so happens because in the IVT we have substituted  the address of this new function for the address of the actual routine. The our( ) function first hands over the control to the ROM-BIOS routine. When the control comes back from this routine the statement *kb = *kb | 64 turns the sixthbit on. The bitwise OR operator | has been used to ensure that the other bits in 417h remain unchanged. 

Let us now imagine how our( ) would work in three situations. 

  • When any key other than Caps Lock is pressed:  The ROM-BIOS routine (called through ( *prev )( )) will not make any change in the Caps Lock bit whereas *kb = *kb | 64 will set the Caps Lock bit to 1.

  • When Caps Lock is on and Caps Lock key is pressed:  The ROM-BIOS routine will turn the Caps Lock bit off and *kb = *kb | 64 will immediately set the Caps Lock bit once again to 1.

  • When Caps Lock is off and Caps Lock key is pressed: The ROM-BIOS routine will turn the Caps Lock bit on and *kb = *kb | 64 will ensure that the Caps Lock bit remains 1.

What do you think would happen if the sequence of statements in our( ) is changed? Would the Caps Lock still remain permanently on? Yes, because when the Caps Lock key is pressed the ROM-BIOS routine toggles the sixth bit in 417h, whereas when the Caps Lock key is released the bit remains unchanged. To make absolutely sure that the Caps Lock does remain on you can examine how our( ) works in the three situations given above. The way sixth bit of memory location 417h controls the status of Caps Lock key, bits 2 and 3 contain the status of Ctrl and Alt keys respectively. 


 Deactivating Ctrl+Alt+Del

we can write a TSR which ensures that the user cannot use Ctrl-Alt-Del combination to reboot the computer. This can be achieved by letting the ROM-BIOS routine get called and then setting the Ctrl and Alt bits in 417h to 0 using the statement, *kb = *kb & 0xF3 ; 

Here is a program which shows how this can be achieved.

#include "dos.h" 

 

void interrupt ( *prev )( ) ; 

void interrupt our( ) ; 

char far *kb = ( char far * ) 0x417 ; 

 

main( ) 

prev = getvect ( 9 ) ; 

setvect ( 9, our ) ; 

keep ( 0, 1000 ) ; 

 

void interrupt our( ) 

( *prev )( ) ; 

*kb = *kb & 0xF3 ; 


 Changing Screen Color

The following TSR changes the screen color every 10 seconds. 

#include "dos.h" 

void interrupt newroutine( ) ; 

void interrupt ( *oldroutine )( ) ; 

char far *s = ( char far * ) 0xB8000000 ; 

int k = 0, i, color = 0 ; 

main( ) 

{

oldroutine = getvect ( 8 ) ; 

setvect ( 8, newroutine ) ; 

keep ( 0, 1000 ) ; 

 

void interrupt newroutine( ) 

k++ ; 

if ( k > 182 )  

for ( i = 1 ; i <= 3999 ; i += 2 ) 

*( s + i ) = color ; 

color++ ; 

( *oldroutine )( ) ; 

}

In main( ) we first change the address in IVT corresponding to interrupt number 8 (timer) so that instead of pointing to a ROM - BIOS routine it points to our TSR. However we save the address of the ROM-BIOS routine in the variable oldroutine. Every time the timer ticks and interrupt occurs control would now reach newroutine( ) where we increment k. As soon as k exceeds 182 (that is after every 10 seconds) we assign a value color to all the color bytes in VDU memory. Consequently the color of the screen would change. Irrespective of whether the color of the screen is changed or not control is passed to ROM-BIOS routine through the statement

( * oldroutine )( ) ;

Create an EXE file,  quit out of Turbo-C and then run the program and  then  decide for yourselves, whether you would  like  to  do programming in C or COBOL rest of your life. These are just a few tricks that one can perform with TSR's. There are infinite  more tricks! All that you have to do is let your mind soar high  and heart roam free... rest believe me would be a cakewalk!


 The Printer Is Virused

Yes, that is what I believed when I tried to print out a file  and found  that my printer is printing all gibberish. I  checked  the file and found it in perfect shape. I called the hardware man and got  my printer checked up. It too was alright. Then I realised may  be my computer is virused, and to my horror I found it  was. All  that  this  virus was doing was every time a was to be printed  it  printed b, everytime a b was to  be  printed  it printed c and so on. Hence the gibberish. Here is a program that does something similar. 

#include "dos.h" 

void interrupt newroutine( ) ; 

void interrupt ( *oldroutine )( ) ; 

main( ) 

oldroutine = getvect ( 23 ) ; 

setvect ( 23, newroutine ) ; 

keep ( 0, 1000 ) ; 

void interrupt newroutine( ) 

if ( _AH == 0 ) /* use underscore not minus */ 

_AL = _AL + 1 ; /* use underscore not minus */ 

( *oldroutine )( ) ; 

}

To  understand its working we will have to understand how  normal printing  is carried out. Whenever Wordstar or dBASE or  whatever sends  a file for printing it takes the help of ROM-BIOS  routine to  carry  out  the  printing. This  ROM-BIOS  routine  uses  CPU  registers called AH and AL to print a character. For example,  if  'A'  is to be printed then the AH register should contain a  zero whereas the AL register should contain 'A'. Similarly if '+' is to be printed AH should contain zero and AL should contain '+'.  The above  program  tinkers  around with the contents of  AH and AL registers using pseudo variables _AH and _AL provided by Turbo C. Any change in the pseudo variables is reflected in CPU registers. Our program is a TSR which has caught hold of the printer interrupt (interrupt number 23). Every time interrupt 23  occurs (and it would occur every time a printout is to be taken)  the TSR monitors whether AH register contains a zero. If it finds  so it coolly increments  the contents of AL and sends it to the printer. Hence in place of 'A' a 'B' gets printed.


 The Printer is Jammed

With this program on the roll, you can make the printer jam! The stationery attached to the printer advances by one line when an end of line is reached or 80 characters have been printed on the same line (assuming that we are using an 80 column printer). The end of line is signified by a \r and \n (carriage return and line feed) combination. When a \r is sent to the printer, the printer head is brought to the beginning of the same line, whereas when a \n is sent the stationery is advanced by one line. The global variable counter keeps a track of the number of characters printed in the current line. Once 80 characters have been printed in a line a \r is placed in _AL and the print routine is called. This places the printer head at the beginning of the same line. Thus the TSR sees to it that everything sent to the printer is printed on the same line.

#include "dos.h" 

 

void interrupt newroutine( ) ; 

void interrupt ( *oldroutine )( ) ; 

int counter ; 

 

main( ) 

oldroutine = getvect ( 23 ) ; 

setvect ( 23, newroutine ) ; 

keep ( 0, 1000 ) ; 

void interrupt newroutine( ) 

if ( _AH == 0 ) 

counter++ ; 

if ( counter == 80 )  

counter = 0 ; 

_AL != '\r' ) 

else 

if ( _AL == '\n' )  

_AL = '\r' ; 

( *oldroutine)( ) ; 

 } 

 else 

( *oldroutine)( ) ; 

}

But remember the above programs have not virused  the printer. Nor are they viruses in true sense. Why ? One  because no virus can go and sit inside the printer.  Second because  these programs do not spread and infect other  programs. But all in all they are pure fun. One small reminder again, compile the programs to get .EXE files and then run them at DOS prompt after quitting out of Turbo C and not through DOS shell.

Back


Home | Online Courses | Free C Source Code | Free VC++ Source Code | COM/DCOM Stuff |  Courses@Nagpur | Project Ideas | Ask Queries | COM FAQs |  Conferences | Discussion Board | Previous Weekly Updates | Good Books | Vedic Maths | Time Pass |  Submit Code | About Us | Advertise | Disclaimer  


 Designed and Managed by
DCube Software Technologies, Nagpur (India) 
Last Revised: 10 May 2000 21:27:20