ai_root_shield 0.5.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,513 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'digest'
5
+
6
+ module AiRootShield
7
+ module Platform
8
+ # iOS-specific security module with advanced jailbreak detection
9
+ class IosSecurityModule
10
+ # iOS jailbreak detection categories
11
+ JAILBREAK_INDICATORS = {
12
+ file_system: %w[
13
+ /Applications/Cydia.app
14
+ /Applications/blackra1n.app
15
+ /Applications/FakeCarrier.app
16
+ /Applications/Icy.app
17
+ /Applications/IntelliScreen.app
18
+ /Applications/MxTube.app
19
+ /Applications/RockApp.app
20
+ /Applications/SBSettings.app
21
+ /Applications/WinterBoard.app
22
+ /Library/MobileSubstrate/MobileSubstrate.dylib
23
+ /Library/MobileSubstrate/DynamicLibraries/LiveClock.plist
24
+ /Library/MobileSubstrate/DynamicLibraries/Veency.plist
25
+ /private/var/lib/apt
26
+ /private/var/lib/cydia
27
+ /private/var/mobile/Library/SBSettings/Themes
28
+ /private/var/stash
29
+ /private/var/tmp/cydia.log
30
+ /System/Library/LaunchDaemons/com.ikey.bbot.plist
31
+ /System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist
32
+ /usr/bin/sshd
33
+ /usr/libexec/sftp-server
34
+ /usr/sbin/sshd
35
+ /etc/apt
36
+ /bin/bash
37
+ /bin/sh
38
+ /usr/bin/ssh
39
+ ],
40
+ url_schemes: %w[
41
+ cydia://
42
+ undecimus://
43
+ sileo://
44
+ zbra://
45
+ filza://
46
+ activator://
47
+ ],
48
+ dyld_libraries: %w[
49
+ MobileSubstrate
50
+ SubstrateLoader
51
+ SSLKillSwitch
52
+ SSLKillSwitch2
53
+ LibertaLite
54
+ Shadow
55
+ FlyJB
56
+ Substitute
57
+ ]
58
+ }.freeze
59
+
60
+ def initialize
61
+ @detection_cache = {}
62
+ end
63
+
64
+ # Comprehensive iOS security analysis
65
+ def analyze_device_security(device_logs)
66
+ results = {
67
+ jailbreak_detection: detect_jailbreak(device_logs),
68
+ code_signing: analyze_code_signing(device_logs),
69
+ sandbox_integrity: analyze_sandbox_integrity(device_logs),
70
+ dyld_injection: detect_dyld_injection(device_logs),
71
+ hardware_security: analyze_hardware_security(device_logs),
72
+ system_integrity: analyze_system_integrity(device_logs),
73
+ risk_factors: [],
74
+ risk_score: 0
75
+ }
76
+
77
+ calculate_ios_risk_score(results)
78
+ results
79
+ end
80
+
81
+ private
82
+
83
+ # Advanced jailbreak detection using multiple techniques
84
+ def detect_jailbreak(device_logs)
85
+ {
86
+ file_system_check: check_jailbreak_files(device_logs),
87
+ url_scheme_check: check_jailbreak_url_schemes(device_logs),
88
+ dyld_library_check: check_jailbreak_libraries(device_logs),
89
+ sandbox_violation_check: check_sandbox_violations(device_logs),
90
+ fork_restriction_check: check_fork_restrictions(device_logs),
91
+ symbolic_link_check: check_symbolic_links(device_logs),
92
+ system_call_check: check_system_calls(device_logs),
93
+ runtime_manipulation_check: check_runtime_manipulation(device_logs)
94
+ }
95
+ end
96
+
97
+ # Analyze iOS code signing integrity
98
+ def analyze_code_signing(device_logs)
99
+ code_signing_data = device_logs.dig('code_signing') || {}
100
+
101
+ {
102
+ main_bundle_signed: code_signing_data['mainBundleSigned'] || false,
103
+ embedded_provisioning: code_signing_data['embeddedProvisioning'] || false,
104
+ team_identifier: code_signing_data['teamIdentifier'],
105
+ code_directory_hash: code_signing_data['codeDirectoryHash'],
106
+ entitlements_valid: code_signing_data['entitlementsValid'] || false,
107
+ signature_version: code_signing_data['signatureVersion'],
108
+ certificate_chain_valid: code_signing_data['certificateChainValid'] || false,
109
+ developer_certificate: analyze_developer_certificate(code_signing_data)
110
+ }
111
+ end
112
+
113
+ # Analyze iOS sandbox integrity
114
+ def analyze_sandbox_integrity(device_logs)
115
+ sandbox_data = device_logs.dig('sandbox') || {}
116
+
117
+ {
118
+ container_integrity: sandbox_data['containerIntegrity'] || false,
119
+ file_access_violations: sandbox_data['fileAccessViolations'] || [],
120
+ network_access_violations: sandbox_data['networkAccessViolations'] || [],
121
+ ipc_violations: sandbox_data['ipcViolations'] || [],
122
+ entitlement_violations: sandbox_data['entitlementViolations'] || [],
123
+ sandbox_profile_valid: sandbox_data['sandboxProfileValid'] || false
124
+ }
125
+ end
126
+
127
+ # Detect DYLD injection attacks
128
+ def detect_dyld_injection(device_logs)
129
+ dyld_data = device_logs.dig('dyld') || {}
130
+
131
+ {
132
+ loaded_libraries: analyze_loaded_libraries(dyld_data['loadedLibraries'] || []),
133
+ injection_detected: check_library_injection(dyld_data),
134
+ hooking_frameworks: detect_hooking_frameworks(dyld_data),
135
+ runtime_modifications: detect_runtime_modifications(dyld_data),
136
+ method_swizzling: detect_method_swizzling(dyld_data)
137
+ }
138
+ end
139
+
140
+ # Analyze iOS hardware security features
141
+ def analyze_hardware_security(device_logs)
142
+ hardware_data = device_logs.dig('hardware_security') || {}
143
+
144
+ {
145
+ secure_enclave_available: hardware_data['secureEnclaveAvailable'] || false,
146
+ touch_id_available: hardware_data['touchIdAvailable'] || false,
147
+ face_id_available: hardware_data['faceIdAvailable'] || false,
148
+ biometric_consistency: analyze_biometric_consistency(hardware_data),
149
+ keychain_accessibility: hardware_data['keychainAccessibility'] || 'unknown',
150
+ secure_boot_chain: hardware_data['secureBootChain'] || false,
151
+ hardware_encryption: hardware_data['hardwareEncryption'] || false
152
+ }
153
+ end
154
+
155
+ # Analyze iOS system integrity
156
+ def analyze_system_integrity(device_logs)
157
+ system_data = device_logs.dig('system_integrity') || {}
158
+
159
+ {
160
+ system_version_authentic: system_data['systemVersionAuthentic'] || false,
161
+ kernel_integrity: system_data['kernelIntegrity'] || false,
162
+ amfi_enabled: system_data['amfiEnabled'] || false,
163
+ sip_enabled: system_data['sipEnabled'] || false,
164
+ code_injection_protection: system_data['codeInjectionProtection'] || false,
165
+ library_validation: system_data['libraryValidation'] || false,
166
+ runtime_protections: system_data['runtimeProtections'] || []
167
+ }
168
+ end
169
+
170
+ # Check for jailbreak-related files
171
+ def check_jailbreak_files(device_logs)
172
+ file_system_data = device_logs.dig('file_system', 'files') || []
173
+ detected_files = []
174
+
175
+ JAILBREAK_INDICATORS[:file_system].each do |suspicious_path|
176
+ if file_system_data.any? { |file| file['path'] == suspicious_path }
177
+ detected_files << suspicious_path
178
+ end
179
+ end
180
+
181
+ {
182
+ detected: detected_files.any?,
183
+ files: detected_files,
184
+ count: detected_files.size
185
+ }
186
+ end
187
+
188
+ # Check for jailbreak URL schemes
189
+ def check_jailbreak_url_schemes(device_logs)
190
+ url_schemes = device_logs.dig('url_schemes') || []
191
+ detected_schemes = []
192
+
193
+ JAILBREAK_INDICATORS[:url_schemes].each do |scheme|
194
+ if url_schemes.include?(scheme)
195
+ detected_schemes << scheme
196
+ end
197
+ end
198
+
199
+ {
200
+ detected: detected_schemes.any?,
201
+ schemes: detected_schemes,
202
+ count: detected_schemes.size
203
+ }
204
+ end
205
+
206
+ # Check for jailbreak-related dynamic libraries
207
+ def check_jailbreak_libraries(device_logs)
208
+ loaded_libs = device_logs.dig('dyld', 'loadedLibraries') || []
209
+ detected_libs = []
210
+
211
+ JAILBREAK_INDICATORS[:dyld_libraries].each do |lib_name|
212
+ if loaded_libs.any? { |lib| lib.include?(lib_name) }
213
+ detected_libs << lib_name
214
+ end
215
+ end
216
+
217
+ {
218
+ detected: detected_libs.any?,
219
+ libraries: detected_libs,
220
+ count: detected_libs.size
221
+ }
222
+ end
223
+
224
+ # Check for sandbox violations
225
+ def check_sandbox_violations(device_logs)
226
+ sandbox_data = device_logs.dig('sandbox') || {}
227
+ violations = []
228
+
229
+ # Check file access violations
230
+ file_violations = sandbox_data['fileAccessViolations'] || []
231
+ violations.concat(file_violations.map { |v| { type: 'file_access', details: v } })
232
+
233
+ # Check network violations
234
+ network_violations = sandbox_data['networkAccessViolations'] || []
235
+ violations.concat(network_violations.map { |v| { type: 'network_access', details: v } })
236
+
237
+ {
238
+ detected: violations.any?,
239
+ violations: violations,
240
+ count: violations.size
241
+ }
242
+ end
243
+
244
+ # Check fork() restrictions (jailbroken devices often allow fork)
245
+ def check_fork_restrictions(device_logs)
246
+ fork_data = device_logs.dig('fork_test') || {}
247
+
248
+ {
249
+ fork_allowed: fork_data['forkAllowed'] || false,
250
+ detected: fork_data['forkAllowed'] == true
251
+ }
252
+ end
253
+
254
+ # Check for suspicious symbolic links
255
+ def check_symbolic_links(device_logs)
256
+ symlinks = device_logs.dig('symbolic_links') || []
257
+ suspicious_links = []
258
+
259
+ symlinks.each do |link|
260
+ if link['target']&.include?('/var/stash') ||
261
+ link['target']&.include?('/private/var/mobile')
262
+ suspicious_links << link
263
+ end
264
+ end
265
+
266
+ {
267
+ detected: suspicious_links.any?,
268
+ links: suspicious_links,
269
+ count: suspicious_links.size
270
+ }
271
+ end
272
+
273
+ # Check for suspicious system calls
274
+ def check_system_calls(device_logs)
275
+ syscalls = device_logs.dig('system_calls') || {}
276
+
277
+ {
278
+ ptrace_detected: syscalls['ptraceDetected'] || false,
279
+ sysctl_bypass: syscalls['sysctlBypass'] || false,
280
+ dlopen_hooking: syscalls['dlopenHooking'] || false,
281
+ detected: (syscalls['ptraceDetected'] || syscalls['sysctlBypass'] || syscalls['dlopenHooking']) == true
282
+ }
283
+ end
284
+
285
+ # Check for runtime manipulation
286
+ def check_runtime_manipulation(device_logs)
287
+ runtime_data = device_logs.dig('runtime_manipulation') || {}
288
+
289
+ {
290
+ method_swizzling_detected: runtime_data['methodSwizzlingDetected'] || false,
291
+ class_dump_detected: runtime_data['classDumpDetected'] || false,
292
+ runtime_injection: runtime_data['runtimeInjection'] || false,
293
+ detected: (runtime_data.values.any? { |v| v == true })
294
+ }
295
+ end
296
+
297
+ # Analyze loaded libraries for suspicious patterns
298
+ def analyze_loaded_libraries(libraries)
299
+ suspicious_libraries = []
300
+
301
+ libraries.each do |lib|
302
+ # Check for common jailbreak libraries
303
+ if lib.match?(/substrate|substitute|frida|cycript|liberty/i)
304
+ suspicious_libraries << {
305
+ library: lib,
306
+ reason: 'Known jailbreak/hooking framework'
307
+ }
308
+ end
309
+
310
+ # Check for unsigned libraries in system paths
311
+ if lib.start_with?('/System/') && !lib.match?(/\.framework\//)
312
+ suspicious_libraries << {
313
+ library: lib,
314
+ reason: 'Unsigned library in system path'
315
+ }
316
+ end
317
+ end
318
+
319
+ {
320
+ total_libraries: libraries.size,
321
+ suspicious_libraries: suspicious_libraries,
322
+ suspicious_count: suspicious_libraries.size
323
+ }
324
+ end
325
+
326
+ # Check for library injection
327
+ def check_library_injection(dyld_data)
328
+ injected_libs = dyld_data['injectedLibraries'] || []
329
+
330
+ {
331
+ detected: injected_libs.any?,
332
+ libraries: injected_libs,
333
+ count: injected_libs.size
334
+ }
335
+ end
336
+
337
+ # Detect hooking frameworks
338
+ def detect_hooking_frameworks(dyld_data)
339
+ frameworks = []
340
+ loaded_libs = dyld_data['loadedLibraries'] || []
341
+
342
+ hooking_patterns = [
343
+ /substrate/i,
344
+ /substitute/i,
345
+ /frida/i,
346
+ /cycript/i,
347
+ /theos/i,
348
+ /logos/i
349
+ ]
350
+
351
+ loaded_libs.each do |lib|
352
+ hooking_patterns.each do |pattern|
353
+ if lib.match?(pattern)
354
+ frameworks << {
355
+ library: lib,
356
+ framework: pattern.source
357
+ }
358
+ end
359
+ end
360
+ end
361
+
362
+ {
363
+ detected: frameworks.any?,
364
+ frameworks: frameworks,
365
+ count: frameworks.size
366
+ }
367
+ end
368
+
369
+ # Detect runtime modifications
370
+ def detect_runtime_modifications(dyld_data)
371
+ modifications = dyld_data['runtimeModifications'] || []
372
+
373
+ {
374
+ detected: modifications.any?,
375
+ modifications: modifications,
376
+ count: modifications.size
377
+ }
378
+ end
379
+
380
+ # Detect method swizzling
381
+ def detect_method_swizzling(dyld_data)
382
+ swizzling_data = dyld_data['methodSwizzling'] || {}
383
+
384
+ {
385
+ detected: swizzling_data['detected'] || false,
386
+ swizzled_methods: swizzling_data['swizzledMethods'] || [],
387
+ count: (swizzling_data['swizzledMethods'] || []).size
388
+ }
389
+ end
390
+
391
+ # Analyze developer certificate
392
+ def analyze_developer_certificate(code_signing_data)
393
+ cert_data = code_signing_data['certificate'] || {}
394
+
395
+ {
396
+ is_development: cert_data['isDevelopment'] || false,
397
+ is_distribution: cert_data['isDistribution'] || false,
398
+ is_enterprise: cert_data['isEnterprise'] || false,
399
+ is_adhoc: cert_data['isAdhoc'] || false,
400
+ expiration_date: cert_data['expirationDate'],
401
+ issuer: cert_data['issuer']
402
+ }
403
+ end
404
+
405
+ # Analyze biometric consistency
406
+ def analyze_biometric_consistency(hardware_data)
407
+ biometric_data = hardware_data['biometrics'] || {}
408
+
409
+ {
410
+ touch_id_enrolled: biometric_data['touchIdEnrolled'] || false,
411
+ face_id_enrolled: biometric_data['faceIdEnrolled'] || false,
412
+ biometric_changes_detected: biometric_data['biometricChangesDetected'] || false,
413
+ hardware_tamper_detected: biometric_data['hardwareTamperDetected'] || false
414
+ }
415
+ end
416
+
417
+ # Calculate iOS-specific risk score
418
+ def calculate_ios_risk_score(results)
419
+ risk_score = 0
420
+ risk_factors = []
421
+
422
+ # Jailbreak detection analysis
423
+ jailbreak = results[:jailbreak_detection]
424
+
425
+ if jailbreak[:file_system_check][:detected]
426
+ risk_score += 30
427
+ risk_factors << 'IOS_JAILBREAK_FILES_DETECTED'
428
+ end
429
+
430
+ if jailbreak[:url_scheme_check][:detected]
431
+ risk_score += 20
432
+ risk_factors << 'IOS_JAILBREAK_URL_SCHEMES_DETECTED'
433
+ end
434
+
435
+ if jailbreak[:dyld_library_check][:detected]
436
+ risk_score += 25
437
+ risk_factors << 'IOS_JAILBREAK_LIBRARIES_DETECTED'
438
+ end
439
+
440
+ if jailbreak[:sandbox_violation_check][:detected]
441
+ risk_score += 20
442
+ risk_factors << 'IOS_SANDBOX_VIOLATIONS_DETECTED'
443
+ end
444
+
445
+ if jailbreak[:fork_restriction_check][:detected]
446
+ risk_score += 15
447
+ risk_factors << 'IOS_FORK_RESTRICTIONS_BYPASSED'
448
+ end
449
+
450
+ # Code signing analysis
451
+ code_signing = results[:code_signing]
452
+ unless code_signing[:main_bundle_signed]
453
+ risk_score += 25
454
+ risk_factors << 'IOS_MAIN_BUNDLE_NOT_SIGNED'
455
+ end
456
+
457
+ unless code_signing[:certificate_chain_valid]
458
+ risk_score += 20
459
+ risk_factors << 'IOS_INVALID_CERTIFICATE_CHAIN'
460
+ end
461
+
462
+ if code_signing[:developer_certificate][:is_development]
463
+ risk_score += 10
464
+ risk_factors << 'IOS_DEVELOPMENT_CERTIFICATE'
465
+ end
466
+
467
+ # DYLD injection analysis
468
+ dyld = results[:dyld_injection]
469
+ if dyld[:injection_detected][:detected]
470
+ risk_score += 25
471
+ risk_factors << 'IOS_DYLD_INJECTION_DETECTED'
472
+ end
473
+
474
+ if dyld[:hooking_frameworks][:detected]
475
+ risk_score += 20
476
+ risk_factors << 'IOS_HOOKING_FRAMEWORKS_DETECTED'
477
+ end
478
+
479
+ # Hardware security analysis
480
+ hardware = results[:hardware_security]
481
+ unless hardware[:secure_enclave_available]
482
+ risk_score += 10
483
+ risk_factors << 'IOS_SECURE_ENCLAVE_UNAVAILABLE'
484
+ end
485
+
486
+ if hardware[:biometric_consistency][:hardware_tamper_detected]
487
+ risk_score += 15
488
+ risk_factors << 'IOS_BIOMETRIC_HARDWARE_TAMPER'
489
+ end
490
+
491
+ # System integrity analysis
492
+ system = results[:system_integrity]
493
+ unless system[:amfi_enabled]
494
+ risk_score += 20
495
+ risk_factors << 'IOS_AMFI_DISABLED'
496
+ end
497
+
498
+ unless system[:sip_enabled]
499
+ risk_score += 15
500
+ risk_factors << 'IOS_SIP_DISABLED'
501
+ end
502
+
503
+ unless system[:library_validation]
504
+ risk_score += 10
505
+ risk_factors << 'IOS_LIBRARY_VALIDATION_DISABLED'
506
+ end
507
+
508
+ results[:risk_score] = [risk_score, 100].min
509
+ results[:risk_factors] = risk_factors
510
+ end
511
+ end
512
+ end
513
+ end