Supports three packing modes: - append (default) — data after IEND marker - chunk — private pnZp PNG chunk - lsb — least significant bits of pixels Includes Python (pack.py/unpack.py) and PowerShell (pack.ps1/unpack.ps1) implementations with full cross-compatibility. Features: self-extract bootstrap, metadata one-liners (eXIf/tEXt), CRC32 integrity check, PNG clean mode.
81 lines
4.6 KiB
Markdown
81 lines
4.6 KiB
Markdown
# png-zip: PowerShell версия
|
||
|
||
Упаковка и распаковка файлов внутри PNG без Python. Только PowerShell 5.1+ (встроен в Windows 10/11).
|
||
|
||
## Упаковка
|
||
|
||
```powershell
|
||
powershell -File pack.ps1 cover.png secret.txt -Output packed.png
|
||
```
|
||
|
||
### Self-extract
|
||
|
||
Встраивает `unpack.ps1` внутрь PNG — на целевой машине не нужны никакие скрипты:
|
||
|
||
```powershell
|
||
powershell -File pack.ps1 cover.png secret.txt -Output bootstrap.png -SelfExtract
|
||
```
|
||
|
||
Внутри `bootstrap.png`: `unpack.ps1` + `secret.txt`. Извлечение на целевой машине — см. раздел «Bootstrap».
|
||
|
||
При `-SelfExtract` все bootstrap-однострочники (Python, Python CMD, PowerShell, PowerShell CMD) автоматически сохраняются в метаданных PNG — eXIf (EXIF UserComment) и tEXt (Comment). Их видно в свойствах файла:
|
||
|
||
- **Windows**: правый клик → Свойства → Details → Comments
|
||
- **PowerShell**: `exiftool bootstrap.png`
|
||
|
||
> Base64/EncodedCommand варианты генерируются динамически с реальным именем выходного файла.
|
||
|
||
## Распаковка
|
||
|
||
```powershell
|
||
powershell -File unpack.ps1 packed.png
|
||
powershell -File unpack.ps1 packed.png -OutDir .\out
|
||
powershell -File unpack.ps1 packed.png -List
|
||
powershell -File unpack.ps1 packed.png -All
|
||
```
|
||
|
||
## Bootstrap: доставка без ничего
|
||
|
||
На целевой машине есть только `bootstrap.png` (созданный с `-SelfExtract`) и PowerShell.
|
||
|
||
### 1. Извлечь unpack.ps1 однострочником
|
||
|
||
Замените `IMG` на имя вашего файла:
|
||
|
||
```powershell
|
||
$d=[IO.File]::ReadAllBytes('IMG');$t=[Text.Encoding]::GetEncoding(28591).GetString($d);$s='PNGZIP';$i=-1;do{$i=$t.IndexOf($s,$i+1,[StringComparison]::Ordinal)}while($i-ge0-and($d[$i+6]-ne0-or$d[$i+7]-ne1));$p=$i+8;$nl=$d[$p]*256+$d[$p+1];$p+=2;$n=[Text.Encoding]::UTF8.GetString($d,$p,$nl);$p+=$nl;$pl=[uint64]0;for($k=0;$k-lt8;$k++){$pl=$pl*256+$d[$p+$k]};$p+=8;$ms=New-Object IO.MemoryStream;$ms.Write($d,$p+2,$pl-6);[void]$ms.Seek(0,0);$ds=New-Object IO.Compression.DeflateStream($ms,[IO.Compression.CompressionMode]::Decompress);$os=New-Object IO.MemoryStream;$ds.CopyTo($os);[IO.File]::WriteAllBytes($n,$os.ToArray());Write-Host "Extracted: $n"
|
||
```
|
||
|
||
Ищет первый `PNGZIP` с байтами `\x00\x01` после — это встроенный `unpack.ps1`.
|
||
|
||
**Windows CMD** — готовый EncodedCommand-однострочник (с уже подставленным именем файла) выводится при паковке и сохраняется в метаданных PNG. Скопируйте из консоли или из свойств файла (Details → Comments).
|
||
|
||
### 2. Извлечь основной файл
|
||
|
||
```powershell
|
||
powershell -File unpack.ps1 bootstrap.png
|
||
```
|
||
|
||
### Однострочник (без bootstrap)
|
||
|
||
Извлечь последний payload напрямую (если self-extract не использовался). Замените `IMG` на имя файла:
|
||
|
||
```powershell
|
||
$d=[IO.File]::ReadAllBytes('IMG');$t=[Text.Encoding]::GetEncoding(28591).GetString($d);$s='PNGZIP';$i=$d.Length;do{$i=$t.LastIndexOf($s,$i-1,[StringComparison]::Ordinal)}while($i-ge0-and($d[$i+6]-ne0-or$d[$i+7]-ne1));$p=$i+8;$nl=$d[$p]*256+$d[$p+1];$p+=2;$n=[Text.Encoding]::UTF8.GetString($d,$p,$nl);$p+=$nl;$pl=[uint64]0;for($k=0;$k-lt8;$k++){$pl=$pl*256+$d[$p+$k]};$p+=8;$ms=New-Object IO.MemoryStream;$ms.Write($d,$p+2,$pl-6);[void]$ms.Seek(0,0);$ds=New-Object IO.Compression.DeflateStream($ms,[IO.Compression.CompressionMode]::Decompress);$os=New-Object IO.MemoryStream;$ds.CopyTo($os);[IO.File]::WriteAllBytes($n,$os.ToArray());Write-Host "Extracted: $n"
|
||
```
|
||
|
||
## Очистка PNG
|
||
|
||
Удалить все встроенные данные (payload, bootstrap-метаданные eXIf/tEXt):
|
||
|
||
```powershell
|
||
powershell -File pack.ps1 packed.png -Clean -Output clean.png
|
||
```
|
||
|
||
## Ограничения
|
||
|
||
- Только append-режим. Для chunk и lsb используйте Python-версию (`pack.py` / `unpack.py`).
|
||
- CRC32 и Adler32 реализованы через inline C# (`Add-Type`), первый запуск чуть медленнее из-за компиляции.
|
||
- Для файлов > 100 MB может быть медленнее Python-версии.
|
||
- Формат payload полностью совместим с Python-версией — можно паковать на одной ОС, распаковывать на другой.
|