PF-Grivet/ULWrap
GitHub: PF-Grivet/ULWrap
Stars: 0 | Forks: 0
# ulwrap
CLI Python pour interroger l'Unified Log macOS, orienté threat hunting.
ulwrap wrappe la commande native `log show` avec des presets prêts à l'emploi, du filtrage, de la couleur et un moteur d'analyse qui détecte les patterns suspects.
## Installation
git clone https://github.com/your-user/ulwrap.git
cd ulwrap
bash install.sh
Nécessite Python 3.8+ et macOS. Aucune dépendance externe.
Après installation, `ulwrap` est disponible depuis n'importe quel dossier.
## Utilisation
### Lister les presets disponibles
ulwrap --list-presets
### Lancer une requête avec un preset
ulwrap --preset tcc --last 1h
ulwrap --preset keychain --last 30m
ulwrap --preset persistence --last 24h
### Voir le predicate d'un preset sans l'exécuter
ulwrap --preset tcc --show-predicate
Affiche le predicate, la description et les notes. Utile pour apprendre comment fonctionne l'Unified Log.
### Requête libre avec un predicate custom
ulwrap --predicate 'process == "sshd"' --last 30m
ulwrap --predicate 'subsystem == "com.apple.network"' --last 1h
### Fenêtre de temps
ulwrap --preset tcc --last 5m # 5 dernières minutes
ulwrap --preset tcc --last 1h # dernière heure
ulwrap --preset tcc --last 2d # 2 derniers jours
ulwrap --preset tcc --start "2025-01-15 09:00:00" --end "2025-01-15 12:00:00"
### Filtrer les résultats
ulwrap --preset keychain --last 5m --filter "trustd"
Affiche uniquement les entrées contenant le mot-clé. Le compteur montre le ratio filtré/total.
### Analyser les résultats
ulwrap --preset tcc --last 1h --analyze
ulwrap --preset codesign --last 24h --analyze
Le mode `--analyze` scanne chaque entrée contre des règles de détection et affiche les alertes par sévérité : critical, high, medium, low.
### Sortie JSON
ulwrap --preset tcc --last 1h --json
### Sauvegarder dans un fichier
ulwrap --preset dns --last 1h --json --output results.json
ulwrap --preset tcc --last 1h --output results.txt
### Options supplémentaires
ulwrap --preset tcc --last 1h --no-color # Désactiver les couleurs
ulwrap --preset tcc --last 1h --presets-file ~/my-presets.json # Fichier presets custom
## Presets disponibles
### Presets de base
| Preset | Description |
|--------|-------------|
| `tcc` | Accès TCC (Transparency, Consent, and Control) |
| `dns` | Résolutions DNS avec pid et processus appelant |
| `launchd` | Activité des services launchd |
| `auth` | Authentification sudo |
| `gatekeeper` | Vérifications Gatekeeper sur les exécutables |
### Presets threat hunting
| Preset | Menaces couvertes | Description |
|--------|-------------------|-------------|
| `persistence` | Adware, Backdoors, RATs | LaunchAgent/LaunchDaemon ajoutés ou modifiés |
| `keychain` | Infostealers | Accès au trousseau de mots de passe |
| `gatekeeper-bypass` | Trojans, Apps crackées, Phishing | Contournement quarantine et notarization |
| `xpc` | Backdoors, RATs | Communications inter-processus |
| `installer` | Trojans, Adware, Malvertising | Installations de packages |
| `codesign` | Apps crackées | Validation de signature de code |
| `screen-capture` | RATs | Capture d'écran et monitoring clavier |
| `xprotect` | Malware | Scans et détections XProtect |
| `sip` | Backdoors, RATs | System Integrity Protection |
## Analyse et règles de détection
Le mode `--analyze` utilise deux niveaux de règles définies dans `presets/rules.json` :
### Règles générales (tous les presets)
- Processus lancé depuis `/tmp/` ou `/var/tmp/`
- Processus lancé depuis le dossier Downloads
- Processus dans un dossier caché (dot-prefixed)
### Règles par preset
Chaque preset a ses propres règles. Exemples :
- **tcc** : accès caméra, micro, capture écran, Full Disk Access
- **keychain** : accès par un processus non-Apple
- **codesign** : signature invalide
- **xprotect** : détection malware (avec exclusion des scans normaux)
- **sip** : SIP désactivé ou modifié
### Ajouter ses propres règles
Editer `presets/rules.json`. Chaque règle a cette structure :
{
"id": "mon-id-unique",
"name": "Nom de l'alerte",
"severity": "high",
"description": "Ce que ca signifie",
"conditions": [{"type": "msg_contains", "value": "texte a chercher"}]
}
Pour une règle générale, ajouter dans le tableau `general`.
Pour une règle liée à un preset, ajouter dans `preset > nom_du_preset`.
#### Types de conditions
| Type | Paramètre | Description |
|------|-----------|-------------|
| `msg_contains` | `value` | Le message contient ce texte |
| `msg_regex` | `value` | Le message matche cette regex |
| `path_contains` | `value` | Le chemin du processus contient ce texte |
| `non_apple_process` | — | Le processus n'est pas un binaire Apple |
| `hidden_path` | — | Le processus est dans un dossier caché |
#### Exclure des faux positifs
Ajouter un champ `exclude` avec les mêmes types de conditions :
{
"id": "ma-regle",
"name": "Ma regle",
"severity": "medium",
"description": "Description",
"conditions": [{"type": "msg_regex", "value": "(detect|malware)"}],
"exclude": [{"type": "msg_regex", "value": "(Found scanner|activity)"}]
}
### Ajouter un preset
Editer `presets/presets.json` :
{
"mon-preset": {
"predicate": "process == \"monprocess\"",
"description": "Ce que ce preset surveille",
"notes": "Informations utiles",
"level": "info",
"threats": ["infostealers", "backdoors"]
}
}
## Niveaux d'accès
| Mode | Ce que tu vois |
|------|----------------|
| Normal | Logs standard, certaines données masquées (``, hostnames DNS en `mask.hash`) |
| `sudo ulwrap ...` | Tout en clair, y compris les données marquées `` |
Pour du threat hunting de base, le mode normal suffit.
## Architecture
ulwrap/
├── ulwrap.py # CLI entry point
├── install.sh # Script d'installation
├── core/
│ ├── runner.py # Execute la commande log native
│ ├── parser.py # Parse le JSON retourne par log
│ ├── formatter.py # Sortie human-readable, couleurs, filtrage, compteur
│ └── analyzer.py # Moteur d'analyse, charge rules.json
├── presets/
│ ├── presets.json # Presets avec predicates visibles
│ └── rules.json # Regles de detection (editables)
├── lib/
│ └── ulwrap.py # API Python reutilisable
└── tests/
├── test_parser.py
├── test_formatter.py
├── test_presets.py
└── test_runner.py
## Principe de design
Les predicates sont toujours visibles via `--show-predicate`. L'outil eduque autant qu'il aide — l'utilisateur peut modifier et apprendre.