Skip to content

krsnaSuraj/APK-Viper

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

3 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

APK Viper

On-device Android APK security analyzer β€” 38+ detection engines, 9-phase pipeline, 100% offline.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    APK VIPER v1.1.0                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Static β†’ Heuristic β†’ Advanced β†’ Deep β†’ Detection β†’ Profiling β†’ Score    β”‚
β”‚  All analysis runs on-device. Zero data leaves your phone.  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Quick Start

# Prerequisites: JDK 17+, Android SDK 34+
# Build
./gradlew assembleDebug

# Run tests
./gradlew cleanTest testDebugUnitTest
# β†’ 1194 unit tests, all passing (0 failures)

# Install
./gradlew installDebug

Features

Detection Engines (38+ across a 9-phase pipeline)

Phase Engines What They Detect
1 Β· Extract & Hash XapkExtractor, HashUtils (SHA256/MD5), ApkIntegrityVerifier, KnownMalwareDB, KnownGoodDB File/XAPK extraction, integrity check, known-good & known-bad hash matching
2 · Decompile DecompilerManager, DexParser, SmaliDisassembler, AxmlDecoder, DexOpcodeAnalyzer, TaintAnalyzer (smali) DEX→Smali→Java stubs, binary AXML manifest decode, opcode & smali-level taint
3 Β· Static (13 parallel) ManifestAnalyzer, PermissionAnalyzer, CodeAnalyzer, StringExtractor, CertificateAnalyzer, PackerDetector, CryptoMinerDetector, BehavioralDetector, ApiCallGraphAnalyzer, PermissionRiskMatrix, SecretLeakScanner, TinyMLClassifier, TaintAnalyzer Manifest/permission/cert issues, code & string patterns, hardcoded secrets, miners, behaviors, ML probability
4 Β· Deep (3 parallel) ObfuscationDetector, EntropyAnalyzer, OpcodeNgramAnalyzer Obfuscation, entropy, N-gram byte patterns
5 Β· Signature & Native (11 parallel) MalwarePatternDetector, YaraEngine, NativeAnalyzer, NativeCallGraphCorrelator, NativeBytecodeScanner, NativeLibraryDiffer, EntropyPackerDetector, NetworkAnalyzer, FrameworkIntegrityChecker, CfgStructuralAnalyzer, IntentRelationGraphAnalyzer YARA rules, native .so behavior, network sinks, CFG similarity, intent graphs, framework tampering
6 Β· Supply Chain (2) SDKAnalyzer, FrameworkIntegrityChecker Vulnerable/outdated SDKs, framework integrity
7 Β· Anti-Evasion + Intel (2) AntiEvasionDetector, ThreatIntelDB Evasion (debugger/VM/sandbox), C2 IPs & malicious domains
8 Β· Behavioral Profiling (9 parallel) NativeBehaviorAnalyzer, PhishingOverlayAnalyzer, NetworkBehaviorProfiler, BehaviorTimelineAnalyzer, BackgroundResourceMonitor, ModApkDetector, ShizukuDetector, VirtualAppDetector, AccessibilityChainAnalyzer Overlay phishing, virtual environments, modded/repackaged apps, accessibility abuse, resource abuse
9 Β· Scoring (3) PrivacyScorer, ThreatScorer, ThreatClassifier Privacy risk, weighted threat score, classification + remediation

Additional Capabilities

  • PDF Report Generation β€” Multi-page professional PDF with cover page, real app icon (composited from ic_launcher_foreground + ic_launcher_background β€” no fallbacks), severity gauge, info cards, severity breakdown bar, MITRE ATT&CK table, finding detail cards, remediation checklist, file analysis table
  • 9-Phase Scan Pipeline β€” 38+ analyzers running in parallel (supervisorScope + 45s per-analyzer timeout) with cancellation support and per-phase progress
  • Verdict Gating (FP-safe) β€” a MALICIOUS verdict (score β‰₯ 91) requires β‰₯ 2 independent strong findings; noisy heuristics can at most reach HIGH. See Verdict Gating
  • Real-time Terminal Log β€” Live scan progress with current analyzer activity and dynamic weighted ETA
  • APK File Monitor β€” Background service watching Downloads/ for new APKs
  • Threat Timeline β€” Per-package score trend in dashboard
  • Scan History β€” Room database with timeline queries and package-name grouping (confidence + ruleSource preserved)
  • Auto-Update Engine β€” Background rules + hashes + threat intel sync
  • XAPK Support β€” Split APK extraction and per-split analysis
  • Storage Cleaner β€” Temp file cleanup (scan extracts, XAPK dirs, stale logs) with size/age guards
  • 1194 Unit Tests β€” All passing (0 failures), covering every analyzer, data layer, service, UI logic, and PDF generation

