FileForums

FileForums (https://fileforums.com/index.php)
-   Conversion Tutorials (https://fileforums.com/forumdisplay.php?f=55)
-   -   FXPacker v2.0 - A Data Protector for InnoSetup (https://fileforums.com/showthread.php?t=106104)

BLACKFIRE69 12-10-2023 01:52

FXPacker v2.0 - A Data Protector for InnoSetup
 
3 Attachment(s)
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.

Code:

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:

Code:

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;


Code:

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:

Code:

{ 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;

Code:

{ 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

Update
 
Code:

* Added missing event 'FXPackItemOnProgress'.
  -- procedure FXPackItemOnProgress(Callback: TItemOnProg);


BLACKFIRE69 13-10-2023 07:56

Optional Update
 
Optional Update:


Code:

* Included FastMM for improved memory management.
    -- FastMM - Github
* Reduced the file size for enhanced performance and efficiency.
    -- 211kb  >>  139kb


BLACKFIRE69 14-10-2023 22:23

FXPackerApi - Updates
 
1 Attachment(s)
Updates available! - [2023-Oct-15]


Code:

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:
Code:

StrList := TStringList.Create;
try
    StrList.LoadFromFile(ExpandConatant('{src}\FileList.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.
Code:

FXPckrAddFile('C:\my_test\filetest.txt|my_test\file_name.txt');
This would allow using files with the same names for different cases.
Thanks!

BLACKFIRE69 08-04-2026 13:09

8 Attachment(s)
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.

Code:

> 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.

Code:

> 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.

Code:

> 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

Code:

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 -

Code:

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

Code:


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(FXUnpackGetStoredInnoEncryptionKey));
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  if CurPageID = wpPassword then
    WizardForm.PasswordEdit.Text := FXUnpackRefineStr(FXUnpackGetStoredInnoEncryptionKey)
  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

Code:

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

Code:

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)

Code:

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 -

Code:

- Same as the 'Basic DataFile Creation'.
Code:

* 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.


.


All times are GMT -7. The time now is 15:48.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2026, vBulletin Solutions Inc.
FileForums @ https://fileforums.com