ai_root_shield 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -1
- data/Gemfile.lock +10 -1
- data/LICENSE +1 -1
- data/README.md +84 -29
- data/lib/ai_root_shield/ai_behavioral_analyzer.rb +512 -0
- data/lib/ai_root_shield/detector.rb +31 -3
- data/lib/ai_root_shield/risk_calculator.rb +8 -1
- data/lib/ai_root_shield/version.rb +1 -1
- data/lib/ai_root_shield.rb +1 -0
- data/models/README.md +72 -0
- metadata +31 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4058e912dcc5fae977252eb4ef275a26aed884396fecb5f8b43502d2f4fc677e
|
4
|
+
data.tar.gz: 4f181c2508ca61cfbc1cb72ddd0da47849db2692b4cf8f49ff3c0880999479b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2962bc0900324a1facec5c601fd63348bc13e39f9fb7c43c463c69174f4270f2131f54e5917d663b9d03ad488abce82ef3069de735bddbd96a5dc333b6a38577
|
7
|
+
data.tar.gz: 1740c00fe8e574f0f44d860c4b269a61b5fc6ed36091481a79ab504d6592f76dbfbddeac75803814216684f6e90fb6c994962227294ed4d96ac6dbbe1df87150
|
data/CHANGELOG.md
CHANGED
@@ -8,11 +8,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
8
8
|
## [Unreleased]
|
9
9
|
|
10
10
|
### Added
|
11
|
-
- AI behavioral analysis integration (ONNX model support)
|
12
11
|
- Enhanced hooking detection for iOS method swizzling
|
13
12
|
- Real-time threat monitoring capabilities
|
14
13
|
- Custom rule engine for security policies
|
15
14
|
|
15
|
+
## [0.2.0] - 2024-01-02
|
16
|
+
|
17
|
+
### Added
|
18
|
+
- **AI Behavioral Analysis**: ONNX-powered behavioral pattern analysis with anomaly detection
|
19
|
+
- **ML-Based Emulator Detection**: Advanced machine learning techniques for emulator identification
|
20
|
+
- **AI Confidence Scoring**: Confidence metrics integrated into risk assessment
|
21
|
+
- File access pattern analysis with entropy calculation
|
22
|
+
- Sensor data consistency validation
|
23
|
+
- Hardware fingerprinting with advanced characteristics
|
24
|
+
- Process behavior monitoring and analysis
|
25
|
+
- Network pattern analysis for anomaly detection
|
26
|
+
- Timing analysis for attack indicator detection
|
27
|
+
- System call entropy analysis
|
28
|
+
- Memory access pattern monitoring
|
29
|
+
- ONNX runtime integration with fallback to rule-based analysis
|
30
|
+
- AI confidence weighting in overall risk calculation
|
31
|
+
- Comprehensive behavioral analysis test suite
|
32
|
+
|
33
|
+
### Changed
|
34
|
+
- Updated risk calculator to incorporate AI confidence metrics
|
35
|
+
- Enhanced detector to support AI behavioral analysis
|
36
|
+
- Improved CLI with AI-specific configuration options
|
37
|
+
- Updated documentation with AI behavioral analysis features
|
38
|
+
|
39
|
+
### Dependencies
|
40
|
+
- Added `onnxruntime` for AI model inference
|
41
|
+
- Added `numo-narray` for numerical computations
|
42
|
+
|
16
43
|
## [0.1.0] - 2024-09-09
|
17
44
|
|
18
45
|
### Added
|
data/Gemfile.lock
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ai_root_shield (0.
|
4
|
+
ai_root_shield (0.2.0)
|
5
5
|
digest (~> 3.1)
|
6
6
|
json (~> 2.6)
|
7
|
+
numo-narray (~> 0.9)
|
8
|
+
onnxruntime (~> 0.7)
|
7
9
|
openssl (~> 3.0)
|
8
10
|
|
9
11
|
GEM
|
@@ -14,10 +16,17 @@ GEM
|
|
14
16
|
diff-lcs (1.6.2)
|
15
17
|
digest (3.2.0)
|
16
18
|
docile (1.4.1)
|
19
|
+
ffi (1.17.2)
|
20
|
+
ffi (1.17.2-arm64-darwin)
|
17
21
|
json (2.13.2)
|
18
22
|
language_server-protocol (3.17.0.5)
|
19
23
|
lint_roller (1.1.0)
|
20
24
|
method_source (1.1.0)
|
25
|
+
numo-narray (0.9.2.1)
|
26
|
+
onnxruntime (0.10.0)
|
27
|
+
ffi
|
28
|
+
onnxruntime (0.10.0-arm64-darwin)
|
29
|
+
ffi
|
21
30
|
openssl (3.3.0)
|
22
31
|
parallel (1.27.0)
|
23
32
|
parser (3.3.9.0)
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -10,17 +10,21 @@
|
|
10
10
|
|
11
11
|
An AI-powered Ruby library that performs comprehensive on-device compromise detection for mobile applications without requiring a backend. Protects against root/jailbreak, emulators, hooking frameworks, and provides behavioral risk analysis.
|
12
12
|
|
13
|
-
##
|
14
|
-
|
15
|
-
- **Root & Jailbreak Detection**:
|
16
|
-
- **Emulator/Simulator Detection**: Identifies
|
17
|
-
- **Hooking
|
18
|
-
- **
|
19
|
-
- **Network Security Analysis**:
|
20
|
-
- **AI Behavioral Analysis**:
|
21
|
-
- **
|
22
|
-
|
23
|
-
|
13
|
+
## Features
|
14
|
+
|
15
|
+
- **Root & Jailbreak Detection**: Comprehensive detection of rooted Android devices and jailbroken iOS devices
|
16
|
+
- **Emulator/Simulator Detection**: Identifies virtual devices, emulators, and simulators
|
17
|
+
- **Hooking Framework Detection**: Detects Frida, Xposed, Substrate, and other instrumentation tools
|
18
|
+
- **Application Integrity Checks**: Validates app signatures and detects repackaging/tampering
|
19
|
+
- **Network Security Analysis**: Identifies TLS issues, custom CAs, and MITM tools
|
20
|
+
- **AI Behavioral Analysis**: ONNX-powered behavioral pattern analysis with anomaly detection
|
21
|
+
- **ML-Based Emulator Detection**: Advanced machine learning techniques for emulator identification
|
22
|
+
- **AI Confidence Scoring**: Confidence metrics integrated into risk assessment
|
23
|
+
- **Risk Scoring System**: Comprehensive risk assessment with weighted factors (0-100 scale)
|
24
|
+
- **CLI Tool**: Command-line interface with multiple output formats
|
25
|
+
- **Privacy-First**: Completely offline, no data collection or external dependencies
|
26
|
+
|
27
|
+
## Installation
|
24
28
|
|
25
29
|
Add this line to your application's Gemfile:
|
26
30
|
|
@@ -40,7 +44,7 @@ Or install it yourself as:
|
|
40
44
|
$ gem install ai_root_shield
|
41
45
|
```
|
42
46
|
|
43
|
-
##
|
47
|
+
## Usage
|
44
48
|
|
45
49
|
### Basic Usage
|
46
50
|
|
@@ -64,7 +68,9 @@ config = {
|
|
64
68
|
enable_hooking_detection: true,
|
65
69
|
enable_integrity_checks: true,
|
66
70
|
enable_network_analysis: true,
|
67
|
-
|
71
|
+
enable_ai_behavioral_analysis: true, # New in v0.2.0
|
72
|
+
risk_threshold: 70,
|
73
|
+
ai_confidence_threshold: 0.7 # New in v0.2.0
|
68
74
|
}
|
69
75
|
|
70
76
|
result = AiRootShield.scan_device_with_config("device_logs/sample.json", config)
|
@@ -96,7 +102,32 @@ $ ai_root_shield --no-emulator --no-network device_logs/sample.json
|
|
96
102
|
$ ai_root_shield --help
|
97
103
|
```
|
98
104
|
|
99
|
-
##
|
105
|
+
## AI Behavioral Analysis (New in v0.2.0)
|
106
|
+
|
107
|
+
AI Root Shield now includes advanced behavioral analysis powered by ONNX machine learning models:
|
108
|
+
|
109
|
+
### Features
|
110
|
+
- **File Access Pattern Analysis**: Detects unusual file system access patterns
|
111
|
+
- **Sensor Data Consistency**: Validates sensor data against real device behavior
|
112
|
+
- **Hardware Fingerprinting**: Advanced hardware characteristic analysis
|
113
|
+
- **Process Behavior Analysis**: Monitors process execution patterns
|
114
|
+
- **Network Pattern Analysis**: Analyzes network behavior for anomalies
|
115
|
+
- **Timing Analysis**: Detects timing-based attack indicators
|
116
|
+
- **System Call Entropy**: Analyzes system call distribution patterns
|
117
|
+
- **Memory Access Patterns**: Monitors memory usage behavior
|
118
|
+
|
119
|
+
### ONNX Model Integration
|
120
|
+
|
121
|
+
Place your trained ONNX model at `models/behavioral_model.onnx` for AI-powered analysis. The system falls back to rule-based analysis if no model is available.
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
# AI analysis is automatically enabled
|
125
|
+
result = AiRootShield.scan_device('device_logs.json')
|
126
|
+
puts "AI Confidence: #{result[:ai_confidence]}"
|
127
|
+
puts "ML Emulator Score: #{result[:ml_emulator_score]}"
|
128
|
+
```
|
129
|
+
|
130
|
+
## Risk Scoring
|
100
131
|
|
101
132
|
The library provides a comprehensive risk score (0-100) based on detected security factors:
|
102
133
|
|
@@ -115,7 +146,35 @@ The library provides a comprehensive risk score (0-100) based on detected securi
|
|
115
146
|
| Integrity | `REPACKAGED_APP`, `DEX_TAMPERED` | Medium (10-18) |
|
116
147
|
| Network | `TLS_UNPINNED`, `MITM_PROXY_DETECTED` | Medium (8-18) |
|
117
148
|
|
118
|
-
##
|
149
|
+
## Device Log Format
|
150
|
+
|
151
|
+
The library expects device logs in JSON format with the following structure:
|
152
|
+
|
153
|
+
```json
|
154
|
+
{
|
155
|
+
"risk_score": 85,
|
156
|
+
"factors": [
|
157
|
+
"ROOT_BINARY_DETECTED",
|
158
|
+
"SUPERUSER_APP_INSTALLED",
|
159
|
+
"SELINUX_DISABLED",
|
160
|
+
"EMULATOR_DETECTED",
|
161
|
+
"FRIDA_SERVER_RUNNING",
|
162
|
+
"BEHAVIORAL_ANOMALY_DETECTED",
|
163
|
+
"ML_EMULATOR_CONFIDENCE_HIGH"
|
164
|
+
],
|
165
|
+
"ai_confidence": 0.92,
|
166
|
+
"ml_emulator_score": 0.87,
|
167
|
+
"anomaly_indicators": [
|
168
|
+
"SUSPICIOUS_FILE_ACCESS_PATTERN",
|
169
|
+
"SENSOR_DATA_INCONSISTENCY",
|
170
|
+
"ABNORMAL_TIMING_PATTERNS"
|
171
|
+
],
|
172
|
+
"timestamp": 1640995200,
|
173
|
+
"version": "0.2.0"
|
174
|
+
}
|
175
|
+
```
|
176
|
+
|
177
|
+
### Device Log Input Format
|
119
178
|
|
120
179
|
The library expects device logs in JSON format with the following structure:
|
121
180
|
|
@@ -123,22 +182,18 @@ The library expects device logs in JSON format with the following structure:
|
|
123
182
|
{
|
124
183
|
"platform": "android",
|
125
184
|
"system_info": {
|
126
|
-
"os_version": "
|
127
|
-
"
|
128
|
-
"
|
129
|
-
|
130
|
-
|
185
|
+
"os_version": "11",
|
186
|
+
"api_level": 30,
|
187
|
+
"build_tags": "release-keys"
|
188
|
+
},
|
189
|
+
"hardware_info": {
|
190
|
+
"model": "Pixel 5",
|
191
|
+
"manufacturer": "Google"
|
131
192
|
},
|
132
|
-
"installed_packages": [
|
133
|
-
{
|
134
|
-
"name": "com.example.app",
|
135
|
-
"signature": "release-keys"
|
136
|
-
}
|
137
|
-
],
|
138
193
|
"file_system": {
|
139
|
-
"
|
140
|
-
|
141
|
-
|
194
|
+
"files": [
|
195
|
+
{"path": "/system/bin/su", "permissions": "755", "owner": "root"}
|
196
|
+
]
|
142
197
|
},
|
143
198
|
"running_processes": [
|
144
199
|
{
|
@@ -0,0 +1,512 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "onnxruntime"
|
4
|
+
require "numo/narray"
|
5
|
+
|
6
|
+
module AiRootShield
|
7
|
+
# AI-powered behavioral analysis using ONNX models
|
8
|
+
class AiBehavioralAnalyzer
|
9
|
+
DEFAULT_MODEL_PATH = File.join(__dir__, "..", "..", "models", "behavioral_model.onnx")
|
10
|
+
|
11
|
+
# Feature indices for the ML model
|
12
|
+
FEATURE_INDICES = {
|
13
|
+
file_access_entropy: 0,
|
14
|
+
sensor_consistency_score: 1,
|
15
|
+
hardware_fingerprint_score: 2,
|
16
|
+
process_behavior_score: 3,
|
17
|
+
network_pattern_score: 4,
|
18
|
+
timing_analysis_score: 5,
|
19
|
+
system_call_entropy: 6,
|
20
|
+
memory_access_pattern: 7
|
21
|
+
}.freeze
|
22
|
+
|
23
|
+
def initialize(model_path: nil)
|
24
|
+
@model_path = model_path || DEFAULT_MODEL_PATH
|
25
|
+
@model = nil
|
26
|
+
@confidence_threshold = 0.7
|
27
|
+
load_model if File.exist?(@model_path)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Perform AI behavioral analysis on device data
|
31
|
+
# @param device_data [Hash] Parsed device data
|
32
|
+
# @return [Hash] Analysis result with AI confidence and behavioral factors
|
33
|
+
def analyze(device_data)
|
34
|
+
return fallback_analysis(device_data) unless @model
|
35
|
+
|
36
|
+
features = extract_behavioral_features(device_data)
|
37
|
+
prediction = run_inference(features)
|
38
|
+
|
39
|
+
{
|
40
|
+
ai_confidence: prediction[:confidence],
|
41
|
+
behavioral_risk_score: prediction[:risk_score],
|
42
|
+
behavioral_factors: prediction[:factors],
|
43
|
+
anomaly_indicators: detect_anomalies(device_data, features),
|
44
|
+
ml_emulator_score: calculate_ml_emulator_score(features)
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def load_model
|
51
|
+
begin
|
52
|
+
@model = OnnxRuntime::Model.new(@model_path)
|
53
|
+
rescue => e
|
54
|
+
puts "Warning: Could not load ONNX model at #{@model_path}: #{e.message}"
|
55
|
+
@model = nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def extract_behavioral_features(device_data)
|
60
|
+
features = Numo::SFloat.zeros(FEATURE_INDICES.size)
|
61
|
+
|
62
|
+
# File access pattern entropy
|
63
|
+
features[FEATURE_INDICES[:file_access_entropy]] = calculate_file_access_entropy(device_data)
|
64
|
+
|
65
|
+
# Sensor data consistency
|
66
|
+
features[FEATURE_INDICES[:sensor_consistency_score]] = calculate_sensor_consistency(device_data)
|
67
|
+
|
68
|
+
# Hardware fingerprint score
|
69
|
+
features[FEATURE_INDICES[:hardware_fingerprint_score]] = calculate_hardware_fingerprint_score(device_data)
|
70
|
+
|
71
|
+
# Process behavior analysis
|
72
|
+
features[FEATURE_INDICES[:process_behavior_score]] = analyze_process_behavior(device_data)
|
73
|
+
|
74
|
+
# Network pattern analysis
|
75
|
+
features[FEATURE_INDICES[:network_pattern_score]] = analyze_network_patterns(device_data)
|
76
|
+
|
77
|
+
# Timing analysis
|
78
|
+
features[FEATURE_INDICES[:timing_analysis_score]] = analyze_timing_patterns(device_data)
|
79
|
+
|
80
|
+
# System call entropy
|
81
|
+
features[FEATURE_INDICES[:system_call_entropy]] = calculate_system_call_entropy(device_data)
|
82
|
+
|
83
|
+
# Memory access patterns
|
84
|
+
features[FEATURE_INDICES[:memory_access_pattern]] = analyze_memory_patterns(device_data)
|
85
|
+
|
86
|
+
features
|
87
|
+
end
|
88
|
+
|
89
|
+
def calculate_file_access_entropy(device_data)
|
90
|
+
file_accesses = extract_file_accesses(device_data)
|
91
|
+
return 0.0 if file_accesses.empty?
|
92
|
+
|
93
|
+
# Calculate Shannon entropy of file access patterns
|
94
|
+
access_counts = file_accesses.group_by(&:itself).transform_values(&:size)
|
95
|
+
total_accesses = file_accesses.size.to_f
|
96
|
+
|
97
|
+
entropy = access_counts.values.reduce(0.0) do |sum, count|
|
98
|
+
probability = count / total_accesses
|
99
|
+
sum - (probability * Math.log2(probability))
|
100
|
+
end
|
101
|
+
|
102
|
+
# Normalize to 0-1 range (typical entropy range is 0-8 for file paths)
|
103
|
+
[entropy / 8.0, 1.0].min
|
104
|
+
end
|
105
|
+
|
106
|
+
def calculate_sensor_consistency(device_data)
|
107
|
+
sensors = device_data.dig(:hardware_info, :sensors) || []
|
108
|
+
return 0.0 if sensors.empty?
|
109
|
+
|
110
|
+
# Expected sensor combinations for real devices
|
111
|
+
expected_sensors = %w[accelerometer gyroscope magnetometer proximity light]
|
112
|
+
missing_sensors = expected_sensors - sensors.map(&:downcase)
|
113
|
+
|
114
|
+
# Check for sensor data consistency
|
115
|
+
sensor_data = device_data[:sensor_data] || {}
|
116
|
+
consistency_score = 0.0
|
117
|
+
|
118
|
+
# Accelerometer consistency (should have realistic values and noise)
|
119
|
+
if sensor_data["accelerometer"]
|
120
|
+
accel_values = sensor_data["accelerometer"]["values"] || []
|
121
|
+
consistency_score += analyze_sensor_realism(accel_values, "accelerometer")
|
122
|
+
end
|
123
|
+
|
124
|
+
# Gyroscope consistency
|
125
|
+
if sensor_data["gyroscope"]
|
126
|
+
gyro_values = sensor_data["gyroscope"]["values"] || []
|
127
|
+
consistency_score += analyze_sensor_realism(gyro_values, "gyroscope")
|
128
|
+
end
|
129
|
+
|
130
|
+
# Penalize for missing critical sensors
|
131
|
+
consistency_score -= (missing_sensors.size * 0.2)
|
132
|
+
|
133
|
+
[consistency_score, 1.0].min.clamp(0.0, 1.0)
|
134
|
+
end
|
135
|
+
|
136
|
+
def calculate_hardware_fingerprint_score(device_data)
|
137
|
+
hardware = device_data[:hardware_info] || {}
|
138
|
+
|
139
|
+
# Analyze hardware characteristics for emulator indicators
|
140
|
+
score = 1.0
|
141
|
+
|
142
|
+
# Device model analysis
|
143
|
+
device_model = hardware[:device_model].to_s.downcase
|
144
|
+
if device_model.include?("generic") || device_model.include?("emulator")
|
145
|
+
score -= 0.3
|
146
|
+
end
|
147
|
+
|
148
|
+
# Manufacturer analysis
|
149
|
+
manufacturer = hardware[:manufacturer].to_s.downcase
|
150
|
+
if manufacturer.include?("android") || manufacturer.empty?
|
151
|
+
score -= 0.2
|
152
|
+
end
|
153
|
+
|
154
|
+
# Serial number patterns
|
155
|
+
serial = hardware[:serial_number].to_s
|
156
|
+
if serial.include?("android") || serial == "unknown" || serial.empty?
|
157
|
+
score -= 0.2
|
158
|
+
end
|
159
|
+
|
160
|
+
# Baseband analysis
|
161
|
+
baseband = hardware[:baseband_version]
|
162
|
+
if baseband.nil? || baseband.to_s.empty?
|
163
|
+
score -= 0.3
|
164
|
+
end
|
165
|
+
|
166
|
+
[score, 1.0].min.clamp(0.0, 1.0)
|
167
|
+
end
|
168
|
+
|
169
|
+
def analyze_process_behavior(device_data)
|
170
|
+
processes = device_data[:processes] || []
|
171
|
+
return 0.5 if processes.empty?
|
172
|
+
|
173
|
+
suspicious_patterns = 0
|
174
|
+
total_processes = processes.size
|
175
|
+
|
176
|
+
processes.each do |process|
|
177
|
+
next unless process.is_a?(Hash)
|
178
|
+
|
179
|
+
process_name = process["name"].to_s.downcase
|
180
|
+
|
181
|
+
# Check for emulator-specific processes
|
182
|
+
if process_name.match?(/qemu|goldfish|ranchu|genymotion/)
|
183
|
+
suspicious_patterns += 1
|
184
|
+
end
|
185
|
+
|
186
|
+
# Check for debugging processes
|
187
|
+
if process_name.match?(/gdb|lldb|frida|strace/)
|
188
|
+
suspicious_patterns += 1
|
189
|
+
end
|
190
|
+
|
191
|
+
# Analyze process memory patterns
|
192
|
+
memory_maps = process["memory_maps"] || []
|
193
|
+
if memory_maps.any? { |map| map["permissions"]&.include?("x") && map["path"]&.start_with?("/data") }
|
194
|
+
suspicious_patterns += 1
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# Return normalized suspicion score (lower is more suspicious)
|
199
|
+
1.0 - (suspicious_patterns.to_f / [total_processes, 1].max)
|
200
|
+
end
|
201
|
+
|
202
|
+
def analyze_network_patterns(device_data)
|
203
|
+
network = device_data[:network_config] || {}
|
204
|
+
|
205
|
+
score = 1.0
|
206
|
+
|
207
|
+
# Proxy configuration analysis
|
208
|
+
if network.dig(:proxy_settings, "enabled")
|
209
|
+
proxy_host = network.dig(:proxy_settings, "host").to_s
|
210
|
+
proxy_port = network.dig(:proxy_settings, "port")
|
211
|
+
|
212
|
+
# Localhost proxies are suspicious
|
213
|
+
if proxy_host.match?(/localhost|127\.0\.0\.1|::1/)
|
214
|
+
score -= 0.3
|
215
|
+
end
|
216
|
+
|
217
|
+
# Common MITM ports
|
218
|
+
if [8080, 8888, 3128, 8081, 8082].include?(proxy_port)
|
219
|
+
score -= 0.2
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# VPN analysis
|
224
|
+
if network[:vpn_active]
|
225
|
+
score -= 0.1 # VPN itself is not necessarily suspicious
|
226
|
+
end
|
227
|
+
|
228
|
+
# Certificate analysis
|
229
|
+
certificates = network[:certificates] || []
|
230
|
+
user_certs = certificates.count { |cert| cert["user_installed"] }
|
231
|
+
if user_certs > 0
|
232
|
+
score -= (user_certs * 0.15)
|
233
|
+
end
|
234
|
+
|
235
|
+
[score, 1.0].min.clamp(0.0, 1.0)
|
236
|
+
end
|
237
|
+
|
238
|
+
def analyze_timing_patterns(device_data)
|
239
|
+
# Analyze timing patterns in system events
|
240
|
+
logs = device_data[:logs] || []
|
241
|
+
return 0.5 if logs.empty?
|
242
|
+
|
243
|
+
# Extract timestamps if available
|
244
|
+
timestamps = logs.filter_map do |log|
|
245
|
+
next unless log.is_a?(Hash) && log["timestamp"]
|
246
|
+
Time.parse(log["timestamp"]) rescue nil
|
247
|
+
end
|
248
|
+
|
249
|
+
return 0.5 if timestamps.size < 2
|
250
|
+
|
251
|
+
# Calculate time intervals between events
|
252
|
+
intervals = timestamps.each_cons(2).map { |t1, t2| (t2 - t1).abs }
|
253
|
+
|
254
|
+
# Real devices should have some variation in timing
|
255
|
+
if intervals.uniq.size == 1
|
256
|
+
# Perfectly regular intervals suggest automation/emulation
|
257
|
+
return 0.2
|
258
|
+
end
|
259
|
+
|
260
|
+
# Calculate coefficient of variation
|
261
|
+
mean_interval = intervals.sum / intervals.size
|
262
|
+
variance = intervals.sum { |i| (i - mean_interval) ** 2 } / intervals.size
|
263
|
+
std_dev = Math.sqrt(variance)
|
264
|
+
|
265
|
+
cv = mean_interval > 0 ? std_dev / mean_interval : 0
|
266
|
+
|
267
|
+
# Higher variation is more realistic (up to a point)
|
268
|
+
[cv * 2, 1.0].min
|
269
|
+
end
|
270
|
+
|
271
|
+
def calculate_system_call_entropy(device_data)
|
272
|
+
# Analyze system call patterns from logs
|
273
|
+
logs = device_data[:logs] || []
|
274
|
+
system_calls = logs.filter_map do |log|
|
275
|
+
log_text = log.is_a?(Hash) ? log["message"] : log.to_s
|
276
|
+
# Extract system call names from log entries
|
277
|
+
log_text.scan(/\b(open|read|write|close|mmap|ioctl|socket)\b/).flatten
|
278
|
+
end
|
279
|
+
|
280
|
+
return 0.5 if system_calls.empty?
|
281
|
+
|
282
|
+
# Calculate entropy of system call distribution
|
283
|
+
call_counts = system_calls.group_by(&:itself).transform_values(&:size)
|
284
|
+
total_calls = system_calls.size.to_f
|
285
|
+
|
286
|
+
entropy = call_counts.values.reduce(0.0) do |sum, count|
|
287
|
+
probability = count / total_calls
|
288
|
+
sum - (probability * Math.log2(probability))
|
289
|
+
end
|
290
|
+
|
291
|
+
# Normalize entropy (typical range 0-3 for system calls)
|
292
|
+
[entropy / 3.0, 1.0].min
|
293
|
+
end
|
294
|
+
|
295
|
+
def analyze_memory_patterns(device_data)
|
296
|
+
processes = device_data[:processes] || []
|
297
|
+
return 0.5 if processes.empty?
|
298
|
+
|
299
|
+
suspicious_memory_patterns = 0
|
300
|
+
total_memory_regions = 0
|
301
|
+
|
302
|
+
processes.each do |process|
|
303
|
+
next unless process.is_a?(Hash)
|
304
|
+
|
305
|
+
memory_maps = process["memory_maps"] || []
|
306
|
+
total_memory_regions += memory_maps.size
|
307
|
+
|
308
|
+
memory_maps.each do |map|
|
309
|
+
next unless map.is_a?(Hash)
|
310
|
+
|
311
|
+
# Check for suspicious memory patterns
|
312
|
+
if map["path"]&.include?("/dev/ashmem") && map["size"].to_i > 100_000_000
|
313
|
+
suspicious_memory_patterns += 1
|
314
|
+
end
|
315
|
+
|
316
|
+
# Executable memory in data segments
|
317
|
+
if map["permissions"]&.include?("x") && map["path"]&.start_with?("/data")
|
318
|
+
suspicious_memory_patterns += 1
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
return 0.5 if total_memory_regions == 0
|
324
|
+
|
325
|
+
# Return normalized score (lower means more suspicious)
|
326
|
+
1.0 - (suspicious_memory_patterns.to_f / total_memory_regions)
|
327
|
+
end
|
328
|
+
|
329
|
+
def run_inference(features)
|
330
|
+
return fallback_prediction(features) unless @model
|
331
|
+
|
332
|
+
begin
|
333
|
+
# Prepare input for ONNX model
|
334
|
+
input_data = { "input" => features.reshape(1, -1) }
|
335
|
+
|
336
|
+
# Run inference
|
337
|
+
output = @model.predict(input_data)
|
338
|
+
|
339
|
+
# Extract predictions (assuming model outputs risk_score and confidence)
|
340
|
+
risk_score = output["risk_score"].first.first
|
341
|
+
confidence = output["confidence"].first.first
|
342
|
+
|
343
|
+
# Generate factors based on feature analysis
|
344
|
+
factors = generate_behavioral_factors(features, risk_score)
|
345
|
+
|
346
|
+
{
|
347
|
+
risk_score: (risk_score * 100).round,
|
348
|
+
confidence: confidence,
|
349
|
+
factors: factors
|
350
|
+
}
|
351
|
+
rescue => e
|
352
|
+
puts "Warning: ONNX inference failed: #{e.message}"
|
353
|
+
fallback_prediction(features)
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
def fallback_prediction(features)
|
358
|
+
# Simple rule-based prediction when ONNX model is not available
|
359
|
+
risk_indicators = 0
|
360
|
+
|
361
|
+
# Check each feature for suspicious values
|
362
|
+
risk_indicators += 1 if features[FEATURE_INDICES[:file_access_entropy]] < 0.3
|
363
|
+
risk_indicators += 1 if features[FEATURE_INDICES[:sensor_consistency_score]] < 0.5
|
364
|
+
risk_indicators += 1 if features[FEATURE_INDICES[:hardware_fingerprint_score]] < 0.6
|
365
|
+
risk_indicators += 1 if features[FEATURE_INDICES[:process_behavior_score]] < 0.5
|
366
|
+
risk_indicators += 1 if features[FEATURE_INDICES[:network_pattern_score]] < 0.7
|
367
|
+
|
368
|
+
risk_score = (risk_indicators / FEATURE_INDICES.size.to_f * 100).round
|
369
|
+
confidence = 0.6 # Lower confidence for fallback method
|
370
|
+
|
371
|
+
{
|
372
|
+
risk_score: risk_score,
|
373
|
+
confidence: confidence,
|
374
|
+
factors: generate_behavioral_factors(features, risk_score / 100.0)
|
375
|
+
}
|
376
|
+
end
|
377
|
+
|
378
|
+
def generate_behavioral_factors(features, risk_score)
|
379
|
+
factors = []
|
380
|
+
|
381
|
+
factors << "LOW_FILE_ACCESS_ENTROPY" if features[FEATURE_INDICES[:file_access_entropy]] < 0.3
|
382
|
+
factors << "INCONSISTENT_SENSOR_DATA" if features[FEATURE_INDICES[:sensor_consistency_score]] < 0.5
|
383
|
+
factors << "SUSPICIOUS_HARDWARE_FINGERPRINT" if features[FEATURE_INDICES[:hardware_fingerprint_score]] < 0.6
|
384
|
+
factors << "ANOMALOUS_PROCESS_BEHAVIOR" if features[FEATURE_INDICES[:process_behavior_score]] < 0.5
|
385
|
+
factors << "SUSPICIOUS_NETWORK_PATTERNS" if features[FEATURE_INDICES[:network_pattern_score]] < 0.7
|
386
|
+
factors << "IRREGULAR_TIMING_PATTERNS" if features[FEATURE_INDICES[:timing_analysis_score]] < 0.4
|
387
|
+
factors << "LOW_SYSTEM_CALL_ENTROPY" if features[FEATURE_INDICES[:system_call_entropy]] < 0.3
|
388
|
+
factors << "ANOMALOUS_MEMORY_PATTERNS" if features[FEATURE_INDICES[:memory_access_pattern]] < 0.4
|
389
|
+
|
390
|
+
# Add high-level behavioral indicators
|
391
|
+
factors << "AI_BEHAVIORAL_ANOMALY" if risk_score > 0.7
|
392
|
+
factors << "ML_EMULATOR_DETECTED" if calculate_ml_emulator_score(features) > 0.8
|
393
|
+
|
394
|
+
factors
|
395
|
+
end
|
396
|
+
|
397
|
+
def detect_anomalies(device_data, features)
|
398
|
+
anomalies = []
|
399
|
+
|
400
|
+
# File access anomalies
|
401
|
+
if features[FEATURE_INDICES[:file_access_entropy]] < 0.2
|
402
|
+
anomalies << {
|
403
|
+
type: "file_access_pattern",
|
404
|
+
severity: "high",
|
405
|
+
description: "Extremely low entropy in file access patterns suggests automated behavior"
|
406
|
+
}
|
407
|
+
end
|
408
|
+
|
409
|
+
# Sensor anomalies
|
410
|
+
if features[FEATURE_INDICES[:sensor_consistency_score]] < 0.3
|
411
|
+
anomalies << {
|
412
|
+
type: "sensor_inconsistency",
|
413
|
+
severity: "medium",
|
414
|
+
description: "Sensor data patterns inconsistent with real device behavior"
|
415
|
+
}
|
416
|
+
end
|
417
|
+
|
418
|
+
# Hardware fingerprint anomalies
|
419
|
+
if features[FEATURE_INDICES[:hardware_fingerprint_score]] < 0.4
|
420
|
+
anomalies << {
|
421
|
+
type: "hardware_fingerprint",
|
422
|
+
severity: "high",
|
423
|
+
description: "Hardware characteristics suggest emulated environment"
|
424
|
+
}
|
425
|
+
end
|
426
|
+
|
427
|
+
anomalies
|
428
|
+
end
|
429
|
+
|
430
|
+
def calculate_ml_emulator_score(features)
|
431
|
+
# ML-based emulator detection using multiple features
|
432
|
+
emulator_indicators = 0
|
433
|
+
total_indicators = 5
|
434
|
+
|
435
|
+
# Hardware fingerprint is strong indicator
|
436
|
+
emulator_indicators += 2 if features[FEATURE_INDICES[:hardware_fingerprint_score]] < 0.5
|
437
|
+
|
438
|
+
# Sensor consistency
|
439
|
+
emulator_indicators += 1 if features[FEATURE_INDICES[:sensor_consistency_score]] < 0.4
|
440
|
+
|
441
|
+
# Process behavior
|
442
|
+
emulator_indicators += 1 if features[FEATURE_INDICES[:process_behavior_score]] < 0.3
|
443
|
+
|
444
|
+
# Memory patterns
|
445
|
+
emulator_indicators += 1 if features[FEATURE_INDICES[:memory_access_pattern]] < 0.3
|
446
|
+
|
447
|
+
(emulator_indicators.to_f / total_indicators).clamp(0.0, 1.0)
|
448
|
+
end
|
449
|
+
|
450
|
+
def fallback_analysis(device_data)
|
451
|
+
{
|
452
|
+
ai_confidence: 0.5,
|
453
|
+
behavioral_risk_score: 0,
|
454
|
+
behavioral_factors: [],
|
455
|
+
anomaly_indicators: [],
|
456
|
+
ml_emulator_score: 0.0
|
457
|
+
}
|
458
|
+
end
|
459
|
+
|
460
|
+
# Helper methods for feature extraction
|
461
|
+
|
462
|
+
def extract_file_accesses(device_data)
|
463
|
+
file_accesses = []
|
464
|
+
|
465
|
+
# Extract from logs
|
466
|
+
logs = device_data[:logs] || []
|
467
|
+
logs.each do |log|
|
468
|
+
log_text = log.is_a?(Hash) ? log["message"] : log.to_s
|
469
|
+
# Extract file paths from log entries
|
470
|
+
file_paths = log_text.scan(%r{/[/\w.-]+})
|
471
|
+
file_accesses.concat(file_paths)
|
472
|
+
end
|
473
|
+
|
474
|
+
# Extract from process information
|
475
|
+
processes = device_data[:processes] || []
|
476
|
+
processes.each do |process|
|
477
|
+
next unless process.is_a?(Hash)
|
478
|
+
|
479
|
+
if process["open_files"]
|
480
|
+
file_accesses.concat(process["open_files"])
|
481
|
+
end
|
482
|
+
end
|
483
|
+
|
484
|
+
file_accesses.uniq
|
485
|
+
end
|
486
|
+
|
487
|
+
def analyze_sensor_realism(values, sensor_type)
|
488
|
+
return 0.0 if values.empty?
|
489
|
+
|
490
|
+
# Convert to numeric values
|
491
|
+
numeric_values = values.filter_map { |v| Float(v) rescue nil }
|
492
|
+
return 0.0 if numeric_values.empty?
|
493
|
+
|
494
|
+
case sensor_type
|
495
|
+
when "accelerometer"
|
496
|
+
# Accelerometer should have realistic range and noise
|
497
|
+
realistic_range = numeric_values.all? { |v| v.abs <= 20.0 } # Reasonable G-force range
|
498
|
+
has_variation = numeric_values.uniq.size > 1
|
499
|
+
|
500
|
+
realistic_range && has_variation ? 0.5 : 0.0
|
501
|
+
when "gyroscope"
|
502
|
+
# Gyroscope should have realistic angular velocity range
|
503
|
+
realistic_range = numeric_values.all? { |v| v.abs <= 2000.0 } # Degrees per second
|
504
|
+
has_variation = numeric_values.uniq.size > 1
|
505
|
+
|
506
|
+
realistic_range && has_variation ? 0.5 : 0.0
|
507
|
+
else
|
508
|
+
0.3 # Default score for other sensors
|
509
|
+
end
|
510
|
+
end
|
511
|
+
end
|
512
|
+
end
|
@@ -11,12 +11,15 @@ module AiRootShield
|
|
11
11
|
enable_hooking_detection: true,
|
12
12
|
enable_integrity_checks: true,
|
13
13
|
enable_network_analysis: true,
|
14
|
-
|
14
|
+
enable_ai_behavioral_analysis: true,
|
15
|
+
risk_threshold: 50,
|
16
|
+
ai_confidence_threshold: 0.7
|
15
17
|
}.freeze
|
16
18
|
|
17
19
|
def initialize(config = {})
|
18
20
|
@config = DEFAULT_CONFIG.merge(config)
|
19
21
|
@analyzers = initialize_analyzers
|
22
|
+
@ai_analyzer = AiBehavioralAnalyzer.new if @config[:enable_ai_behavioral_analysis]
|
20
23
|
end
|
21
24
|
|
22
25
|
# Perform comprehensive device security scan
|
@@ -27,6 +30,7 @@ module AiRootShield
|
|
27
30
|
|
28
31
|
detected_factors = []
|
29
32
|
risk_scores = []
|
33
|
+
ai_result = nil
|
30
34
|
|
31
35
|
@analyzers.each do |analyzer|
|
32
36
|
next unless analyzer_enabled?(analyzer)
|
@@ -36,14 +40,36 @@ module AiRootShield
|
|
36
40
|
risk_scores << result[:risk_score]
|
37
41
|
end
|
38
42
|
|
39
|
-
|
43
|
+
# Perform AI behavioral analysis if enabled
|
44
|
+
if @ai_analyzer && @config[:enable_ai_behavioral_analysis]
|
45
|
+
ai_result = @ai_analyzer.analyze(device_data)
|
46
|
+
detected_factors.concat(ai_result[:behavioral_factors])
|
47
|
+
risk_scores << ai_result[:behavioral_risk_score]
|
48
|
+
end
|
49
|
+
|
50
|
+
overall_risk = RiskCalculator.calculate_overall_risk(
|
51
|
+
risk_scores,
|
52
|
+
detected_factors,
|
53
|
+
ai_confidence: ai_result&.dig(:ai_confidence)
|
54
|
+
)
|
40
55
|
|
41
|
-
{
|
56
|
+
result = {
|
42
57
|
risk_score: overall_risk,
|
43
58
|
factors: detected_factors.uniq,
|
44
59
|
timestamp: Time.now.to_i,
|
45
60
|
version: AiRootShield::VERSION
|
46
61
|
}
|
62
|
+
|
63
|
+
# Add AI-specific results if available
|
64
|
+
if ai_result
|
65
|
+
result.merge!({
|
66
|
+
ai_confidence: ai_result[:ai_confidence],
|
67
|
+
ml_emulator_score: ai_result[:ml_emulator_score],
|
68
|
+
anomaly_indicators: ai_result[:anomaly_indicators]
|
69
|
+
})
|
70
|
+
end
|
71
|
+
|
72
|
+
result
|
47
73
|
end
|
48
74
|
|
49
75
|
private
|
@@ -70,6 +96,8 @@ module AiRootShield
|
|
70
96
|
@config[:enable_integrity_checks]
|
71
97
|
when "NetworkAnalyzer"
|
72
98
|
@config[:enable_network_analysis]
|
99
|
+
when "AiBehavioralAnalyzer"
|
100
|
+
@config[:enable_ai_behavioral_analysis]
|
73
101
|
else
|
74
102
|
true
|
75
103
|
end
|
@@ -43,8 +43,9 @@ module AiRootShield
|
|
43
43
|
# Calculate overall risk score from individual analyzer results
|
44
44
|
# @param risk_scores [Array<Integer>] Individual risk scores from analyzers
|
45
45
|
# @param factors [Array<String>] Detected risk factors
|
46
|
+
# @param ai_confidence [Float, nil] AI confidence score (0.0-1.0)
|
46
47
|
# @return [Integer] Overall risk score (0-100)
|
47
|
-
def calculate_overall_risk(risk_scores, factors)
|
48
|
+
def calculate_overall_risk(risk_scores, factors, ai_confidence: nil)
|
48
49
|
return 0 if factors.empty?
|
49
50
|
|
50
51
|
# Calculate weighted score based on detected factors
|
@@ -59,6 +60,12 @@ module AiRootShield
|
|
59
60
|
# Apply risk amplification for multiple high-risk factors
|
60
61
|
amplified_score = apply_risk_amplification(combined_score, factors)
|
61
62
|
|
63
|
+
# Apply AI confidence weighting if available
|
64
|
+
if ai_confidence && ai_confidence > 0.5
|
65
|
+
ai_weight = (ai_confidence - 0.5) * 2 # Scale 0.5-1.0 to 0.0-1.0
|
66
|
+
amplified_score *= (1.0 + ai_weight * 0.2) # Up to 20% boost for high confidence
|
67
|
+
end
|
68
|
+
|
62
69
|
# Ensure score is within bounds
|
63
70
|
[amplified_score.round, 100].min
|
64
71
|
end
|
data/lib/ai_root_shield.rb
CHANGED
@@ -7,6 +7,7 @@ require_relative "ai_root_shield/analyzers/emulator_detector"
|
|
7
7
|
require_relative "ai_root_shield/analyzers/hooking_detector"
|
8
8
|
require_relative "ai_root_shield/analyzers/integrity_checker"
|
9
9
|
require_relative "ai_root_shield/analyzers/network_analyzer"
|
10
|
+
require_relative "ai_root_shield/ai_behavioral_analyzer"
|
10
11
|
require_relative "ai_root_shield/risk_calculator"
|
11
12
|
require_relative "ai_root_shield/device_log_parser"
|
12
13
|
|
data/models/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# AI Root Shield - Behavioral Analysis Models
|
2
|
+
|
3
|
+
This directory contains ONNX models for AI-powered behavioral analysis.
|
4
|
+
|
5
|
+
## Model Architecture
|
6
|
+
|
7
|
+
The behavioral analysis model (`behavioral_model.onnx`) is designed to analyze device behavior patterns and detect anomalies that may indicate compromise or emulation.
|
8
|
+
|
9
|
+
### Input Features (8 dimensions)
|
10
|
+
|
11
|
+
1. **File Access Entropy** (0.0-1.0): Shannon entropy of file access patterns
|
12
|
+
2. **Sensor Consistency Score** (0.0-1.0): Consistency of sensor data with real device behavior
|
13
|
+
3. **Hardware Fingerprint Score** (0.0-1.0): Hardware characteristics analysis
|
14
|
+
4. **Process Behavior Score** (0.0-1.0): Process execution patterns analysis
|
15
|
+
5. **Network Pattern Score** (0.0-1.0): Network behavior analysis
|
16
|
+
6. **Timing Analysis Score** (0.0-1.0): Event timing pattern analysis
|
17
|
+
7. **System Call Entropy** (0.0-1.0): System call distribution entropy
|
18
|
+
8. **Memory Access Pattern** (0.0-1.0): Memory usage pattern analysis
|
19
|
+
|
20
|
+
### Output
|
21
|
+
|
22
|
+
- **Risk Score** (0.0-1.0): Behavioral risk assessment
|
23
|
+
- **Confidence** (0.0-1.0): Model confidence in the prediction
|
24
|
+
|
25
|
+
## Model Training
|
26
|
+
|
27
|
+
The model should be trained on labeled datasets containing:
|
28
|
+
- Legitimate device telemetry data
|
29
|
+
- Emulator/simulator data
|
30
|
+
- Compromised device data
|
31
|
+
- Synthetic attack scenarios
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
The model is automatically loaded by `AiBehavioralAnalyzer` if present in this directory. If the model file is not available, the analyzer falls back to rule-based analysis.
|
36
|
+
|
37
|
+
## Creating Your Own Model
|
38
|
+
|
39
|
+
To create a custom behavioral analysis model:
|
40
|
+
|
41
|
+
1. Collect training data with the 8 input features
|
42
|
+
2. Train using your preferred ML framework (TensorFlow, PyTorch, etc.)
|
43
|
+
3. Export to ONNX format as `behavioral_model.onnx`
|
44
|
+
4. Place in this directory
|
45
|
+
|
46
|
+
Example Python code for model creation:
|
47
|
+
|
48
|
+
```python
|
49
|
+
import onnx
|
50
|
+
import numpy as np
|
51
|
+
from sklearn.ensemble import RandomForestClassifier
|
52
|
+
from skl2onnx import convert_sklearn
|
53
|
+
from skl2onnx.common.data_types import FloatTensorType
|
54
|
+
|
55
|
+
# Train your model
|
56
|
+
model = RandomForestClassifier(n_estimators=100, random_state=42)
|
57
|
+
model.fit(X_train, y_train)
|
58
|
+
|
59
|
+
# Convert to ONNX
|
60
|
+
initial_type = [('input', FloatTensorType([None, 8]))]
|
61
|
+
onnx_model = convert_sklearn(model, initial_types=initial_type)
|
62
|
+
|
63
|
+
# Save model
|
64
|
+
with open("behavioral_model.onnx", "wb") as f:
|
65
|
+
f.write(onnx_model.SerializeToString())
|
66
|
+
```
|
67
|
+
|
68
|
+
## Security Considerations
|
69
|
+
|
70
|
+
- Models should be validated for adversarial robustness
|
71
|
+
- Regular retraining is recommended as attack techniques evolve
|
72
|
+
- Consider model versioning for production deployments
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ai_root_shield
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ahmet KAHRAMAN
|
@@ -51,6 +51,34 @@ dependencies:
|
|
51
51
|
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
version: '3.0'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: onnxruntime
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0.7'
|
61
|
+
type: :runtime
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0.7'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: numo-narray
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0.9'
|
75
|
+
type: :runtime
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0.9'
|
54
82
|
- !ruby/object:Gem::Dependency
|
55
83
|
name: bundler
|
56
84
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,6 +170,7 @@ files:
|
|
142
170
|
- examples/device_logs/rooted_android.json
|
143
171
|
- exe/ai_root_shield
|
144
172
|
- lib/ai_root_shield.rb
|
173
|
+
- lib/ai_root_shield/ai_behavioral_analyzer.rb
|
145
174
|
- lib/ai_root_shield/analyzers/emulator_detector.rb
|
146
175
|
- lib/ai_root_shield/analyzers/hooking_detector.rb
|
147
176
|
- lib/ai_root_shield/analyzers/integrity_checker.rb
|
@@ -151,6 +180,7 @@ files:
|
|
151
180
|
- lib/ai_root_shield/device_log_parser.rb
|
152
181
|
- lib/ai_root_shield/risk_calculator.rb
|
153
182
|
- lib/ai_root_shield/version.rb
|
183
|
+
- models/README.md
|
154
184
|
homepage: https://github.com/ahmetxhero/ai-root-shield
|
155
185
|
licenses:
|
156
186
|
- MIT
|