What's New in v1.1.0

APK Viper v1.1.0 hardens the scanner so modded, legitimate, and sideloaded apps are never mislabeled as malware / RAT, and fixes a crash that could occur when scanning large APKs.

False-Positive Safety (mod-aware)

  • Benign obfuscation whitelist β€” Facebook Audience Network's redex tooling emits classes named Lcom_facebook_ads_redexgen_X_* whose new-array β†’ fill-array-data and dead-code patterns look like encrypted payloads. These are now skipped (mirrors the native-framework downgrade list), eliminating thousands of bogus "Suspicious Opcode Sequence" findings on any app that bundles the Facebook ads SDK.
  • Keylogger rule requires a real IME β€” ordinary keyboard handling (onKey / KeyEvent / dispatchKeyEvent) in games no longer triggers a Keylogger verdict. A genuine keylogger needs an InputMethodService (or accessibility key-capture), which is now mandatory.
  • Verdict gate preserved β€” a MALICIOUS verdict still requires β‰₯ 2 independent strong findings or a known-malware hash; noisy heuristics are capped at HIGH.

Stability

  • Foreground-service crash fixed β€” ScanForegroundService now always promotes to foreground (with a safe fallback notification) even on redelivered intents, eliminating RemoteServiceException$ForegroundServiceDidNotStartInTimeException on scan resume.
  • Crash-safe scan coroutine β€” ScanViewModel and ApkFileMonitorService now catch Throwable (including R8/ART VerifyError) so a single engine or ART error can never kill the process and trigger a redelivery crash.
  • R8 -dontoptimize added to ProGuard rules to prevent verifier-rejected-class crashes on some devices.

Architecture

9-Phase Pipeline

graph TB
    subgraph "Phase 1: Extract + Hash"
        P1[APK Extraction<br/>SHA256/MD5<br/>Integrity Check<br/>Known Malware Hash]
    end

    subgraph "Phase 2: Decompile"
        P2[DEX Parsing<br/>Smali Generation<br/>Java Decompilation<br/>Manifest Decode<br/>Native Lib Cache]
    end

    subgraph "Phase 3: Static Analysis 5 engines"
        P3[Manifest Analyzer<br/>Permission Analyzer<br/>Code Analyzer<br/>String Extractor<br/>Certificate Analyzer<br/>+ Packer, Miner, Opcode<br/>Taint, Behavioral, CallGraph<br/>PermMatrix, Secrets, ML]
    end

    subgraph "Phase 4: Deep Analysis 4 engines"
        P4[Obfuscation Detector<br/>Entropy Analyzer<br/>N-gram Analyzer<br/>Intent Graph]
    end

    subgraph "Phase 5: Signature + Native 11 engines"
        P5[YARA Engine<br/>Native Analyzer<br/>Network Analyzer<br/>Certificate Deep Scan<br/>Native Call Graph<br/>Bytecode Scanner<br/>Library Differ<br/>Entropy Packer<br/>+ MalwarePattern]
    end

    subgraph "Phase 6: Supply Chain 3 engines"
        P6[SDK Analyzer<br/>Framework Integrity<br/>CFG Structural]
    end

    subgraph "Phase 7: Anti-Evasion + Intel 2 engines"
        P7[Anti-Evasion Detector<br/>Threat Intel DB]
    end

    subgraph "Phase 8: Behavioral Profiling 10 engines"
        P8[Native Behaviors<br/>String Deobfuscator<br/>Phishing Overlay<br/>Network Profiler<br/>Behavior Timeline<br/>Mod APK Detector<br/>Shizuku Detector<br/>Virtual App Detector<br/>Accessibility Chain<br/>Resource Monitor]
    end

    subgraph "Phase 9: Scoring"
        P9[Privacy Scorer<br/>Threat Scorer<br/>Threat Classifier<br/>β†’ Score + Classification]
    end

    P1 --> P2 --> P3 --> P4 --> P5 --> P6 --> P7 --> P8 --> P9

    style P1 fill:#1e293b,color:#fff
    style P2 fill:#1e293b,color:#fff
    style P3 fill:#1e293b,color:#fff
    style P4 fill:#334155,color:#fff
    style P5 fill:#1e293b,color:#fff
    style P6 fill:#334155,color:#fff
    style P7 fill:#1e293b,color:#fff
    style P8 fill:#334155,color:#fff
    style P9 fill:#eab308,color:#000
