Update README.md
This commit is contained in:
parent
e3313dbc1b
commit
1d1435f36a
702
README.md
702
README.md
|
|
@ -1,351 +1,351 @@
|
||||||
# ICEYOU - Personal Anti-Intrusion Monitor
|
# ICEYOU - Personal Anti-Intrusion Monitor
|
||||||
|
|
||||||
ICEYOU watches your Windows machine while you're away. The moment any input, USB event, or camera tamper happens after idle, it locks the screen behind a full-screen white overlay with a mandatory password / face-unlock gate, snaps a photo of whoever is at the keyboard, records what they typed, and emails you the evidence.
|
ICEYOU watches your Windows machine while you're away. The moment any input, USB event, or camera tamper happens after idle, it locks the screen behind a full-screen white overlay with a mandatory password / face-unlock gate, snaps a photo of whoever is at the keyboard, records what they typed, and emails you the evidence.
|
||||||
|
|
||||||
## What It Does
|
## What It Does
|
||||||
|
|
||||||
| Capability | Detail |
|
| Capability | Detail |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Idle / away detection | Configurable idle timeout flips ICEYOU into "away" mode |
|
| Idle / away detection | Configurable idle timeout flips ICEYOU into "away" mode |
|
||||||
| Whiteout lockout | Full-screen overlay with embedded password + face unlock |
|
| Whiteout lockout | Full-screen overlay with embedded password + face unlock |
|
||||||
| Motion recording | Rolling 5s pre + event + 5s post AVI clips saved to `motion_clips/` while locked |
|
| Motion recording | Rolling 5s pre + event + 5s post AVI clips saved to `motion_clips/` while locked |
|
||||||
| Escape-key blocking | Low-level Windows keyboard hook blocks CTRL+ESC, ALT+TAB, WIN, ALT+F4, CTRL+SHIFT+ESC, etc. while locked |
|
| Escape-key blocking | Low-level Windows keyboard hook blocks CTRL+ESC, ALT+TAB, WIN, ALT+F4, CTRL+SHIFT+ESC, etc. while locked |
|
||||||
| Snapshot on attempt | Webcam photo for every unlock attempt (success or failure) |
|
| Snapshot on attempt | Webcam photo for every unlock attempt (success or failure) |
|
||||||
| Credential logging | Failed password attempts saved to `events.log` and emailed |
|
| Credential logging | Failed password attempts saved to `events.log` and emailed |
|
||||||
| Face recognition unlock | LBPH-based owner verification with `Unlock by Face` button + auto-attempt |
|
| Face recognition unlock | LBPH-based owner verification with `Unlock by Face` button + auto-attempt |
|
||||||
| Camera tamper detection | Triggers full lockdown if lens is covered while locked |
|
| Camera tamper detection | Triggers full lockdown if lens is covered while locked |
|
||||||
| USB / device monitor | Drive insertions/removals during away are treated as intrusions |
|
| USB / device monitor | Drive insertions/removals during away are treated as intrusions |
|
||||||
| Email alerts | SMTP with photo attachment + entered credentials |
|
| Email alerts | SMTP with photo attachment + entered credentials |
|
||||||
| OS workstation lock | After N failed password attempts, Windows lock kicks in (whiteout reappears on resume) |
|
| OS workstation lock | After N failed password attempts, Windows lock kicks in (whiteout reappears on resume) |
|
||||||
| System tray UI | Pause/resume monitoring, force away, send test email, open snapshots/log |
|
| System tray UI | Pause/resume monitoring, force away, send test email, open snapshots/log |
|
||||||
| Hotkeys | Force away & re-show unlock prompt globally |
|
| Hotkeys | Force away & re-show unlock prompt globally |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
1. **Create a virtualenv** (recommended — opencv-contrib requires numpy < 2):
|
1. **Create a virtualenv** (recommended - opencv-contrib requires numpy < 2):
|
||||||
```powershell
|
```powershell
|
||||||
python -m venv .venv
|
python -m venv .venv
|
||||||
.\.venv\Scripts\Activate.ps1
|
.\.venv\Scripts\Activate.ps1
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Copy & edit config**:
|
2. **Copy & edit config**:
|
||||||
```powershell
|
```powershell
|
||||||
copy config.example.json config.json
|
copy config.example.json config.json
|
||||||
notepad config.json
|
notepad config.json
|
||||||
```
|
```
|
||||||
- Set `unlock_password` to your phrase.
|
- Set `unlock_password` to your phrase.
|
||||||
- Fill SMTP details (Gmail App Password recommended).
|
- Fill SMTP details (Gmail App Password recommended).
|
||||||
- Pick the correct `camera_device_index` (run `python face_enrollment.py --list-cameras` to enumerate).
|
- Pick the correct `camera_device_index` (run `python face_enrollment.py --list-cameras` to enumerate).
|
||||||
|
|
||||||
3. **(Optional) Enroll your face**:
|
3. **(Optional) Enroll your face**:
|
||||||
```powershell
|
```powershell
|
||||||
python face_enrollment.py --name owner
|
python face_enrollment.py --name owner
|
||||||
```
|
```
|
||||||
Re-run with the same `--name` for each accessory combination (glasses, headphones, hat) to build a robust model.
|
Re-run with the same `--name` for each accessory combination (glasses, headphones, hat) to build a robust model.
|
||||||
|
|
||||||
4. **Run**:
|
4. **Run**:
|
||||||
```powershell
|
```powershell
|
||||||
python main.py
|
python main.py
|
||||||
```
|
```
|
||||||
A red shield tray icon appears. Right-click for the menu.
|
A red shield tray icon appears. Right-click for the menu.
|
||||||
|
|
||||||
5. *(Optional)* Use the **Add to Windows Startup** option (via `startup.py`) so ICEYOU launches at login.
|
5. *(Optional)* Use the **Add to Windows Startup** option (via `startup.py`) so ICEYOU launches at login.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Hotkeys & Manual Control
|
## Hotkeys & Manual Control
|
||||||
|
|
||||||
| Hotkey (default) | Action |
|
| Hotkey (default) | Action |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `Ctrl+Alt+L` | Force away mode + show whiteout immediately |
|
| `Ctrl+Alt+L` | Force away mode + show whiteout immediately |
|
||||||
| `Ctrl+Alt+U` | Re-show the whiteout password prompt (useful if it was hidden) |
|
| `Ctrl+Alt+U` | Re-show the whiteout password prompt (useful if it was hidden) |
|
||||||
| `Ctrl+Alt+M` | **Toggle Monitoring** — Pause or resume monitoring (motion + intrusion detection) |
|
| `Ctrl+Alt+M` | **Toggle Monitoring** - Pause or resume monitoring (motion + intrusion detection) |
|
||||||
| `Ctrl+Alt+S` | **Stop Monitoring** — Immediately pause motion recording and intrusion detection |
|
| `Ctrl+Alt+S` | **Stop Monitoring** - Immediately pause motion recording and intrusion detection |
|
||||||
|
|
||||||
Combos are configurable in `config.json → hotkeys` using pynput syntax (`<ctrl>+<shift>+<alt>+p`, etc.). Restart ICEYOU after editing.
|
Combos are configurable in `config.json -> hotkeys` using pynput syntax (`<ctrl>+<shift>+<alt>+p`, etc.). Restart ICEYOU after editing.
|
||||||
|
|
||||||
**Automatic behavior**: When the user successfully unlocks the whiteout, monitoring is automatically **paused** (no more motion recording or intrusion detection). It will **automatically resume** the next time the machine idles for the configured timeout.
|
**Automatic behavior**: When the user successfully unlocks the whiteout, monitoring is automatically **paused** (no more motion recording or intrusion detection). It will **automatically resume** the next time the machine idles for the configured timeout.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Tray Menu
|
## Tray Menu
|
||||||
|
|
||||||
| Item | Description |
|
| Item | Description |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **Stop Monitoring** | Immediately pauses motion recording, intrusion detection, **and releases the camera** |
|
| **Stop Monitoring** | Immediately pauses motion recording, intrusion detection, **and releases the camera** |
|
||||||
| **Resume Monitoring** | Re-enables idle detection, motion recording, and intrusion triggers |
|
| **Resume Monitoring** | Re-enables idle detection, motion recording, and intrusion triggers |
|
||||||
| Toggle Away Mode | Manual away on/off (away forces the whiteout) |
|
| Toggle Away Mode | Manual away on/off (away forces the whiteout) |
|
||||||
| Toggle White Screen | Disable the whiteout while still monitoring |
|
| Toggle White Screen | Disable the whiteout while still monitoring |
|
||||||
| Open Snapshots Folder | Browse all captured photos |
|
| Open Snapshots Folder | Browse all captured photos |
|
||||||
| View Motion Clips | Open `motion_clips/` (post-auth in practice) |
|
| View Motion Clips | Open `motion_clips/` (post-auth in practice) |
|
||||||
| Open Log File | View `events.log` |
|
| Open Log File | View `events.log` |
|
||||||
| **Send Test Email** | Sanity-check SMTP without triggering an intrusion |
|
| **Send Test Email** | Sanity-check SMTP without triggering an intrusion |
|
||||||
| Settings | Opens `config.json` in Notepad (restart to apply) |
|
| Settings | Opens `config.json` in Notepad (restart to apply) |
|
||||||
| Exit | Stops everything cleanly |
|
| Exit | Stops everything cleanly |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Intrusion Response Flow
|
## Intrusion Response Flow
|
||||||
|
|
||||||
1. **Detect** — Idle ≥ `idle_timeout_seconds` (or you pressed `Ctrl+Alt+L`) → away mode + whiteout up.
|
1. **Detect** - Idle ≥ `idle_timeout_seconds` (or you pressed `Ctrl+Alt+L`) -> away mode + whiteout up.
|
||||||
2. **Trigger** — Any keyboard, mouse, USB, or camera-obscured event during away fires an intrusion:
|
2. **Trigger** - Any keyboard, mouse, USB, or camera-obscured event during away fires an intrusion:
|
||||||
- Snapshot captured (saved to `snapshots/`)
|
- Snapshot captured (saved to `snapshots/`)
|
||||||
- `intrusion_detected` event logged
|
- `intrusion_detected` event logged
|
||||||
- Email alert sent with photo
|
- Email alert sent with photo
|
||||||
- Whiteout stays up with the password / face-unlock prompt
|
- Whiteout stays up with the password / face-unlock prompt
|
||||||
3. **Locked state** — `manual_lock` is set; ordinary activity **cannot** clear away mode. Only a correct unlock does.
|
3. **Locked state** - `manual_lock` is set; ordinary activity **cannot** clear away mode. Only a correct unlock does.
|
||||||
4. **Password gate** — Cannot be cancelled or closed. After `max_unlock_attempts` (default 3) wrong passwords, Windows workstation lock kicks in. When the user returns from the Windows lock screen the **ICEYOU whiteout is still there** — unlocking Windows alone is not enough.
|
4. **Password gate** - Cannot be cancelled or closed. After `max_unlock_attempts` (default 3) wrong passwords, Windows workstation lock kicks in. When the user returns from the Windows lock screen the **ICEYOU whiteout is still there** - unlocking Windows alone is not enough.
|
||||||
5. **Success** — Whiteout dismisses, failure counter resets, auto-away is snoozed briefly so you can work.
|
5. **Success** - Whiteout dismisses, failure counter resets, auto-away is snoozed briefly so you can work.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Unlock Attempt Audit Trail
|
## Unlock Attempt Audit Trail
|
||||||
|
|
||||||
Every interaction with the unlock prompt is recorded:
|
Every interaction with the unlock prompt is recorded:
|
||||||
|
|
||||||
- **Snapshot** of whoever is at the keyboard: `snapshots/snapshot_<timestamp>_unlock_<success|fail>_<password|face>.jpg`
|
- **Snapshot** of whoever is at the keyboard: `snapshots/snapshot_<timestamp>_unlock_<success|fail>_<password|face>.jpg`
|
||||||
- **Structured log entry** appended to `events.log` (one JSON object per line):
|
- **Structured log entry** appended to `events.log` (one JSON object per line):
|
||||||
- `method` — `"password"` or `"face"`
|
- `method` - `"password"` or `"face"`
|
||||||
- `success` — boolean
|
- `success` - boolean
|
||||||
- `snapshot` — path to the photo
|
- `snapshot` - path to the photo
|
||||||
- `entered` — **only on failed password attempts** — the literal text the intruder typed
|
- `entered` - **only on failed password attempts** - the literal text the intruder typed
|
||||||
- `label`, `confidence` — for face attempts
|
- `label`, `confidence` - for face attempts
|
||||||
- **Email alert** (if `email.enabled`) with the snapshot attached:
|
- **Email alert** (if `email.enabled`) with the snapshot attached:
|
||||||
- Failed password attempts include the typed text in the body
|
- Failed password attempts include the typed text in the body
|
||||||
- Successful unlocks confirm but **never** include your real password
|
- Successful unlocks confirm but **never** include your real password
|
||||||
- Auto face attempts (every 4 s) are silent (no log / no email) to avoid flooding. Only **manual** `Unlock by Face` clicks and **successful** matches are recorded.
|
- Auto face attempts (every 4 s) are silent (no log / no email) to avoid flooding. Only **manual** `Unlock by Face` clicks and **successful** matches are recorded.
|
||||||
|
|
||||||
If alerts aren't arriving: tray → **Send Test Email** (or `python test_email.py`). SMTP errors land in `events.log` as `email_failed`. Gmail → external-domain alerts often hit **Spam** — check there first and mark "Not spam" to whitelist.
|
If alerts aren't arriving: tray -> **Send Test Email** (or `python test_email.py`). SMTP errors land in `events.log` as `email_failed`. Gmail -> external-domain alerts often hit **Spam** - check there first and mark "Not spam" to whitelist.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Face Recognition Unlock
|
## Face Recognition Unlock
|
||||||
|
|
||||||
Optional second unlock path next to the password.
|
Optional second unlock path next to the password.
|
||||||
|
|
||||||
1. **Install the contrib OpenCV build** (required for `cv2.face`):
|
1. **Install the contrib OpenCV build** (required for `cv2.face`):
|
||||||
```powershell
|
```powershell
|
||||||
pip install --upgrade --force-reinstall opencv-contrib-python
|
pip install --upgrade --force-reinstall opencv-contrib-python
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Enroll** your face — multi-pose, multi-look:
|
2. **Enroll** your face - multi-pose, multi-look:
|
||||||
```powershell
|
```powershell
|
||||||
python face_enrollment.py --name owner
|
python face_enrollment.py --name owner
|
||||||
python face_enrollment.py --camera 1 --list-cameras
|
python face_enrollment.py --camera 1 --list-cameras
|
||||||
```
|
```
|
||||||
The capture window cycles through 5 poses (straight, left, right, up, down). Controls:
|
The capture window cycles through 5 poses (straight, left, right, up, down). Controls:
|
||||||
- **Click** the preview window — most reliable capture
|
- **Click** the preview window - most reliable capture
|
||||||
- **SPACE / ENTER / C** — capture (window must have focus)
|
- **SPACE / ENTER / C** - capture (window must have focus)
|
||||||
- Hold a steady face ≥ 2 s — auto-capture
|
- Hold a steady face ≥ 2 s - auto-capture
|
||||||
- **R** restart, **Q / ESC** quit
|
- **R** restart, **Q / ESC** quit
|
||||||
|
|
||||||
For glasses / headphones / hats, **re-run with the same `--name`** so LBPH learns all your looks under one identity. Each session appends to `faces/<label>/capture_NN.png` and re-trains `faces/model.yml`.
|
For glasses / headphones / hats, **re-run with the same `--name`** so LBPH learns all your looks under one identity. Each session appends to `faces/<label>/capture_NN.png` and re-trains `faces/model.yml`.
|
||||||
|
|
||||||
3. **Enable in `config.json`**:
|
3. **Enable in `config.json`**:
|
||||||
```json
|
```json
|
||||||
"face_recognition_enabled": true,
|
"face_recognition_enabled": true,
|
||||||
"face_unlock": {
|
"face_unlock": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"confidence_threshold": 85.0,
|
"confidence_threshold": 85.0,
|
||||||
"auto_attempt": true,
|
"auto_attempt": true,
|
||||||
"attempt_interval_seconds": 4.0,
|
"attempt_interval_seconds": 4.0,
|
||||||
"frames_per_attempt": 4,
|
"frames_per_attempt": 4,
|
||||||
"allowed_labels": ["owner"]
|
"allowed_labels": ["owner"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- `confidence_threshold` — **lower = stricter** (LBPH distance). 50 = very strong, 70 = balanced, 85 = lenient. Tune based on the `conf=…` value shown on misses.
|
- `confidence_threshold` - **lower = stricter** (LBPH distance). 50 = very strong, 70 = balanced, 85 = lenient. Tune based on the `conf=…` value shown on misses.
|
||||||
- `allowed_labels` — list of enrolled identities allowed to unlock. `null` = any enrolled label.
|
- `allowed_labels` - list of enrolled identities allowed to unlock. `null` = any enrolled label.
|
||||||
- `auto_attempt` — background tries every `attempt_interval_seconds` while the whiteout is up.
|
- `auto_attempt` - background tries every `attempt_interval_seconds` while the whiteout is up.
|
||||||
|
|
||||||
While the whiteout is shown:
|
While the whiteout is shown:
|
||||||
- Auto-attempts run silently every 4 s (default).
|
- Auto-attempts run silently every 4 s (default).
|
||||||
- The **Unlock by Face** button lets you trigger a manual attempt (this is logged + emailed; auto attempts are not).
|
- The **Unlock by Face** button lets you trigger a manual attempt (this is logged + emailed; auto attempts are not).
|
||||||
- Face failures do **not** count toward the 3-strike OS-lock — only typed passwords do, so a bad camera angle can never lock you out.
|
- Face failures do **not** count toward the 3-strike OS-lock - only typed passwords do, so a bad camera angle can never lock you out.
|
||||||
|
|
||||||
**Status hint**: failed face attempts show `Face not recognised (best=<label>, conf=<value>)` on the whiteout. If you consistently see `conf` slightly above your threshold, either raise the threshold or enroll more samples.
|
**Status hint**: failed face attempts show `Face not recognised (best=<label>, conf=<value>)` on the whiteout. If you consistently see `conf` slightly above your threshold, either raise the threshold or enroll more samples.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Camera Tamper Detection
|
## Camera Tamper Detection
|
||||||
|
|
||||||
When the whiteout is active, ICEYOU periodically samples the camera (default every 12 s). If the frame mean brightness or pixel variance drops below thresholds (lens covered, sticker over webcam, etc.), it immediately triggers full lockdown — email alert + OS workstation lock — **without** waiting for input. Configure in `config.json → camera_obscured_detection`.
|
When the whiteout is active, ICEYOU periodically samples the camera (default every 12 s). If the frame mean brightness or pixel variance drops below thresholds (lens covered, sticker over webcam, etc.), it immediately triggers full lockdown - email alert + OS workstation lock - **without** waiting for input. Configure in `config.json -> camera_obscured_detection`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Motion Recording
|
## Motion Recording
|
||||||
|
|
||||||
While the whiteout is up, [src/iceyou/motion_recorder.py](src/iceyou/motion_recorder.py) continuously samples the webcam and keeps a **rolling 5 s pre-buffer** of frames. When motion is detected (frame differencing above `sensitivity`), it writes the buffered pre-roll + the event + 5 s of post-roll to `motion_clips/motion_<timestamp>.avi` (MJPG codec). Each finalized clip:
|
While the whiteout is up, [src/iceyou/motion_recorder.py](src/iceyou/motion_recorder.py) continuously samples the webcam and keeps a **rolling 5 s pre-buffer** of frames. When motion is detected (frame differencing above `sensitivity`), it writes the buffered pre-roll + the event + 5 s of post-roll to `motion_clips/motion_<timestamp>.avi` (MJPG codec). Each finalized clip:
|
||||||
|
|
||||||
- Logs a `motion_recorded` line to `events.log` with the clip path.
|
- Logs a `motion_recorded` line to `events.log` with the clip path.
|
||||||
- Pops a system-tray notification ("Motion event saved: motion_…avi").
|
- Pops a system-tray notification ("Motion event saved: motion_…avi").
|
||||||
- Does **not** trigger an email (snapshots + unlock attempts already cover that).
|
- Does **not** trigger an email (snapshots + unlock attempts already cover that).
|
||||||
|
|
||||||
Recording starts on `WhiteScreen.show()` and stops on `WhiteScreen.hide()` — there is no recording when ICEYOU is not in the locked state.
|
Recording starts on `WhiteScreen.show()` and stops on `WhiteScreen.hide()` - there is no recording when ICEYOU is not in the locked state.
|
||||||
|
|
||||||
**Viewing clips post-authentication:** the tray menu has a **View Motion Clips** item that opens the `motion_clips/` folder in Explorer. While the whiteout is up the escape-key hook prevents the intruder from reaching the tray icon, so this item is effectively post-authentication. Once you unlock, right-click the tray icon and pick **View Motion Clips** to review.
|
**Viewing clips post-authentication:** the tray menu has a **View Motion Clips** item that opens the `motion_clips/` folder in Explorer. While the whiteout is up the escape-key hook prevents the intruder from reaching the tray icon, so this item is effectively post-authentication. Once you unlock, right-click the tray icon and pick **View Motion Clips** to review.
|
||||||
|
|
||||||
Config (`config.json → motion_recording`):
|
Config (`config.json -> motion_recording`):
|
||||||
|
|
||||||
```jsonc
|
```jsonc
|
||||||
"motion_recording": {
|
"motion_recording": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"clips_dir": "motion_clips",
|
"clips_dir": "motion_clips",
|
||||||
"fps": 15,
|
"fps": 15,
|
||||||
"pre_seconds": 5.0,
|
"pre_seconds": 5.0,
|
||||||
"post_seconds": 5.0,
|
"post_seconds": 5.0,
|
||||||
"sensitivity": 2500, // min contour area in pixels; lower = more sensitive
|
"sensitivity": 2500, // min contour area in pixels; lower = more sensitive
|
||||||
"cooldown_seconds": 8.0 // min gap between separate clips
|
"cooldown_seconds": 8.0 // min gap between separate clips
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Escape-Key Blocking
|
## Escape-Key Blocking
|
||||||
|
|
||||||
While the whiteout is shown, a low-level Windows keyboard hook ([src/iceyou/keyboard_block.py](src/iceyou/keyboard_block.py)) swallows:
|
While the whiteout is shown, a low-level Windows keyboard hook ([src/iceyou/keyboard_block.py](src/iceyou/keyboard_block.py)) swallows:
|
||||||
|
|
||||||
- `WIN` (left + right)
|
- `WIN` (left + right)
|
||||||
- `CTRL+ESC` (Start menu)
|
- `CTRL+ESC` (Start menu)
|
||||||
- `ALT+TAB`, `ALT+ESC` (task switching)
|
- `ALT+TAB`, `ALT+ESC` (task switching)
|
||||||
- `ALT+F4` (close window)
|
- `ALT+F4` (close window)
|
||||||
- `ALT+SPACE` (window menu)
|
- `ALT+SPACE` (window menu)
|
||||||
- `CTRL+SHIFT+ESC` (Task Manager hotkey)
|
- `CTRL+SHIFT+ESC` (Task Manager hotkey)
|
||||||
|
|
||||||
Disable with `"block_escape_keys": false` if needed (e.g. development). The hook is removed automatically on unlock.
|
Disable with `"block_escape_keys": false` if needed (e.g. development). The hook is removed automatically on unlock.
|
||||||
|
|
||||||
**Hard limits (Windows-enforced, cannot be intercepted from user mode):**
|
**Hard limits (Windows-enforced, cannot be intercepted from user mode):**
|
||||||
|
|
||||||
- `CTRL+ALT+DEL` — Secure Attention Sequence is kernel-enforced. An intruder can still reach the security screen → Task Manager → kill `python.exe`.
|
- `CTRL+ALT+DEL` - Secure Attention Sequence is kernel-enforced. An intruder can still reach the security screen -> Task Manager -> kill `python.exe`.
|
||||||
- Hard power off, pulling the keyboard.
|
- Hard power off, pulling the keyboard.
|
||||||
- Logging in as a different Windows user.
|
- Logging in as a different Windows user.
|
||||||
|
|
||||||
To harden against CTRL+ALT+DEL → Task Manager, run as Administrator and set the registry value `HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System\DisableTaskMgr = 1 (DWORD)`. ICEYOU does **not** apply this automatically because it's a system-wide setting affecting every program.
|
To harden against CTRL+ALT+DEL -> Task Manager, run as Administrator and set the registry value `HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System\DisableTaskMgr = 1 (DWORD)`. ICEYOU does **not** apply this automatically because it's a system-wide setting affecting every program.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Configuration Reference (`config.json`)
|
## Configuration Reference (`config.json`)
|
||||||
|
|
||||||
```jsonc
|
```jsonc
|
||||||
{
|
{
|
||||||
"idle_timeout_seconds": 100, // Idle seconds before auto-away
|
"idle_timeout_seconds": 100, // Idle seconds before auto-away
|
||||||
"monitoring_enabled": true, // Master on/off (start in monitoring mode)
|
"monitoring_enabled": true, // Master on/off (start in monitoring mode)
|
||||||
"camera_device_index": 1, // (Legacy single-cam fallback - used only if camera_device_indices is omitted)
|
"camera_device_index": 1, // (Legacy single-cam fallback - used only if camera_device_indices is omitted)
|
||||||
"camera_device_indices": [0, 1], // Multi-cam: probe each of these. Dead indices are auto-skipped.
|
"camera_device_indices": [0, 1], // Multi-cam: probe each of these. Dead indices are auto-skipped.
|
||||||
"camera_probe_timeout_seconds": 2.5, // Per-camera open+first-frame budget; phantom devices that block longer are marked DEAD
|
"camera_probe_timeout_seconds": 2.5, // Per-camera open+first-frame budget; phantom devices that block longer are marked DEAD
|
||||||
"snapshot_on_trigger": true, // Save a photo on every intrusion / attempt (one per alive camera)
|
"snapshot_on_trigger": true, // Save a photo on every intrusion / attempt (one per alive camera)
|
||||||
"snapshot_dir": "snapshots",
|
"snapshot_dir": "snapshots",
|
||||||
"log_file": "events.log",
|
"log_file": "events.log",
|
||||||
|
|
||||||
"email": {
|
"email": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"smtp_server": "smtp.gmail.com",
|
"smtp_server": "smtp.gmail.com",
|
||||||
"smtp_port": 587,
|
"smtp_port": 587,
|
||||||
"use_tls": true,
|
"use_tls": true,
|
||||||
"username": "you@gmail.com",
|
"username": "you@gmail.com",
|
||||||
"password": "APP_PASSWORD", // Gmail App Password, no spaces
|
"password": "APP_PASSWORD", // Gmail App Password, no spaces
|
||||||
"from_addr": "you@gmail.com",
|
"from_addr": "you@gmail.com",
|
||||||
"to_addr": "alerts@you.com",
|
"to_addr": "alerts@you.com",
|
||||||
"subject_prefix": "[ICEYOU Alert]"
|
"subject_prefix": "[ICEYOU Alert]"
|
||||||
},
|
},
|
||||||
|
|
||||||
"lock_workstation": true, // OS lock after max_unlock_attempts password fails
|
"lock_workstation": true, // OS lock after max_unlock_attempts password fails
|
||||||
"device_monitoring": true, // Watch USB drives
|
"device_monitoring": true, // Watch USB drives
|
||||||
"white_screen_on_away": true, // Show the whiteout when away
|
"white_screen_on_away": true, // Show the whiteout when away
|
||||||
"unlock_password": "iceyou2026!", // Your secret phrase
|
"unlock_password": "iceyou2026!", // Your secret phrase
|
||||||
"max_unlock_attempts": 3, // Wrong passwords before OS lock
|
"max_unlock_attempts": 3, // Wrong passwords before OS lock
|
||||||
"block_escape_keys": true, // Install OS keyboard hook while locked
|
"block_escape_keys": true, // Install OS keyboard hook while locked
|
||||||
|
|
||||||
"camera_obscured_detection": {
|
"camera_obscured_detection": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"brightness_threshold": 25,
|
"brightness_threshold": 25,
|
||||||
"variance_threshold": 10,
|
"variance_threshold": 10,
|
||||||
"check_interval_seconds": 6
|
"check_interval_seconds": 6
|
||||||
},
|
},
|
||||||
|
|
||||||
"hotkeys": {
|
"hotkeys": {
|
||||||
"force_away": "<ctrl>+<alt>+l",
|
"force_away": "<ctrl>+<alt>+l",
|
||||||
"unlock": "<ctrl>+<alt>+u"
|
"unlock": "<ctrl>+<alt>+u"
|
||||||
},
|
},
|
||||||
|
|
||||||
"face_recognition_enabled": true,
|
"face_recognition_enabled": true,
|
||||||
"face_unlock": {
|
"face_unlock": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"confidence_threshold": 85.0, // Lower = stricter (LBPH distance)
|
"confidence_threshold": 85.0, // Lower = stricter (LBPH distance)
|
||||||
"auto_attempt": true,
|
"auto_attempt": true,
|
||||||
"attempt_interval_seconds": 4.0,
|
"attempt_interval_seconds": 4.0,
|
||||||
"frames_per_attempt": 4,
|
"frames_per_attempt": 4,
|
||||||
"allowed_labels": ["owner"] // null = accept any enrolled label
|
"allowed_labels": ["owner"] // null = accept any enrolled label
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
| Symptom | Fix |
|
| Symptom | Fix |
|
||||||
|---|---|
|
|---|---|
|
||||||
| No tray icon | Make sure `python main.py` is running; check `events.log` for startup errors. |
|
| No tray icon | Make sure `python main.py` is running; check `events.log` for startup errors. |
|
||||||
| Email alerts not arriving | Check Spam folder. Use **Send Test Email** in tray (or `python test_email.py`). Look for `email_failed` in `events.log`. |
|
| Email alerts not arriving | Check Spam folder. Use **Send Test Email** in tray (or `python test_email.py`). Look for `email_failed` in `events.log`. |
|
||||||
| Face unlock never matches | Status line shows `conf=<value>`. Either raise `confidence_threshold` in `config.json` or re-enroll with more samples / better lighting / same accessories you're wearing now. |
|
| Face unlock never matches | Status line shows `conf=<value>`. Either raise `confidence_threshold` in `config.json` or re-enroll with more samples / better lighting / same accessories you're wearing now. |
|
||||||
| Password field clears mid-typing | Already fixed — input while the whiteout is up is treated as challenge, not re-intrusion. Pull latest `monitor.py` + `white_screen.py`. |
|
| Password field clears mid-typing | Already fixed - input while the whiteout is up is treated as challenge, not re-intrusion. Pull latest `monitor.py` + `white_screen.py`. |
|
||||||
| Tk error `Tcl_AsyncDelete: async handler deleted by the wrong thread` | Already fixed — `WhiteScreen` uses a persistent Tk root on a dedicated thread. |
|
| Tk error `Tcl_AsyncDelete: async handler deleted by the wrong thread` | Already fixed - `WhiteScreen` uses a persistent Tk root on a dedicated thread. |
|
||||||
| Tk error `can't set fullscreen attribute… override-redirect flag is set` | Already fixed — `WhiteScreen` sizes to screen via `geometry()` instead of `-fullscreen`. |
|
| Tk error `can't set fullscreen attribute… override-redirect flag is set` | Already fixed - `WhiteScreen` sizes to screen via `geometry()` instead of `-fullscreen`. |
|
||||||
| `numpy<2` conflict with `opencv-contrib-python` | Use the recommended `.venv` virtualenv. |
|
| `numpy<2` conflict with `opencv-contrib-python` | Use the recommended `.venv` virtualenv. |
|
||||||
| Antivirus flags ICEYOU | Low-level keyboard hooks trigger heuristics. Whitelist the project folder. |
|
| Antivirus flags ICEYOU | Low-level keyboard hooks trigger heuristics. Whitelist the project folder. |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
ICEYOU/
|
ICEYOU/
|
||||||
├── main.py Tray app entrypoint
|
├── main.py Tray app entrypoint
|
||||||
├── face_enrollment.py Standalone face capture + LBPH training
|
├── face_enrollment.py Standalone face capture + LBPH training
|
||||||
├── test_email.py CLI SMTP sanity check
|
├── test_email.py CLI SMTP sanity check
|
||||||
├── config.json Runtime settings (gitignored)
|
├── config.json Runtime settings (gitignored)
|
||||||
├── config.example.json Template
|
├── config.example.json Template
|
||||||
├── events.log JSON-lines event audit trail
|
├── events.log JSON-lines event audit trail
|
||||||
├── snapshots/ All captured webcam photos
|
├── snapshots/ All captured webcam photos
|
||||||
├── motion_clips/ 5s-before + event + 5s-after AVI clips from the whiteout
|
├── motion_clips/ 5s-before + event + 5s-after AVI clips from the whiteout
|
||||||
├── faces/
|
├── faces/
|
||||||
│ ├── model.yml Trained LBPH model
|
│ ├── model.yml Trained LBPH model
|
||||||
│ ├── labels.json Label id → name map
|
│ ├── labels.json Label id -> name map
|
||||||
│ └── <label>/capture_NN.png Enrolled photos per identity
|
│ └── <label>/capture_NN.png Enrolled photos per identity
|
||||||
└── src/iceyou/
|
└── src/iceyou/
|
||||||
├── tray_app.py System tray + wiring
|
├── tray_app.py System tray + wiring
|
||||||
├── monitor.py Away state machine + intrusion trigger
|
├── monitor.py Away state machine + intrusion trigger
|
||||||
├── white_screen.py Persistent Tk fullscreen lockout + unlock UI
|
├── white_screen.py Persistent Tk fullscreen lockout + unlock UI
|
||||||
├── face_recognizer.py LBPH recognizer with multi-crop verification
|
├── face_recognizer.py LBPH recognizer with multi-crop verification
|
||||||
├── motion_recorder.py Rolling-buffer motion clips while locked
|
├── motion_recorder.py Rolling-buffer motion clips while locked
|
||||||
├── keyboard_block.py Low-level Windows keyboard hook
|
├── keyboard_block.py Low-level Windows keyboard hook
|
||||||
├── camera.py Webcam capture, snapshots, obscured detection
|
├── camera.py Webcam capture, snapshots, obscured detection
|
||||||
├── input_hooks.py pynput keyboard + mouse global hooks
|
├── input_hooks.py pynput keyboard + mouse global hooks
|
||||||
├── device_monitor.py Drive insertion/removal poller
|
├── device_monitor.py Drive insertion/removal poller
|
||||||
├── actions.py Email alerts (intrusion + unlock attempts)
|
├── actions.py Email alerts (intrusion + unlock attempts)
|
||||||
├── utils.py Win32 idle time, lock workstation, timestamps
|
├── utils.py Win32 idle time, lock workstation, timestamps
|
||||||
├── startup.py HKCU Run registry add/remove
|
├── startup.py HKCU Run registry add/remove
|
||||||
└── config.py Deep-merged config loader with dotted-key get
|
└── config.py Deep-merged config loader with dotted-key get
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Privacy & Use
|
## Privacy & Use
|
||||||
|
|
||||||
ICEYOU accesses your camera, keyboard, mouse, and writes intruder photos + entered text to local disk and email. It is intended **strictly for protecting your own machine**. Do not use it for unauthorized surveillance of others.
|
ICEYOU accesses your camera, keyboard, mouse, and writes intruder photos + entered text to local disk and email. It is intended **strictly for protecting your own machine**. Do not use it for unauthorized surveillance of others.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
- Encrypted at-rest storage of snapshots and log
|
- Encrypted at-rest storage of snapshots and log
|
||||||
- Optional cloud upload of evidence
|
- Optional cloud upload of evidence
|
||||||
- Windows service mode (run without an interactive session)
|
- Windows service mode (run without an interactive session)
|
||||||
- Web dashboard for remote review
|
- Web dashboard for remote review
|
||||||
- DNN-based face recognition (FaceNet / dlib) for higher accuracy than LBPH
|
- DNN-based face recognition (FaceNet / dlib) for higher accuracy than LBPH
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user