diff --git a/.dockerignore b/.dockerignore index 8bf9eacf..03f9e5b1 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,85 +1,42 @@ -# Git -.git -.github -.gitignore -.gitattributes +# Docker build context exclusions +# This prevents platform-specific build artifacts from being copied into Docker builds -# Node.js -node_modules -npm-debug.log -yarn-error.log -pnpm-debug.log +# ============================================================================== +# Build Artifacts (platform-specific object files, binaries, etc.) +# ============================================================================== -# Build outputs -dist -build -# But keep downloaded dependencies for Docker builds -!packages/build-infra/build/downloaded -!packages/binject/build/downloaded -*.log -*.tmp -*.temp - -# Development files -.vscode -.idea -*.swp -*.swo -*~ -.DS_Store +# Platform-specific build artifacts (dev/prod builds with .o files, binaries) +packages/binject/build/ +packages/binpress/build/ +packages/binflate/build/ +packages/bin-infra/build/ +packages/node-smol-builder/build/ -# Documentation -*.md -!README.md -docs +# Keep pre-built libraries needed for Docker builds +!packages/build-infra/build/downloaded/ -# Test files -test -tests -*.test.js -*.test.ts -*.spec.js -*.spec.ts -__tests__ -coverage -.nyc_output +# Compiled binaries +packages/binpress/out/ +packages/binflate/out/ +packages/binject/out/ -# CI/CD -.github -.gitlab-ci.yml -.travis.yml -circle.yml -appveyor.yml +# Distribution binaries (E2E test artifacts) +**/dist/ -# Package manager lock files (keep pnpm-lock.yaml for reproducible builds) -package-lock.json -yarn.lock +# ============================================================================== +# Git and CI +# ============================================================================== -# Environment files -.env -.env.local -.env.*.local -.env.production -.env.development -.env.test +.git/ +.github/ -# Secrets and credentials -*.key -*.pem -*.p12 -*.pfx -secrets.json -credentials.json +# ============================================================================== +# Logs and Temporary Files +# ============================================================================== -# Cache directories -.cache -.parcel-cache -.next -.nuxt -.eslintcache -.stylelintcache - -# Temporary files -tmp -temp -*.bak +*.log +**/*.log +.DS_Store +*.swp +*.swo +*~ diff --git a/.gitmodules b/.gitmodules index a5bdfe44..9266e585 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,7 @@ [submodule "packages/node-smol-builder/upstream/node"] path = packages/node-smol-builder/upstream/node url = https://github.com/nodejs/node.git - # v24.11.1 + # v24.11.2 ref = 18aefb2d2b36938316d27b5cb53089e97632f0c3 shallow = true [submodule "packages/yoga-layout-builder/upstream/yoga"] @@ -19,7 +19,7 @@ [submodule "packages/bin-infra/upstream/lief"] path = packages/bin-infra/upstream/lief url = https://github.com/lief-project/LIEF.git - # v0.17.2 + # v0.17.3 ref = aa2b617f47c2f75fca9ff00b146dabbaf1b9f422 shallow = true [submodule "packages/bin-infra/upstream/lzfse"] diff --git a/packages/bin-infra/package.json b/packages/bin-infra/package.json index 200b7f12..d3a36594 100644 --- a/packages/bin-infra/package.json +++ b/packages/bin-infra/package.json @@ -1,6 +1,6 @@ { "name": "bin-infra", - "version": "0.0.0", + "version": "0.0.1", "description": "Shared binary infrastructure for binject and binpress", "private": true, "license": "MIT", diff --git a/packages/binflate/package.json b/packages/binflate/package.json index 1e46a014..a17eb73a 100644 --- a/packages/binflate/package.json +++ b/packages/binflate/package.json @@ -1,6 +1,6 @@ { "name": "binflate", - "version": "0.0.0", + "version": "0.0.1", "description": "Binary decompression tool", "private": true, "license": "MIT", diff --git a/packages/binject/Dockerfile.glibc b/packages/binject/Dockerfile.glibc index 1df84d86..6a5ff264 100644 --- a/packages/binject/Dockerfile.glibc +++ b/packages/binject/Dockerfile.glibc @@ -28,6 +28,8 @@ RUN echo "Cache buster: ${CACHE_BUSTER}" && \ openssl-devel \ cmake \ patch \ + wget \ + perl \ && \ # Install GitHub CLI. dnf -y install 'dnf-command(config-manager)' && \ @@ -39,6 +41,17 @@ RUN echo "Cache buster: ${CACHE_BUSTER}" && \ npm install -g pnpm@10.26.1 && \ dnf clean all +# Build OpenSSL 1.1.1w from source (required for SHA512 in dlx_cache_common.h) +WORKDIR /tmp/openssl-build +RUN wget https://www.openssl.org/source/openssl-1.1.1w.tar.gz && \ + tar xzf openssl-1.1.1w.tar.gz && \ + cd openssl-1.1.1w && \ + ./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl no-shared && \ + make -j$(nproc) && \ + make install && \ + cd / && \ + rm -rf /tmp/openssl-build + # Set working directory. WORKDIR /workspace @@ -54,9 +67,10 @@ RUN LIBLZMA_ARCH=$([ "$TARGETARCH" = "amd64" ] && echo "x64" || echo "arm64") && cp -r "${LIBLZMA_DIR}/include" /usr/local/ # Add /usr/local/lib to library path for static liblzma. +# Include OpenSSL paths and -lcrypto for SHA512 linking (fixes undefined reference to 'SHA512') ENV PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH -ENV LDFLAGS="-L/usr/local/lib" -ENV CFLAGS="-I/usr/local/include" +ENV LDFLAGS="-L/usr/local/lib -L/usr/local/ssl/lib -lcrypto" +ENV CFLAGS="-I/usr/local/include -I/usr/local/ssl/include" ENV CXXFLAGS="" # Install workspace dependencies. diff --git a/packages/binject/package.json b/packages/binject/package.json index 95961005..5554af90 100644 --- a/packages/binject/package.json +++ b/packages/binject/package.json @@ -1,6 +1,6 @@ { "name": "binject", - "version": "0.0.0", + "version": "0.0.1", "description": "Binary resource injection tool", "private": true, "license": "MIT", diff --git a/packages/binject/src/binject.c b/packages/binject/src/binject.c index 4b64f654..87e35001 100644 --- a/packages/binject/src/binject.c +++ b/packages/binject/src/binject.c @@ -626,7 +626,7 @@ int binject_single(const char *executable, const char *output, const char *resou /* CLI: batch inject command (SEA and/or VFS in one pass) */ int binject_batch(const char *executable, const char *output, const char *sea_resource, const char *vfs_resource, - int vfs_in_memory) { + int vfs_in_memory, int skip_repack) { (void)vfs_in_memory; // Reserved for future VFS extraction control at runtime /* Check if this is a compressed stub */ @@ -728,14 +728,21 @@ int binject_batch(const char *executable, const char *output, /* If this was a compressed stub, repack it with the modified binary */ if (is_compressed) { - printf("\n"); - printf("Repacking compressed stub...\n"); - rc = binject_repack_workflow(executable, target_binary, output); - if (rc != BINJECT_OK) { - fprintf(stderr, "Error: Failed to repack compressed stub\n"); - return rc; + if (skip_repack) { + printf("\n"); + printf("⚠ Skipping stub repacking (--skip-repack flag)\n"); + printf("✓ Modified extracted binary: %s\n", target_binary); + printf(" You can test this binary directly before repacking.\n"); + } else { + printf("\n"); + printf("Repacking compressed stub...\n"); + rc = binject_repack_workflow(executable, target_binary, output); + if (rc != BINJECT_OK) { + fprintf(stderr, "Error: Failed to repack compressed stub\n"); + return rc; + } + printf("✓ Stub repacking complete\n"); } - printf("✓ Stub repacking complete\n"); } return rc; diff --git a/packages/binject/src/binject.h b/packages/binject/src/binject.h index 77eef642..96db7efd 100644 --- a/packages/binject/src/binject.h +++ b/packages/binject/src/binject.h @@ -44,7 +44,7 @@ int binject_single(const char *executable, const char *output, const char *resou const char *section_name); int binject_batch(const char *executable, const char *output, const char *sea_resource, const char *vfs_resource, - int vfs_in_memory); + int vfs_in_memory, int skip_repack); int binject_list(const char *executable); int binject_extract(const char *executable, const char *section_name, const char *output_file); diff --git a/packages/binject/src/elf_inject_lief.cpp b/packages/binject/src/elf_inject_lief.cpp index ef5638ba..714dcacf 100644 --- a/packages/binject/src/elf_inject_lief.cpp +++ b/packages/binject/src/elf_inject_lief.cpp @@ -135,13 +135,10 @@ extern "C" int binject_elf_lief(const char* executable, printf("Writing modified binary...\n"); - // Use raw write approach to bypass LIEF's ~1MB note size limit - int write_result = elf_note_utils::write_with_notes_raw( - binary.get(), executable, tmpfile); - if (write_result != 0) { - fprintf(stderr, "Error: Failed to write binary with raw notes\n"); - return BINJECT_ERROR; - } + // Use LIEF approach with proper fixes for SEA/VFS injection + // This includes: PT_NOTE p_vaddr fixes, ALLOC flag removal, + // matching PT_LOAD segments, and triple-write pattern + elf_note_utils::write_with_notes(binary.get(), tmpfile); // Verify file was actually written result = binject::verify_file_written(tmpfile); @@ -282,16 +279,12 @@ extern "C" int binject_elf_lief_batch( printf("Writing modified binary...\n"); - // Use raw write approach to bypass LIEF's ~1MB note size limit - // This writes notes directly to the binary without LIEF's builder - int write_result = elf_note_utils::write_with_notes_raw( - binary.get(), executable, tmpfile); - if (write_result != 0) { - fprintf(stderr, "Error: Failed to write binary with raw notes\n"); - return BINJECT_ERROR; - } + // Use LIEF approach with proper fixes for SEA/VFS injection + // This includes: PT_NOTE p_vaddr fixes, ALLOC flag removal, + // matching PT_LOAD segments, and triple-write pattern + elf_note_utils::write_with_notes(binary.get(), tmpfile); - printf("Wrote binary with PT_NOTE segments (raw)\n"); + printf("Wrote binary with PT_NOTE segments (LIEF)\n"); // Verify file was actually written int result = binject::verify_file_written(tmpfile); diff --git a/packages/binject/src/main.c b/packages/binject/src/main.c index 8b53a9e9..faef5598 100644 --- a/packages/binject/src/main.c +++ b/packages/binject/src/main.c @@ -424,7 +424,7 @@ static char* generate_sea_blob_from_config(const char *config_path) { static void print_usage(const char *program) { printf("binject - Pure C alternative to postject\n\n"); printf("Usage:\n"); - printf(" %s inject -e -o [--sea ] [--vfs |--vfs-on-disk |--vfs-in-memory |--vfs-compat]\n", program); + printf(" %s inject -e -o [--sea ] [--vfs |--vfs-on-disk |--vfs-in-memory |--vfs-compat] [--skip-repack]\n", program); printf(" %s list \n", program); printf(" %s extract -e [--vfs|--sea] -o \n", program); printf(" %s verify -e [--vfs|--sea]\n", program); @@ -443,6 +443,7 @@ static void print_usage(const char *program) { printf(" --vfs-in-memory Inject VFS blob and keep in memory at runtime (no extraction)\n"); printf(" --vfs-compat Enable VFS support without bundling files (compatibility mode)\n"); printf(" --sea Inject SEA blob to NODE_SEA/__NODE_SEA_BLOB\n"); + printf(" --skip-repack Skip repacking compressed stub (for testing extracted binary)\n"); printf(" If path ends in .json, runs: node --experimental-sea-config \n"); printf(" -h, --help Show this help message\n"); printf(" -v, --version Show version information\n"); @@ -474,6 +475,7 @@ int main(int argc, char *argv[]) { const char *sea_resource = NULL; const char *vfs_resource = NULL; int vfs_in_memory = 0; // Default: extract VFS to disk at runtime + int skip_repack = 0; // Default: repack compressed stubs for (int i = 2; i < argc; i++) { if (strcmp(argv[i], "-e") == 0 || strcmp(argv[i], "--executable") == 0) { @@ -489,6 +491,8 @@ int main(int argc, char *argv[]) { vfs_resource = ""; // Empty string marker for VFS compatibility mode } else if (strcmp(argv[i], "--sea") == 0) { if (i + 1 < argc) sea_resource = argv[++i]; + } else if (strcmp(argv[i], "--skip-repack") == 0) { + skip_repack = 1; } } @@ -515,7 +519,7 @@ int main(int argc, char *argv[]) { sea_resource = generated_blob; // Use generated blob instead } - int result = binject_batch(executable, output, sea_resource, vfs_resource, vfs_in_memory); + int result = binject_batch(executable, output, sea_resource, vfs_resource, vfs_in_memory, skip_repack); // Clean up generated blob if we created one if (generated_blob) { diff --git a/packages/binpress/package.json b/packages/binpress/package.json index 47decf70..32e23382 100644 --- a/packages/binpress/package.json +++ b/packages/binpress/package.json @@ -1,6 +1,6 @@ { "name": "binpress", - "version": "0.0.0", + "version": "0.0.1", "description": "Binary compression tool", "private": true, "license": "MIT", diff --git a/packages/node-smol-builder/package.json b/packages/node-smol-builder/package.json index 3a1d47ca..310e2829 100644 --- a/packages/node-smol-builder/package.json +++ b/packages/node-smol-builder/package.json @@ -13,6 +13,8 @@ "clean:dist": "node scripts/clean.mjs --dist", "cover": "node scripts/cover.mjs", "test": "vitest run", + "test:linux-x64-docker": "node scripts/test-linux-x64-docker.mjs", + "test:linux-x64-docker:musl": "node scripts/test-linux-x64-docker.mjs --musl", "test:node-suite": "node scripts/test-node-suite.mjs", "test:node-suite:dev": "node scripts/test-node-suite.mjs --dev", "test:node-suite:prod": "node scripts/test-node-suite.mjs --prod", diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 4b695340..bbad93cd 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -7,7 +7,7 @@ catalog: '@biomejs/biome': 2.2.4 '@dotenvx/dotenvx': 1.31.0 '@socketsecurity/lib': 5.4.0 - '@types/node': 24.9.2 + '@types/node': 25.0.6 acorn: 8.14.0 acorn-walk: 8.3.4 adm-zip: 0.5.16