Loading

Data Flow

flowchart TD
    APK[APK/XAPK File] --> P1[Phase 1: Extract + Hash<br/>SHA256/MD5 + ZIP parse<br/>Integrity Verification<br/>Known Malware Check]
    P1 --> P2[Phase 2: Decompile<br/>DEX parse β†’ Smali + Java<br/>AXML manifest decode<br/>Native lib caching]
    P2 --> P2B[Phase 2.5: Process Sources<br/>allSourceText join<br/>Permission extraction<br/>Native lib cache build]
    P2B --> P3[Phase 3: Static Analysis<br/>13 engines in parallel<br/>supervisorScope + async/awaitAll]
    P3 --> P4[Phase 4: Deep Analysis<br/>4 engines: Obfuscation, Entropy<br/>N-Gram, Intent Graph]
    P4 --> P5[Phase 5: Signature + Native<br/>11 engines: YARA, Native<br/>Network, Cert, EntropyPacker]
    P5 --> P6[Phase 6: Supply Chain<br/>3 engines: SDK, Integrity, CFG]
    P6 --> P7[Phase 7: Anti-Evasion<br/>2 engines: Evasion + Threat Intel]
    P7 --> P8[Phase 8: Behavioral Profiling<br/>10 engines in parallel]
    P8 --> P9[Phase 9: Scoring<br/>PrivacyScorer β†’ ThreatScorer<br/>β†’ ThreatClassifier]
    P9 --> DB[(Room DB: Scan History)]
    P9 --> PDF[PDF Report<br/>Cover + Summary + MITRE<br/>+ Findings Detail Pages]
    DB --> DASH[Dashboard<br/>Per-package score trend]

    style APK fill:#334155,color:#fff
    style P9 fill:#eab308,color:#000
    style PDF fill:#eab308,color:#000
    style DB fill:#1e293b,color:#fff
    style DASH fill:#22c55e,color:#000
Loading

Scan Progress Flow

sequenceDiagram
    participant User
    participant HomeScreen
    participant ScanViewModel
    participant ScanPipeline
    participant Decompiler
    participant Analyzers
    participant DB as Room DB

    User->>HomeScreen: Select APK file
    HomeScreen->>ScanViewModel: startScan(uri, name)
    ScanViewModel->>ScanViewModel: state = PREPARING
    Note over ScanViewModel: acquire WakeLock<br/>start ForegroundService

    rect rgb(30, 41, 59)
        Note over ScanPipeline: Phase 1: Extract + Hash
        ScanPipeline->>ScanPipeline: copy APK to cache<br/>SHA256/MD5 hash<br/>XAPK detection
        ScanPipeline-->>ScanViewModel: progress(1/9, "Extracting APK")
    end

    rect rgb(30, 41, 59)
        Note over ScanPipeline,Decompiler: Phase 2: Decompile
        ScanPipeline->>Decompiler: decompile(apkFile)
        Decompiler->>Decompiler: DEX parse β†’ smali β†’ Java<br/>manifest decode<br/>withTimeout(120-300s)
        Decompiler-->>ScanPipeline: DecompileResult
        ScanPipeline-->>ScanViewModel: progress(2/9, "11358 classes extracted")
        Note over ScanPipeline: Phase 2.5: Process Sources<br/>join allSourceText<br/>build native lib cache<br/>WITH progress updates
        ScanPipeline-->>ScanViewModel: progress update every 500 sources
    end

    rect rgb(30, 41, 59)
        Note over ScanPipeline,Analyzers: Phase 3-8: Main Analysis
        loop Each Phase (3 through 8)
            ScanPipeline->>Analyzers: supervisorScope { async(...) }
            par All Analyzers In Phase
                Analyzers-->>ScanPipeline: List<Finding>
            end
            ScanPipeline-->>ScanViewModel: progress(N/9, "Analyzer activity...")
            ScanPipeline-->>ScanViewModel: onFinding(severity, title)
        end
    end

    rect rgb(234, 179, 8)
        Note over ScanPipeline: Phase 9: Scoring
        ScanPipeline->>Analyzers: PrivacyScorer β†’ ThreatScorer β†’ ThreatClassifier
        Analyzers-->>ScanPipeline: scores + classification
    end

    ScanPipeline-->>ScanViewModel: ScanResult
    ScanViewModel->>DB: insert(result)
    ScanViewModel->>ScanViewModel: state = COMPLETE
    ScanViewModel-->>HomeScreen: auto-navigate to Results
    ScanViewModel->>ScanViewModel: release WakeLock<br/>stop ForegroundService
