Monday, May 16, 2011

EXE File Which Doesn’t Execute!

Surprised? Well really speaking it’s a very simple matter. All that you have to do is to change the first two bytes of the file the EXE file to 0xCD 0x20. Once this is done if you try to execute the EXE file it gets loaded from the disk but doesn't get executed. This is because 0xCD 0x20 is the code for terminating the execution of a program. Therefore, no sooner does the execution begins it gets terminated. Here is a program which shows how to do this...
# include
main( )
{
unsigned char ch1 = 0xCD ;
unsigned char ch2 = 0X20 ;
FILE *fp ;
fp = fopen ( "DISPLAY.EXE", "rb+" ) ;
if ( fp == NULL )
{
printf ( "Cannot open file" ) ;
exit ( 1 ) ;
}
putc ( ch1, fp ) ;
putc ( ch2, fp ) ;
fclose ( fp ) ;
}
Now onto the program which allows an EXE file to get executed only five times. For this you must first write in the EXE file itself, the maximum number of executions you want to permit (say 5). And then keep reducing this figure every time the file is executed. When the file is executed the fifth time this figure would become 0. There onwards when this file is executed its execution would be immediately terminated.
Suppose, we want to ensure that a file called HELLO.EXE should be executed only 5 times, then to achieve this we will have to write two programs:
a. A program (INIT.C) which writes a 5 in the file HELLO.EXE
b. A program (HELLO.C) which goes on reducing this number till it becomes zero. The moment it becomes zero this program writes 0xCD, 0x20 at the beginning of HELLO.EXE.
You would agree that if INIT.C is to write 5 in HELLO.EXE we will have to first write HELLO.C, compile it, get HELLO.EXE and then run INIT.C. Hence we will have to first write HELLO.C.
/* HELLO.C */
# include
main( )
{
char n ;
unsigned int dat_pos, header[3] ;
FILE *fp ;
if ( ( fp = fopen ( "HELLO.EXE", "rb+" ) ) == NULL )
{
printf ( "\nUnable to open file" ) ;
exit ( 0 ) ;
}
if ( ( fread ( header, sizeof ( int ), 3, fp ) ) != 3 )
{
printf ( "\nRead failure" ) ;
fclose ( fp ) ;
exit ( 0 ) ;
}
dat_pos = 512 * ( header[2] - 1 ) + ( header[1] + 1 ) ;
fseek ( fp, dat_pos, SEEK_SET ) ;
n = getc ( fp ) ;
if ( n == 0 )
{
printf ( "\nFile executions over" ) ;
fclose ( fp ) ;
exit ( 0 ) ;
}
printf ( "\nExecution no. %d ", 6 - n ) ;
n-- ;
fseek ( fp, dat_pos, SEEK_SET ) ;
putc ( n, fp ) ;
fclose ( fp ) ;
/* here onwards you should write the rest of the code */
}
But how would 5 get stored in HELLO.EXE in the first place. For this you have to first compile the above program, get its EXE file and then compile and run the following program.
/* INIT.C */
# include
main( )
{
FILE *fp ;
unsigned int dat_pos, header[3] ;
char n = 5 ;
if ( ( fp = fopen ( "HELLO.EXE", "rb+" ) ) == NULL )
{
printf ( "\nUnable to open file" ) ;
exit ( 0 ) ;
}
if ( ( fread ( header, sizeof ( int ), 3, fp ) ) != 3 )
{
printf ( "\nCan't read data" ) ;
fclose ( fp ) ;
exit ( 0 ) ;
}
dat_pos = 512 * ( header[2] - 1 ) + header[1] + 1 ;
fseek ( fp, dat_pos, SEEK_SET ) ;
fwrite ( &n, sizeof ( n ), 1, fp ) ;
fclose ( fp ) ;
}
Here the file HELLO.EXE is opened in "rb+" mode since we have to read some information from it, perform some calculations and then write data into it. If you observe the EXE file header carefully you would find the entries ‘bytes in last sector’ and ‘total number of sector’. Since DOS allocates space for a file on disk one cluster at a time it may so happen that the last cluster allocated by DOS for the EXE file has not been fully consumed by the file. These unused bytes in the last cluster can be used to stored the number of executions that we wish to perform through the statements,
dat_pos = 512 * ( header[2] – 1 ) + header[1] + 1 ;
fseek ( fp, dat_pos, SEEK_SET ) ;
fwrite ( &n, sizeof ( n ), 1, fp ) ;
That's another set of programs which I suppose establishes the power of this wonderful language beyond any doubt. Try them out and then join me to tap still more power.