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
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). 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.
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 ;
}
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! 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. 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.
|
|
Designed and
Managed by |
|