Loading

Clean Architecture Layers

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    UI LAYER (Jetpack Compose + Material3)        β”‚
β”‚  HomeScreen β”‚ ScanScreen β”‚ ResultsScreen β”‚ Dashboard β”‚ Settings β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚   ScanViewModel      β”‚     β”‚  Room DB /        β”‚
                    β”‚  State Machine        β”‚     β”‚  DataStore        β”‚
                    │  IDLE→PREPARING→     │     │  (Scan History)   │
                    β”‚  SCANNINGβ†’COMPLETE    β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚ withContext(IO)
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚             ScanPipeline                     β”‚
                    β”‚  supervisorScope / async / awaitAll          β”‚
                    β”‚  Phases 1-9 β†’ 38+ analyzers in parallel     β”‚
                    β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                    β”‚  Cancellation: parseCancelled flag checked   β”‚
                    β”‚  before every phase and every 100 sources    β”‚
                    β”‚  OOM Guard: 5000 classes / 50MB cap          β”‚
                    β”‚  Per-analyzer: 45s timeout via tryAnalyze    β”‚
                    β”‚  Decompile: 120-300s timeout + partial return β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Threat Scoring

Level Score Criteria
SAFE 0–25 No suspicious indicators
LOW 26–50 Minor concerns (debug cert, backup enabled)
MEDIUM 51–65 Several moderate indicators
HIGH 66–80 Major findings (packer, evasion)
CRITICAL 81–90 Severe threats (ransomware, banking trojan)
MALICIOUS 91–100 Confirmed malicious payload
SAFE β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘  0-25
LOW  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 26-50
MED  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 51-65
HIGH β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 66-80
CRIT β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 81-90
 MAL  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 91-100

Verdict Gating (False-Positive Safety)

A MALICIOUS verdict (score β‰₯ 91) is deliberately hard to reach so that legitimate, modded, or sideloaded apps are never mislabeled as malware. This mirrors how top-tier detectors (VirusTotal, MobSF, DREBIN) refuse to call an app malware on heuristic volume alone.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              VERDICT GATE β€” False-Positive SAFETY                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Each Finding has confidence ∈ {HIGH, MEDIUM, LOW} and ruleSource.  β”‚
β”‚  STRONG evidence = confidence != LOW  AND  ruleSource != "community"β”‚
β”‚                                                                     β”‚
β”‚  MALICIOUS (score >= 91) is ONLY emitted when:                      β”‚
β”‚     β€’ a known-malware HASH matched (HIGH),  OR                      β”‚
β”‚     β€’ >= 2 independent STRONG findings agree                       β”‚
β”‚                                                                     β”‚
β”‚  Otherwise the verdict is capped at HIGH (<= 80) β€” never MALICIOUS. β”‚
β”‚                                                                     β”‚
β”‚  High-fidelity malware (Keylogger / Accessibility Abuse /           β”‚
β”‚  Device-Admin Abuse) emits MEDIUM confidence (strong, not noisy).   β”‚
β”‚  Noisy heuristics (API chains, data-exfil combos, generic          β”‚
β”‚  anti-analysis) emit LOW confidence and can NEVER alone drive a     β”‚
β”‚  MALICIOUS verdict β€” modded / genuine apps stay capped.            β”‚
β”‚                                                                     β”‚
β”‚  Extra FP guards: known-benign obfuscation packages (e.g. Facebook  β”‚
β”‚  redexgen) are skipped, and the Keylogger rule requires a real IME. β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
flowchart TD
    F[Scan Findings] --> G{"\u2265 2 independent STRONG findings\nOR known-malware hash?"}
    G -- "No" --> CAP["Capped at HIGH \u2264 80\nModded / genuine apps stay safe"]
    G -- "Yes" --> M["MALICIOUS \u2265 91"]
    STRONG["STRONG = confidence != LOW\nAND ruleSource != community"] --> G
    style CAP fill:#22c55e,color:#000
    style M fill:#ef4444,color:#fff
    style STRONG fill:#1e293b,color:#fff
