Solved

Patch an exe file?

Posted on 2001-07-20
26
533 Views
Last Modified: 2010-04-04
Hi.
I want to know how i can patch an exe file.
I mean where i search in the exe for a string, then replace it with another.

I found this one on Torry.net:
http://www.swissdelphicenter.ch/torry/showcode.php?id=25

But it don't seems to work with long strings.
Please help me, there must another way doing this.

Dennis
0
Comment
Question by:Dennis9
  • 14
  • 9
  • 2
  • +1
26 Comments
 
LVL 5

Expert Comment

by:Gwena
ID: 6304373
I just load the whole exe file into a TMemoryStream
and then alter it and save it back to the same file name
:-)

use LoadFromFile. then alter the file and finally  SaveToFile.

It's also easy to simply load an entire exe and convert it to a string...then use delphi string handling to locate the part you want to change ... use pos to find the string and then use insert and delete to make changes...just be sure to leave the exe the same length that it was... and DO NOT alter anything other than the string data or the whole thing will crash badly.

It's also possible for an exe to alter a string within itself while it is running... it's a bit tricky but it seems to work reliably.... look at my web site for some strange examples of this sort of thing :-)
http://delphi.does.it

If you need more help I could write you a tiny demo that changes a string inside an exe..let me know :-)
0
 

Expert Comment

by:St3v13
ID: 6304670
If you want to patch a string with another string, I use:

procedure TForm1.Button1Click(Sender: TObject);
var
  f: file;
  l: longint;
  datei,
  altstring,
  neustring,
  s: string;
begin
  altstring := 'Windows 95 wird gestartet...';   // oldstring
  neustring := 'Windows 95 sturzt ab...     ';   // newstring
  datei := 'C:\kopie von io.sys';                // filename

  s := altstring;
  assignFile(f, datei);
  reset(f,1);
  for l := 0 to filesize(f)-length(altstring)-1 do
  begin
    Application.ProcessMessages;
    seek(f,l);
    blockread(f,altstring[1],length(altstring));
    if altstring = s then
    begin
      seek(f,l);
      blockwrite(f,neustring[1],length(neustring));
      // String was found and patched.
      ShowMessage('Status: Stelle gefunden und gepatcht!');
    end;
    Application.ProcessMessages;
  end;
  closeFile(f);
end;

I forget where i got this from but it works fine with  me, just play about with it,

Regards,
St3v13
0
 
LVL 1

Author Comment

by:Dennis9
ID: 6304888
St3v13: thats the one that are on my link, and i have troubles with long strings.

Dennis
0
 
LVL 1

Author Comment

by:Dennis9
ID: 6304891
Hi Gwena.
I have downloaded the selfmod.exe u had long time ago:)
I have been playing with it, and its cool.

But if u can make a demo to me showing how to replace a string in an exe, i would be happy.

Dennis
0
 

Expert Comment

by:felonious
ID: 6304983
hi Dennis,

  Its kinda funny that you should post this question because last night I was searching through E-E and totally by change I found something that might help you.  Here is the link to the E-E question: http://www.experts-exchange.com/jsp/qShow.jsp?qid=10314362

Anyway, here is what the message theard basicly says:

[QUOTE BEGIN] ---------------

From: Gwena  Date: 03/20/2000 09:47PM PST  

It should be easy to just append a few bytes to the end of an exe file...
It does no harm to lengthen an exe... I have done it a few times.

It is a bit problematic though to get your program to read the bytes that have been added to it's length...



But I think that the following is what you really need to try.....


If I wanted to add things to an exe file that it could easily work with I would simply create a string
variable and give it a holding value

mykey := 'allowed users is xxx';

then have your program read it's own exe file as I detailed above and
simply look for the string 'allowed users is xxx' and change it to something like 'allowed users is
050' ..... when the program runs it simply checks mykey
to see how many users are allowed :-)

! don't use a string like 'aaaaaaaaaaaaaaaaaaa' to create a string for this purpose because delphi will
compress this to a shorter value when it compiles! ... strings with repeated values and identical strings
are compressed to save space.




Here is a very simple program that shows what I'm getting at

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 Buttons;

type
 TForm1 = class(TForm)
   SpeedButton1: TSpeedButton;
   procedure SpeedButton1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 mykey: string;

implementation

{$R *.DFM}

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
mykey := 'hello world';
speedbutton1.caption := mykey;
end;

end.



