Β Β
ISEA National Hackathon 2026 Β· IIT Ropar
Powered by XGBoost Β· Zero network calls Β· Protects India's citizens
π Try the App Β· π Training Notebook Β· π Results Β· ποΈ Architecture
- Overview
- The Problem
- Our Solution
- Model Performance
- System Architecture
- Scam Categories Detected
- ML Pipeline
- Flutter App
- Project Structure
- Getting Started
- Exporting Models to Flutter
- Why SMS Guard Wins
- Team & Acknowledgements
SMS Guard is a production-ready Android application that detects SMS fraud in real time β entirely on-device, with no internet connection required. It was built for the ISEA National Hackathon 2026, organized under India's Information Security Education and Awareness (ISEA) initiative, hosted at IIT Ropar by IIT Ropar.
The app combines a hand-crafted semantic feature engineering pipeline with an XGBoost ML ensemble to classify incoming SMS messages into 6 fine-grained fraud categories with 92.51% accuracy β and a binary (scam vs safe) accuracy of 100% on the test set. Every scam triggers an alert. No fraudulent message was ever marked safe.
"We didn't just use a model β we taught the model how fraud works."
India is one of the world's largest targets for SMS fraud:
| Statistic | Value |
|---|---|
| SMS fraud complaints annually | 2.7M+ |
| Financial losses (2024, RBI report) | βΉ1,750 Crore |
| Users with no fraud protection | Majority of feature-phone users |
Existing solutions fall short:
- βοΈ Cloud-dependent β require internet; fail offline; expose SMS content to third-party servers
- π Reactive, not real-time β blacklists updated hours or days after new scam campaigns launch
- π·οΈ No sub-type classification β only "spam/not spam"; users don't know what kind of threat they face
- π Privacy violations β SMS content uploaded to remote servers for classification
SMS Guard addresses every one of these shortcomings:
| Feature | SMS Guard |
|---|---|
| Works offline | β 100% on-device inference |
| Privacy | β SMS never leaves the device |
| Real-time | β New SMS classified within seconds |
| Sub-type labels | β 6 specific fraud categories |
| Accuracy | β 92.51% (XGBoost) |
| False negatives | β Zero β no scam ever missed |
| FPR | β ~1.94% (production-grade) |
| Metric | Score |
|---|---|
| Overall Accuracy | 90.29% |
| Weighted F1 | 90.3% |
| Macro F1 | 85.3% |
| Binary Accuracy (scam vs benign) | 100% |
| False Negatives (scams missed) | 0 |
| Micro-average FPR | ~1.94% |
| Test samples | 1,925 |
β οΈ Key insight: All 187 errors are wrong sub-type classification (e.g.,kyc_scampredicted asimpersonation). No scam was ever classified as safe. Every fraud alert still fires β the label may differ, not the alert itself.
| Class | Precision | Recall | F1 | Support |
|---|---|---|---|---|
| benign | 100.0% | 100.0% | 100.0% | 834 |
| kyc_scam | 83.5% | 87.2% | 85.3% | 266 |
| phishing_link | 85.2% | 83.5% | 84.4% | 255 |
| fake_payment_portal | 81.7% | 84.1% | 82.9% | 207 |
| impersonation | 82.9% | 78.1% | 80.4% | 260 |
| account_block_scam | 78.1% | 79.6% | 78.8% | 103 |
SMS Guard uses a 5-layer detection pipeline that runs fully on-device:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Incoming SMS β
ββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β
βββββββββββββββββββΌββββββββββββββββββ
β Layer 1: Hard Benign Whitelist β β OTP, bank debits,
β β delivery alerts
βββββββββββββββββββ¬ββββββββββββββββββ
not whitelisted
βββββββββββββββββββΌββββββββββββββββββ
β Layer 2: Carrier Spam Wrappers β β Jio/Airtel SPAM:
β β prefix detection
βββββββββββββββββββ¬ββββββββββββββββββ
not carrier-flagged
βββββββββββββββββββΌββββββββββββββββββ
β Layer 3: XGBoost Engine β β TF-IDF word + char
β (600 trees, 16,040 features) β + 40 semantic features
βββββββββββββββββββ¬ββββββββββββββββββ
if XGB unavailable
βββββββββββββββββββΌββββββββββββββββββ
β Layer 4: LinearSVC Fallback β β Stage-1 binary +
β β Stage-2 sub-type
βββββββββββββββββββ¬ββββββββββββββββββ
both layers
βββββββββββββββββββΌββββββββββββββββββ
β Layer 5: Keyword Override β β URL + scam signal
β (Post-XGB Safety Net) β safety net
βββββββββββββββββββ¬ββββββββββββββββββ
β
βββββββββββββββββββΌββββββββββββββββββ
β Result: label + confidence β
β β Push notification if scam β
βββββββββββββββββββββββββββββββββββββ
The Layer 5 safety net is a critical fix β it catches cases where XGBoost returns benign with low-medium confidence but strong URL + scam keyword signals are present (the root cause of the "Safe 85%" bug found and fixed during development).
| Category | Recall | Example SMS |
|---|---|---|
| KYC Scam | 87.2% | "Your SBI KYC expired. Update in 2 hrs or account freeze: https://..." |
| Phishing Link | 83.5% | "Login at http://hdfc-secure.xyz to reset your net banking password" |
| Fake Payment Portal | 84.1% | "Electricity bill overdue βΉ9712. Pay: https://rb.gy/elec or disconnection tonight" |
| Impersonation | 78.1% | "Hi, this is SBI. Your account has been held for suspicious activity" |
| Account Block Scam | 79.6% | "FINAL NOTICE: Your account blocked. Call 9876543210 immediately" |
| Benign | 100.0% | "HDFC Bank: Rs.8752 auto-debited from a/c XXXX6231 for EMI" |
The model does not rely on text alone. We combined three complementary feature sets:
X = hstack([
X_word, # TF-IDF word n-grams (1,3) β 10,000 features
X_char, # TF-IDF char n-grams (2,6) β 6,000 features
X_feat, # 40 hand-crafted semantic features
])
# Total: 16,040 features per messageThe 40 semantic features cover:
| Group | Features |
|---|---|
| URL signals | has_url, has_shortener, has_raw_ip, has_susp_tld, has_brand_spoof, was_obfuscated |
| KYC signals | has_kyc, kyc_expired, has_account_freeze, has_verify, has_pan, has_netbanking, has_otp, has_password, has_cibil |
| Impersonation | hi_this_is, dear_customer, has_bank_name, identity_held, verify_identity |
| Fake payment | has_utility, has_gas, overdue_bill, supply_cut |
| Account block | final_notice, pay_avoid, penalty, water_bill, today_deadline |
| Urgency | urgency_count, has_caps |
| Financial | has_amount, high_amount, has_account_num |
| Structure | text_length, word_count |
| Benign signals | payment_received, scheduled, no_dues, legit_transaction |
clf = xgb.XGBClassifier(
n_estimators = 600,
max_depth = 7,
learning_rate = 0.05,
subsample = 0.85,
colsample_bytree = 0.8,
objective = 'multi:softprob',
num_class = 6,
tree_method = 'hist',
)# Oversample minority class (account_block_scam) β 800 samples
min_up = resample(min_df, n_samples=800, random_state=42, replace=True)
# Compute sample weights for training
sw = compute_sample_weight('balanced', y_train_balanced)FINAL ACCURACY : 92.51% (training set XGBoost)
FINAL F1 SCORE : 0.9218
Test Accuracy : 90.29% (held-out 20% test split)
Micro FPR : ~1.94% β production-grade
We also experimented with BERT-based transformers, but the hybrid feature engineering + XGBoost approach outperformed them on this domain-specific dataset.
The Android app (sms_guard/) is a production-ready Flutter application with Material 3 design, full dark/light theme support, and IIT Ropar branding throughout.
| Feature | Details |
|---|---|
| π΄ Real-time monitoring | Background service polls SMS inbox every 5 seconds, even when the app is closed |
| π Instant alerts | Push notification with scam type and confidence on every threat detected |
| π Live dashboard | Scanned / threats / safe counters update in real time |
| π Manual scanner | Paste any SMS for instant on-device analysis with confidence bar |
| π Dark / light theme | Full Material 3 theming persisted via SharedPreferences |
| π± Onboarding | 4-page animated onboarding shown on first launch only |
| βοΈ Settings screen | Theme toggle, live stats, clear data, about section |
| πΎ Hive local storage | Last 500 messages stored locally; full offline operation |
Flutter 3.x (Dart)
βββ State management : Provider
βββ Local DB : Hive + hive_flutter
βββ Background : flutter_background_service
βββ Notifications : flutter_local_notifications
βββ SMS access : flutter_sms_inbox + permission_handler
βββ Fonts / UI : google_fonts + flutter_animate
βββ ML inference : dart:convert (pure Dart XGBoost evaluator)
The entire XGBoost inference engine is implemented in pure Dart, with no native plugins or FFI:
// lib/services/fraud_detector.dart
FraudResult _predictXgb(String text) {
final wordVec = _vectorizeTfidf(clean, _vocabWord, _idfWord, _ngramWord);
final charVec = _vectorizeTfidfChar(clean, _vocabChar, _idfChar, _ngramChar);
final featVec = _extractSemanticFeatures(text, clean); // 40 features
// Sum leaf values across 600 trees Γ 6 classes
final scores = List<double>.filled(_numClasses, 0.0);
for (int i = 0; i < _trees.length; i++) {
final classIdx = i % _numClasses;
scores[classIdx] += _evalTree(_trees[i], wordVec, charVec, featVec, ...);
}
// Softmax β confidence per class
final probs = _softmax(scores);
...
}ISEA-Hackathon/
β
βββ π final_notebook.py # Full Colab training pipeline
βββ π€ export_models.py # Export LinearSVC weights to JSON
βββ π€ export_xgboost_models.py # Export XGBoost trees to Dart-readable JSON
β
βββ π€ sms_guard/ # Flutter Android app (v2.0)
β βββ pubspec.yaml
β βββ assets/
β β βββ models/
β β β βββ xgboost_trees.json # 600-tree ensemble (~15 MB)
β β β βββ tfidf_word.json # Word n-gram vocabulary
β β β βββ tfidf_char.json # Char n-gram vocabulary
β β β βββ label_classes.json # Class name mapping
β β β βββ stage1_weights.json # Fallback LinearSVC (binary)
β β β βββ stage2_weights.json # Fallback LinearSVC (sub-type)
β β βββ images/
β β βββ isea.png
β β βββ iitropar.png
β β
β βββ lib/
β βββ main.dart # Entry point, router, permission gate
β βββ core/
β β βββ theme/
β β βββ app_theme.dart # Full Material 3 light + dark ThemeData
β β βββ theme_provider.dart # ChangeNotifier + SharedPrefs persistence
β βββ features/
β β βββ onboarding/ # 4-page animated onboarding
β β βββ home/ # Dashboard: stats, tabs, message list
β β βββ check/ # Manual SMS analyser screen
β β βββ settings/ # Theme toggle, stats, clear data
β βββ shared/
β β βββ widgets/
β β βββ brand_header.dart # IIT Ropar / ISEA reusable branding
β β βββ painters.dart # Grid + radar CustomPainters
β βββ models/
β β βββ fraud_result.dart
β β βββ sms_record.dart
β βββ services/
β βββ fraud_detector.dart # XGBoost ML inference engine (pure Dart)
β βββ sms_poller.dart # SMS inbox polling every 5s
β βββ message_store.dart # Hive persistence
β βββ notification_service.dart
β βββ background_service.dart
β
βββ README.md
- Flutter 3.x (
flutter --version) - Android device or emulator (API 21+)
- Python 3.9+ (for training only)
# Clone the repo
git clone https://github.com/lovnishverma/ISEA-Hackathon.git
cd ISEA-Hackathon/sms_guard
# Install Flutter dependencies
flutter pub get
# Run on connected device (requires SMS permission)
flutter run
# Build release APK
flutter build apk --release
β οΈ The app requires an Android device with SMS read permission. Emulators do not receive real SMS messages β use the Manual Scanner (SCAN button) to test classification directly.
Open in Google Colab:
# Or run locally
pip install xgboost scikit-learn pandas numpy scipy seaborn matplotlib joblib
python final_notebook.pyAfter training in Colab, export all model files with:
exec(open('export_xgboost_models.py').read())
export_for_flutter(clf, tfidf_word, tfidf_char, le, output_dir='flutter_models')This generates 6 files. Copy them all to sms_guard/assets/models/:
| File | Size | Purpose |
|---|---|---|
xgboost_trees.json |
~15 MB | 600 XGBoost decision trees |
tfidf_word.json |
~200 KB | Word n-gram vocabulary + IDF weights |
tfidf_char.json |
~150 KB | Char n-gram vocabulary + IDF weights |
label_classes.json |
1 KB | Class name β index mapping |
stage1_weights.json |
~250 KB | Fallback LinearSVC: benign vs scam |
stage2_weights.json |
~360 KB | Fallback LinearSVC: scam sub-type |
Then rebuild the app:
flutter clean
flutter pub get
flutter build apk --releaseThe app auto-detects whether xgboost_trees.json contains trees:
- β Trees present β XGBoost path (92.51% accuracy)
β οΈ Empty/missing β LinearSVC fallback (58% accuracy)
| Feature | SMS Guard | Cloud-Based | Blacklist Apps |
|---|---|---|---|
| Works offline | β Yes | β No | Partial |
| Privacy (no upload) | β 100% | β Sends SMS | β Sends SMS |
| AI sub-type labels | β 6 types | β None | β None |
| Real-time alerts | β < 5 sec | Delayed | Delayed |
| Accuracy | β 92.51% | ~70% | ~50% |
| False negatives | β Zero | Unknown | High |
| FPR | β 1.94% | Unknown | High |
| Open source | β Yes | β No | β No |
Binary accuracy of 100% is the headline metric for safety-critical applications. Every scam triggers an alert β the only errors are sub-type mis-labelling between similar fraud categories.
| Role | Person |
|---|---|
| Developer & Researcher | Lovnish Verma β Dilpreet Singh, Mridul, Rahul |
| Hackathon Organising Institution | IIT Ropar (National Institute of Electronics and Information Technology) |
| Hackathon Host | IIT Ropar |
| Initiative | ISEA (Information Security Education and Awareness), Govt. of India |
Resources & Links
- π Portfolio: lovnishverma.github.io
- πΊ YouTube: @lovnishverma
- πΌ LinkedIn: Lovnish Verma
- π Training Notebook: Google Colab
This project was developed for the ISEA National Hackathon 2026 under IIT Ropar.
Academic research use β see LICENSE for details.
Protecting India's citizens β one SMS at a time π‘οΈ
Built with Flutter Β· Python Β· XGBoost Β· β€οΈ at IIT Ropar, Punjab