PDA

View Full Version : getting an exe that you are running to read from its self


Enlighten
11-14-2002, 09:59 AM
ok i'll try explain it right

i have a project, i run it it attempts to read from its own file using filesteams BUT it fails, with an EFOpenError can't open file...

so anyone know a way around this or another way to get it to read from its self.

what it is ment to do is there is for example a ini file stored inside it, when it runs its ment to extract itself so that it can be used, and once the program is finished it adds its self again.

can't get the to add bit, cos i've been trying to get it to read just now and all attempts have failed on my part, so anyone know a way of doing this?

i've tried filestreams on this one... with fmopenread.... not know what else to try to be honest, i've tried all the modes.


thanks

JockWhiteside
11-14-2002, 11:02 AM
Heres a bit of code that helped me it saves the form size in the exe i hope it helps you.


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,Inifiles;

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
MyAppini : TIniFile;
begin
try
MyAppini := TIniFile.Create(ExtractFileName(Application.ExeNam e));
Left := MyAppini.ReadInteger(Caption,'Left',Left);
Top := MyAppini.ReadInteger(Caption,'Top',Top);
Width := MyAppini.ReadInteger(Caption,'Width',Width);
Height := MyAppini.ReadInteger(Caption,'Height',Height);
finally
MyAppini.Free;
end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
MyAppini : TIniFile;
begin
try
MyAppini := TIniFile.Create(ExtractFileName(Application.ExeNam e));
MyAppini.WriteInteger(Caption,'Top',Top);
MyAppini.WriteInteger(Caption,'Left',Left);
MyAppini.WriteInteger(Caption,'Width',Width);
MyAppini.WriteInteger(Caption,'Height',Height);
finally
MyAppini.Free;
end;
end;
end.

slavikn
11-14-2002, 11:50 AM
This should help:

unit ExeMod;
{
Written by G.A. Carpenter
This is FreeWare for any purpose...use as you will.

This code lets you make things like program generators and
self modifying exe's. I removed the code that allowed direct
modification of the running exe by altering the hd sectors
directly... I was simply unable to make the code 100% safe..
WinDoze lets you modify the file of an exe while it runs but
after running a test exe that constantly modified itself I
found that after a few days the hd became corrupted... this
is really lame! .. I guess I just don't know enough about
Windows to keep windows from trying to move or alter a file
at the same time other low-level code is doing the same :-(
Anyway I still have the code that allows modifying an exe as it
runs by doing a strange little dance that consists of ejecting
a copy of the exe that then modifies the original and erases
itself after re-starting the modified program... this method
works really well and is completely SAFE... and it actually
works better and has more features than the old method :-)
------
I have introduced a strange little bug somehow :-( it causes the
exe modify to fail if the original exe has a space character in it's
name...this bug is somewhere in the initialization section...if
you fix the bug before I get the time to do so please let me know :-)
------

If you use ExeMod.pas on an NT machine then you may need to run the exe
outside the delphi ide... for some reason NT causes the debugger to
faint at the sight of my code :-) the exe files run just fine on NT
but just not from inside the ide....

I am working on the procedures that will allow you to work with
the bytes of the running exe directly in memory... I'm almost done
with it and it will be added soonest.

I am also close to adding the ability to add PE sections to your delphi
exe and inject another exe in there that will run before it turns control
over to the original program....this also will work on non delphi programs.

-------
I tend to sooner or later convert everything
to a string... I think maybe it's a girl thing... I just seem to relate
to strings better than I do to arrays and streams... anyway it all seems
to work somehow and all the pascal string handling routines make it
really easy to play with data held in strings :-) Well anyway... here
are some simple demos for you to look over.

(Remember to put ExeMod.pas into your compiler's path or into your
project's directory... then add ExeMod to your program's uses clause)
------------------------------------------------------------------------
-Code to alter a byte in an exe and then alter the exe at runtime and
put the change onto the exe's file on disk

procedure TForm1.Button1Click(Sender: TObject);
begin
ReadExe; //Read exe file from disk and put into global string named Exe
Exe[3] := 'A'; //Change byte 3 of Global string Exe
AlterExe; //Alter the exe file on disk then quickly restart program
end;
------------------------------------------------------------------------
-Code to add a file from disk to the end of the exe at runtime.
Assume a small txt file named C:\myfile.txt exists and contains
the text 'test'

procedure TForm1.Button1Click(Sender: TObject);
begin
AddFile2Exe('gac1','C:\myfile.txt');
AlterExe;
end;

The string 'gac1' serves to locate the data at the end of the exe
here is what is added to the exe at runtime when you click the button

SO!#GAC1testEO!#GAC1

The data from the file is the 4 bytes 'test' all the rest is just delimiter
data so that ExeMod can locate the data in the exe file.
AddFile2Exe will load the exe from disk if it has not already been
loaded... it checks to see if Exe = '' and if so does a ReadExe;
-----------------------------------------------------------------------
-Code to extract an ExeMod data block from the exe at runtime and save
it to a file on disk... then remove the block from the exe and alter the
exe on disk so that it no longer contains any trace of the data block.