Loading

Mod APK Detection (3-Tier)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              ModApkDetector β€” 3-Tier Hybrid                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   TIER 1      β”‚     TIER 2        β”‚      TIER 3           β”‚
β”‚  SOO Anomaly  β”‚  Cross-Validation  β”‚  Confidence Scoring   β”‚
β”‚               β”‚                   β”‚                       β”‚
β”‚  DEX string   β”‚ Check if findings β”‚ isLikelyGenuineMod(): β”‚
β”‚  offset order β”‚ span multiple     β”‚ downgrade if only     β”‚
β”‚  disruption   β”‚ categories (perm, β”‚ harmless perms +      β”‚
β”‚  detection    β”‚ api, native, comp)β”‚ known mod signers     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Project Structure

app/src/main/java/com/apkviper/
β”œβ”€β”€ App.kt                       # Application β€” schedules auto-update
β”œβ”€β”€ MainActivity.kt              # Entry point + Compose navigation
β”œβ”€β”€ data/
β”‚   β”œβ”€β”€ AppDatabase.kt           # Room DB + Gson TypeConverters
β”‚   β”œβ”€β”€ ScanDao.kt               # DAO: recent, timeline, package queries
β”‚   └── SettingsDataStore.kt     # DataStore: auto-update, signature counts
β”œβ”€β”€ dex/
β”‚   β”œβ”€β”€ AxmlDecoder.kt           # Binary AndroidManifest β†’ text
β”‚   β”œβ”€β”€ DexParser.kt             # Custom DEX parser (string/field/method/class)
β”‚   └── SmaliDisassembler.kt     # DEX bytecode β†’ smali text
β”œβ”€β”€ engine/
β”‚   β”œβ”€β”€ ScanPipeline.kt          # Central orchestrator β€” 9 phases
β”‚   β”œβ”€β”€ StorageCleaner.kt        # Temp file cleanup + entropy-based ranking
β”‚   β”œβ”€β”€ advanced/                # 26 advanced analysis engines
β”‚   β”œβ”€β”€ classification/          # ThreatClassifier
β”‚   β”œβ”€β”€ decompile/               # DecompilerManager
β”‚   β”œβ”€β”€ dex/                     # DexOpcodeAnalyzer
β”‚   β”œβ”€β”€ heuristic/               # 6 heuristic detectors
β”‚   β”œβ”€β”€ malware/                 # KnownMalwareDB, KnownGoodDB
β”‚   β”œβ”€β”€ native/                  # FrameworkWhitelist, NativeAnalyzer
β”‚   β”œβ”€β”€ network/                 # NetworkAnalyzer
β”‚   β”œβ”€β”€ report/                  # PdfGenerator (real app logo, no fallbacks)
β”‚   β”œβ”€β”€ scoring/                 # ThreatScorer, PrivacyScorer
β”‚   β”œβ”€β”€ static/                  # 5 static analyzers
β”‚   β”œβ”€β”€ supplychain/             # SDKAnalyzer
β”‚   β”œβ”€β”€ taint/                   # TaintAnalyzer
β”‚   β”œβ”€β”€ update/                  # AutoUpdateEngine, UpdateScheduler
β”‚   β”œβ”€β”€ xapk/                    # XapkExtractor
β”‚   └── yara/                    # YaraEngine (Aho-Corasick automaton)
β”œβ”€β”€ model/
β”‚   └── ScanModels.kt            # ScanResult, Finding, DecompileResult, enums
β”œβ”€β”€ service/
β”‚   β”œβ”€β”€ ApkFileMonitorService.kt # FileObserver: watches Downloads for APKs
β”‚   └── ScanForegroundService.kt # BG scan notification with progress
β”œβ”€β”€ ui/
β”‚   β”œβ”€β”€ dashboard/               # History dashboard + per-package score trend
β”‚   β”œβ”€β”€ home/                    # Main screen + tab navigation + file picker
β”‚   β”œβ”€β”€ results/                 # Scan results with expandable finding cards
β”‚   β”œβ”€β”€ scan/                    # ScanView: terminal + progress + ETA
β”‚   β”œβ”€β”€ settings/                # Configuration + APK monitor toggle
β”‚   β”œβ”€β”€ terminal/                # Terminal log models
β”‚   └── theme/                   # Colors (copper/amber, warm surfaces), typography, theme
└── util/
    └── HashUtils.kt             # Streaming SHA256/MD5 hashing

