PDA

View Full Version : FXPacker v2.0 - A Data Protector for InnoSetup


BLACKFIRE69
12-10-2023, 01:52
FXPacker API


Introduction:

FXPacker started as a side project to 'FMXInno', primarily dedicated to safeguarding various data types, such as (graphical content: images, music, text, etc.), used in the installer from unauthorized access.


Changes:

This is Version 2. Let's review the changes it introduces.

1. Improved speed and reliability compared to previous versions.
-- Note: This may cause compatibility issues with previous versions.

2. Now supports larger files.
-- Please ensure that the total size of the files remains below 800 MB.
(Total_File_Size * 2 + Extra should be less than 2 GB)

3. Added new events:
-- OnProgress, OnDataSaving, OnItemUnpack, OnEncrypt, OnDecrypt.

4. Introduced additional functions.
-- For a better understanding of how to use these functions,
refer to the examples provided in the attachment.


Simple Example:

Pack:

var
FXOk: Boolean;
BufferA: AnsiString;
BufferW: WideString;
Count: Cardinal;
FSize: Integer;
LPtr: Longint;

begin
FXOk := FXPckrInit('@#123_Test', ExpandConstant('{src}\MySetup.exe'), False);

if FXOk then
begin
// Img1
FXPckrAddFile(ExpandConstant('{src}\Files\Img1.png '));

// Img2
FileSize(ExpandConstant('{src}\Files\Img2.png'), FSize);
SetLength(BufferA, FSize);
FXFileToBuffer1A(ExpandConstant('{src}\Files\Img2. png'), BufferA);
FXPckrAddFromBuffer1A('Img2.png', BufferA);

// Save
FXPckrSave(ExpandConstant('{src}\Setup.dat'));
end;


{ CleanUp }
FXPckrFree;
end;


Unpack:

var
FXOk: Boolean;
BufferA: AnsiString;
BufferW: WideString;
Count: Cardinal;
FSize: Integer;
LPtr: Longint;

begin
FXOk := FXUnPckrInit(ExpandConstant('{src}\Setup.dat'), '@#123_Test');

if not FXOk then
begin
ShowErr('Failed to initialize the setup. The installation process cannot continue.');
end else
begin
// Img1
FXUnPckrExtract('Img1.png', ExpandConstant('{src}'));

// Img2
FSize := FXUnPckrExtractFileSize('Img2.png');
SetLength(BufferA, FSize);
FXUnPckrExtractToBuffer1A('Img2.png', BufferA);
end;


{ CleanUp }
FXUnPckrFree;
end;


Functions / Methods:

{ Pckr }
function FXPckrInit(const Password, ExeFile: WideString; DebugMode: Boolean): Boolean;
function FXPckrAddFile(const FileName: WideString): Boolean;
function FXPckrAddFromStream(const DisplayFilename: WideString; Source: TStream): Boolean;
function FXPckrAddFromBuffer1A(const DisplayFilename: WideString; const Buffer: AnsiString): Boolean;
function FXPckrAddFromBuffer1W(const DisplayFilename: WideString; const Buffer: WideString): Boolean;
function FXPckrAddFromBuffer2A(const DisplayFilename: WideString; const Buffer: PAnsiChar; const Count: Cardinal): Boolean;
function FXPckrAddFromBuffer2W(const DisplayFilename: WideString; const Buffer: PWideChar; const Count: Cardinal): Boolean;
function FXPckrAddFromBuffer3AW(const DisplayFilename: WideString; const Buffer: Longint; const Count: Cardinal): Boolean;
procedure FXPckrSave(const DestPackfile: WideString);
procedure FXPckrFree;

{ Unpckr }
function FXUnPckrInit(const PackFile, Password: WideString): Boolean;
function FXUnPckrFileExist(const DisplayFilename: WideString): Boolean;
function FXUnPckrExtract(const DisplayFilename, DestPath: WideString): Boolean;
function FXUnPckrExtractToStream(const DisplayFilename: WideString; Dest: TStream): Boolean;
function FXUnPckrExtractToBuffer1A(const DisplayFilename: WideString; var Buffer: AnsiString): Boolean;
function FXUnPckrExtractToBuffer1W(const DisplayFilename: WideString; var Buffer: WideString): Boolean;
function FXUnPckrExtractToBuffer2A(const DisplayFilename: WideString; const Buffer: PAnsiChar; var Count: Cardinal): Boolean;
function FXUnPckrExtractToBuffer2W(const DisplayFilename: WideString; const Buffer: PWideChar; var Count: Cardinal): Boolean;
function FXUnPckrExtractToBuffer3AW(const DisplayFilename: WideString; const Buffer: Longint; var Count: Cardinal): Boolean;
function FXUnPckrExtractFileSize(const DisplayFilename: WideString): Cardinal;
procedure FXUnPckrFree;

