Contributor: BJORN FELTEN             

{
OK. Maybe this isn't exactly what you were asking for, but I've seen quite a
number of variations on this peeka-boo-into-the-exe-file, so I felt I just had
to write a comment to this matter.

   Using some kind of a magic constant, which is then searched for in the exe
file, probably is the most common approach to this kind of problem. But there's
really no need to do a search. You can calculate exactly where any const is (or
should be) located.

   The trick is to use a couple of simple facts:

   1/ The size of the exe header, in paragraphs, is located at byte 8 in the
header (actually it's a word made up by bytes 8 and 9 but I still haven't seen
an exe header of more than 4k, so I make it simple for myself using only the
byte).

   2/ After the exe header comes the code segment and then directly the data
segment. Thus the size of the code segment can be calculated by a simple dseg-
cseg. Still talking paragraphs.

   3/ Now we've reached the data segment in the exe file. The location in the
data segment can be found with ofs. Here we're talking bytes.

   Using these facts, here's a simple sample that let's you change a const
string to whatever paramstr(1) you supply. Hope you'll be able to pick out the
stuff you may find any need for.

   Since this code was extracted from a pretty small program I once wrote, it
uses the rather crude method to read the entire exe file into a buffer, and
then creating a new file blockwriting the entire buffer. If your program is
larger than 64k you obviously need to use some other method.
}

program SelfModifier;   (* Looks for a const and alters it *)
                        (* Puts paramstr(1) into Name *)

const
    Name : string = 'Fix me up';      {get 256 bytes to play with}
type
    Buffer = array[0..$3fff] of byte;
var
    ExeFile : file;
    P       : ^Buffer;
    N,I,O   : word;
    NStr    : string;

begin
 begin
  new(P);                             {get mem for our buffer}
  assign(ExeFile,paramstr(0));        {get myself}
  reset(ExeFile,1);
  blockread(ExeFile,P^,sizeof(Buffer),N);
  close(ExeFile);                     {got it into Buf, now close it}
  O:=(dseg-cseg+word(P^[8])) shl 4;   {start of data seg in exe file}
  writeln('Name: ',Name);
  NStr := paramstr(1);                {new string to put in Name}
  inc(O,ofs(Name));                   {where Name is located}
  move(NStr[0],P^[O],length(NStr)+1); {move string incl. length byte}
  rewrite(ExeFile,1);                 {create new version}
  blockwrite(ExeFile,P^,N);           {write it}
  close(ExeFile);                     {close it...}
  dispose(P)                          {...and release mem}
 end
end.