Bom fiz este programa somente para matar o tempo.
É um Patcher para múltiplos programas, ele carrega as informações de um XML com o seguinte formato.
- Nó <App> = Nó base de cada aplicação.
- Atributo Name = Nome da aplicação.
- Atributo MD5 = Opcional Hash MD5 do arquivo para evitar que um arquivo incorreto seja escolhido.
- Nó <Binary> (Podem existir múltiplos nós para um mesmo arquivo) = Dados a serem inseridos formatados byte a byte "AA FF 11"...
- Atributo Offset = Posição a partir dá qual inserir os dados.
Obs: Os Bytes e o Offset devem ser informados em formato Hexadecimal.
Código PHP:
<Applications>
<App Name="AppName" MD5="6271587C9C3067E16D857BAA4AC59004">
<Binary Offset="00000000">00 11 22 33 44 55 66 77 88 99</Binary>
<Binary Offset="000000FF">AA BB CC DD EE FF</Binary>
</App>
<App Name="Teste">
<Binary Offset="00000000">01 02 03 04 04 05 06 07 08 09</Binary>
</App>
</Applications>
Somente para constar utilizei o Delphi XE2
Código PHP:
unit UnitPatcher;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, Generics.Collections,
Vcl.Imaging.jpeg;
type
TFrmPatcher = class(TForm)
Image1: TImage;
CmbApps: TComboBox;
Label1: TLabel;
BtnPatch: TButton;
procedure FormCreate(Sender: TObject);
procedure BtnPatchClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
OffsetData = record
Offset: Integer;
Data: TList<Byte>;
end;
AppInfo = record
Name: string;
MD5: string;
Offsets: TList<OffsetData>;
end;
var
FrmPatcher: TFrmPatcher;
implementation
uses
System.StrUtils, System.Types, IdHashMessageDigest, Xml.XMLDoc, Xml.XMLIntf;
var
Apps: TList<AppInfo>;
{$R *.dfm}
procedure TFrmPatcher.BtnPatchClick(Sender: TObject);
var
Dialog: TOpenDialog;
AppStream: TFileStream;
Offset: OffsetData;
MD5Hash: TIdHashMessageDigest5;
B: Byte;
I: Integer;
N: Integer;
begin
Dialog:= TOpenDialog.Create(Self);
MD5Hash:= TIdHashMessageDigest5.Create;
try
Dialog.Options:= [ofOverwritePrompt, ofHideReadOnly, ofFileMustExist, ofExtensionDifferent];
Dialog.Filter:= 'Executable|*.exe|Any|*.*';
if(Dialog.Execute(Self.Handle))then
begin
CopyFile(PWideChar(Dialog.FileName), PWideChar(Dialog.FileName + '.bkp'), false);
AppStream:= TFileStream.Create(Dialog.FileName, fmOpenReadWrite);
if((MD5Hash.HashStreamAsHex(AppStream) = Apps.Items[CmbApps.ItemIndex].MD5) or (Apps.Items[CmbApps.ItemIndex].MD5 = ''))then
begin
for I := 0 to Apps.Items[CmbApps.ItemIndex].Offsets.Count -1 do
begin
Offset:= Apps.Items[CmbApps.ItemIndex].Offsets[I];
AppStream.Seek(Offset.Offset, soFromBeginning);
for N := 0 to Offset.Data.Count -1 do
begin
B:= Offset.Data.Items[N];
AppStream.Write(B, 1);
end;
end;
Application.MessageBox('Patch Successfully!', 'Patched', MB_OK + MB_ICONINFORMATION);
end
else
begin
Raise(Exception.Create('Invalid MD5 hash'));
end;
end;
except on E: Exception do
Application.MessageBox(PWideChar(E.Message), 'Patch Failed', MB_OK + MB_ICONERROR);
end;
Dialog.Free;
MD5Hash.Free;
AppStream.Free;
end;
procedure TFrmPatcher.FormCreate(Sender: TObject);
var
Doc: TXMLDocument;
NodeApp: IXMLNode;
App: AppInfo;
Offset: OffsetData;
Bytes: TStringDynArray;
I: Integer;
N: Integer;
B: Integer;
begin
Apps:= TList<AppInfo>.Create;
Doc:= TXMLDocument.Create(Self);
try
Doc.LoadFromFile('.\Applications.xml');
except on E: Exception do
begin
Doc.Free;
Application.MessageBox(PWideChar(E.Message), 'Fatal Error', MB_OK + MB_ICONERROR);
Application.Terminate;
end
end;
try
for I := 0 to Doc.ChildNodes['Applications'].ChildNodes.Count -1 do
begin
App.Offsets:= TList<OffsetData>.Create;
NodeApp:= Doc.ChildNodes['Applications'].ChildNodes[I];
App.Name:= NodeApp.Attributes['Name'];
try
App.MD5:= NodeApp.Attributes['MD5'];
except
App.MD5:= '';
end;
for N := 0 to NodeApp.ChildNodes.Count -1 do
begin
Offset.Data:= TList<Byte>.Create;
Offset.Offset:= StrToInt('$' + NodeApp.ChildNodes[N].Attributes['Offset']);
Bytes:= SplitString(NodeApp.ChildNodes[N].Text, ' ');
for B := 0 to Length(Bytes) -1 do
begin
Offset.Data.Add(StrToInt('$' + Bytes[B]));
end;
App.Offsets.Add(Offset);
SetLength(Bytes, 0);
Offset.Offset:= 0;
end;
Apps.Add(App);
App.Name:= '';
App.MD5:= '';
end;
except on E: Exception do
begin
App.Offsets.Free;
Offset.Data.Free;
Doc.Free;
Application.MessageBox(PWideChar(E.Message), 'Fatal Error', MB_OK + MB_ICONERROR);
Application.Terminate;
end
end;
for I := 0 to Apps.Count -1 do
begin
CmbApps.Items.Add(Apps.Items[I].Name);
end;
CmbApps.ItemIndex:= 0;
Doc.Free;
end;
procedure TFrmPatcher.FormDestroy(Sender: TObject);
var
I: Integer;
N: Integer;
begin
for I := 0 to Apps.Count -1 do
begin
for N := 0 to Apps.Items[I].Offsets.Count -1 do
begin
Apps.Items[I].Offsets.Items[N].Data.Free;
end;
Apps.Items[I].Offsets.Free;
end;
Apps.Free;
end;
end.
Espero que seja útil á alguém
.