A WebAssembly-powered binary file analyzer built with Rust.
- Multi-Format Analysis: PE (Windows), MSI (Windows), DMG (macOS), DEB (Linux), RPM (Linux)
- PE Metadata Extraction: Version info, company, product details, timestamps
- 32-bit & 64-bit Support: Handles both x86 and x64 PE files
- WebAssembly: Runs directly in the browser with native Rust performance
- Production Ready: Minified JS, optimized WASM builds
- TypeScript Support: Full type definitions with IntelliSense
Backend:
- Rust - Core analysis engine
- goblin - Multi-format binary parsing (PE)
- pelite - Advanced PE file analysis
- cfb - Compound File Binary format parsing (MSI)
- wasm-bindgen - Rust/JavaScript interop
Frontend:
- Vanilla JavaScript (ES6 modules)
- Terser - JavaScript minification
-
Rust - Install from https://rustup.rs/
-
wasm-pack - Install via:
cargo install wasm-pack
-
Node.js - For development server and minification
# Build WASM only
npm run build
# Start dev server (uses dev/app.js - unminified)
npm run devOpens at http://localhost:8888/dev/ with unminified JavaScript for debugging.
# Full build (WASM + minification)
./build.sh
# Start production server (uses public/app.min.js - minified)
npm run serveOpens at http://localhost:8888/public/ with optimized code.
The project uses automated tools to maintain code quality and detect dead code:
# Run all lints (Rust clippy, TypeScript ESLint, Knip, cargo-machete)
npm run lint
# Individual linters
npm run lint:rust # Rust clippy
npm run lint:ts # TypeScript ESLint
npm run lint:knip # Dead code detection (TypeScript/JavaScript)
npm run lint:rust:deps # Unused dependencies (Rust)Knip (TypeScript/JavaScript):
- Detects unused files, exports, dependencies, and types
- Configuration:
knip.json - Ignores: generated files (
pkg/,dist/), examples
cargo-machete (Rust):
- Detects unused Rust dependencies in
Cargo.toml - Configuration:
[package.metadata.cargo-machete]inCargo.toml - Install globally:
cargo install cargo-machete
Pre-commit hooks automatically run linters before commits:
# Install hooks (runs automatically after npm install)
npm run prek:install
# Run hooks manually on all files
npm run prek:run
# Bypass hooks (use sparingly)
git commit --no-verifyKnip: Add to knip.json:
{
"ignoreDependencies": ["package-name"],
"ignore": ["path/to/file/**"]
}cargo-machete: Add to Cargo.toml:
[package.metadata.cargo-machete]
ignored = ["crate-name"]upload-analyzer/
βββ src/
β βββ rs/ # Rust source code
β β βββ lib.rs # Main Rust entry point
β β βββ pe.rs # PE file analysis module
β β βββ msi.rs # MSI file analysis module
β β βββ dmg.rs # DMG file analysis module
β β βββ deb.rs # DEB file analysis module
β β βββ rpm.rs # RPM file analysis module
β β
β βββ ts/ # TypeScript source code
β βββ helpers.ts # Type guards and parsers (source)
β βββ types/ # TypeScript definitions
β β βββ index.d.ts # Main type definitions
β β βββ README.md # Types documentation
β βββ examples/ # Usage examples (not published)
β βββ typescript-usage.ts
β
βββ dist/ # Compiled TypeScript (auto-generated)
β βββ helpers.js
β βββ helpers.d.ts
β
βββ dev/ # Development demo
β βββ index.html # Dev page
β βββ app.js # UI JavaScript (unminified)
β
βββ public/ # Production demo
β βββ index.html # Production page
β βββ app.min.js # Bundled JS + WASM loader (auto-generated)
β βββ upload_analyzer_bg.wasm # WASM binary (auto-generated)
β
βββ pkg/ # NPM package (auto-generated)
β βββ upload_analyzer.js
β βββ upload_analyzer_bg.js
β βββ upload_analyzer.d.ts # TypeScript definitions
β βββ upload_analyzer_bg.wasm
β
βββ scripts/ # Build scripts
β βββ bundle-single.js # Production bundler
β
βββ .well-known/ # Browser config
βββ Cargo.toml # Rust dependencies
βββ package.json # Node.js dependencies
βββ tsconfig.json # TypeScript configuration
βββ build.sh # Build script
βββ README.md
Key Directories:
src/rs/- Rust source codesrc/ts/- TypeScript source code, type definitions, and examplesdist/- Compiled TypeScript outputdev/- Development demo with unminified JavaScriptpublic/- Production-ready demo (3 files: HTML, JS, WASM)pkg/- NPM package with TypeScript definitions (auto-generated)scripts/- Build and bundling scripts
To publish this library to npm:
# Build everything (WASM + production demo)
./build.sh
# Or just build the NPM package
npm run build
# Publish to npm
cd pkg
npm publishThe pkg/ folder contains:
upload_analyzer.js- Main entry pointupload_analyzer_bg.js- WASM glue codeupload_analyzer.d.ts- TypeScript definitionsupload_analyzer_bg.wasm- WebAssembly binary (~223 KB)package.json- Package metadata
Package Features:
- β Full TypeScript support
- β Works with bundlers (webpack, rollup, vite)
- β Tree-shakeable ES modules
- β Optimized for production
The public/ folder is production-ready and contains only 3 files (~235 KB total):
./build.sh # Build everythingThen deploy the entire public/ folder to any static host:
- Netlify
- Vercel
- GitHub Pages
- AWS S3
- Any CDN or web server
What's in public/:
index.html- Main pageapp.min.js- Bundled JavaScript with WASM loader (6.4 KB)upload_analyzer_bg.wasm- WebAssembly binary (228 KB)
Full type safety with IntelliSense support:
import init, { analyze_pe_file, get_file_info } from 'upload-analyzer';
import type { FileAnalysis, PEAnalysis } from 'upload-analyzer/types';
import { isPEAnalysis, isAnalysisError } from 'upload-analyzer/helpers';
// Initialize WASM
await init();
// Analyze file
const file = await fetch('example.exe').then(r => r.arrayBuffer());
const data = new Uint8Array(file);
const result = analyze_pe_file(data);
const analysis = JSON.parse(result) as FileAnalysis;
if (isAnalysisError(analysis)) {
console.error('Error:', analysis.error);
} else if (isPEAnalysis(analysis)) {
// TypeScript knows all available fields
console.log('Company:', analysis.CompanyName); // β Autocomplete
console.log('Product:', analysis.ProductName); // β Type-safe
console.log('Version:', analysis.FileVersionNumber); // β IntelliSense
console.log('Signed by:', analysis.SignedBy);
if (analysis.InstallerType) {
console.log('Installer:', analysis.InstallerType);
}
}See types/README.md for complete TypeScript documentation.
import * as analyzer from 'upload-analyzer';
// Initialize
analyzer.init();
// Read file
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', async (e) => {
const file = e.target.files[0];
const buffer = await file.arrayBuffer();
const data = new Uint8Array(buffer);
try {
// Get basic file info
const info = analyzer.get_file_info(data);
console.log('File info:', JSON.parse(info));
// Analyze PE file
const analysis = analyzer.analyze_pe_file(data);
console.log('Analysis:', JSON.parse(analysis));
} catch (error) {
console.error('Analysis failed:', error);
}
});const fs = require('fs');
const analyzer = require('upload-analyzer');
// Read file
const data = fs.readFileSync('example.exe');
const buffer = new Uint8Array(data);
// Get file info
const info = analyzer.get_file_info(buffer);
console.log('File info:', JSON.parse(info));
// Analyze PE file
try {
const analysis = analyzer.analyze_pe_file(buffer);
const result = JSON.parse(analysis);
console.log('Format:', result.Format);
console.log('Architecture:', result.architecture);
console.log('Sections:', result.sections);
console.log('Imports:', result.imports);
console.log('Exports:', result.exports);
} catch (error) {
console.error('Analysis failed:', error);
}Initialize the WASM module. Call this once before using other functions.
Get basic information about a binary file.
Parameters:
data: Uint8Array containing the file data
Returns: JSON string with file information
Perform detailed analysis of a PE file.
Parameters:
data: Uint8Array containing the PE file data
Returns: JSON string with analysis results including:
Format: Type of file (PE, MSI, DMG, DEB, RPM)architecture: CPU architecture (x86, x86_64)sections: Array of section informationimports: List of imported functionsexports: List of exported functionsis_64bit: Boolean indicating 64-bit PEentry_point: Entry point address
{
"Format": "PE",
"architecture": "x86_64",
"is_64bit": true,
"entry_point": 4096,
"sections": [
{
"name": ".text",
"virtual_size": 8192,
"virtual_address": 4096,
"raw_data_size": 8192
}
],
"imports": [
"ExitProcess (KERNEL32.dll)",
"GetLastError (KERNEL32.dll)"
],
"exports": [
"MainFunction"
]
}MIT
Contributions are welcome! Please feel free to submit a Pull Request.