[Back to MISC SWAG index] [Back to Main SWAG index] [Original]

    (*
    GABE KRUPA

    > I need to add some information to the end of an EXE file and be able
    > Say a PCX image for example.  I'm concerned about the EXE file alread
    > open due to being executed.  Does info tacked to the end of an EXE ge
    > into memory automatically, etc.  I haven't tried this yet but am abou
    > hoping someone who has tried it can assist me to avoid some of the pi
    > they may have encountered.  Thanks.  (BTW, I am experienced in Pas &

      Well, I made a unit for that purpose, but my unit only tacks on 1K of
    storage space... You can make it as large as you want it, but it'll be a
    REAL time consumer and it might push your text editor to the limits (I'm
    not sure if the IDE has a file size limit).

      Here it is (in a VERY shortened version )
    }
    unit inject1k;

    interface
    implementation
    const doesnt_matter_what_this_is_called : boolean = false;

    procedure never_really_call_this_procedure;
    begin
      if doesnt_matter_what_this_is_called then
        inline( 228/229/230/231/231/233/234/  { this I use for a ID string }
                234/234/234/234/234/234/234/
                234/234/234/234/243/234/234/
    { repeat as many times until you get enough .. each '234/' is 1 byte }
                234/234/234/234/234/234/234/
                234/234/234/234/234/234/234/  { this is the actual 'junk' }
               ); { inline }
    end; { procedure }

    end. { unit }
    {
      I only inject 1024 into my EXE file... If you want, you can make
    identical units like that, but the DATA area will NOT be in one long
    string unless all the bytes are in one unit.
      I use the ID string to correctly place the file pointer. Just open the
    EXE, read in bytes until you get a 228. Read another, if it's a 229
    etc.. Keep looping until you get a 228-229-230-231-232-233-234 and then
    you can start reading/writing. It's by no means the easiest way, but I
    prefer it over trying to append to the end. I tried that, but I kept
    getting errors and such. As long as the PCX file is fairly small, you
    won't have too much of a problem.
      I'm not sure what the chances are, they must be pretty slim to find a
    string (228-234) one after the other in an EXE. If you think they are
    higher, or whatever, just put your own in. You could probably even put
    text in like this:
    }
    inline('D'/'A'/'T'/'A'/' '/'S'/'T'/'A'/'R'/'T'/'S'/' '/'H'/'E'/'R'/'E'/
    111/111/111/111  { etc... } );
    {
             I hope this helps, or gives you some ideas. Note, the unit will
    be about TWICE as large as the number of bytes you inject (maybe 1000
    more), but the EXE will only increse by the number you add. I'm pretty
    sure that the extra bytes are just data/debug info in the TPU file.
    *)

    {
    MARK LEWIS

    > I need to add some information to the end of an EXE file and be able
    > Say a PCX image for example.  I'm concerned about the EXE file alread

    [... trim ...]

    > Well, I made a unit for that purpose, but my unit only tacks on
    > 1K of storage space... You can make it as large as you want it,
    > but it'll be a REAL time consumer and it might push your text
    > editor to the limits (I'm not sure if the IDE has a file size
    > limit). Here it is (in a VERY shortened version )
    > unit inject1k;

    [... trim ...]

    interesting<<smile>>... i never thought of doing it like that.. hehe.. here's
    a unit i got from this echo or the other PASCAL echo several years ago.. i've
    used it in self-limiting programs (ones that only run a certain number of
    times) and other programs that may be subject to hacking of various forms...
    i've modified it slightly for my purposes...
    }
    unit selfmod;

    { Allows a program to self modify a typed constant in the .exe file.  It     }
    { also performs an automatic checksum type .exe file integrity check.        }
    { A longint value is added to the end of the exe file.  This can be read by  }
    { a separate configuration program to enable it to determine the start of    }
    { the programs configuration data area.  To use this the configuration       }
    { typed constant should be added immediately following the declaration of    }
    { ExeData.                                                                   }
    { Where this unit is used, it should always be the FIRST unit listed in the  }
    { uses declaration area of the main program.                                 }
    { Requires DOS 3.3 or later.  Program must not be used with PKLite or LZExe  }
    { or any similar exe file compression programs.                              }
    { The stack size needed is at least 9,000 bytes.                             }

    interface

    type
      ExeDatatype    = record
                         IDStr      : string[8];
                         FirstTime  : boolean;
                         Hsize      : word;
                         ExeSize    : longint;
                         CheckSum   : longint;
                         StartConst : longint;
                       end;

    const
      ExeData : ExeDatatype = (IDStr     : 'IDSTRING';
                               FirstTime : true;
                               Hsize     : 0;
                               ExeSize   : 0;
                               CheckSum  : 0;
                               StartConst: 0);

    { IMPORTANT: Put any config data typed constants here }

    procedure Write2Exec(var data; size: word);

    {============================================================================}

    implementation

    procedure InitConstants;
      var
        f           : file;
        tbuff       : array[0..1] of word;

      function GetCheckSum : longint;
        { Performs a checksum calculation on the exe file }
        var
          finished  : boolean;
          x,
          CSum      : longint;
          BytesRead : word;
          buffer    : array[0..4095] of word;
        begin
          {$I-}
          seek(f,0);
          finished := false;  CSum := 0;  x := 0;
          BlockRead(f,buffer,sizeof(buffer),BytesRead);
          while not finished do begin             { do the checksum calculations }
            repeat         { until file has been read up to start of config area }
              inc(CSum,buffer[x mod 4096]);
              inc(x);
              finished := ((x shl 1) >= ExeData.StartConst);
            until ((x mod 4096) = 0) or finished;
            if not finished then                { data area has not been reached }
              BlockRead(f,buffer,sizeof(buffer),BytesRead);
          end;
          GetCheckSum := CSum;
        end;

      begin
        assign(f, ParamStr(0));
        {$I-} Reset(f,1);
        with ExeData do begin
          if FirstTime and (IOResult = 0) then begin
            Seek(f,2);                  { this location has the executable size }
            BlockRead(f,tbuff,4);
            ExeSize := tbuff[0]+(pred(tbuff[1]) shl 9);
            seek(f,8);                                   {  get the header size }
            BlockRead(f,hsize,2);
            FirstTime := false;
            StartConst := longint(hsize+Seg(ExeData)-PrefixSeg) shl 4 +
                          Ofs(ExeData) - 256;
            CheckSum := GetCheckSum;
            Seek(f,StartConst);
            BlockWrite(f,ExeData,sizeof(ExeData));
            seek(f,FileSize(f));
            BlockWrite(f,StartConst,4);
          end
          else
            if GetCheckSum <> CheckSum then begin
              writeln;
              writeln(#7,#7,'Program file has been UNLAWFULLY modified!',#7,#7);
              writeln;
              writeln('It may have a Virus attached or someone may have made');
              writeln('an attempt to HACK it. You should check your system for');
              writeln('virus'' before continuing....');
              writeln;
              writeln('Please reinstall the .EXE file from the original archive.');
              writeln('Aborting....');
              halt(255);
            end
            else
              begin
                writeln;
                writeln('Integrity Validated.');
              end;
        end;  { with }
        Close(f); {$I+}
        if IOResult <> 0 then begin
          writeln('Unable to initialise program');
          halt;
        end;
      end; { InitConstants }

    procedure Write2Exec(var data; size: word);
     { writes a new typed constant into the executable file. }
      var
         f          : file;
      begin
        assign(f, ParamStr(0));
        {$I-} Reset(f,1);
        Seek(f,longint(ExeData.Hsize+Seg(data)-PrefixSeg) shl 4 + Ofs(data)- 256);
        BlockWrite(f,data,size);
        Close(f); {$I+}
        if IOResult <> 0 then;
      end; { Write2Exec }

    begin
      writeln('Please Standby...');
      InitConstants;
    end.

[Back to MISC SWAG index] [Back to Main SWAG index] [Original]