Skip to content

Commit 3f5c93b

Browse files
errorcodeQQerrorcodeQQ
authored andcommitted
feat: Introduce deep-level advanced sandbox toggles
1 parent 9409bfe commit 3f5c93b

6 files changed

Lines changed: 105 additions & 8 deletions

File tree

CSGuard/src/main/kotlin/com/csguard/AllowlistStore.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ object AllowlistStore {
1414
private const val KEY_BLOCKED_PROVIDERS = "blocked_providers"
1515
private const val KEY_GLOBAL_STRICT = "global_strict"
1616
private const val KEY_BLOCKED = "blocked_attempts_log"
17+
18+
const val KEY_BLOCK_POPUPS = "setting_block_popups"
19+
const val KEY_BLOCK_CLIPBOARD = "setting_block_clipboard"
20+
const val KEY_BLOCK_BACKGROUND = "setting_block_bg"
21+
const val KEY_SANDBOX_PREFS = "setting_sandbox_prefs"
22+
const val KEY_WATCHDOG = "setting_watchdog"
1723
private const val MAX_BLOCKED_LOG = 200
1824

1925
@Volatile private var prefs: SharedPreferences? = null
@@ -61,6 +67,14 @@ fun alwaysAllow(): Set<String> {
6167
prefs?.edit()?.putBoolean(KEY_GLOBAL_STRICT, strict)?.apply()
6268
}
6369

70+
fun isSettingEnabled(key: String, default: Boolean = true): Boolean {
71+
return prefs?.getBoolean(key, default) ?: default
72+
}
73+
74+
fun setSettingEnabled(key: String, enabled: Boolean) {
75+
prefs?.edit()?.putBoolean(key, enabled)?.apply()
76+
}
77+
6478
fun blockedProviders(): Set<String> {
6579
val raw = prefs?.getString(KEY_BLOCKED_PROVIDERS, "[]") ?: "[]"
6680
return try {

CSGuard/src/main/kotlin/com/csguard/CSGuardPlugin.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,12 @@ try {
8080
blockKnownAdHosts = true,
8181
blockAdPaths = true,
8282
blockAllUnknown = isStrict,
83-
showToast = false
83+
showToast = false,
84+
blockPopups = AllowlistStore.isSettingEnabled(AllowlistStore.KEY_BLOCK_POPUPS),
85+
blockClipboard = AllowlistStore.isSettingEnabled(AllowlistStore.KEY_BLOCK_CLIPBOARD),
86+
blockBackgroundTasks = AllowlistStore.isSettingEnabled(AllowlistStore.KEY_BLOCK_BACKGROUND),
87+
sandboxPreferences = AllowlistStore.isSettingEnabled(AllowlistStore.KEY_SANDBOX_PREFS),
88+
watchdogEnabled = AllowlistStore.isSettingEnabled(AllowlistStore.KEY_WATCHDOG)
8489
)
8590
ProviderSanitizer.start(context)
8691
Log.i(TAG, "✓ Started ProviderSanitizer (policy.blockAllUnknown=$isStrict)")

CSGuard/src/main/kotlin/com/csguard/GuardSettingsDialog.kt

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,26 @@ class GuardSettingsDialog(
8484
}
8585
}
8686

87+
container.addView(TextView(context).apply {
88+
text = "Advanced Sandbox Controls"
89+
textSize = 18f
90+
typeface = Typeface.DEFAULT_BOLD
91+
setTextColor(Color.parseColor("#E0E0E0"))
92+
setPadding(0, 32, 0, 16)
93+
})
94+
95+
var blockPopups = current.blockPopups
96+
var blockClipboard = current.blockClipboard
97+
var blockBg = current.blockBackgroundTasks
98+
var sandboxPrefs = current.sandboxPreferences
99+
var watchdog = current.watchdogEnabled
100+
101+
container.addView(createRow("Block UI Popups & Toasts", blockPopups) { blockPopups = it })
102+
container.addView(createRow("Block Clipboard Access", blockClipboard) { blockClipboard = it })
103+
container.addView(createRow("Block Background Services", blockBg) { blockBg = it })
104+
container.addView(createRow("Sandbox Plugin Data (Anti-Theft)", sandboxPrefs) { sandboxPrefs = it })
105+
container.addView(createRow("Anti-Tamper Watchdog (Reflection)", watchdog) { watchdog = it })
106+
87107
val scroll = ScrollView(context).apply {
88108
addView(container)
89109
}
@@ -97,12 +117,22 @@ class GuardSettingsDialog(
97117
blockedSet.forEach { AllowlistStore.addBlockedProvider(it) }
98118

99119
AllowlistStore.setGlobalStrict(isGlobalStrict)
120+
AllowlistStore.setSettingEnabled(AllowlistStore.KEY_BLOCK_POPUPS, blockPopups)
121+
AllowlistStore.setSettingEnabled(AllowlistStore.KEY_BLOCK_CLIPBOARD, blockClipboard)
122+
AllowlistStore.setSettingEnabled(AllowlistStore.KEY_BLOCK_BACKGROUND, blockBg)
123+
AllowlistStore.setSettingEnabled(AllowlistStore.KEY_SANDBOX_PREFS, sandboxPrefs)
124+
AllowlistStore.setSettingEnabled(AllowlistStore.KEY_WATCHDOG, watchdog)
100125

101126
val newPolicy = GuardPolicy(
102127
blockKnownAdHosts = true,
103128
blockAdPaths = true,
104129
blockAllUnknown = isGlobalStrict,
105-
showToast = current.showToast
130+
showToast = current.showToast,
131+
blockPopups = blockPopups,
132+
blockClipboard = blockClipboard,
133+
blockBackgroundTasks = blockBg,
134+
sandboxPreferences = sandboxPrefs,
135+
watchdogEnabled = watchdog
106136
)
107137
onApply(newPolicy)
108138
}

CSGuard/src/main/kotlin/com/csguard/GuardedContext.kt

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,12 @@ class GuardedContext(
111111
override fun getSystemService(name: String): Any? {
112112
when (name) {
113113
Context.WINDOW_SERVICE,
114-
Context.CLIPBOARD_SERVICE,
115-
Context.NOTIFICATION_SERVICE,
114+
Context.NOTIFICATION_SERVICE -> {
115+
if (policy.blockPopups && isCallerBlocked()) return null
116+
}
117+
Context.CLIPBOARD_SERVICE -> {
118+
if (policy.blockClipboard && isCallerBlocked()) return null
119+
}
116120
Context.VIBRATOR_SERVICE,
117121
Context.LOCATION_SERVICE,
118122
Context.AUDIO_SERVICE -> {
@@ -123,26 +127,39 @@ class GuardedContext(
123127
}
124128

125129
override fun sendBroadcast(intent: Intent?) {
126-
if (isCallerBlocked()) return
130+
if (policy.blockBackgroundTasks && isCallerBlocked()) return
127131
super.sendBroadcast(intent)
128132
}
129133

130134
override fun startService(service: Intent?): android.content.ComponentName? {
131-
if (isCallerBlocked()) return null
135+
if (policy.blockBackgroundTasks && isCallerBlocked()) return null
132136
return super.startService(service)
133137
}
134138

135139
override fun bindService(service: Intent, conn: android.content.ServiceConnection, flags: Int): Boolean {
136-
if (isCallerBlocked()) return false
140+
if (policy.blockBackgroundTasks && isCallerBlocked()) return false
137141
return super.bindService(service, conn, flags)
138142
}
143+
144+
override fun getSharedPreferences(name: String?, mode: Int): android.content.SharedPreferences {
145+
if (policy.sandboxPreferences && isCallerBlocked()) {
146+
return super.getSharedPreferences("sandbox_$name", mode)
147+
}
148+
return super.getSharedPreferences(name, mode)
149+
}
139150
}
140151

141152
data class GuardPolicy(
142153
val blockKnownAdHosts: Boolean = true,
143154
val blockAdPaths: Boolean = true,
144155
val blockAllUnknown: Boolean = true,
145156
val showToast: Boolean = false,
157+
158+
val blockPopups: Boolean = true,
159+
val blockClipboard: Boolean = true,
160+
val blockBackgroundTasks: Boolean = true,
161+
val sandboxPreferences: Boolean = true,
162+
val watchdogEnabled: Boolean = true
146163
) {
147164
companion object {
148165
val DEFAULT get() = STRICT
@@ -152,20 +169,35 @@ data class GuardPolicy(
152169
blockAdPaths = true,
153170
blockAllUnknown = false,
154171
showToast = true,
172+
blockPopups = false,
173+
blockClipboard = false,
174+
blockBackgroundTasks = false,
175+
sandboxPreferences = false,
176+
watchdogEnabled = false
155177
)
156178

157179
val STRICT = GuardPolicy(
158180
blockKnownAdHosts = true,
159181
blockAdPaths = true,
160182
blockAllUnknown = true,
161-
showToast = false, // silent void
183+
showToast = false,
184+
blockPopups = true,
185+
blockClipboard = true,
186+
blockBackgroundTasks = true,
187+
sandboxPreferences = true,
188+
watchdogEnabled = true
162189
)
163190

164191
val STRICT_VERBOSE = GuardPolicy(
165192
blockKnownAdHosts = true,
166193
blockAdPaths = true,
167194
blockAllUnknown = true,
168195
showToast = true,
196+
blockPopups = true,
197+
blockClipboard = true,
198+
blockBackgroundTasks = true,
199+
sandboxPreferences = true,
200+
watchdogEnabled = true
169201
)
170202
}
171203

CSGuard/src/main/kotlin/com/csguard/InstrumentationHook.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,17 @@ object InstrumentationHook {
7777
}
7878
}
7979

80+
fun isHookIntact(): Boolean {
81+
if (!installed) return false
82+
try {
83+
val activityThread = currentActivityThread() ?: return false
84+
val field = findField(activityThread.javaClass, "mInstrumentation") ?: return false
85+
field.isAccessible = true
86+
val current = field.get(activityThread)
87+
return current is GuardInstrumentation
88+
} catch (_: Throwable) { return false }
89+
}
90+
8091
private fun currentActivityThread(): Any? {
8192
return try {
8293
val cls = Class.forName("android.app.ActivityThread")

CSGuard/src/main/kotlin/com/csguard/ProviderSanitizer.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ object ProviderSanitizer {
2525
override fun run() {
2626
try {
2727
sanitizeAllProviders()
28+
29+
if (policy.watchdogEnabled && !InstrumentationHook.isHookIntact()) {
30+
Log.w(TAG, "Watchdog detected unhooked Instrumentation! Re-installing...")
31+
InstrumentationHook.install { policy }
32+
}
2833
} catch (t: Throwable) {
2934
Log.e(TAG, "Sanitizer poll failed", t)
3035
}

0 commit comments

Comments
 (0)