If you compile this to an exe and run it it simply displays 'hello world' as the caption of the button
when you click it.... you can use a hex editor to find the string 'hello world' inside the exe file
... then change it to something else like 'hello there' and save it.. when you run the program now it
displays 'hello there'

It is easy to make the program do this sort of simple alteration to it's own exe...and even simpler
to write a small stand alone exe that does this to other exe files... it's like a simple patcher program....just
use ordinary file handling techniques to search for the string to change and to alter the file :-)  


[QUOTE END] ---------------

If this helps you should consider giving the points to Gwena since he is the origin of the text I quoted.

-felonious

0
 
LVL 5

Expert Comment

by:Gwena
ID: 6305770
Hi Dennis9 :-)

I will have to wait until monday or tuesday to write you a little demo... so if you can hang on till then I will email it to you or post it here...


Hi felonius :-)

I'm a 'she' not a 'he'  :-)
0
 
LVL 1

Author Comment

by:Dennis9
ID: 6305972
Hi Gwena.

I can wait to monday if it gonna be a good demo ;-)
Just kiddin.

My email is: dkn@pc.dk


Dennis
0
 
LVL 5

Expert Comment

by:Gwena
ID: 6307336
Hi Dennis9 :-)

 I just whipped up a quickie file patcher for you.. It's up on the web at...

http://www.codearchive.com/~gac/ezpatch.exe
http://www.codearchive.com/~gac/ezpatch.zip

the first file is a compiled exe demo (80kb)
the second link is the full source code

Just enter the string you want to find and change in edit1
and the string you want to change it to in edit2... then just click the button to choose the file to patch... remember that case IS important and that if you patch an exe both strings may need to be the same size! You can modify the code to easily change any data inside a file..no matter how large or small or what type data...and you could call it in a loop to change all occurances of a string in a file or group of files....

I hope that it works OK.. I just tried it on one file...it changed it just fine :-)

If this is what you were looking for just paste the PatchFile procedure I wrote into your program and you have a simple file patcher :-)

0
 
LVL 1

Author Comment

by:Dennis9
ID: 6307670
Hi Gwena.
It work!
But as u say "if you patch an exe both strings may need to be the same size!"

Then i just now want to hear how many points u want, if u can tell me how to modify the code so it can change without knowing the size or length of string.

Thanks for the good looking demo ;-)
Dennis
0
 
LVL 5

Expert Comment

by:Gwena
ID: 6307942
Hi Dennis9 :-)

  If you let me know exactly what it is you want to do I may be able to modify the code to handle it...

  If you are creating a string constant inside your exe that you want to be able to change by directly modifying the file instead of re-compiling it then that is easy...is that what you need?

  If you want to change something like the size of a form or the captions of buttons or some similar thing then that is also easy...

  If you want to alter an exe that was made by someone else and change a string value then that is a bit harder because you will be limited to keeping the string lengths equal...but you might be able to pad the string out using space characters.. i.e
'This String        '  could probably replace this one
'The Original String'

To accomplish this padding simply add spaces till the string lengths are equal.

20 points is more than enough for this question... I don't care much about accumulating them anyway :-)

Just let me know the details of what you want your program to do :-)
0
 
LVL 5

Expert Comment

by:Gwena
ID: 6307958
eek!
the formatting of my last comment made the strings unequal in size ... they were supposed to be the same length..EE sometimes does funny things to the way a comment looks :-)

using dashes instead of spaces

'This String--------' could replace this one
'The Original String'

Hope it formats better now :-)
0
 
LVL 5

Expert Comment

by:Gwena
ID: 6307959
Hmmm? they still look unequal..Oh Well I bet you get the idea anyway :-)
0
 
LVL 1

Author Comment

by:Dennis9
ID: 6308004
Gwena I think I get it ;-)

But anyway the thing i want to modify is a string i have in a program (exe) i have made.

I have made it is a Const, like this exampel:
-----------------------------------------------------------
Const
  AppName = 'My Old Caption';//14 letters

//Then in the Forms Oncreate there could be this:

Caption := AppName;
-----------------------------------------------------------
Something like that i have ;-)

And it is easy to modify, example call to the Procedure u made:
PatchFile(MyFile, 'My Old Caption', '14 Letters....');

But the problem is, if the New string gets longer, or shorter. The exe will not work, because the data has been moved a bit.

How can it modify that, without the exe gets destroyed??


Dennis
(If u need more info then just ask;-))
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 5

