Свободные альтернативы UPX для сжатия исполняемых файлов

Ищу свободные альтернативы к UPX (Ultimate Packer for eXecutables).

Причины:

  1. Часть кода UPX защищена авторскими правами.
  2. UPX добавляет информацию об авторских правах создателей в сжатые исполняемые файлы и запрещает её удалять.

Есть ли какие-нибудь свободные альтернативы, которые, как и UPX, обеспечивают возможность запуска сжатого исполняемого файла без распаковки?

Может быть, есть способ упаковать сжатый в другой программе файл в новый исполняемый?


Ответы (2 шт):

Автор решения: eri

Для Виндовс нашел список упаковщиков PE: http://pect.atspace.com/

  • ASPACK
  • BAMBAM
  • CRUNCH
  • EXE32PACK
  • EXPRESSOR
  • EZIP
  • FSG
  • JDPACK
  • MEW10
  • MEW11 SE
  • NEOLITE
  • NsPACK
  • PACKLITE
  • PACKMAN
  • PCSHRINKER
  • PECOMPACT
  • PEDIMINISHER
  • PEPACK
  • PEQUAKE
  • PETITE
  • PEX
  • PKLITE32
  • POLYENE
  • SHRINKER32
  • TELOCK
  • THUNDERBOLT
  • UPACK
  • UPX
  • WWPACK32
→ Ссылка
Автор решения: eri

Для Линукса можно упаковать готовый экзешник таким образом:

packed.c

#define _GNU_SOURCE
#include <sys/mman.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <lzma.h>

#include "bin.h"

int main(int argc, char *argv[], char *envp[]) {
    int fd = memfd_create(argv[0], 0);
    lzma_stream strm = LZMA_STREAM_INIT;
    lzma_filter filters[LZMA_FILTERS_MAX + 1];
    filters[0].id = LZMA_FILTER_LZMA2;
    static lzma_options_lzma opt_lzma;
    filters[0].options = &opt_lzma;
    lzma_lzma_preset(&opt_lzma, LZMA_PRESET_DEFAULT);
    filters[1].id = LZMA_VLI_UNKNOWN;
    lzma_ret ret = lzma_raw_decoder(&strm, filters);
    if (ret != LZMA_OK)
        return EXIT_FAILURE;
    uint8_t *inbuf;
    uint8_t outbuf[BUFSIZ];
    strm.next_in = NULL;
    strm.avail_in = BUFSIZ;
    strm.next_out = outbuf;
    strm.avail_out = sizeof(outbuf);
    lzma_action action = LZMA_RUN;
    for (ssize_t i = 0; i < bin_len; i += BUFSIZ) {
        strm.next_in = &(bin[i]);
        strm.avail_in = BUFSIZ;
        if (i + BUFSIZ > bin_len) {
            action = LZMA_FINISH;
            strm.avail_in = bin_len - i;
        }
        do {
            strm.next_out = outbuf;
            strm.avail_out = sizeof(outbuf);
            ret = lzma_code(&strm, action);
            if ((ret != LZMA_OK) && (ret != LZMA_STREAM_END))
                return EXIT_FAILURE;
            else
                write(fd, outbuf, (BUFSIZ - strm.avail_out));
        } while (strm.avail_out == 0);
    }
    lzma_end(&strm);
    fchmod(fd, S_IRWXU);
    return fexecve(fd, argv, envp);
}

build.sh

#!/bin/bash

if [ -z "$1" ]; then
    echo "Ошибка: Не хватает аргумента командной строки."
    exit 1
fi

IN=$1
OUT=$(basename "$1")"_compressed"

echo -e "#include <sys/types.h>\n\nconst unsigned char bin[] = {" > bin.h
cat $IN | lzma -9 --format=raw | xxd -i >> bin.h
echo -e "};\n\nconst ssize_t bin_len = sizeof(bin) / sizeof(bin[0]);" >> bin.h

gcc ./packed.c -Os -flto -s -Wl,-s -Wl,--gc-sections -o $OUT -llzma
strip -s $OUT

Использование:

# Установка необходимых пакетов
apt install gcc liblzma-dev xxd xz-utils binutils
# Сборка сжатого исполняемого файла (например, /usr/bin/nano)
./build.sh /usr/bin/nano
# Запуск собранного файла
./nano_compressed

Исполнимый файл будет распакован в память. Имя файлу присвоено не будет и поэтому возможны проблемы с этим связанные. Замените тогда memfd_creat на tmpfile или creat.

→ Ссылка