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/package.json b/package.json index 82d61846..fc89516e 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ }, "devDependencies": { "@biomejs/biome": "catalog:", - "@eslint/compat": "1.3.2", + "@eslint/compat": "2.0.1", "@eslint/js": "9.35.0", "@socketsecurity/lib": "5.5.1", "eslint": "9.35.0", 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-lock.yaml b/pnpm-lock.yaml index 4c6340ef..1f612f1b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -48,8 +48,8 @@ importers: specifier: 'catalog:' version: 2.2.4 '@eslint/compat': - specifier: 1.3.2 - version: 1.3.2(eslint@9.35.0(jiti@2.6.1)) + specifier: 2.0.1 + version: 2.0.1(eslint@9.35.0(jiti@2.6.1)) '@eslint/js': specifier: 9.35.0 version: 9.35.0 @@ -544,9 +544,9 @@ packages: resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/compat@1.3.2': - resolution: {integrity: sha512-jRNwzTbd6p2Rw4sZ1CgWRS8YMtqG15YyZf7zvb6gY2rB2u6n+2Z+ELW0GtL0fQgyl0pr4Y/BzBfng/BdsereRA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/compat@2.0.1': + resolution: {integrity: sha512-yl/JsgplclzuvGFNqwNYV4XNPhP3l62ZOP9w/47atNAdmDtIFCx6X7CSk/SlWUuBGkT4Et/5+UD+WyvX2iiIWA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} peerDependencies: eslint: ^8.40 || 9 peerDependenciesMeta: @@ -565,6 +565,10 @@ packages: resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@1.0.1': + resolution: {integrity: sha512-r18fEAj9uCk+VjzGt2thsbOmychS+4kxI14spVNibUO2vqKX7obOG+ymZljAwuPZl+S3clPGwCwTDtrdqTiY6Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@eslint/eslintrc@3.3.3': resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2005,10 +2009,12 @@ packages: tar@7.4.3: resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} engines: {node: '>=18'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me tar@7.5.2: resolution: {integrity: sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==} engines: {node: '>=18'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me taze@19.9.2: resolution: {integrity: sha512-If8bq7lSckIMPfXV+C9jjEfdsQnRryh/foKfpX/ah6zI0TrQfUGWSGCaaD32Bqy5/KGRmLZie3EwMSr3Au21XQ==} @@ -2400,7 +2406,9 @@ snapshots: '@eslint-community/regexpp@4.12.2': {} - '@eslint/compat@1.3.2(eslint@9.35.0(jiti@2.6.1))': + '@eslint/compat@2.0.1(eslint@9.35.0(jiti@2.6.1))': + dependencies: + '@eslint/core': 1.0.1 optionalDependencies: eslint: 9.35.0(jiti@2.6.1) @@ -2418,6 +2426,10 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 + '@eslint/core@1.0.1': + dependencies: + '@types/json-schema': 7.0.15 + '@eslint/eslintrc@3.3.3': dependencies: ajv: 6.12.6