{ Extra }
function FXBufferToFile1A(const Buffer: AnsiString; const OutFile: WideString): Boolean;
function FXBufferToFile1W(const Buffer: WideString; const OutFile: WideString): Boolean;
function FXBufferToFile2A(const Buffer: PAnsiChar; const Count: Cardinal; const OutFile: WideString): Boolean;
function FXBufferToFile2W(const Buffer: PWideChar; const Count: Cardinal; const OutFile: WideString): Boolean;
function FXBufferToFile3AW(const Buffer: Longint; const Count: Cardinal; const OutFile: WideString): Boolean;

function FXFileToBuffer1A(const FileName: WideString; var Buffer: AnsiString): Boolean;
function FXFileToBuffer1W(const FileName: WideString; var Buffer: WideString): Boolean;
function FXFileToBuffer2A(const FileName: WideString; const Buffer: PAnsiChar; var Count: Cardinal): Boolean;
function FXFileToBuffer2W(const FileName: WideString; const Buffer: PWideChar; var Count: Cardinal): Boolean;
function FXFileToBuffer3AW(const FileName: WideString; const Buffer: Longint; var Count: Cardinal): Boolean;

function FXCastStringToIntegerA(var S: AnsiString): LongInt;
function FXCastStringToIntegerW(var S: WideString): LongInt;
function FXCastIntegerToStringA(const L: LongInt): AnsiString;
function FXCastIntegerToStringW(const L: LongInt): WideString;
function FXAnsiBufferToStr(const ABuffer: AnsiString): WideString;

function FXFreeBufferA(const Buffer: PAnsiChar): Integer;
function FXFreeBufferW(const Buffer: PWideChar): Integer;

{ Events }
procedure FXArchiveOnProgress(Callback: TArchiveOnProg);
procedure FXArchiveOnSaving(Callback: TArchiveOnProg);
procedure FXPackItemOnProgress(Callback: TItemOnProg);
procedure FXUnpackItemOnProgress(Callback: TItemOnProg);
procedure FXEncryptOnProgress(Callback: TCryptOnProg);
procedure FXDecryptOnProgress(Callback: TCryptOnProg);


.

BLACKFIRE69
12-10-2023, 10:58
* Added missing event 'FXPackItemOnProgress'.
-- procedure FXPackItemOnProgress(Callback: TItemOnProg);

BLACKFIRE69
13-10-2023, 07:56
Optional Update:


* Included FastMM for improved memory management.
-- FastMM - Github (https://github.com/pleriche/FastMM5)
* Reduced the file size for enhanced performance and efficiency.
-- 211kb >> 139kb

BLACKFIRE69
14-10-2023, 22:23
Updates available! - [2023-Oct-15]


FXPackerApi v2.0:

* Now supports threading.
-- It'll no longer affect the main thread of the client app (setup.exe)
and will run in its own thread, preventing client app freezing.

* Added a new function.
-- function FXGetItemFileName(const Item: Longint): WideString;


FXPacker GUI v2.0:

* Updated to FXPackerApi v2.0.
* Added the ability to include entire directories, including subdirectories.
* Now you can remove multiple items at once.
* Added a feature to prevent adding duplicate items.


.

Cesar82
15-10-2023, 09:36
@BLACKFIRE69, Thank you very much for the updates.
Maybe you can include an additional function...
function FXPckrAddFileList(const FileList: WideString): Boolean;

Usage like this:
StrList := TStringList.Create;
try
StrList.LoadFromFile(ExpandConatant('{src}\FileLis t.txt'));
FXPckrAddFileList(StrList.Text);
finally
StrList.Free;
end;
You could also store files with a folder structure inside Data.dat.
To do this, use the character "|" as an option to inform the destination path in the internal structure of Data.dat. If "|" does not exist, add as a file without a subfolder in the internal structure of the items.
FXPckrAddFile('C:\my_test\filetest.txt|my_test\fil e_name.txt');
This would allow using files with the same names for different cases.
Thanks!

BLACKFIRE69
08-04-2026, 13:09
FXPacker API Interface
======================

Secure archive handling library designed for integration with Inno Setup.
Provides multi-layered protection with password-based access control (AES-256),
executable binding verification, Runtime executable state matching and
Host-state coupling synchronization.

> Support:
- Supports both standard distribution (external data file) and
Single-EXE distribution (data file embedded directly inside the installer).

> Compatibility:
- Inno Setup v6.0 or later (Required)
- Inno Setup v6.5 or later (Required for Partial Safe Mode)

> Specifications:
- Version : 3.0.0.0
- Author : BLACKFIRE69
- Build : 699CEA00
- Compatibility : Inno Setup v6.x, v6.5 or later
- License : Proprietary (See LICENSE file for details)

> Distribution:
- FXPackerAPI.dll — Core API library. Exposes all packing and unpacking
functions for direct integration into Inno Setup
pascal scripts.

- FXPackerCLI.exe — Command-line interface. Provides full packing
functionality via terminal commands. Suitable for
build pipeline and automation integration.

- FXPackerGUI.exe — Graphical interface. Provides full packing
functionality via a visual interface. Suitable for
manual archive creation and workflow configuration.

> Protection Layers:
- Layer 1 — Password-based access control (AES-256)
- Layer 2 — Executable binding verification
- Layer 3 — Runtime executable state matching and Host-state coupling synchronization.

> Modes:
- Safe Mode : Full protection — all 3 layers active.
Standard distribution with an external data file.

- Partial Safe Mode : Embedded distribution — Designed to allow the data
file to be embedded directly into the installer (Single-EXE)
via Inno Setup compilation.

- Unsafe Mode : Layer 1 only — password protection exclusively.
Anyone with the correct password can extract the
data file. Intended for initial template creation
in the Partial Safe workflow and debugging purposes only.

> Important:
- Safe and Partial Safe modes require the exact same executable that was
present during the packing process. The correct password alone is not
sufficient to extract the data file — the executable identity must also
match. Only Unsafe mode allows extraction with the password alone.

> Features:
- Standard and Single-EXE (embedded) distribution modes
- Detailed logging support (API, CLI, and GUI)
- Automatic protection mode detection on extraction
- Inno Setup credential storage and retrieval
- Buffer, stream, and file input/output support
- Progress tracking for packing, extraction, and processing
- Detailed error reporting via FXGetLastError
- Cross-platform pointer and type conversion utilities


* Basic DataFile Creation

1. Open `Example.iss` and compile it (`MySetup.exe`).

2. Generate Data File:

FXPackerCLI.exe ^
-e:".\MySetup.exe" ^
-p:"Secret123" ^
-i:"inno_key_here" ^
".\Resources\*" ^
".\Img\*.png"

- innosetup-unpacking -

[Setup]
// Encryption
Encryption=True
Password=inno_key_here
//


function InitializeSetup(): Boolean;
begin
Result := FXUnpackInit(ExpandConstant('{src}\Setup.dat'), 'Secret123');

if not Result then
ShowErr('Failed to initialize the setup. Error: ' + FXGetLastError());
end;

function CheckPassword(Password: String): Boolean;
begin
Result := (Password = FXUnpackRefineStr(FXUnpackGetStoredInnoEncryptionK ey));
end;

procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = wpPassword then
WizardForm.PasswordEdit.Text := FXUnpackRefineStr(FXUnpackGetStoredInnoEncryptionK ey)
else
WizardForm.PasswordEdit.Text := '';
end;

procedure InitializeWizard();
var
Res: Boolean;
begin
Res := FXUnpackExtractFile('button.png', ExpandConstant('{src}\_OutImg'));
end;

procedure DeinitializeSetup();
begin
FXUnpackReleaseResources;
end;


* Partial Secure (Embedded Mode) - 3 Pass Workflow:

This mode allows the data file to be embedded directly into the installer (Single-EXE) via Inno Setup compilation.

Step-by-Step Workflow

# Pass 1: The Initial Template

1. Create Initial Archive: Open `FXPacker.exe`. Add your files and set a password.
2. Enable 'Unsafe Mode': This allows the initial archive to be created without an EXE target.
3. Generate Data: Click 'Create Archive'. This creates your initial `Setup.dat`.
4. Compile Setup: Open `Example.iss` and compile it.
> Result: You now have a "Template EXE" (`MySetup.exe`).

code:
FXPackerCLI.exe ^
--unsafe ^
-p="@#123_Test" ^
-i="Jrsoftware" ^
".\Files\Img\*"

# Pass 2: Binding Step 1

5. Configure Packer:
- In `FXPacker.exe`, select the `MySetup.exe` you just created as the Target EXE.
- Set the `Setup.dat` from Pass 1 as the Parent File.
6. Disable 'Unsafe Mode': Security must be active for this step.
7. Enable 'Partial Secure': This triggers the internal identity-binding logic.
8. Select 'Partial Step 1': Required for the first binding pass.
9. Update Data: Click 'Create Archive' to overwrite `Setup.dat`.
10. Compile Setup: Go back to Inno Setup and compile the script again.

code:
FXPackerCLI.exe ^
--psafe ^
-s=1 ^
-e="MySetup.exe" ^
-o="Setup.dat" ^
-p="@#123_Test" ^
-i="Jrsoftware" ^
".\Files\Img\*"

# Pass 3: Binding Step 2 (Final)

11. Configure Packer:
- Keep `MySetup.exe` as the Target EXE.
- Use the updated `Setup.dat` from Pass 2 as the Parent File.
12. Select 'Partial Step 2': This performs the final verification wrap.
13. Finalize Data: Click 'Create Archive' to overwrite `Setup.dat` one last time.
14. Re-Compile: Go back to Inno Setup and compile the script for the final build.

code:
FXPackerCLI.exe ^
--psafe ^
-s=2 ^
-e="MySetup.exe" ^
-o="Setup.dat" ^
-p="@#123_Test" ^
-i="Jrsoftware" ^
".\Files\Img\*"

- innosetup-unpacking -

- Same as the 'Basic DataFile Creation'.

* Result:

You can now distribute just `MySetup.exe`.
It contains the finalized, calibrated `Setup.dat` embedded internally.
No external data file is needed!

* Security Note:

If you change your installer script (code, icons, or version),
you must repeat the binding steps to ensure the security handshake remains valid.


.