trigdroid 2.0.0__py3-none-any.whl
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,1150 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: trigdroid
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: Android Sandbox Payload Trigger Framework for Security Research
|
|
5
|
+
Project-URL: Homepage, https://github.com/fkie-cad/Sandroid_TrigDroid
|
|
6
|
+
Project-URL: Documentation, https://fkie-cad/Sandroid_TrigDroid
|
|
7
|
+
Project-URL: Repository, https://github.com/fkie-cad/Sandroid_TrigDroid.git
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/fkie-cad/Sandroid_TrigDroid/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/fkie-cad/Sandroid_TrigDroid/blob/main/CHANGELOG.md
|
|
10
|
+
Author-email: Daniel Baier <daniel.baier@fkie.fraunhofer.de>, Simon HΓΌsch <simon.huesch@smail.inf.h-brs.de>
|
|
11
|
+
Maintainer-email: TrigDroid Team <contact@trigdroid.org>
|
|
12
|
+
License: MIT License
|
|
13
|
+
|
|
14
|
+
Copyright (c) 2025 FKIE-CAD
|
|
15
|
+
|
|
16
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
17
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
18
|
+
in the Software without restriction, including without limitation the rights
|
|
19
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
20
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
21
|
+
furnished to do so, subject to the following conditions:
|
|
22
|
+
|
|
23
|
+
The above copyright notice and this permission notice shall be included in all
|
|
24
|
+
copies or substantial portions of the Software.
|
|
25
|
+
|
|
26
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
27
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
28
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
29
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
30
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
31
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
32
|
+
SOFTWARE.
|
|
33
|
+
License-File: LICENSE
|
|
34
|
+
Keywords: android,frida,malware-analysis,mobile-security,penetration-testing,reverse-engineering,security
|
|
35
|
+
Classifier: Development Status :: 4 - Beta
|
|
36
|
+
Classifier: Environment :: Console
|
|
37
|
+
Classifier: Environment :: Other Environment
|
|
38
|
+
Classifier: Intended Audience :: Developers
|
|
39
|
+
Classifier: Intended Audience :: Science/Research
|
|
40
|
+
Classifier: Intended Audience :: System Administrators
|
|
41
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
42
|
+
Classifier: Natural Language :: English
|
|
43
|
+
Classifier: Operating System :: MacOS
|
|
44
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
45
|
+
Classifier: Programming Language :: JavaScript
|
|
46
|
+
Classifier: Programming Language :: Python :: 3
|
|
47
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
48
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
49
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
50
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
51
|
+
Classifier: Topic :: Security
|
|
52
|
+
Classifier: Topic :: Software Development :: Testing
|
|
53
|
+
Classifier: Topic :: System :: Systems Administration
|
|
54
|
+
Classifier: Topic :: Utilities
|
|
55
|
+
Classifier: Typing :: Typed
|
|
56
|
+
Requires-Python: >=3.9
|
|
57
|
+
Requires-Dist: click>=8.1.0
|
|
58
|
+
Requires-Dist: colorama>=0.4.6
|
|
59
|
+
Requires-Dist: pydantic>=2.0.0
|
|
60
|
+
Requires-Dist: pyyaml>=6.0
|
|
61
|
+
Requires-Dist: requests>=2.31.0
|
|
62
|
+
Requires-Dist: rich>=13.0.0
|
|
63
|
+
Requires-Dist: termcolor>=2.3.0
|
|
64
|
+
Provides-Extra: dev
|
|
65
|
+
Requires-Dist: black>=23.0.0; extra == 'dev'
|
|
66
|
+
Requires-Dist: isort>=5.12.0; extra == 'dev'
|
|
67
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
68
|
+
Requires-Dist: pre-commit>=3.0.0; extra == 'dev'
|
|
69
|
+
Requires-Dist: pylint>=2.17.0; extra == 'dev'
|
|
70
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
71
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
72
|
+
Requires-Dist: pytest-mock>=3.10.0; extra == 'dev'
|
|
73
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
74
|
+
Requires-Dist: types-pyyaml>=6.0.0; extra == 'dev'
|
|
75
|
+
Requires-Dist: types-requests>=2.31.0; extra == 'dev'
|
|
76
|
+
Provides-Extra: docs
|
|
77
|
+
Requires-Dist: mkdocs-click>=0.8.0; extra == 'docs'
|
|
78
|
+
Requires-Dist: mkdocs-material>=9.0.0; extra == 'docs'
|
|
79
|
+
Requires-Dist: mkdocs>=1.5.0; extra == 'docs'
|
|
80
|
+
Requires-Dist: mkdocstrings[python]>=0.22.0; extra == 'docs'
|
|
81
|
+
Provides-Extra: frida
|
|
82
|
+
Requires-Dist: frida-tools>=12.0.0; extra == 'frida'
|
|
83
|
+
Requires-Dist: frida>=16.0.0; extra == 'frida'
|
|
84
|
+
Provides-Extra: full
|
|
85
|
+
Requires-Dist: appium-python-client>=3.0.0; extra == 'full'
|
|
86
|
+
Requires-Dist: frida-tools>=12.0.0; extra == 'full'
|
|
87
|
+
Requires-Dist: frida>=16.0.0; extra == 'full'
|
|
88
|
+
Requires-Dist: numpy>=1.24.0; extra == 'full'
|
|
89
|
+
Requires-Dist: pillow>=9.0.0; extra == 'full'
|
|
90
|
+
Requires-Dist: selenium>=4.0.0; extra == 'full'
|
|
91
|
+
Provides-Extra: lint
|
|
92
|
+
Requires-Dist: black>=23.0.0; extra == 'lint'
|
|
93
|
+
Requires-Dist: isort>=5.12.0; extra == 'lint'
|
|
94
|
+
Requires-Dist: mypy>=1.0.0; extra == 'lint'
|
|
95
|
+
Requires-Dist: pylint>=2.17.0; extra == 'lint'
|
|
96
|
+
Requires-Dist: ruff>=0.1.0; extra == 'lint'
|
|
97
|
+
Provides-Extra: test
|
|
98
|
+
Requires-Dist: coverage[toml]>=7.0.0; extra == 'test'
|
|
99
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'test'
|
|
100
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'test'
|
|
101
|
+
Requires-Dist: pytest-mock>=3.10.0; extra == 'test'
|
|
102
|
+
Requires-Dist: pytest>=7.0.0; extra == 'test'
|
|
103
|
+
Description-Content-Type: text/markdown
|
|
104
|
+
|
|
105
|
+
# TrigDroid π€
|
|
106
|
+
|
|
107
|
+
**Android Sandbox Payload Trigger Framework for Security Research**
|
|
108
|
+
|
|
109
|
+
[](https://www.python.org/downloads/)
|
|
110
|
+
[](LICENSE)
|
|
111
|
+
[]()
|
|
112
|
+
[]()
|
|
113
|
+
|
|
114
|
+
TrigDroid is a modern Android security testing framework designed to trigger payloads in potentially malicious Android applications through sophisticated environmental manipulation. Built for security researchers, malware analysts, and penetration testers, it provides both a powerful command-line interface and a flexible Python API. It is part of the Android Sandbox Sandroid.
|
|
115
|
+
|
|
116
|
+
## π― Key Features
|
|
117
|
+
|
|
118
|
+
- **π Payload Trigger Detection**: Sophisticated environmental manipulation to trigger hidden malicious behaviors
|
|
119
|
+
- **π± Multi-Device Support**: Works with physical devices and emulators
|
|
120
|
+
- **π§ Dual Interface**: Both CLI and Python API for maximum flexibility
|
|
121
|
+
- **β‘ Frida Integration**: Advanced runtime instrumentation with TypeScript hooks
|
|
122
|
+
- **π Network Manipulation**: WiFi, mobile data, and Bluetooth state changes
|
|
123
|
+
- **π Sensor Simulation**: Accelerometer, gyroscope, light, pressure, and more
|
|
124
|
+
- **π Battery Simulation**: Dynamic battery level and charging state changes
|
|
125
|
+
- **π Comprehensive Reporting**: Detailed test results with timing and metrics
|
|
126
|
+
- **ποΈ Modern Architecture**: Built with SOLID principles and type safety
|
|
127
|
+
|
|
128
|
+
## π Quick Start
|
|
129
|
+
|
|
130
|
+
### Installation
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Install TrigDroid with full features
|
|
134
|
+
pip install trigdroid[full]
|
|
135
|
+
|
|
136
|
+
# Install minimal version
|
|
137
|
+
pip install trigdroid
|
|
138
|
+
|
|
139
|
+
# Install with specific features
|
|
140
|
+
pip install trigdroid[frida] # Just Frida support
|
|
141
|
+
pip install trigdroid[dev] # Development tools
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Prerequisites
|
|
145
|
+
|
|
146
|
+
- **Python 3.9+**
|
|
147
|
+
- **Android Debug Bridge (ADB)**
|
|
148
|
+
- **Android device or emulator** with USB debugging enabled
|
|
149
|
+
- **Node.js** (optional, for TypeScript Frida hooks)
|
|
150
|
+
|
|
151
|
+
### Basic Usage
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# Test an Android app with basic payload triggers
|
|
155
|
+
trigdroid -p com.example.app
|
|
156
|
+
|
|
157
|
+
# Advanced testing with sensor manipulation
|
|
158
|
+
trigdroid -p com.suspicious.app --acceleration 8 --battery 3 --wifi
|
|
159
|
+
|
|
160
|
+
# List available Android devices
|
|
161
|
+
trigdroid devices
|
|
162
|
+
|
|
163
|
+
# Get detailed app information
|
|
164
|
+
trigdroid info com.example.app
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## π Command Line Interface
|
|
168
|
+
|
|
169
|
+
### Core Commands
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# Basic app analysis
|
|
173
|
+
trigdroid -p <package_name>
|
|
174
|
+
|
|
175
|
+
# Advanced options
|
|
176
|
+
trigdroid -p com.example.app \
|
|
177
|
+
--acceleration 5 \ # Sensor elaborateness (0-10)
|
|
178
|
+
--battery 3 \ # Battery rotation level (0-4)
|
|
179
|
+
--wifi \ # Enable WiFi state changes
|
|
180
|
+
--data \ # Enable mobile data changes
|
|
181
|
+
--frida \ # Enable Frida hooks
|
|
182
|
+
--timeout 600 # Test timeout in seconds
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Device Management
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
# List all connected devices
|
|
189
|
+
trigdroid devices
|
|
190
|
+
|
|
191
|
+
# Get detailed device information
|
|
192
|
+
trigdroid devices --verbose
|
|
193
|
+
|
|
194
|
+
# Test specific device
|
|
195
|
+
trigdroid -p com.example.app -d emulator-5554
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Configuration Files
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# Create configuration template
|
|
202
|
+
trigdroid --create-config default
|
|
203
|
+
|
|
204
|
+
# Use configuration file
|
|
205
|
+
trigdroid test-config config.yaml
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Example Configuration (config.yaml)
|
|
209
|
+
|
|
210
|
+
```yaml
|
|
211
|
+
package: "com.example.app"
|
|
212
|
+
acceleration: 5
|
|
213
|
+
sensors:
|
|
214
|
+
- accelerometer
|
|
215
|
+
- gyroscope
|
|
216
|
+
- light
|
|
217
|
+
network_states:
|
|
218
|
+
- wifi
|
|
219
|
+
- data
|
|
220
|
+
battery_rotation: 3
|
|
221
|
+
frida_hooks: true
|
|
222
|
+
timeout: 300
|
|
223
|
+
verbose: true
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## π Python API
|
|
227
|
+
|
|
228
|
+
### Simple Usage
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
from trigdroid import quick_test
|
|
232
|
+
|
|
233
|
+
# Quick test with default settings
|
|
234
|
+
result = quick_test("com.example.app")
|
|
235
|
+
print(f"Test successful: {result.success}")
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Advanced Usage
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
from trigdroid import TrigDroidAPI, TestConfiguration
|
|
242
|
+
|
|
243
|
+
# Create detailed configuration
|
|
244
|
+
config = TestConfiguration(
|
|
245
|
+
package="com.suspicious.app",
|
|
246
|
+
acceleration=8, # High sensor activity
|
|
247
|
+
sensors=["accelerometer", "gyroscope", "light"],
|
|
248
|
+
network_states=["wifi", "data"], # Network state changes
|
|
249
|
+
battery_rotation=3, # Battery level simulation
|
|
250
|
+
frida_hooks=True, # Enable runtime instrumentation
|
|
251
|
+
timeout=600, # 10 minute timeout
|
|
252
|
+
verbose=True
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
# Run comprehensive test
|
|
256
|
+
with TrigDroidAPI() as trigdroid:
|
|
257
|
+
trigdroid.configure(config)
|
|
258
|
+
result = trigdroid.run_tests()
|
|
259
|
+
|
|
260
|
+
# Analyze results
|
|
261
|
+
if result.success:
|
|
262
|
+
print(f"β
Test completed in {result.duration_seconds:.1f}s")
|
|
263
|
+
print(f"π Tests run: {result.total_tests}")
|
|
264
|
+
print(f"β
Passed: {result.passed_tests}")
|
|
265
|
+
print(f"β Failed: {result.failed_tests}")
|
|
266
|
+
else:
|
|
267
|
+
print(f"β Test failed: {result.error}")
|
|
268
|
+
|
|
269
|
+
# Check for suspicious behavior
|
|
270
|
+
if result.app_crashed:
|
|
271
|
+
print("β οΈ App crashed during testing")
|
|
272
|
+
if result.frida_errors:
|
|
273
|
+
print(f"π Frida instrumentation issues: {result.frida_errors}")
|
|
274
|
+
|
|
275
|
+
# Access detailed metrics
|
|
276
|
+
print(f"π± Sensor tests: {len(result.sensor_tests_executed)}")
|
|
277
|
+
print(f"π Network changes: {len(result.network_state_changes)}")
|
|
278
|
+
print(f"π Background time: {result.app_background_time:.1f}s")
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Device Management API
|
|
282
|
+
|
|
283
|
+
```python
|
|
284
|
+
from trigdroid import DeviceManager, scan_devices
|
|
285
|
+
|
|
286
|
+
# Scan for available devices
|
|
287
|
+
devices = scan_devices()
|
|
288
|
+
for device in devices:
|
|
289
|
+
print(f"Device: {device['id']} ({device['status']})")
|
|
290
|
+
|
|
291
|
+
# Advanced device management
|
|
292
|
+
manager = DeviceManager()
|
|
293
|
+
device = manager.connect_to_device("emulator-5554")
|
|
294
|
+
|
|
295
|
+
if device:
|
|
296
|
+
print(f"Connected to: {device.device_id}")
|
|
297
|
+
info = device.get_device_info()
|
|
298
|
+
print(f"Model: {info.get('model', 'Unknown')}")
|
|
299
|
+
print(f"Android: {info.get('version', 'Unknown')}")
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Environment Validation
|
|
303
|
+
|
|
304
|
+
```python
|
|
305
|
+
from trigdroid.api.quick_start import validate_environment, setup_environment
|
|
306
|
+
|
|
307
|
+
# Check if environment is ready
|
|
308
|
+
status = validate_environment()
|
|
309
|
+
if all(status.values()):
|
|
310
|
+
print("π Environment is ready!")
|
|
311
|
+
else:
|
|
312
|
+
print("β Issues found:")
|
|
313
|
+
for check, result in status.items():
|
|
314
|
+
if not result:
|
|
315
|
+
print(f" β’ {check}")
|
|
316
|
+
|
|
317
|
+
# Automatically setup environment
|
|
318
|
+
if setup_environment():
|
|
319
|
+
print("β
Environment setup complete")
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## π§ Advanced Features
|
|
323
|
+
|
|
324
|
+
### Sensor Manipulation
|
|
325
|
+
|
|
326
|
+
TrigDroid can simulate various Android sensors to trigger environment-dependent payloads:
|
|
327
|
+
|
|
328
|
+
- **Accelerometer**: Motion detection triggers
|
|
329
|
+
- **Gyroscope**: Rotation-based activations
|
|
330
|
+
- **Light Sensor**: Ambient light conditions
|
|
331
|
+
- **Pressure**: Atmospheric pressure changes
|
|
332
|
+
- **Magnetometer**: Magnetic field variations
|
|
333
|
+
- **Proximity**: Near/far object detection
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
# Fine-tuned sensor testing
|
|
337
|
+
trigdroid -p com.example.app \
|
|
338
|
+
--acceleration 7 \
|
|
339
|
+
--gyroscope 5 \
|
|
340
|
+
--light 3 \
|
|
341
|
+
--pressure 4
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Network State Manipulation
|
|
345
|
+
|
|
346
|
+
Simulate different connectivity scenarios:
|
|
347
|
+
|
|
348
|
+
```bash
|
|
349
|
+
# Test with network state changes
|
|
350
|
+
trigdroid -p com.example.app --wifi --data --bluetooth
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Frida Runtime Instrumentation
|
|
354
|
+
|
|
355
|
+
TrigDroid includes sophisticated Frida hooks written in TypeScript:
|
|
356
|
+
|
|
357
|
+
- **Method interception**: Hook critical Android APIs
|
|
358
|
+
- **Parameter modification**: Alter method arguments and return values
|
|
359
|
+
- **Behavior monitoring**: Track app interactions with system APIs
|
|
360
|
+
- **Anti-analysis detection**: Identify evasion techniques
|
|
361
|
+
|
|
362
|
+
### Battery and System Simulation
|
|
363
|
+
|
|
364
|
+
```bash
|
|
365
|
+
# Simulate battery level changes and system states
|
|
366
|
+
trigdroid -p com.example.app \
|
|
367
|
+
--battery 4 \ # Maximum battery simulation
|
|
368
|
+
--background-time 30 \ # 30 seconds in background
|
|
369
|
+
--min-runtime 5 # Minimum 5 minutes runtime
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## π Understanding Results
|
|
373
|
+
|
|
374
|
+
### Test Result Structure
|
|
375
|
+
|
|
376
|
+
```python
|
|
377
|
+
# Example result analysis
|
|
378
|
+
result = api.run_tests()
|
|
379
|
+
|
|
380
|
+
# Basic status
|
|
381
|
+
print(f"Success: {result.success}")
|
|
382
|
+
print(f"Phase: {result.phase}") # setup, execution, teardown
|
|
383
|
+
print(f"Duration: {result.duration_seconds}s")
|
|
384
|
+
|
|
385
|
+
# Test statistics
|
|
386
|
+
print(f"Total tests: {result.total_tests}")
|
|
387
|
+
print(f"Success rate: {result.success_rate:.1f}%")
|
|
388
|
+
|
|
389
|
+
# App behavior analysis
|
|
390
|
+
print(f"App started: {result.app_started}")
|
|
391
|
+
print(f"App crashed: {result.app_crashed}")
|
|
392
|
+
print(f"Background time: {result.app_background_time}s")
|
|
393
|
+
|
|
394
|
+
# Instrumentation results
|
|
395
|
+
print(f"Frida hooks loaded: {result.frida_hooks_loaded}")
|
|
396
|
+
print(f"Frida hooks active: {result.frida_hooks_active}")
|
|
397
|
+
|
|
398
|
+
# Sensor test results
|
|
399
|
+
for sensor, changed in result.sensor_values_changed.items():
|
|
400
|
+
print(f"Sensor {sensor}: {changed} value changes")
|
|
401
|
+
|
|
402
|
+
# Export results
|
|
403
|
+
result_dict = result.to_dict()
|
|
404
|
+
summary = result.summary() # Human-readable summary
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### Interpreting Security Findings
|
|
408
|
+
|
|
409
|
+
**π Suspicious Indicators:**
|
|
410
|
+
- App crashes during sensor manipulation
|
|
411
|
+
- Unexpected network activity during state changes
|
|
412
|
+
- Frida hook detection or evasion attempts
|
|
413
|
+
- Unusual battery usage patterns
|
|
414
|
+
- Background behavior changes
|
|
415
|
+
|
|
416
|
+
**β
Normal Behavior:**
|
|
417
|
+
- Consistent app performance across all tests
|
|
418
|
+
- No crashes or errors
|
|
419
|
+
- Predictable sensor responses
|
|
420
|
+
- Standard network usage patterns
|
|
421
|
+
|
|
422
|
+
## π οΈ Development and Integration
|
|
423
|
+
|
|
424
|
+
### Third-Party Project Integration
|
|
425
|
+
|
|
426
|
+
```python
|
|
427
|
+
# In your security analysis tool
|
|
428
|
+
from trigdroid import TrigDroidAPI, TestConfiguration
|
|
429
|
+
|
|
430
|
+
def analyze_apk(package_name: str) -> dict:
|
|
431
|
+
"""Analyze an APK for malicious behavior."""
|
|
432
|
+
config = TestConfiguration(
|
|
433
|
+
package=package_name,
|
|
434
|
+
acceleration=8, # High intensity testing
|
|
435
|
+
timeout=600,
|
|
436
|
+
frida_hooks=True
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
with TrigDroidAPI() as trigdroid:
|
|
440
|
+
result = trigdroid.run_tests()
|
|
441
|
+
|
|
442
|
+
return {
|
|
443
|
+
"malicious": not result.success,
|
|
444
|
+
"confidence": result.success_rate,
|
|
445
|
+
"indicators": {
|
|
446
|
+
"crashed": result.app_crashed,
|
|
447
|
+
"evasion_detected": len(result.frida_errors) > 0,
|
|
448
|
+
"suspicious_network": len(result.network_state_changes) > 5
|
|
449
|
+
},
|
|
450
|
+
"report": result.summary()
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
# Usage
|
|
454
|
+
analysis = analyze_apk("com.suspicious.app")
|
|
455
|
+
if analysis["malicious"]:
|
|
456
|
+
print(f"β οΈ Malicious behavior detected (confidence: {analysis['confidence']:.1f}%)")
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### CI/CD Integration
|
|
460
|
+
|
|
461
|
+
```yaml
|
|
462
|
+
# .github/workflows/security-scan.yml
|
|
463
|
+
name: Android Security Scan
|
|
464
|
+
|
|
465
|
+
on: [push, pull_request]
|
|
466
|
+
|
|
467
|
+
jobs:
|
|
468
|
+
security-scan:
|
|
469
|
+
runs-on: ubuntu-latest
|
|
470
|
+
|
|
471
|
+
steps:
|
|
472
|
+
- uses: actions/checkout@v3
|
|
473
|
+
|
|
474
|
+
- name: Setup Python
|
|
475
|
+
uses: actions/setup-python@v4
|
|
476
|
+
with:
|
|
477
|
+
python-version: '3.9'
|
|
478
|
+
|
|
479
|
+
- name: Install TrigDroid
|
|
480
|
+
run: pip install trigdroid[frida]
|
|
481
|
+
|
|
482
|
+
- name: Setup Android Emulator
|
|
483
|
+
uses: reactivecircus/android-emulator-runner@v2
|
|
484
|
+
with:
|
|
485
|
+
api-level: 29
|
|
486
|
+
script: |
|
|
487
|
+
adb devices
|
|
488
|
+
trigdroid devices
|
|
489
|
+
|
|
490
|
+
- name: Security Analysis
|
|
491
|
+
run: |
|
|
492
|
+
trigdroid -p com.example.testapp \
|
|
493
|
+
--acceleration 5 \
|
|
494
|
+
--timeout 300 \
|
|
495
|
+
--frida
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
## π Security Considerations
|
|
499
|
+
|
|
500
|
+
**β οΈ Important**: TrigDroid is designed for **defensive security research** and **malware analysis** only.
|
|
501
|
+
|
|
502
|
+
### Ethical Usage Guidelines
|
|
503
|
+
|
|
504
|
+
- β
**Authorized Testing**: Only test applications you own or have explicit permission to analyze
|
|
505
|
+
- β
**Research Purposes**: Use for academic research, security analysis, and malware detection
|
|
506
|
+
- β
**Controlled Environment**: Run tests in isolated environments or sandboxes
|
|
507
|
+
- β **No Malicious Use**: Do not use to enhance or create malicious capabilities
|
|
508
|
+
- β **No Unauthorized Testing**: Do not test third-party applications without permission
|
|
509
|
+
|
|
510
|
+
### Privacy and Legal Compliance
|
|
511
|
+
|
|
512
|
+
- Ensure compliance with local laws and regulations
|
|
513
|
+
- Respect application privacy policies and terms of service
|
|
514
|
+
- Use appropriate data handling and retention practices
|
|
515
|
+
- Consider ethical implications of security research
|
|
516
|
+
|
|
517
|
+
## π Troubleshooting
|
|
518
|
+
|
|
519
|
+
### Common Issues
|
|
520
|
+
|
|
521
|
+
**Device Not Found**
|
|
522
|
+
```bash
|
|
523
|
+
# Check ADB connection
|
|
524
|
+
adb devices
|
|
525
|
+
|
|
526
|
+
# Restart ADB server
|
|
527
|
+
adb kill-server && adb start-server
|
|
528
|
+
|
|
529
|
+
# Enable USB debugging on device
|
|
530
|
+
# Developer options β USB debugging
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
**Frida Hooks Fail to Load**
|
|
534
|
+
```bash
|
|
535
|
+
# Check Frida installation
|
|
536
|
+
python -c "import frida; print(frida.__version__)"
|
|
537
|
+
|
|
538
|
+
# Reinstall Frida
|
|
539
|
+
pip install --upgrade frida frida-tools
|
|
540
|
+
|
|
541
|
+
# Check device architecture
|
|
542
|
+
adb shell getprop ro.product.cpu.abi
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
**TypeScript Compilation Errors**
|
|
546
|
+
```bash
|
|
547
|
+
# Check Node.js installation
|
|
548
|
+
node --version && npm --version
|
|
549
|
+
|
|
550
|
+
# Rebuild TypeScript hooks
|
|
551
|
+
cd frida-hooks
|
|
552
|
+
rm -rf node_modules dist
|
|
553
|
+
npm install && npm run build
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
**Permission Errors**
|
|
557
|
+
```bash
|
|
558
|
+
# Grant app permissions manually
|
|
559
|
+
adb shell pm grant com.example.app android.permission.READ_PHONE_STATE
|
|
560
|
+
|
|
561
|
+
# Use TrigDroid's permission management
|
|
562
|
+
trigdroid -p com.example.app --grant-permission android.permission.CAMERA
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
### Getting Help
|
|
566
|
+
|
|
567
|
+
- **Documentation**: Full documentation at [docs.trigdroid.org](https://docs.trigdroid.org)
|
|
568
|
+
- **Issues**: Report bugs at [GitHub Issues](https://github.com/trigdroid/trigdroid/issues)
|
|
569
|
+
- **Discussions**: Join the community at [GitHub Discussions](https://github.com/trigdroid/trigdroid/discussions)
|
|
570
|
+
|
|
571
|
+
## π€ Contributing
|
|
572
|
+
|
|
573
|
+
We welcome contributions from the security research community!
|
|
574
|
+
|
|
575
|
+
```bash
|
|
576
|
+
# Development setup
|
|
577
|
+
git clone https://github.com/trigdroid/trigdroid.git
|
|
578
|
+
cd trigdroid
|
|
579
|
+
pip install -e ".[dev]"
|
|
580
|
+
|
|
581
|
+
# Run tests
|
|
582
|
+
pytest tests/
|
|
583
|
+
|
|
584
|
+
# Code quality checks
|
|
585
|
+
black src/ tests/
|
|
586
|
+
mypy src/
|
|
587
|
+
ruff check src/ tests/
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed contribution guidelines.
|
|
591
|
+
|
|
592
|
+
## π License
|
|
593
|
+
|
|
594
|
+
TrigDroid is released under the [MIT License](LICENSE). See LICENSE file for details.
|
|
595
|
+
|
|
596
|
+
## π οΈ Development Guide
|
|
597
|
+
|
|
598
|
+
### Modern Architecture Overview
|
|
599
|
+
|
|
600
|
+
TrigDroid has been completely refactored following **SOLID principles** with a clean dual-layer architecture:
|
|
601
|
+
|
|
602
|
+
```
|
|
603
|
+
βββ src/ # π New Refactored Code (SOLID Architecture)
|
|
604
|
+
β βββ trigdroid/ # Modern Public API Layer (lowercase)
|
|
605
|
+
β β βββ api/ # External interface with context managers
|
|
606
|
+
β β β βββ main.py # TrigDroidAPI class
|
|
607
|
+
β β β βββ config.py # Type-safe TestConfiguration
|
|
608
|
+
β β β βββ results.py # Comprehensive TestResult classes
|
|
609
|
+
β β β βββ devices.py # Device management wrapper
|
|
610
|
+
β β β βββ runners.py # Test runner wrapper
|
|
611
|
+
β β β βββ quick_start.py # Convenience functions
|
|
612
|
+
β β βββ cli/ # Rich CLI interface using Click
|
|
613
|
+
β β β βββ main.py # Modern CLI with subcommands
|
|
614
|
+
β β βββ core/ # Core utilities and enums
|
|
615
|
+
β β β βββ enums.py # Type-safe enumerations
|
|
616
|
+
β β β βββ cleanup.py # Resource management
|
|
617
|
+
β β βββ exceptions.py # Exception hierarchy
|
|
618
|
+
β βββ TrigDroid_Infrastructure/ # ποΈ Infrastructure Layer (SOLID)
|
|
619
|
+
β βββ interfaces/ # Protocol-based abstractions
|
|
620
|
+
β β βββ __init__.py # ILogger, ITestRunner, IAndroidDevice, etc.
|
|
621
|
+
β βββ infrastructure/ # Dependency injection + implementations
|
|
622
|
+
β β βββ dependency_injection.py # DI container
|
|
623
|
+
β β βββ configuration.py # Config providers
|
|
624
|
+
β β βββ logging.py # Logger implementations
|
|
625
|
+
β β βββ android.py # Device management
|
|
626
|
+
β βββ application/ # Application orchestration
|
|
627
|
+
β β βββ orchestrator.py # Main workflow coordinator
|
|
628
|
+
β βββ test_runners/ # Test execution implementations
|
|
629
|
+
βββ src/ # ποΈ Legacy Code (Original Implementation)
|
|
630
|
+
β βββ TrigDroid/ # Legacy TrigDroid (preserved for compatibility)
|
|
631
|
+
β βββ logger/ # Original logging utilities
|
|
632
|
+
β βββ interaction/ # Legacy UI components
|
|
633
|
+
β βββ utils/ # Legacy utility functions
|
|
634
|
+
β βββ frida/ # Legacy JavaScript hooks
|
|
635
|
+
β βββ ... # Other legacy components
|
|
636
|
+
βββ frida-hooks/ # π§ TypeScript Frida Hooks (New)
|
|
637
|
+
β βββ main.ts # Hook entry point
|
|
638
|
+
β βββ hooks/ # Individual hook modules
|
|
639
|
+
β β βββ android-sensors.ts
|
|
640
|
+
β β βββ android-build.ts
|
|
641
|
+
β βββ types.ts # TypeScript type definitions
|
|
642
|
+
β βββ utils.ts # Common hook utilities
|
|
643
|
+
β βββ package.json # Node.js build configuration
|
|
644
|
+
β βββ tsconfig.json # TypeScript compiler settings
|
|
645
|
+
βββ scripts/ # π Build and installation scripts
|
|
646
|
+
β βββ build.py # Cross-platform build script
|
|
647
|
+
β βββ install.sh # Automated installation
|
|
648
|
+
βββ pyproject.toml # Modern Python packaging (PEP 621)
|
|
649
|
+
βββ Makefile # Development workflow commands
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
### SOLID Principles Implementation
|
|
653
|
+
|
|
654
|
+
#### **1. Single Responsibility Principle**
|
|
655
|
+
Each class has one reason to change:
|
|
656
|
+
- `AndroidDevice`: Only handles device operations
|
|
657
|
+
- `StandardLogger`: Only handles logging
|
|
658
|
+
- `SensorTestRunner`: Only executes sensor tests
|
|
659
|
+
|
|
660
|
+
#### **2. Open/Closed Principle**
|
|
661
|
+
Extend functionality without modifying existing code:
|
|
662
|
+
```python
|
|
663
|
+
# Add new test runner without changing existing ones
|
|
664
|
+
class CustomTestRunner(TestRunnerBase):
|
|
665
|
+
def can_run(self, test_type: str) -> bool:
|
|
666
|
+
return test_type == "custom"
|
|
667
|
+
|
|
668
|
+
def _execute_internal(self, context: ITestContext) -> TestResult:
|
|
669
|
+
# Custom test logic
|
|
670
|
+
return TestResult.SUCCESS
|
|
671
|
+
|
|
672
|
+
# Register in DI container
|
|
673
|
+
container.register_transient(ITestRunner, CustomTestRunner, "custom")
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
#### **3. Liskov Substitution Principle**
|
|
677
|
+
All implementations follow their interfaces:
|
|
678
|
+
```python
|
|
679
|
+
# Any ILogger implementation works seamlessly
|
|
680
|
+
logger: ILogger = StandardLogger() # or FilteredLogger()
|
|
681
|
+
logger.info("Test message") # Works the same way
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
#### **4. Interface Segregation Principle**
|
|
685
|
+
Small, focused interfaces instead of large monolithic ones:
|
|
686
|
+
```python
|
|
687
|
+
class ILogger(Protocol):
|
|
688
|
+
def debug(self, message: str) -> None: ...
|
|
689
|
+
def info(self, message: str) -> None: ...
|
|
690
|
+
|
|
691
|
+
class IConfigurationProvider(Protocol):
|
|
692
|
+
def get_value(self, key: str) -> ConfigValue: ...
|
|
693
|
+
def set_value(self, key: str, value: ConfigValue) -> None: ...
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
#### **5. Dependency Inversion Principle**
|
|
697
|
+
Depend on abstractions, inject dependencies:
|
|
698
|
+
```python
|
|
699
|
+
class SensorTestRunner(TestRunnerBase):
|
|
700
|
+
def __init__(self, logger: ILogger, device: IAndroidDevice):
|
|
701
|
+
super().__init__(logger)
|
|
702
|
+
self._device = device # Injected dependency
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
### Development Environment Setup
|
|
706
|
+
|
|
707
|
+
#### **Quick Development Setup**
|
|
708
|
+
```bash
|
|
709
|
+
# 1. Clone and setup development environment
|
|
710
|
+
git clone https://github.com/trigdroid/trigdroid.git
|
|
711
|
+
cd trigdroid
|
|
712
|
+
|
|
713
|
+
# 2. Use our automated installer
|
|
714
|
+
./scripts/install.sh --mode dev
|
|
715
|
+
|
|
716
|
+
# 3. Alternative: Manual setup
|
|
717
|
+
python -m venv venv
|
|
718
|
+
source venv/bin/activate # On Windows: venv\Scripts\activate
|
|
719
|
+
pip install -e ".[full,dev,test,docs]"
|
|
720
|
+
|
|
721
|
+
# 4. Build TypeScript hooks
|
|
722
|
+
cd frida-hooks
|
|
723
|
+
npm install && npm run build
|
|
724
|
+
cd ..
|
|
725
|
+
|
|
726
|
+
# 5. Verify installation
|
|
727
|
+
trigdroid --version
|
|
728
|
+
pytest tests/ -v
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
#### **Development Workflow Commands**
|
|
732
|
+
```bash
|
|
733
|
+
# Development commands (see Makefile)
|
|
734
|
+
make setup-dev-env # Initial environment setup
|
|
735
|
+
make dev-install # Install in development mode
|
|
736
|
+
make build # Build all components (Python + TypeScript)
|
|
737
|
+
|
|
738
|
+
# Code quality
|
|
739
|
+
make format # Auto-format with black + isort
|
|
740
|
+
make lint # Type checking with mypy + ruff
|
|
741
|
+
make check # Run all quality checks
|
|
742
|
+
make pre-commit # Format + lint + fast tests
|
|
743
|
+
|
|
744
|
+
# Testing
|
|
745
|
+
make test # All tests
|
|
746
|
+
make test-unit # Unit tests only
|
|
747
|
+
make test-integration # Integration tests
|
|
748
|
+
make test-fast # Skip slow tests
|
|
749
|
+
make coverage # Generate coverage report
|
|
750
|
+
|
|
751
|
+
# Build and distribution
|
|
752
|
+
make package # Build wheel/sdist
|
|
753
|
+
make hooks # Build TypeScript hooks only
|
|
754
|
+
make clean # Clean build artifacts
|
|
755
|
+
```
|
|
756
|
+
|
|
757
|
+
### Adding New Features
|
|
758
|
+
|
|
759
|
+
#### **1. Create New Test Runner**
|
|
760
|
+
```python
|
|
761
|
+
# src2/TrigDroid_Infrastructure/test_runners/custom_test_runner.py
|
|
762
|
+
from ..interfaces import ITestRunner, ITestContext, TestResult, TestRunnerBase
|
|
763
|
+
|
|
764
|
+
class CustomTestRunner(TestRunnerBase):
|
|
765
|
+
"""Example custom test runner."""
|
|
766
|
+
|
|
767
|
+
def can_run(self, test_type: str) -> bool:
|
|
768
|
+
return test_type == "custom"
|
|
769
|
+
|
|
770
|
+
def _execute_internal(self, context: ITestContext) -> TestResult:
|
|
771
|
+
# Implement your test logic
|
|
772
|
+
self._logger.info("Running custom test")
|
|
773
|
+
|
|
774
|
+
# Access dependencies through context
|
|
775
|
+
device = context.device
|
|
776
|
+
config = context.config
|
|
777
|
+
package = context.package_name
|
|
778
|
+
|
|
779
|
+
# Your test implementation
|
|
780
|
+
success = self._run_custom_test(device, package)
|
|
781
|
+
|
|
782
|
+
return TestResult.SUCCESS if success else TestResult.FAILURE
|
|
783
|
+
|
|
784
|
+
def _run_custom_test(self, device, package) -> bool:
|
|
785
|
+
# Custom test implementation
|
|
786
|
+
return True
|
|
787
|
+
|
|
788
|
+
# Register in dependency_injection.py
|
|
789
|
+
container.register_transient(ITestRunner, CustomTestRunner, "custom")
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
#### **2. Add New Configuration Provider**
|
|
793
|
+
```python
|
|
794
|
+
# src2/TrigDroid_Infrastructure/infrastructure/configuration.py
|
|
795
|
+
class DatabaseConfigProvider(ConfigurationProviderBase):
|
|
796
|
+
"""Load configuration from database."""
|
|
797
|
+
|
|
798
|
+
def _load_configuration(self) -> Dict[str, ConfigValue]:
|
|
799
|
+
# Load from database
|
|
800
|
+
return {"custom_setting": "value"}
|
|
801
|
+
|
|
802
|
+
# Register in configure_container()
|
|
803
|
+
container.register_transient(IConfigurationProvider, DatabaseConfigProvider, "database")
|
|
804
|
+
```
|
|
805
|
+
|
|
806
|
+
#### **3. Create TypeScript Frida Hook**
|
|
807
|
+
```typescript
|
|
808
|
+
// frida-hooks/hooks/custom-hook.ts
|
|
809
|
+
import { HookManager } from '../utils';
|
|
810
|
+
|
|
811
|
+
export class CustomHook extends HookManager {
|
|
812
|
+
public hookCustomAPI(): void {
|
|
813
|
+
const SomeClass = Java.use("com.example.SomeClass");
|
|
814
|
+
|
|
815
|
+
SomeClass.someMethod.implementation = function(...args) {
|
|
816
|
+
console.log("[TrigDroid] Custom hook triggered");
|
|
817
|
+
this.logToChangelog("SomeClass.someMethod", "original", "hooked");
|
|
818
|
+
|
|
819
|
+
// Call original method
|
|
820
|
+
return this.someMethod.apply(this, args);
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
// Add to main.ts
|
|
826
|
+
import { CustomHook } from './hooks/custom-hook';
|
|
827
|
+
|
|
828
|
+
function main() {
|
|
829
|
+
const customHook = new CustomHook();
|
|
830
|
+
customHook.hookCustomAPI();
|
|
831
|
+
}
|
|
832
|
+
```
|
|
833
|
+
|
|
834
|
+
### TypeScript Hook Development
|
|
835
|
+
|
|
836
|
+
#### **Building Hooks**
|
|
837
|
+
```bash
|
|
838
|
+
# Build hooks automatically during pip install
|
|
839
|
+
pip install -e .
|
|
840
|
+
|
|
841
|
+
# Manual hook building
|
|
842
|
+
cd frida-hooks
|
|
843
|
+
npm install # Install dependencies
|
|
844
|
+
npm run build # Compile TypeScript to JavaScript
|
|
845
|
+
npm run watch # Watch mode for development
|
|
846
|
+
|
|
847
|
+
# Using make
|
|
848
|
+
make hooks # Build hooks only
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
#### **Hook Development Patterns**
|
|
852
|
+
```typescript
|
|
853
|
+
// frida-hooks/hooks/android-example.ts
|
|
854
|
+
import { AndroidSensorType } from '../types';
|
|
855
|
+
import { HookUtils } from '../utils';
|
|
856
|
+
|
|
857
|
+
export class AndroidExampleHook {
|
|
858
|
+
private hookUtils: HookUtils;
|
|
859
|
+
|
|
860
|
+
constructor() {
|
|
861
|
+
this.hookUtils = new HookUtils();
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
public hookSensorManager(): void {
|
|
865
|
+
try {
|
|
866
|
+
const SensorManager = Java.use("android.hardware.SensorManager");
|
|
867
|
+
|
|
868
|
+
SensorManager.getDefaultSensor.implementation = function(type) {
|
|
869
|
+
const originalSensor = this.getDefaultSensor(type);
|
|
870
|
+
|
|
871
|
+
// Log the hook for debugging
|
|
872
|
+
this.hookUtils.logHookExecution("SensorManager.getDefaultSensor", {
|
|
873
|
+
sensorType: type,
|
|
874
|
+
timestamp: Date.now()
|
|
875
|
+
});
|
|
876
|
+
|
|
877
|
+
// Record change in changelog
|
|
878
|
+
this.hookUtils.writeToChangelog(
|
|
879
|
+
"SensorManager.getDefaultSensor",
|
|
880
|
+
"original_behavior",
|
|
881
|
+
"hooked_behavior",
|
|
882
|
+
`Sensor type ${type} intercepted`
|
|
883
|
+
);
|
|
884
|
+
|
|
885
|
+
return originalSensor;
|
|
886
|
+
};
|
|
887
|
+
|
|
888
|
+
} catch (error) {
|
|
889
|
+
console.error(`[TrigDroid] Hook failed: ${error}`);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
```
|
|
894
|
+
|
|
895
|
+
### Dependency Injection Usage
|
|
896
|
+
|
|
897
|
+
#### **Registering Services**
|
|
898
|
+
```python
|
|
899
|
+
# In configure_container()
|
|
900
|
+
from .my_service import MyService
|
|
901
|
+
|
|
902
|
+
# Singleton (same instance every time)
|
|
903
|
+
container.register_singleton(IMyService, MyService)
|
|
904
|
+
|
|
905
|
+
# Transient (new instance every time)
|
|
906
|
+
container.register_transient(IMyService, MyService)
|
|
907
|
+
|
|
908
|
+
# Factory function
|
|
909
|
+
container.register_singleton(IMyService, lambda: MyService(config="custom"))
|
|
910
|
+
|
|
911
|
+
# Specific instance
|
|
912
|
+
container.register_instance(IMyService, my_service_instance)
|
|
913
|
+
```
|
|
914
|
+
|
|
915
|
+
#### **Resolving Dependencies**
|
|
916
|
+
```python
|
|
917
|
+
# Method 1: Through container
|
|
918
|
+
container = configure_container()
|
|
919
|
+
logger = container.resolve(ILogger)
|
|
920
|
+
|
|
921
|
+
# Method 2: Service Locator (global access)
|
|
922
|
+
ServiceLocator.set_container(container)
|
|
923
|
+
logger = ServiceLocator.get_service(ILogger)
|
|
924
|
+
|
|
925
|
+
# Method 3: Constructor injection
|
|
926
|
+
@inject(logger=ILogger, device=IAndroidDevice)
|
|
927
|
+
class MyTestRunner:
|
|
928
|
+
def __init__(self, logger: ILogger, device: IAndroidDevice):
|
|
929
|
+
self._logger = logger
|
|
930
|
+
self._device = device
|
|
931
|
+
```
|
|
932
|
+
|
|
933
|
+
### Code Quality Standards
|
|
934
|
+
|
|
935
|
+
#### **Type Safety**
|
|
936
|
+
```python
|
|
937
|
+
# Use type hints everywhere
|
|
938
|
+
def process_config(config: TestConfiguration) -> TestResult:
|
|
939
|
+
return TestResult.SUCCESS
|
|
940
|
+
|
|
941
|
+
# Use protocols for interfaces
|
|
942
|
+
class IMyService(Protocol):
|
|
943
|
+
def do_something(self, value: str) -> bool: ...
|
|
944
|
+
|
|
945
|
+
# Use enums for constants
|
|
946
|
+
class TestPhase(Enum):
|
|
947
|
+
SETUP = "setup"
|
|
948
|
+
EXECUTION = "execution"
|
|
949
|
+
TEARDOWN = "teardown"
|
|
950
|
+
```
|
|
951
|
+
|
|
952
|
+
#### **Error Handling**
|
|
953
|
+
```python
|
|
954
|
+
# Proper exception hierarchy
|
|
955
|
+
class TrigDroidException(Exception):
|
|
956
|
+
"""Base exception for TrigDroid."""
|
|
957
|
+
pass
|
|
958
|
+
|
|
959
|
+
class DeviceConnectionError(TrigDroidException):
|
|
960
|
+
"""Device connection failed."""
|
|
961
|
+
pass
|
|
962
|
+
|
|
963
|
+
# Use try/catch with specific exceptions
|
|
964
|
+
try:
|
|
965
|
+
device.connect()
|
|
966
|
+
except DeviceConnectionError as e:
|
|
967
|
+
logger.error(f"Failed to connect: {e}")
|
|
968
|
+
return TestResult.FAILURE
|
|
969
|
+
```
|
|
970
|
+
|
|
971
|
+
#### **Logging Best Practices**
|
|
972
|
+
```python
|
|
973
|
+
# Use structured logging
|
|
974
|
+
logger.info("Test started", extra={
|
|
975
|
+
"package": package_name,
|
|
976
|
+
"phase": "setup",
|
|
977
|
+
"timestamp": time.time()
|
|
978
|
+
})
|
|
979
|
+
|
|
980
|
+
# Use appropriate log levels
|
|
981
|
+
logger.debug("Detailed debugging info") # Development only
|
|
982
|
+
logger.info("Important user information") # Normal operation
|
|
983
|
+
logger.warning("Something might be wrong") # Potential issues
|
|
984
|
+
logger.error("Something failed") # Errors that don't stop execution
|
|
985
|
+
logger.critical("System cannot continue") # Fatal errors
|
|
986
|
+
```
|
|
987
|
+
|
|
988
|
+
### Testing Framework
|
|
989
|
+
|
|
990
|
+
#### **Unit Tests**
|
|
991
|
+
```python
|
|
992
|
+
# tests/unit/test_sensor_runner.py
|
|
993
|
+
import pytest
|
|
994
|
+
from unittest.mock import Mock
|
|
995
|
+
from TrigDroid_Infrastructure.test_runners import SensorTestRunner
|
|
996
|
+
from TrigDroid_Infrastructure.interfaces import ILogger, ITestContext, TestResult
|
|
997
|
+
|
|
998
|
+
def test_sensor_runner_success():
|
|
999
|
+
# Arrange
|
|
1000
|
+
mock_logger = Mock(spec=ILogger)
|
|
1001
|
+
mock_context = Mock(spec=ITestContext)
|
|
1002
|
+
runner = SensorTestRunner(mock_logger)
|
|
1003
|
+
|
|
1004
|
+
# Act
|
|
1005
|
+
result = runner.execute(mock_context)
|
|
1006
|
+
|
|
1007
|
+
# Assert
|
|
1008
|
+
assert result == TestResult.SUCCESS
|
|
1009
|
+
mock_logger.info.assert_called()
|
|
1010
|
+
```
|
|
1011
|
+
|
|
1012
|
+
#### **Integration Tests**
|
|
1013
|
+
```python
|
|
1014
|
+
# tests/integration/test_full_workflow.py
|
|
1015
|
+
@pytest.mark.integration
|
|
1016
|
+
@pytest.mark.requires_device
|
|
1017
|
+
def test_full_testing_workflow(test_device):
|
|
1018
|
+
"""Test complete workflow with real device."""
|
|
1019
|
+
config = TestConfiguration(
|
|
1020
|
+
package="com.example.testapp",
|
|
1021
|
+
acceleration=3,
|
|
1022
|
+
timeout=60
|
|
1023
|
+
)
|
|
1024
|
+
|
|
1025
|
+
with TrigDroidAPI() as api:
|
|
1026
|
+
api.configure(config)
|
|
1027
|
+
api.set_device(test_device.device_id)
|
|
1028
|
+
result = api.run_tests()
|
|
1029
|
+
|
|
1030
|
+
assert result.success
|
|
1031
|
+
assert result.total_tests > 0
|
|
1032
|
+
```
|
|
1033
|
+
|
|
1034
|
+
### Performance Optimization
|
|
1035
|
+
|
|
1036
|
+
#### **Fast Development Cycle**
|
|
1037
|
+
```bash
|
|
1038
|
+
# Skip TypeScript build during development
|
|
1039
|
+
SKIP_HOOKS=1 pip install -e .
|
|
1040
|
+
|
|
1041
|
+
# Run only fast tests
|
|
1042
|
+
make test-fast
|
|
1043
|
+
|
|
1044
|
+
# Use parallel testing
|
|
1045
|
+
pytest -n auto tests/
|
|
1046
|
+
|
|
1047
|
+
# Quick format and lint check
|
|
1048
|
+
make pre-commit
|
|
1049
|
+
```
|
|
1050
|
+
|
|
1051
|
+
#### **Build Optimization**
|
|
1052
|
+
```bash
|
|
1053
|
+
# Build only what changed
|
|
1054
|
+
make hooks-if-changed
|
|
1055
|
+
|
|
1056
|
+
# Use cached dependencies
|
|
1057
|
+
pip install --cache-dir ~/.cache/pip -e .
|
|
1058
|
+
|
|
1059
|
+
# Parallel hook compilation
|
|
1060
|
+
cd frida-hooks && npm run build:parallel
|
|
1061
|
+
```
|
|
1062
|
+
|
|
1063
|
+
### Contributing Guidelines
|
|
1064
|
+
|
|
1065
|
+
#### **Code Standards**
|
|
1066
|
+
- **Readable**: Code should read like well-written prose
|
|
1067
|
+
- **Self-documenting**: Use clear variable and function names
|
|
1068
|
+
- **Consistent**: Follow established patterns
|
|
1069
|
+
- **Simple**: Prefer simple solutions over clever ones
|
|
1070
|
+
- **DRY**: Extract common functionality
|
|
1071
|
+
- **YAGNI**: Don't over-engineer
|
|
1072
|
+
|
|
1073
|
+
#### **Pull Request Process**
|
|
1074
|
+
```bash
|
|
1075
|
+
# 1. Development workflow
|
|
1076
|
+
git checkout -b feature/new-feature
|
|
1077
|
+
make dev-install
|
|
1078
|
+
make pre-commit # Format + lint + fast tests
|
|
1079
|
+
|
|
1080
|
+
# 2. Before committing
|
|
1081
|
+
make test # Full test suite
|
|
1082
|
+
make build # Ensure everything builds
|
|
1083
|
+
make check # Final quality check
|
|
1084
|
+
|
|
1085
|
+
# 3. Create pull request
|
|
1086
|
+
git push origin feature/new-feature
|
|
1087
|
+
# Open PR with detailed description
|
|
1088
|
+
```
|
|
1089
|
+
|
|
1090
|
+
#### **Code Review Checklist**
|
|
1091
|
+
- [ ] Follows SOLID principles
|
|
1092
|
+
- [ ] Has proper type annotations
|
|
1093
|
+
- [ ] Includes unit tests (>90% coverage)
|
|
1094
|
+
- [ ] Updated documentation if needed
|
|
1095
|
+
- [ ] No hardcoded values or magic numbers
|
|
1096
|
+
- [ ] Proper error handling
|
|
1097
|
+
- [ ] TypeScript hooks built successfully
|
|
1098
|
+
- [ ] All quality checks pass
|
|
1099
|
+
|
|
1100
|
+
### Debugging and Troubleshooting
|
|
1101
|
+
|
|
1102
|
+
#### **Development Issues**
|
|
1103
|
+
```bash
|
|
1104
|
+
# TypeScript compilation fails
|
|
1105
|
+
cd frida-hooks
|
|
1106
|
+
rm -rf node_modules dist
|
|
1107
|
+
npm install && npm run build
|
|
1108
|
+
|
|
1109
|
+
# Python import errors
|
|
1110
|
+
pip uninstall trigdroid
|
|
1111
|
+
pip install -e ".[full]"
|
|
1112
|
+
|
|
1113
|
+
# Dependency injection issues
|
|
1114
|
+
# Check container registration in configure_container()
|
|
1115
|
+
container.has_service(IMyService) # Should return True
|
|
1116
|
+
|
|
1117
|
+
# Test runner not found
|
|
1118
|
+
# Verify registration with correct name
|
|
1119
|
+
container.resolve(ITestRunner, "my_runner")
|
|
1120
|
+
```
|
|
1121
|
+
|
|
1122
|
+
#### **Runtime Debugging**
|
|
1123
|
+
```python
|
|
1124
|
+
# Enable debug logging
|
|
1125
|
+
import logging
|
|
1126
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
1127
|
+
|
|
1128
|
+
# Use dependency injection debug mode
|
|
1129
|
+
container = configure_container()
|
|
1130
|
+
if container.has_service(IMyService):
|
|
1131
|
+
service = container.resolve(IMyService)
|
|
1132
|
+
|
|
1133
|
+
# Check service registration
|
|
1134
|
+
print(f"Registered services: {list(container._services.keys())}")
|
|
1135
|
+
```
|
|
1136
|
+
|
|
1137
|
+
This development guide provides comprehensive information for contributing to and extending TrigDroid's modern architecture.
|
|
1138
|
+
|
|
1139
|
+
## π Acknowledgments
|
|
1140
|
+
|
|
1141
|
+
- Built on the foundation of the [Evadroid](https://github.com/evadroid/evadroid) project
|
|
1142
|
+
- Powered by [Frida](https://frida.re/) dynamic instrumentation toolkit
|
|
1143
|
+
- Uses [Click](https://click.palletsprojects.com/) for command-line interface
|
|
1144
|
+
- Enhanced with [Rich](https://rich.readthedocs.io/) for beautiful terminal output
|
|
1145
|
+
|
|
1146
|
+
---
|
|
1147
|
+
|
|
1148
|
+
**Made with β€οΈ for the security research community**
|
|
1149
|
+
|
|
1150
|
+
*TrigDroid helps security researchers and malware analysts understand and detect sophisticated Android threats through intelligent payload triggering and environmental manipulation.*
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
trigdroid-2.0.0.dist-info/METADATA,sha256=9pSwOrwb5-IjdLy5rL5b6lUfTeEJvlUOc35WTM6Xg9E,35985
|
|
2
|
+
trigdroid-2.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
3
|
+
trigdroid-2.0.0.dist-info/entry_points.txt,sha256=X1hWIdaKfwFXxsMMbjkX589do-IJjuVDshe7IHOT3Kk,340
|
|
4
|
+
trigdroid-2.0.0.dist-info/licenses/LICENSE,sha256=1h287Q1gIUpNY2h3QaCowIlE6DoiBmw3WE6wn6bClkM,1065
|
|
5
|
+
trigdroid-2.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
[console_scripts]
|
|
2
|
+
trigdroid = trigdroid.cli.main:main
|
|
3
|
+
trigdroid-legacy = TrigDroid.__main__:main
|
|
4
|
+
|
|
5
|
+
[trigdroid.hooks]
|
|
6
|
+
typescript = frida-hooks.main:main
|
|
7
|
+
|
|
8
|
+
[trigdroid.test_runners]
|
|
9
|
+
frida = TrigDroid_Infrastructure.test_runners.frida_test_runner:FridaTestRunner
|
|
10
|
+
sensor = TrigDroid_Infrastructure.test_runners.sensor_test_runner:SensorTestRunner
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 FKIE-CAD
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|