diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e95c005 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,220 @@ +name: CI/CD Pipeline + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main ] + release: + types: [ published ] + +env: + CARGO_TERM_COLOR: always + RUST_BACKTRACE: 1 + +jobs: + test: + name: Test Suite + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [windows-latest, ubuntu-latest, macos-latest] + rust: [stable, beta] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: ${{ matrix.rust }} + components: rustfmt, clippy + + - name: Cache cargo registry + uses: actions/cache@v3 + with: + path: ~/.cargo/registry + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo index + uses: actions/cache@v3 + with: + path: ~/.cargo/git + key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo build + uses: actions/cache@v3 + with: + path: target + key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} + + - name: Check formatting + run: cargo fmt --all -- --check + + - name: Run clippy + run: cargo clippy --all-targets --all-features -- -D warnings + + - name: Run tests + run: cargo test --all-features --verbose + + - name: Run doc tests + run: cargo test --doc + + security: + name: Security Audit + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + - name: Install cargo-audit + run: cargo install cargo-audit + + - name: Run security audit + run: cargo audit + + - name: Install cargo-deny + run: cargo install cargo-deny + + - name: Run license and dependency check + run: cargo deny check + + coverage: + name: Code Coverage + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + components: llvm-tools-preview + + - name: Install cargo-llvm-cov + run: cargo install cargo-llvm-cov + + - name: Generate coverage + run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info + + - name: Upload to codecov.io + uses: codecov/codecov-action@v3 + with: + file: lcov.info + fail_ci_if_error: false + + benchmark: + name: Performance Benchmarks + runs-on: windows-latest + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + - name: Run benchmarks + run: cargo bench --all-features + + - name: Store benchmark result + uses: benchmark-action/github-action-benchmark@v1 + with: + tool: 'cargo' + output-file-path: target/criterion/benchmark-results.json + github-token: ${{ secrets.GITHUB_TOKEN }} + auto-push: true + + build: + name: Build Release + runs-on: ${{ matrix.os }} + needs: [test, security] + strategy: + matrix: + include: + - os: windows-latest + target: x86_64-pc-windows-msvc + extension: .exe + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + extension: '' + - os: macos-latest + target: x86_64-apple-darwin + extension: '' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - name: Build release + run: cargo build --release --target ${{ matrix.target }} + + - name: Create archive + shell: bash + run: | + if [[ "${{ matrix.os }}" == "windows-latest" ]]; then + 7z a ghost-${{ matrix.target }}.zip target/${{ matrix.target }}/release/ghost-cli.exe + else + tar czf ghost-${{ matrix.target }}.tar.gz -C target/${{ matrix.target }}/release ghost-cli + fi + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: ghost-${{ matrix.target }} + path: ghost-${{ matrix.target }}.* + + release: + name: Create Release + runs-on: ubuntu-latest + needs: [build] + if: github.event_name == 'release' + steps: + - name: Download all artifacts + uses: actions/download-artifact@v3 + + - name: Create release + uses: softprops/action-gh-release@v1 + with: + files: '**/ghost-*' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + docker: + name: Build Docker Image + runs-on: ubuntu-latest + needs: [test, security] + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: | + ghcr.io/${{ github.repository }}:latest + ghcr.io/${{ github.repository }}:${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..65a5eb2 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,53 @@ +# Use multi-stage build for smaller final image +FROM rust:1.75-slim as builder + +WORKDIR /app + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + pkg-config \ + libssl-dev \ + && rm -rf /var/lib/apt/lists/* + +# Copy manifests +COPY Cargo.toml Cargo.lock ./ +COPY ghost-core/Cargo.toml ghost-core/ +COPY ghost-cli/Cargo.toml ghost-cli/ + +# Create dummy source files to build dependencies +RUN mkdir ghost-core/src ghost-cli/src && \ + echo "fn main() {}" > ghost-cli/src/main.rs && \ + echo "" > ghost-core/src/lib.rs + +# Build dependencies +RUN cargo build --release && \ + rm -rf ghost-core/src ghost-cli/src target/release/deps/ghost* + +# Copy source code +COPY ghost-core/src ghost-core/src/ +COPY ghost-cli/src ghost-cli/src/ + +# Build application +RUN cargo build --release --bin ghost-cli + +# Runtime stage +FROM debian:bookworm-slim + +# Install runtime dependencies +RUN apt-get update && apt-get install -y \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +# Create non-root user +RUN useradd -r -s /bin/false ghost + +# Copy binary +COPY --from=builder /app/target/release/ghost-cli /usr/local/bin/ghost + +# Set ownership and permissions +RUN chown root:root /usr/local/bin/ghost && \ + chmod 755 /usr/local/bin/ghost + +USER ghost + +ENTRYPOINT ["/usr/local/bin/ghost"] \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..a3d6964 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,92 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| 0.1.x | :white_check_mark: | + +## Reporting a Vulnerability + +We take security vulnerabilities seriously. If you discover a security issue in Ghost, please follow these steps: + +### For Security Researchers + +1. **DO NOT** create a public GitHub issue for security vulnerabilities +2. Include detailed information about the vulnerability: + - Steps to reproduce + - Potential impact + - Suggested fix (if any) + - Your contact information + +### Response Timeline + +- **Initial Response**: Within 48 hours +- **Assessment**: Within 7 days +- **Fix Timeline**: Varies based on severity + - Critical: Within 7 days + - High: Within 14 days + - Medium: Within 30 days + - Low: Next release cycle + +### Disclosure Policy + +We follow responsible disclosure practices: + +1. Security researcher reports vulnerability privately +2. We acknowledge receipt and begin investigation +3. We develop and test a fix +4. We prepare a security advisory +5. We release the fix and publish the advisory +6. Public disclosure after 90 days (or sooner if fix is available) + +### Security Best Practices for Users + +1. **Keep Ghost Updated**: Always use the latest version +2. **Run with Minimal Privileges**: Don't run as Administrator unless necessary +3. **Validate Detection Results**: Ghost is a tool to assist analysis, not replace human judgment +4. **Secure Your Environment**: Ensure your analysis environment is properly isolated + +### Known Security Considerations + +1. **Memory Access**: Ghost requires elevated privileges to read process memory +2. **False Positives**: Detection engines may flag legitimate software +3. **Evasion**: Advanced malware may evade detection techniques +4. **Performance Impact**: Intensive scanning may affect system performance + +### Security Features + +- Memory-safe Rust implementation +- Input validation on all API boundaries +- Minimal attack surface design +- No network communication by default +- Comprehensive error handling + +### Vulnerability Categories We're Interested In + +**High Priority:** +- Memory safety violations +- Privilege escalation +- Code injection vulnerabilities +- Authentication bypass +- Sensitive data exposure + +**Medium Priority:** +- Denial of service +- Information disclosure +- Logic flaws in detection algorithms + +**Out of Scope:** +- Issues requiring physical access +- Social engineering attacks +- Third-party dependency vulnerabilities (unless exploitable through Ghost) + +### Contact Information + +- **Security Team**: security@ghost-project.dev +- **General Issues**: https://github.com/ghost-project/ghost/issues +- **Discussions**: https://github.com/ghost-project/ghost/discussions + +--- + +*Last updated: November 2024* \ No newline at end of file diff --git a/benches/Cargo.toml b/benches/Cargo.toml new file mode 100644 index 0000000..c31639d --- /dev/null +++ b/benches/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "ghost-bench" +version = "0.1.0" +edition = "2021" + +[[bench]] +name = "detection_performance" +harness = false + +[dependencies] +ghost-core = { path = "../ghost-core" } +criterion = { version = "0.5", features = ["html_reports"] } + +[dev-dependencies] +pprof = { version = "0.13", features = ["criterion", "flamegraph"] } \ No newline at end of file diff --git a/benches/benches/detection_performance.rs b/benches/benches/detection_performance.rs new file mode 100644 index 0000000..2ac2a42 --- /dev/null +++ b/benches/benches/detection_performance.rs @@ -0,0 +1,107 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use ghost_core::{DetectionEngine, MemoryProtection, MemoryRegion, ProcessInfo}; + +fn create_test_process() -> ProcessInfo { + ProcessInfo { + pid: 1234, + ppid: 4, + name: "test.exe".to_string(), + path: Some("C:\\Windows\\System32\\test.exe".to_string()), + thread_count: 4, + } +} + +fn create_memory_regions(count: usize) -> Vec { + (0..count) + .map(|i| MemoryRegion { + base_address: 0x10000000 + (i * 0x1000), + size: 0x1000, + protection: if i % 5 == 0 { + MemoryProtection::ReadWriteExecute + } else { + MemoryProtection::ReadWrite + }, + region_type: if i % 10 == 0 { "IMAGE" } else { "PRIVATE" }.to_string(), + }) + .collect() +} + +fn bench_detection_engine(c: &mut Criterion) { + let mut engine = DetectionEngine::new(); + let process = create_test_process(); + + c.bench_function("process_analysis_small", |b| { + let regions = create_memory_regions(10); + b.iter(|| { + engine.analyze_process(black_box(&process), black_box(®ions), None) + }) + }); + + c.bench_function("process_analysis_medium", |b| { + let regions = create_memory_regions(100); + b.iter(|| { + engine.analyze_process(black_box(&process), black_box(®ions), None) + }) + }); + + c.bench_function("process_analysis_large", |b| { + let regions = create_memory_regions(1000); + b.iter(|| { + engine.analyze_process(black_box(&process), black_box(®ions), None) + }) + }); +} + +fn bench_shellcode_detection(c: &mut Criterion) { + let detector = ghost_core::ShellcodeDetector::new(); + + c.bench_function("shellcode_scan_1kb", |b| { + let data = vec![0x90; 1024]; // 1KB of NOPs + b.iter(|| { + detector.scan_memory_region(black_box(&data), black_box(0x10000000)) + }) + }); + + c.bench_function("shellcode_scan_64kb", |b| { + let data = vec![0x90; 65536]; // 64KB of NOPs + b.iter(|| { + detector.scan_memory_region(black_box(&data), black_box(0x10000000)) + }) + }); + + c.bench_function("shellcode_scan_with_patterns", |b| { + let mut data = vec![0x90; 4096]; // 4KB base + // Add some patterns that will trigger detection + data[100] = 0x4D; data[101] = 0x5A; // MZ header + data[200] = 0xFC; data[201] = 0x48; // Meterpreter pattern + data[300] = 0x64; data[301] = 0x8B; // PEB access + + b.iter(|| { + detector.scan_memory_region(black_box(&data), black_box(0x10000000)) + }) + }); +} + +fn bench_memory_operations(c: &mut Criterion) { + c.bench_function("memory_region_creation", |b| { + b.iter(|| { + create_memory_regions(black_box(100)) + }) + }); + + c.bench_function("memory_region_sorting", |b| { + let mut regions = create_memory_regions(1000); + b.iter(|| { + regions.sort_by_key(|r| r.base_address); + black_box(®ions); + }) + }); +} + +criterion_group!( + benches, + bench_detection_engine, + bench_shellcode_detection, + bench_memory_operations +); +criterion_main!(benches); \ No newline at end of file