Tech Stack

Component Technology
Language Kotlin 1.9.21
UI Jetpack Compose + Material3 (BOM 2024.06.00)
Database Room 2.6.1 + Gson + KSP
Preferences DataStore Preferences 1.0.0
PDF android.graphics.pdf.PdfDocument (zero external deps)
Async Kotlin Coroutines 1.7.3 + Flow
DEX Parsing Custom binary parser (31 KB, no deps)
YARA Custom Aho-Corasick automaton (no native deps)
ML Custom TinyML Random Forest (20 trees)
Networking OkHttp 4.12.0 (update checks only)
Testing JUnit 4.13.2 + Robolectric 4.11.1 + Espresso 3.5.1
Build AGP 8.5.0, Kotlin 1.9.21, KSP
SDK compileSdk=34, targetSdk=34, minSdk=26

Key Flows

Memory-Adaptive Decompilation

flowchart TD
    START([Enter DecompilerManager]) --> CAP{classes > 0?}
    CAP -- Yes --> PROCESS[Process class N<br/>Parse DEX β†’ Generate Smali/Java]
    PROCESS --> MEM{Free mem < 15% max?}
    MEM -- No --> NEXT[Increment counter]
    MEM -- Yes --> GC["System.gc()<br/>Thread.yield()"]
    GC --> CHK{counter % 200 == 0?}
    CHK -- No --> CAP
    NEXT --> CHK
    CHK -- Yes --> MEM2{Free mem < 15% max?}
    MEM2 -- No --> CAP
    MEM2 -- Yes --> TRUNC[Drop remaining classes<br/>return partial result]
    CAP -- No --> DONE([Return DecompileResult])

    style START fill:#22c55e,color:#fff
    style DONE fill:#22c55e,color:#fff
    style GC fill:#eab308,color:#000
    style TRUNC fill:#ef4444,color:#fff
Loading

Dynamic Weighted ETA

flowchart LR
    PHASE["Phase N completes"] --> TRACK["Record actual wall-clock duration<br/>stored per-phase in phaseActualDurations[]"]
    TRACK --> WEIGHT["Sub-elapsed: (now - phaseStart) / 1000<br/>estPhase = max(subElapsed, actualDur or default)"]
    WEIGHT --> PROGRESS["timeBased = (subElapsed / estPhase) * (1/total)<br/>smooth = min(stepBased + timeBased, 1.0)"]
    PROGRESS --> ETA["Weighted ETA:<br/>remaining = Ξ£(actualDur or defaults)<br/>Γ— (1 - subElapsed/estPhase)"]
    ETA --> UI["Display: '~45s remaining'"]

    style PHASE fill:#1e293b,color:#fff
    style ETA fill:#eab308,color:#000
Loading

MITRE ATT&CK PDF Table Layout