Expert Comment

by:Gwena
ID: 6309539
Hi Dennis9 :-)

  OK now I see what you want to do... this will be easy :-)

We can simply set the constant to a longer string like so
AppName = 'My Old Caption plus a lot of extra filler to take up a whole bunch of space and make lots of room';

Then since you are always looking for the same string we can set up our procedure differently... you would call it like this- PatchFile(MyFile,'some new caption'); it only needs the 2 params because you always know the string you are looking for is 'My Old Caption plus a lot of extra filler to take up a whole bunch of space and make lots of room'; and just before the new PatchFile procedure changes the constant it would check to see if the lengths matched.. and if not it would append a string of delimiter characters to the new replacement like so 'This is the new Caption***************************************'
and in your exe you would simply delete all the '*' chars before you set the forms caption :-)

I can code this for you in a jiffy...but I'm not at home right now at my computer.... I'll get back to you soon though :-)

p.s. You cannot use a string like '**********************' inside your exe's source code because the compiler will usually truncate it down to a shorter string... you must use a non-repetitive string to create a holding buffer...Delphi is a very smart compiler and saves space whenever it can... but the repetitive string is just fine when placed inside a compiled exe :-)




0
 

Expert Comment

by:felonious
ID: 6309920
Hi Gwena,

  Now that you have said it, it is, ofcourse, obvious to me that you are female.  Sorry for the 'he'. :)


-felonious
0
 
LVL 5

Expert Comment

by:Gwena
ID: 6311189
Hi Dennis9 :-)

 I created a utility for you to use to embed data into an exe file... it's here http://www.codearchive.com/~gac/data-embeder.exe

 There is a problem with using a constant inside the exe to hold the data... if you ever decide to compress your exe using something like the free exe compressor UPX the constant will be corrupted and made unreadable :-(

  So I devised a new and better way for you to update the caption... this utility stores up to 131 bytes in an unused portion of the exe's PE section. This part of an exe file is left unaltered by an exe compressor and so there will not be a problem :-)

  This is a lot easier to use also... and it does not alter the files length. Feel free to use the util I
wrote for any purpose...I place it in the public domain.
It should also be able to embed a string of data inside other exe's... like a serial number..etc..  But I have not tried to alter non-delphi exe's so proceed with caution :-)

  If you use a hex editor and look at the pe of your exe you will see where the data is being placed ...


To use this util all you need to do is create an oncreate event for your form and replace it with this code



procedure TForm1.FormCreate(Sender: TObject);
Var x: Byte;
begin
Form1.Caption := '';
For X := 121 to 252 do
begin
  if Byte(pointer(Hinstance+X)^) = 0 then Exit;
  Form1.Caption := Form1.Caption + Char(pointer(Hinstance+X)^);
end;
end;

This code looks at the ram image of your exe and sets the form caption to the data that has been embedded :-)

0
 
LVL 5

Expert Comment

by:Gwena
ID: 6311314
I tried it on a few exe's made with other compilers... with some the data embeds without a problem...in others it overwrites some data... better stick to only using it on exe's made with delphi :-)

I also just fixed a bug and uploaded the fixed version of the util....it was leaving part of the old form caption intact if you changed it a second time to a shorter caption ... let me know if you discover any other bug :-)
0
 
LVL 5

Expert Comment

by:Gwena
ID: 6311410
Better use this altered code for the oncreate event
it leaves the default form caption intact until it
has been updated by the util at least once...so your form won't have a blank caption when it first runs..

procedure TForm1.FormCreate(Sender: TObject);
Var x: Byte;
begin
if Byte(pointer(Hinstance+121)^) = 0 then Exit;
Form1.Caption := '';
For X := 121 to 252 do
begin
  if Byte(pointer(Hinstance+X)^) = 0 then Exit;
  Form1.Caption := Form1.Caption + Char(pointer(Hinstance+X)^);
end;
end;

0
 
LVL 1

Author Comment

by:Dennis9
ID: 6312613
Hi Gwena.
I like the new method, and thanks for thinking on the exe compressor, because i probaly gonna use one.
Anyway the new stuff work great! and it is nice, that i don't have to search for anything.

But now i want to know, if there is other places in a exe like that, because i need to store some more data.
I am thinking on useing the last part of the exe (like the selfmod.exe u have made).
Many of the new data i want to save are not longer than 4 letters. But i am very glad that u made that new method.
And if u don't want to use more time on this q, i understand u.

