84 lines
3.5 KiB
Docker
84 lines
3.5 KiB
Docker
# Multi-stage build: Use Alpine for building, scratch for final image
|
|
# Alpine is the smallest base image (~5MB) with package manager
|
|
FROM alpine:latest AS build
|
|
|
|
# Install build dependencies with --no-cache to prevent package cache storage
|
|
# build-base: gcc, make, and essential build tools
|
|
# musl-dev: C library headers for static linking
|
|
# linux-headers: Kernel headers for system calls
|
|
# upx: Ultimate Packer for eXecutables - binary compression tool
|
|
# binutils: For objcopy command
|
|
RUN apk add --no-cache build-base musl-dev linux-headers upx binutils
|
|
|
|
# Set working directory for all subsequent operations
|
|
WORKDIR /src
|
|
|
|
# Copy all yescrypt source and header files flat (no subdirectories)
|
|
COPY yescrypt/*.h .
|
|
COPY yescrypt/yescrypt-ref.c .
|
|
COPY yescrypt/yescrypt-common.c .
|
|
COPY yescrypt/sha256.c .
|
|
COPY yescrypt/insecure_memzero.c .
|
|
|
|
# Copy main bruteforce source code
|
|
COPY bruteforce.c .
|
|
|
|
# Enhanced compilation with maximum size optimization
|
|
# Each flag explained:
|
|
# -static: Create statically linked executable (no external dependencies)
|
|
# -Os: Optimize for size, not speed
|
|
# -s: Strip all symbol table and relocation information
|
|
# -fomit-frame-pointer: Don't keep frame pointer in registers (saves one register)
|
|
# -fdata-sections: Place each data item in its own section (enables dead code elimination)
|
|
# -ffunction-sections: Place each function in its own section (enables dead code elimination)
|
|
# -fno-unwind-tables: Don't generate unwind tables for exception handling
|
|
# -fno-asynchronous-unwind-tables: Don't generate async unwind tables
|
|
# -Wl,--gc-sections: Remove unused sections during linking (dead code elimination)
|
|
# -Wl,--strip-all: Strip all symbols during linking
|
|
RUN gcc -static -Os -s \
|
|
-fomit-frame-pointer \
|
|
-fdata-sections \
|
|
-ffunction-sections \
|
|
-fno-unwind-tables \
|
|
-fno-asynchronous-unwind-tables \
|
|
-Wl,--gc-sections \
|
|
-Wl,--strip-all \
|
|
-o bruteforce \
|
|
bruteforce.c \
|
|
yescrypt-ref.c \
|
|
yescrypt-common.c \
|
|
sha256.c \
|
|
insecure_memzero.c \
|
|
# Additional binary stripping to remove specific sections:
|
|
# --strip-all: Remove all symbol and debug information
|
|
# --remove-section=.comment: Remove compiler/version comments
|
|
# --remove-section=.note.*: Remove all note sections (build info, ABI notes)
|
|
# --remove-section=.eh_frame: Remove exception handling frame information
|
|
&& strip --strip-all \
|
|
--remove-section=.comment \
|
|
--remove-section=.note.* \
|
|
--remove-section=.eh_frame \
|
|
bruteforce \
|
|
# === Remove residual padding BEFORE compression === \
|
|
&& objcopy --pad-to=0 --gap-fill=0 bruteforce bruteforce.pad \
|
|
&& mv bruteforce.pad bruteforce \
|
|
# === UPX variant shoot-out: keep smaller of two compressions === \
|
|
&& cp bruteforce bruteforce.ultra && upx --ultra-brute bruteforce.ultra \
|
|
&& cp bruteforce bruteforce.lzma && upx --lzma --best --no-align bruteforce.lzma \
|
|
&& if [ $(stat -c%s bruteforce.ultra) -le $(stat -c%s bruteforce.lzma) ]; then \
|
|
mv bruteforce.ultra bruteforce; rm bruteforce.lzma; \
|
|
else \
|
|
mv bruteforce.lzma bruteforce; rm bruteforce.ultra; \
|
|
fi
|
|
|
|
# Final stage: Start with completely empty image (scratch)
|
|
# This ensures absolute minimum size - no OS layer at all
|
|
FROM scratch
|
|
|
|
# Copy only the final compressed binary from build stage
|
|
# --from=build: Copy from the build stage, not from host
|
|
COPY --from=build /src/bruteforce /
|
|
|
|
# Set the default command for the container
|
|
# Array format prevents shell interpretation and reduces overhead
|
|
ENTRYPOINT ["/bruteforce"] |