Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 33 additions & 76 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -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
*~
4 changes: 2 additions & 2 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -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"]
Expand All @@ -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"]
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"globals": "16.4.0",
"husky": "9.1.7",
"taze": "19.9.2",
"typescript-eslint": "8.44.1",
"typescript-eslint": "8.53.0",
"vitest": "catalog:",
"yoctocolors-cjs": "catalog:"
}
Expand Down
2 changes: 1 addition & 1 deletion packages/bin-infra/package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
2 changes: 1 addition & 1 deletion packages/binflate/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "binflate",
"version": "0.0.0",
"version": "0.0.1",
"description": "Binary decompression tool",
"private": true,
"license": "MIT",
Expand Down
18 changes: 16 additions & 2 deletions packages/binject/Dockerfile.glibc
Original file line number Diff line number Diff line change
Expand Up @@ -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)' && \
Expand All @@ -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

Expand All @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion packages/binject/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "binject",
"version": "0.0.0",
"version": "0.0.1",
"description": "Binary resource injection tool",
"private": true,
"license": "MIT",
Expand Down
23 changes: 15 additions & 8 deletions packages/binject/src/binject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion packages/binject/src/binject.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
25 changes: 9 additions & 16 deletions packages/binject/src/elf_inject_lief.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 6 additions & 2 deletions packages/binject/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <executable> -o <output> [--sea <path>] [--vfs <path>|--vfs-on-disk <path>|--vfs-in-memory <path>|--vfs-compat]\n", program);
printf(" %s inject -e <executable> -o <output> [--sea <path>] [--vfs <path>|--vfs-on-disk <path>|--vfs-in-memory <path>|--vfs-compat] [--skip-repack]\n", program);
printf(" %s list <executable>\n", program);
printf(" %s extract -e <executable> [--vfs|--sea] -o <output>\n", program);
printf(" %s verify -e <executable> [--vfs|--sea]\n", program);
Expand All @@ -443,6 +443,7 @@ static void print_usage(const char *program) {
printf(" --vfs-in-memory <path> 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 <path> 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 <path>\n");
printf(" -h, --help Show this help message\n");
printf(" -v, --version Show version information\n");
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
}
}

Expand All @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion packages/binpress/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "binpress",
"version": "0.0.0",
"version": "0.0.1",
"description": "Binary compression tool",
"private": true,
"license": "MIT",
Expand Down
2 changes: 2 additions & 0 deletions packages/node-smol-builder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Loading