flowchart TD
    ROW[Each row = 1 MITRE technique] --> L1["Line 1: ID + count pill + Technique name"]
    L1 --> L2["Line 2+: Description word-wrapped across N lines"]
    L2 --> H["rowH = maxOf(line1H+2, line1H+descLines*10+2)"]
    H --> COL["Columns: ID(58pt) | Technique(148pt) | Description(fill)"]
    COL --> PILL["Count pill: compact starburst<br/>fits within ID column"]
    PILL --> ALT["Alt-row shading with padding<br/>via fillRect on even rows"]
    ALT --> NEXT[next row]

    style ROW fill:#1e293b,color:#fff
    style PILL fill:#eab308,color:#000
Loading

Edge Case Handling

flowchart TD
    subgraph "Null Safety"
        NS1["Safe calls: ?."]
        NS2["Elvis defaults: ?: ''"]
        NS3["firstOrNull > first()"]
    end
    subgraph "Memory Protection"
        MP1["5000-class / 50MB dual cap"]
        MP2["Adaptive GC every 200 classes"]
        MP3["ZipFile .use {} auto-close"]
    end
    subgraph "Cancellation Safety"
        CC1["parseCancelled checked<br/>before every phase"]
        CC2["checkCancelled() every<br/>100 sources during join"]
        CC3["buildNativeLibCache<br/>checks parseCancelled"]
    end
    subgraph "Error Resilience"
        ER1["tryAnalyze β†’ emptyList()"]
        ER2["Phase isolation via<br/>supervisorScope"]
        ER3["Decompiler 120s timeout<br/>with partial results"]
    end

    NS1 --> MP1 --> CC1 --> ER1
    NS2 --> MP2 --> CC2 --> ER2
    NS3 --> MP3 --> CC3 --> ER3
Loading
Scenario Protection Location
Empty scan history Returns empty view, no crash DashboardScreen.kt
Null taint register ?: continue guard (no NPE) TaintAnalyzer.kt
Missing icon resource Throws clear error at startup PdfGenerator.kt
Negative notification ID Math.abs(name.hashCode()) ApkFileMonitorService.kt
Memory pressure in decompile System.gc() every 200 classes DecompilerManager.kt
5000+ classes or 50MB+ sources Null allSourceText; sampled analyzers ScanPipeline.kt
ZipFile leak .use {} auto-close on exception ScanPipeline.kt, all analyzers
Race on scan start isScanning/isPreparing/result guards HomeScreen.kt
Scan resume after kill SharedPreferences scan_active checkpoint ScanForegroundService.kt
WakeLock timeout 10-minute timeout prevents battery drain ScanViewModel.kt
Source join for 11K+ classes Progress every 500 sources, cancellation every 100 ScanPipeline.kt
Decompile timeout 120s smali + 120s java timeouts with partial results DecompilerManager.kt

Security

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                 SECURITY PROPERTIES                       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  βœ“ 100% on-device β€” no data ever leaves                   β”‚
β”‚  βœ“ No network permission needed for scanning              β”‚
β”‚  βœ“ Temp files deleted after scan via StorageCleaner       β”‚
β”‚  βœ“ 5000-class / 50MB dual OOM guard on source joins      β”‚
β”‚  βœ“ ZipFile .use{} β€” no file descriptor leaks              β”‚
β”‚  βœ“ parseCancelled flag checked at every phase + sub-step  β”‚
β”‚  βœ“ Foreground service preserves scan across background    β”‚
β”‚  βœ“ Wake lock prevents CPU sleep during scan               β”‚
β”‚  βœ“ PDF report uses real app icon only (no fallbacks)     β”‚
β”‚  βœ“ DecompilerManager: 120s timeouts prevent hangs         β”‚
β”‚  βœ“ ProGuard keep rules for Room entities + Gson models    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

License

Distributed under the MIT License. See LICENSE for full text.

Copyright (c) 2026 β€” APK Viper

All analysis is performed on-device. No data leaves your device.

About

On-device Android APK/XAPK security scanner - 38+ engines, 9-phase pipeline, 100% offline. Mod-aware verdicts: legitimate & modded apps are never mislabeled as malware.

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors