Skip to content

Commit cad0926

Browse files
committed
improved permission logic
1 parent 29e80f1 commit cad0926

File tree

8 files changed

+411
-36
lines changed

8 files changed

+411
-36
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.droid.cybershield.core.monitor
2+
3+
/**
4+
* Curated whitelist of app package names whose notifications are scanned for phishing URLs.
5+
*
6+
* ## How to add a new app
7+
* 1. Find the app's package name from its Play Store URL:
8+
* `play.google.com/store/apps/details?id=<package_name>`
9+
* 2. Add it under the appropriate category below.
10+
*
11+
* ## Why a whitelist?
12+
* `NotificationListenerService` receives every notification on the device.
13+
* This whitelist ensures only relevant messaging/email/social apps are processed,
14+
* keeping CPU and battery usage minimal and avoiding unnecessary URL checks
15+
* on banking, trading, or other non-communication apps.
16+
*/
17+
object MonitoredApps {
18+
19+
val PACKAGES: Set<String> = buildSet {
20+
21+
// ── Instant Messaging ──────────────────────────────────────────────────
22+
add("com.whatsapp") // WhatsApp
23+
add("com.whatsapp.w4b") // WhatsApp Business
24+
add("org.telegram.messenger") // Telegram
25+
add("org.telegram.messenger.web") // Telegram Web
26+
add("com.facebook.orca") // Messenger
27+
add("com.facebook.mlite") // Messenger Lite
28+
add("org.thoughtcrime.securesms") // Signal
29+
add("com.viber.voip") // Viber
30+
add("com.skype.raider") // Skype
31+
add("com.microsoft.teams") // Microsoft Teams
32+
add("com.microsoft.teams.free") // Microsoft Teams Free
33+
add("com.slack") // Slack
34+
add("com.discord") // Discord
35+
add("jp.naver.line.android") // LINE
36+
add("com.kakao.talk") // KakaoTalk
37+
add("com.tencent.mm") // WeChat
38+
39+
40+
// ── SMS / Default Messaging ────────────────────────────────────────────
41+
add("com.google.android.apps.messaging") // Google Messages
42+
add("com.samsung.android.messaging") // Samsung Messages
43+
add("com.android.mms") // AOSP MMS (stock Android)
44+
add("com.google.android.apps.inbox") // Google Inbox (legacy)
45+
46+
// ── Email ──────────────────────────────────────────────────────────────
47+
add("com.google.android.gm") // Gmail
48+
add("com.microsoft.office.outlook") // Outlook
49+
add("com.yahoo.mobile.client.android.mail")// Yahoo Mail
50+
add("eu.faircode.email") // FairEmail
51+
add("ch.protonmail.android") // ProtonMail
52+
53+
// ── Social (link-sharing common) ───────────────────────────────────────
54+
add("com.instagram.android") // Instagram
55+
add("com.twitter.android") // Twitter / X
56+
add("com.linkedin.android") // LinkedIn
57+
add("com.reddit.frontpage") // Reddit
58+
}
59+
}
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
package com.droid.cybershield.core.permission
2+
3+
/**
4+
* App behavioral categories inferred purely from the app's permission fingerprint.
5+
* No internet API required — works fully offline.
6+
*/
7+
enum class AppCategory(val emoji: String, val label: String) {
8+
SOCIAL("📱", "Social"),
9+
COMMUNICATION("💬", "Communication"),
10+
FINANCE("💳", "Finance"),
11+
TRADING("📈", "Trading"),
12+
GAMING("🎮", "Gaming"),
13+
NAVIGATION("🗺️", "Navigation"),
14+
HEALTH("🏃", "Health"),
15+
UTILITY("🔧", "Utility"),
16+
UNKNOWN("📦", "Unknown")
17+
}
18+
19+
/**
20+
* Classifies an app into a behavioral category based on its requested permissions.
21+
*
22+
* Uses a weighted voting system: each permission casts weighted votes for one or
23+
* more candidate categories. The category with the highest total score wins.
24+
*
25+
* If no category reaches a minimum confidence threshold, UNKNOWN is returned.
26+
*/
27+
object AppCategoryClassifier {
28+
29+
// Minimum total score required to claim a category (prevents noise from 1-permission apps)
30+
private const val MIN_SCORE_THRESHOLD = 3
31+
32+
/**
33+
* Each entry maps a permission to a list of (AppCategory, weight) votes.
34+
* Higher weight = stronger signal for that category.
35+
*/
36+
private val PERMISSION_VOTES: Map<String, List<Pair<AppCategory, Int>>> = mapOf(
37+
38+
// ── Location ──────────────────────────────────────────────────────────
39+
"android.permission.ACCESS_FINE_LOCATION" to listOf(
40+
AppCategory.NAVIGATION to 4,
41+
AppCategory.HEALTH to 2,
42+
AppCategory.SOCIAL to 1
43+
),
44+
"android.permission.ACCESS_BACKGROUND_LOCATION" to listOf(
45+
AppCategory.NAVIGATION to 5,
46+
AppCategory.HEALTH to 2
47+
),
48+
"android.permission.ACCESS_COARSE_LOCATION" to listOf(
49+
AppCategory.NAVIGATION to 3,
50+
AppCategory.SOCIAL to 1
51+
),
52+
53+
// ── Camera ────────────────────────────────────────────────────────────
54+
"android.permission.CAMERA" to listOf(
55+
AppCategory.SOCIAL to 3,
56+
AppCategory.FINANCE to 2, // KYC / document scanning
57+
AppCategory.UTILITY to 1
58+
),
59+
60+
// ── Microphone ────────────────────────────────────────────────────────
61+
"android.permission.RECORD_AUDIO" to listOf(
62+
AppCategory.SOCIAL to 3,
63+
AppCategory.COMMUNICATION to 3
64+
),
65+
66+
// ── SMS ───────────────────────────────────────────────────────────────
67+
"android.permission.READ_SMS" to listOf(
68+
AppCategory.COMMUNICATION to 5
69+
),
70+
"android.permission.SEND_SMS" to listOf(
71+
AppCategory.COMMUNICATION to 5
72+
),
73+
"android.permission.RECEIVE_SMS" to listOf(
74+
AppCategory.COMMUNICATION to 4
75+
),
76+
77+
// ── Calls ─────────────────────────────────────────────────────────────
78+
"android.permission.CALL_PHONE" to listOf(
79+
AppCategory.COMMUNICATION to 4
80+
),
81+
"android.permission.READ_CALL_LOG" to listOf(
82+
AppCategory.COMMUNICATION to 3
83+
),
84+
"android.permission.PROCESS_OUTGOING_CALLS" to listOf(
85+
AppCategory.COMMUNICATION to 3
86+
),
87+
88+
// ── Contacts ──────────────────────────────────────────────────────────
89+
"android.permission.READ_CONTACTS" to listOf(
90+
AppCategory.SOCIAL to 2,
91+
AppCategory.COMMUNICATION to 3
92+
),
93+
"android.permission.WRITE_CONTACTS" to listOf(
94+
AppCategory.COMMUNICATION to 2,
95+
AppCategory.SOCIAL to 1
96+
),
97+
98+
// ── Health / Sensors ──────────────────────────────────────────────────
99+
"android.permission.ACTIVITY_RECOGNITION" to listOf(
100+
AppCategory.HEALTH to 5
101+
),
102+
"android.permission.BODY_SENSORS" to listOf(
103+
AppCategory.HEALTH to 5
104+
),
105+
106+
// ── Finance / Banking ─────────────────────────────────────────────────
107+
"android.permission.USE_BIOMETRIC" to listOf(
108+
AppCategory.FINANCE to 4,
109+
AppCategory.TRADING to 3
110+
),
111+
"android.permission.USE_FINGERPRINT" to listOf(
112+
AppCategory.FINANCE to 3,
113+
AppCategory.TRADING to 2
114+
),
115+
116+
// ── Phone state (common in finance/trading for device binding) ─────────
117+
"android.permission.READ_PHONE_STATE" to listOf(
118+
AppCategory.FINANCE to 3,
119+
AppCategory.TRADING to 3,
120+
AppCategory.COMMUNICATION to 1
121+
),
122+
"android.permission.READ_PHONE_NUMBERS" to listOf(
123+
AppCategory.FINANCE to 2,
124+
AppCategory.TRADING to 2
125+
),
126+
127+
// ── Network (weak signal — almost every app uses this) ────────────────
128+
"android.permission.INTERNET" to listOf(
129+
AppCategory.FINANCE to 1,
130+
AppCategory.TRADING to 1,
131+
AppCategory.SOCIAL to 1,
132+
AppCategory.GAMING to 1
133+
),
134+
"android.permission.ACCESS_NETWORK_STATE" to listOf(
135+
AppCategory.TRADING to 1,
136+
AppCategory.GAMING to 1
137+
),
138+
139+
// ── Gaming signals ────────────────────────────────────────────────────
140+
"android.permission.VIBRATE" to listOf(
141+
AppCategory.GAMING to 3
142+
),
143+
"android.permission.WAKE_LOCK" to listOf(
144+
AppCategory.GAMING to 2,
145+
AppCategory.UTILITY to 1
146+
),
147+
148+
// ── Utility signals ───────────────────────────────────────────────────
149+
"android.permission.WRITE_SETTINGS" to listOf(
150+
AppCategory.UTILITY to 4
151+
),
152+
"android.permission.FOREGROUND_SERVICE" to listOf(
153+
AppCategory.UTILITY to 2,
154+
AppCategory.HEALTH to 1
155+
),
156+
"android.permission.WRITE_EXTERNAL_STORAGE" to listOf(
157+
AppCategory.UTILITY to 2
158+
),
159+
"android.permission.READ_EXTERNAL_STORAGE" to listOf(
160+
AppCategory.UTILITY to 1
161+
),
162+
"android.permission.DISABLE_KEYGUARD" to listOf(
163+
AppCategory.UTILITY to 3
164+
),
165+
"android.permission.SYSTEM_ALERT_WINDOW" to listOf(
166+
AppCategory.UTILITY to 3
167+
),
168+
"android.permission.REQUEST_INSTALL_PACKAGES" to listOf(
169+
AppCategory.UTILITY to 3
170+
)
171+
)
172+
173+
/**
174+
* Classifies the app based on its full permission list.
175+
*
176+
* @param permissions Full list of android.permission.* strings declared by the app
177+
* @return The best-matching [AppCategory], or [AppCategory.UNKNOWN] if no clear match
178+
*/
179+
fun classify(permissions: List<String>): AppCategory {
180+
// Accumulate weighted votes per category
181+
val scores = mutableMapOf<AppCategory, Int>()
182+
183+
permissions.forEach { permission ->
184+
PERMISSION_VOTES[permission]?.forEach { (category, weight) ->
185+
scores[category] = (scores[category] ?: 0) + weight
186+
}
187+
}
188+
189+
if (scores.isEmpty()) return AppCategory.UNKNOWN
190+
191+
// Find the winning category
192+
val winner = scores.maxByOrNull { it.value } ?: return AppCategory.UNKNOWN
193+
194+
// Only assign a category if it reaches the minimum confidence threshold
195+
return if (winner.value >= MIN_SCORE_THRESHOLD) winner.key else AppCategory.UNKNOWN
196+
}
197+
}

0 commit comments

Comments
 (0)