Many Thanks for the help!:>

Dennis
0
 
LVL 5

Expert Comment

by:Gwena
ID: 6313875
Hi Dennis9 :-)

 No I like this Q and I don't mind working on it a while longer :-)

 I only make comments on questions that interest me... I have made some code here answering your Q that I can use in the near future in my own programs :-)

 You have 131 bytes in this area alone...I can modify the utility so that it allows a smaller area for the caption data...say 31 bytes... then we have 100 bytes left that I can break into several smaller areas.... it would only take a few minutes to add some more edits to the util that would store different data... just think about it and let me know what you need...

 You can store many megabytes of data in your exe easily :-) I do it all the time... look at my floppy imager program on my web page.... it's not done yet but it works... it stores an entire 1.44mb floppy inside an exe at runtime...then makes a copy of itself with a new name. It uses a different method to store the data though...the direct read of the exe's image in ram is the simplest way and so I used it in your little utility... using it we can store about 400 bytes at the start of an exe. You cannot use this simple method to read data added to the end of an exe though because windows does not write that to ram when the program runs...you can only read that data from disk...but 400 bytes is a lot so maybe that's enough space for you.

 I recommend using the free UPX to compress your exe file..it makes the smallest exe files and the price is right :-) it saves a lot of space on the users hard drive..even compared to zipping your program... the reason is that a user downloads your zip file and then extracts it...but leaves the zip on the drive....thus no space is saved and in fact using zip has caused the program to use more HD space than if you had sent it in uncompressed raw form :-(  to get the smallest exe using UPX use the --best switch like so
UPX --best SomeExe.exe

If you need the source for the utility let me know and I will post it on my site... it's pretty simple and can be easily modified to store data into an exe in several places.
0
 
LVL 1

Author Comment

by:Dennis9
ID: 6313975
hi Gwena.
Then i am very glad u like the subject ;-)

Can i have the source to your data-embeder.exe ?
I think it is enough with 131 bytes, for the things i need to be able to edit.
But with the stuff u already posted i don't think u need to make an demo for me. But if i use a exe compressor like UPX (I like that one ;-)), Then it is still possible to add extra bytes to then end of the exe, right?
Because then i can just edit the code u posted, to search in the end of the exe.

Dennis
0
 
LVL 5

Expert Comment

by:Gwena
ID: 6314648
Yes.. you can add anything to any exe at the end and it will cause no problem... this opens up all sorts of sneaky possibilities ;-) but to access this appended data you must read the exe into a stream... it won't exist in the ram. Anything inserted into the actual exe file will end up in ram and can be accessed very easily and quickly. It is possible to increase the size of an exe so that you can insert as much data as you want...and even add other executables that will run before the main exe does... but I have not had any luck so far with this technique... but I will put some source on my site if I ever master it :-)

There are no problems with adding data to the end of a UPX'ed file... and there is no problem with putting data into the PE of a UPX'ed file -- in fact UPX adds some extra room for data inside the PE and there is no problem with using both techniques in the same exe... it is best to have the exe read it's own file from disk and place all the data into a string when the program first runs... from then on all your data is available from this string using delphi's pascal style string routines...and they are powerful and easy to use.

Reading data from the exe's PE directly from ram is fast and easy...but is only really handy when the total amount of data you need to store is < 400 bytes...and you should use this method whenever your data will fit inside the PE.

By the way here are the things I am interested in working on at right now.

-Self modifying exe's
-Disk Imagers
-Program generators
-Very small operating systems that fit on a floppy
-Adding executable code to existing programs
-Copy Protection for CD's and floppies
-Contolling hardware using the ports

I usually chime in on any Q on EE that involves these topics :-)

I will post the source to the util on my site in just a bit.....
0
 
LVL 5

Accepted Solution

by:
Gwena earned 20 total points
ID: 6314702
http://www.codearchive.com/~gac/de.zip

The link to the source code
0
 
LVL 1

Author Comment

by:Dennis9
ID: 6314723
Thanks Gwena.
I will take a look on it.

Dennis
0
 
LVL 1

Author Comment

by:Dennis9
ID: 6319249
Thanks Gwena for all the help!!

Dennis ;-)
0
 
LVL 5

Expert Comment

by:Gwena
ID: 6319349
Your welcome Dennis9 :-)

   I will leave email notification on for this Q and if you (or any future readers of the PAQ) need any help just add another comment here and if I can help I will :-)

 
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now