procedure TForm1.Button1Click(Sender: TObject);
begin
ExtractAndStrip('gac1','myfile2.txt');
AlterExe;
end;

This extracts the ExeMod data block gac1 to a file named 'myfile2.txt'
the file is placed into the directory where the program's exe file is
located.

This sort of code is good for making a self-extracting installation
program in delphi. All of your help files,dlls..etc can be extracted
during the first run of your program... exe size will be small because
the data will be removed from the exe after extraction. All files will
be extracted to the program's dir unless a full path name is given.
-----------------------------------------------------------------------
Code to save a copy of the running exe

procedure TForm1.Button1Click(Sender: TObject);
begin
Exe2File('MyNewExe.exe');
end;

Saves a copy of the running exe as myNewExe.exe in the same directory
where the running exe is. If Exe has been altered the altered version
will be saved... if Exe has not been loaded yet then ReadExe is called.
-----------------------------------------------------------------------
Code to save a modified copy of the running exe... this simple code
gives you a program generator.

procedure TForm1.Button1Click(Sender: TObject);
begin
ReadExe;
//add code here to modify the string named 'Exe'
Exe2File('MyNewExe.exe');
end;

This simple code is actually VERY powerful and VERY useful...
-----------------------------------------------------------------------

---> Much more Demo code and many more procedures to come..soon as I
get some more free time :-)


}

interface

{$WARN SYMBOL_PLATFORM OFF}

uses
Windows, SysUtils, Classes, Forms, ShellAPI;

var Exe: string;

procedure ReadExe(FileName: String);
procedure String2File(String2BeSaved, FileName: string);
function File2String(FileName: string): string;
procedure ExtractFromExe(DemarcStr: string; var ExtractedStr: string);
procedure DelFromString(DemarcStr: string; var String2Change: string);
procedure DelFromFile(DemarcStr, FileName: string);
procedure Add2File(DemarcStr, FileName, String2Add: string);
procedure ReplaceInFile(DemarcStr, FileName, ReplacementString: string);
procedure TackOnFile(DemarcStr, FileName, File2Add: string);
procedure Add2String(DemarcStr, String2Add: string; var String2Alter: string);
procedure ReplaceInString(DemarcStr, ReplacementString:
string; var String2Alter: string);
procedure AlterExe;
procedure ExtractAndStrip(DemarcStr, FileName: string);
procedure Exe2File(FileName: string);
procedure Extract2File(DemarcStr, FileName: string);
procedure AddFile2Exe(DemarcStr, FileName: string);
procedure Add2Exe(DemarcStr, String2Add: string);
procedure Stream2Exe(TempStream: TMemoryStream);


implementation

//================================================== =

//================================================== =

procedure ReadExe(FileName: String);
var
ExeStream: TFileStream;
begin
ExeStream := TFileStream.Create(FileName, fmOpenRead
or fmShareDenyNone);
try
SetLength(Exe, ExeStream.Size);
ExeStream.ReadBuffer(Pointer(Exe)^, ExeStream.Size);
finally
ExeStream.Free;
end;
end;
//================================================== =

//================================================== =

procedure String2File(String2BeSaved, FileName: string);
var
MyStream: TMemoryStream;
begin
if String2BeSaved = '' then exit;
SetCurrentDir(ExtractFilePath(Application.ExeName) );
MyStream := TMemoryStream.Create;
try
MyStream.WriteBuffer(Pointer(String2BeSaved)^, Length(String2BeSaved));
MyStream.SaveToFile(FileName);
finally
MyStream.Free;
end;
end;
//================================================== =

//================================================== =

function File2String(FileName: string): string;
var
MyStream: TMemoryStream;
MyString: string;
begin
MyStream := TMemoryStream.Create;
try
MyStream.LoadFromFile(FileName);
MyStream.Position := 0;
SetLength(MyString, MyStream.Size);
MyStream.ReadBuffer(Pointer(MyString)^, MyStream.Size);
finally
MyStream.Free;
end;
Result := MyString;
end;
//================================================== =

//================================================== =

procedure ExtractFromExe(DemarcStr: string; var ExtractedStr: string);
var
d, e: integer;
begin
if Length(Exe) = 0 then ReadExe(Application.ExeName);
if Pos(uppercase('so!#' + DemarcStr), Exe) > 0 then
begin
e := Pos(uppercase('eo!#' + DemarcStr), Exe);
d := Abs(e - 8);
ExtractedStr := Copy(Exe, d, e - d);
end;
end;
//================================================== =

//================================================== =

procedure DelFromString(DemarcStr: string; var String2Change: string);
var
a, b: string;
begin
a := UpperCase('so!#' + DemarcStr);
b := UpperCase('eo!#' + DemarcStr);
delete(String2Change, pos(a, String2Change), (pos(b, String2Change)
+ length(b) - pos(a, String2Change)));
end;
//================================================== =

//================================================== =

procedure DelFromFile(DemarcStr, FileName: string);
var
MyString: string;
begin
MyString := File2String(FileName);
DelFromString(DemarcStr, MyString);
String2File(MyString, FileName);
end;
//================================================== =

//================================================== =

procedure Add2File(DemarcStr, FileName, String2Add: string);
var
MyString: string;
begin
MyString := File2String(FileName);
MyString := MyString + uppercase('so!#' + DemarcStr) + String2Add + uppercase
('eo!#' + DemarcStr);
String2File(MyString, FileName);
end;
//================================================== =

//================================================== =

procedure ReplaceInFile(DemarcStr, FileName, ReplacementString: string);
begin
DelFromFile(DemarcStr, FileName);
Add2File(DemarcStr, FileName, ReplacementString);
end;
//================================================== =

//================================================== =

procedure TackOnFile(DemarcStr, FileName, File2Add: string);
var
Mystring: string;
begin
MyString := File2String(File2add);
Add2File(DemarcStr, FileName, MyString);
end;
//================================================== =

//================================================== =

procedure Add2String(DemarcStr, String2Add: string; var String2Alter: string);
begin
String2Alter := String2Alter + uppercase('so!#' + DemarcStr)
+ String2Add + uppercase('eo!#' + DemarcStr);
end;
//================================================== =

//================================================== =

procedure ReplaceInString(DemarcStr, ReplacementString: string;
var String2Alter: string);
begin
if pos(uppercase('so!#' + DemarcStr), String2Alter) = 0 then exit;
DelFromString(DemarcStr, String2Alter);
Add2String(DemarcStr, ReplacementString, String2Alter);
end;
//================================================== =

//================================================== =

procedure AlterExe;
begin
if (Exe) <> '' then
begin
String2File(Exe, 'temp0a0.exe');
ShellExecute(0, 'open', PChar('temp0a0.exe'),
PChar(ExtractFilename(Application.ExeName)), nil, SW_SHOW);
Application.Terminate;
end;
end;
//================================================== =

//================================================== =

procedure ExtractAndStrip(DemarcStr, FileName: string);
var
Temp: string;
begin
ExtractFromExe(DemarcStr, Temp);
DelFromString(DemarcStr, Exe);
String2File(Temp, FileName);
end;
//================================================== =

//================================================== =

procedure Exe2File(FileName: string);
begin
if Exe = '' then ReadExe(Application.ExeName);
String2File(Exe, FileName);
end;
//================================================== =

//================================================== =

procedure Extract2File(DemarcStr, FileName: string);
var
MyString: string;
begin
ExtractFromExe(DemarcStr, MyString);
if MyString <> '' then String2File(MyString, FileName);
end;
//================================================== =

//================================================== =

procedure AddFile2Exe(DemarcStr, FileName: string);
var
MyString: string;
begin
MyString := File2String(FileName);
if Exe = '' then ReadExe(Application.ExeName);
Add2String(DemarcStr, MyString, Exe);
end;
//================================================== =

//================================================== =

procedure Add2Exe(DemarcStr, String2Add: string);
begin
if Exe = '' then readExe(Application.ExeName);
Add2String(DemarcStr, String2Add, Exe);
end;
//================================================== =

//================================================== =

procedure Stream2Exe(TempStream: TMemoryStream);
begin
SetCurrentDir(ExtractFilePath(Application.ExeName) );
TempStream.SaveToFile('temp0a0.exe');
ShellExecute(0, 'open', PChar('temp0a0.exe'),
PChar(ExtractFilename(Application.ExeName)), nil, SW_SHOW);
Application.Terminate;
//beep;
end;
//================================================== =

initialization
begin
SetCurrentDir(ExtractFilePath(Application.ExeName) );
if ParamStr(1) = 'deltemp' then
begin
while not (deletefile('temp0a0.exe')) do
begin
if (FileGetAttr('temp0a0.exe') and faReadOnly) > 0
then FileSetAttr('temp0a0.exe', FileGetAttr('temp0a0.exe')
xor faReadOnly);
sleep(10);
end;
deletefile('temp0a0.exe');
end;
if UpperCase(ExtractFileName(Application.ExeName)) = ('TEMP0A0.EXE') then
begin
ReadExe(Application.ExeName);
while not (deletefile(ParamStr(1))) do
begin
if (FileGetAttr(ParamStr(1)) and faReadOnly) > 0
then FileSetAttr(ParamStr(1), FileGetAttr(ParamStr(1))
xor faReadOnly);
sleep(10);
end;
String2File(Exe, ParamStr(1));
ShellExecute(0, 'open', PChar(ParamStr(1)),
PChar('deltemp'), nil, SW_SHOW);
Application.Terminate;
end;
end;

end.

http://www.organizermp3.com
Essential for all people who have MP3 files!
Most recent release: October 12th, 2002.

slavikn
11-14-2002, 11:53 AM
Use ReadExe and then read the EXE variable.

http://www.organizermp3.com
Essential for all people who have MP3 files!
Most recent release: October 12th, 2002.

slavikn
11-17-2002, 09:25 AM
Did if help?
If yes, please accept.
If not, tell me why and I will help.
Thanks!

http://www.organizermp3.com
Essential for all people who have MP3 files!
Most recent release: October 12th, 2002.

Enlighten
11-17-2002, 03:47 PM
sorry was away for a few days :) lol

the one i was looking for was the one i accepted, cos its not just settings its encrypted passwords and stuff.