forensic-log-tracker 1.0.0__tar.gz
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.
- forensic_log_tracker-1.0.0/LICENSE +21 -0
- forensic_log_tracker-1.0.0/PKG-INFO +301 -0
- forensic_log_tracker-1.0.0/README.md +267 -0
- forensic_log_tracker-1.0.0/core/__init__.py +0 -0
- forensic_log_tracker-1.0.0/core/case_manager.py +11 -0
- forensic_log_tracker-1.0.0/core/executor.py +49 -0
- forensic_log_tracker-1.0.0/core/gpg_signer.py +17 -0
- forensic_log_tracker-1.0.0/core/hasher.py +16 -0
- forensic_log_tracker-1.0.0/core/legal_parser.py +518 -0
- forensic_log_tracker-1.0.0/core/legalizer.py +73 -0
- forensic_log_tracker-1.0.0/core/logger.py +43 -0
- forensic_log_tracker-1.0.0/forensic_log_tracker/__init__.py +1 -0
- forensic_log_tracker-1.0.0/forensic_log_tracker/cli.py +124 -0
- forensic_log_tracker-1.0.0/forensic_log_tracker/config/config.yaml +23 -0
- forensic_log_tracker-1.0.0/forensic_log_tracker/config/explanations.yaml +475 -0
- forensic_log_tracker-1.0.0/forensic_log_tracker/templates/legal.md.j2 +6 -0
- forensic_log_tracker-1.0.0/forensic_log_tracker.egg-info/PKG-INFO +301 -0
- forensic_log_tracker-1.0.0/forensic_log_tracker.egg-info/SOURCES.txt +36 -0
- forensic_log_tracker-1.0.0/forensic_log_tracker.egg-info/dependency_links.txt +1 -0
- forensic_log_tracker-1.0.0/forensic_log_tracker.egg-info/entry_points.txt +2 -0
- forensic_log_tracker-1.0.0/forensic_log_tracker.egg-info/requires.txt +19 -0
- forensic_log_tracker-1.0.0/forensic_log_tracker.egg-info/top_level.txt +3 -0
- forensic_log_tracker-1.0.0/pyproject.toml +56 -0
- forensic_log_tracker-1.0.0/setup.cfg +4 -0
- forensic_log_tracker-1.0.0/test/test_case_manager.py +25 -0
- forensic_log_tracker-1.0.0/test/test_commenter.py +56 -0
- forensic_log_tracker-1.0.0/test/test_executor.py +30 -0
- forensic_log_tracker-1.0.0/test/test_gpg_signer.py +27 -0
- forensic_log_tracker-1.0.0/test/test_hasher.py +32 -0
- forensic_log_tracker-1.0.0/test/test_legal_parser.py +45 -0
- forensic_log_tracker-1.0.0/test/test_legalizer.py +45 -0
- forensic_log_tracker-1.0.0/test/test_logger.py +55 -0
- forensic_log_tracker-1.0.0/utils/__init__.py +0 -0
- forensic_log_tracker-1.0.0/utils/commenter.py +45 -0
- forensic_log_tracker-1.0.0/utils/log.py +30 -0
- forensic_log_tracker-1.0.0/utils/pathing.py +68 -0
- forensic_log_tracker-1.0.0/utils/reporting.py +234 -0
- forensic_log_tracker-1.0.0/utils/shared_config.py +19 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 ahzek
|
|
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.
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: forensic-log-tracker
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: CLI tool for documenting, hashing, and signing forensic investigations
|
|
5
|
+
Author-email: Niklas Heringer <ping@niklas-heringer.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/mev0lent/forensic-log-tracker
|
|
8
|
+
Keywords: forensics,dfir,cli,digital-forensics,chain-of-custody
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Topic :: Security
|
|
12
|
+
Requires-Python: >=3.9
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: click>=8.1.8
|
|
16
|
+
Requires-Dist: colorama>=0.4.6
|
|
17
|
+
Requires-Dist: python-dotenv>=1.1.0
|
|
18
|
+
Requires-Dist: Jinja2>=3.1.6
|
|
19
|
+
Requires-Dist: MarkupSafe>=3.0.2
|
|
20
|
+
Requires-Dist: markdown-it-py>=3.0.0
|
|
21
|
+
Requires-Dist: mdurl>=0.1.2
|
|
22
|
+
Requires-Dist: PyYAML>=6.0.2
|
|
23
|
+
Requires-Dist: rich>=14.0.0
|
|
24
|
+
Requires-Dist: shellingham>=1.5.4
|
|
25
|
+
Requires-Dist: typer>=0.15.2
|
|
26
|
+
Requires-Dist: typing_extensions>=4.13.2
|
|
27
|
+
Requires-Dist: tzdata>=2025.2
|
|
28
|
+
Requires-Dist: Pygments>=2.19.1
|
|
29
|
+
Requires-Dist: path>=17.1.0
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest>=8.3.5; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-cov>=5.0.0; extra == "dev"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# Forensic Log Tracker
|
|
36
|
+
|
|
37
|
+
A modular CLI tool for digital forensic professionals and students. Designed to execute, document, and cryptographically sign forensic commands during investigations — producing structured, auditable evidence records.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## What it does
|
|
42
|
+
|
|
43
|
+
When you run a command through `flt`, it:
|
|
44
|
+
|
|
45
|
+
- Executes the command via the system shell (bash or PowerShell)
|
|
46
|
+
- Logs the output, truncated to a configurable preview
|
|
47
|
+
- Attaches a formal legal explanation for the command (German, from `explanations.yaml`)
|
|
48
|
+
- Hashes the output with SHA256 for integrity verification
|
|
49
|
+
- Optionally signs the log file with your GPG key
|
|
50
|
+
- Organizes everything under a named case folder
|
|
51
|
+
|
|
52
|
+
All evidence is written as plain Markdown `.log` files alongside a `.meta.json` sidecar. Reports are generated as a single `case_report.md` per case.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Requirements
|
|
57
|
+
|
|
58
|
+
- Python 3.9+
|
|
59
|
+
- GPG (GNU Privacy Guard)
|
|
60
|
+
- Linux (tested on Kali) or Windows
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Installation
|
|
65
|
+
|
|
66
|
+
### Linux
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
git clone https://github.com/mev0lent/forensic-log-tracker.git
|
|
70
|
+
cd forensic-log-tracker
|
|
71
|
+
chmod +x setup.sh
|
|
72
|
+
./setup.sh
|
|
73
|
+
source ~/.bashrc # or ~/.zshrc
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The setup script:
|
|
77
|
+
- Creates a virtual environment at `forensic-log-venv/`
|
|
78
|
+
- Installs all dependencies from `pyproject.toml`
|
|
79
|
+
- Registers the `flt` alias in your shell profile
|
|
80
|
+
- Prompts you to generate a GPG key if none exists
|
|
81
|
+
|
|
82
|
+
After setup, activate the environment before use:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
source forensic-log-venv/bin/activate
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Windows
|
|
89
|
+
|
|
90
|
+
```powershell
|
|
91
|
+
git clone https://github.com/mev0lent/forensic-log-tracker.git
|
|
92
|
+
cd forensic-log-tracker
|
|
93
|
+
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
|
|
94
|
+
.\setup.ps1
|
|
95
|
+
. $PROFILE
|
|
96
|
+
.\forensic-log-venv\Scripts\Activate.ps1
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Alternative (requirements.txt)
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
python3 -m venv alt-env
|
|
103
|
+
source alt-env/bin/activate
|
|
104
|
+
pip install -r requirements.txt
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Configuration
|
|
110
|
+
|
|
111
|
+
Edit `config/config.yaml` before first use:
|
|
112
|
+
|
|
113
|
+
```yaml
|
|
114
|
+
project:
|
|
115
|
+
analyst: "Your Name"
|
|
116
|
+
timezone: "Europe/Berlin" # Any IANA timezone string
|
|
117
|
+
|
|
118
|
+
output:
|
|
119
|
+
preview_lines: 20 # Lines shown in log preview
|
|
120
|
+
hash_algorithm: "sha256"
|
|
121
|
+
comment_type: "Comment" # "Comment" or "Callout" (Obsidian-style)
|
|
122
|
+
|
|
123
|
+
gpg:
|
|
124
|
+
enabled: true
|
|
125
|
+
auto_verify: true
|
|
126
|
+
default_key: "" # Optional: GPG key fingerprint
|
|
127
|
+
|
|
128
|
+
logging:
|
|
129
|
+
level: INFO # DEBUG, INFO, WARNING, ERROR, CRITICAL
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
To add or extend tool explanations, edit `config/explanations.yaml`. Each entry maps a command (and optional flags) to a formal explanation used in log output and reports.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Usage
|
|
137
|
+
|
|
138
|
+
### Create a case
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
flt new-case case001 --description "Investigating suspicious USB device"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Creates `logs/case001/` and writes a `description.txt`.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### Run a forensic command
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
flt run "strings /bin/ls" --case case001
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Produces:
|
|
155
|
+
- `logs/case001/<timestamp>_command.log` — Markdown log with output preview, explanation, and hash
|
|
156
|
+
- `logs/case001/<timestamp>_command.meta.json` — structured metadata (command, hash, timestamp)
|
|
157
|
+
- `logs/case001/<timestamp>_command.log.sig` — GPG detached signature (if enabled)
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
### Dry-run mode
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
flt run "fdisk -l /dev/sdb" --case case001 --dry-run
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Logs the command with its explanation and timestamp but does not execute it. Useful for documenting intended actions before touching evidence.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
### Add a comment
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
flt comment --case case001 --text "Drive was write-protected before imaging."
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Creates a `_comment.log` file with the analyst name and timestamp. Signed with GPG if enabled.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
### List all cases
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
flt list-cases
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
### View case description
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
flt case-info --case case001
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### Analyze a case
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
flt analyze --case case001
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Lists all log files and signatures present in the case folder.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
### Generate a report
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
flt report --case case001
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Writes `logs/case001/case001_report.md` containing:
|
|
214
|
+
- Case description
|
|
215
|
+
- Chronological timeline of all commands and comments
|
|
216
|
+
- Output excerpts, SHA256 hashes, legal context, and GPG signature status per entry
|
|
217
|
+
|
|
218
|
+
To skip GPG verification during report generation:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
flt report --case case001 --no-verify
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
### Verify output hashes
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
flt verify-output --case case001
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Recomputes the SHA256 hash of each log's output block and compares it against the stored value. Reports OK or Mismatch per file.
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
### Verify a signature manually
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
gpg --verify logs/case001/<logfile>.log.sig
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Testing
|
|
245
|
+
|
|
246
|
+
Tests run inside Docker to ensure a clean, isolated environment.
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
# Build and run tests separately
|
|
250
|
+
make build
|
|
251
|
+
make test
|
|
252
|
+
|
|
253
|
+
# Build and run in one step
|
|
254
|
+
make run_test
|
|
255
|
+
|
|
256
|
+
# Remove leftover Docker images
|
|
257
|
+
make clean
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## File structure
|
|
263
|
+
|
|
264
|
+
```
|
|
265
|
+
forensic-log-tracker/
|
|
266
|
+
├── core/ # Execution, logging, hashing, signing, legal explanations
|
|
267
|
+
├── utils/ # Config loading, path resolution, reporting, comments
|
|
268
|
+
├── config/
|
|
269
|
+
│ ├── config.yaml # Runtime configuration
|
|
270
|
+
│ └── explanations.yaml # Tool explanation database
|
|
271
|
+
├── templates/ # Jinja2 template for legal explanation rendering
|
|
272
|
+
├── forensic_log_tracker/
|
|
273
|
+
│ └── cli.py # CLI entry point
|
|
274
|
+
├── test/ # pytest test suite
|
|
275
|
+
├── setup.sh # Linux setup script
|
|
276
|
+
├── setup.ps1 # Windows setup script
|
|
277
|
+
└── Makefile # Docker test targets
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Logs are written to `logs/<case-id>/` and are excluded from version control by default.
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## .gitignore
|
|
285
|
+
|
|
286
|
+
Make sure your `.gitignore` includes the following to avoid committing evidence or keys:
|
|
287
|
+
|
|
288
|
+
```
|
|
289
|
+
logs/
|
|
290
|
+
*.sig
|
|
291
|
+
*.log
|
|
292
|
+
*.meta.json
|
|
293
|
+
forensic-log-venv/
|
|
294
|
+
__pycache__/
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## License
|
|
300
|
+
|
|
301
|
+
MIT — free to use, modify, and extend.
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# Forensic Log Tracker
|
|
2
|
+
|
|
3
|
+
A modular CLI tool for digital forensic professionals and students. Designed to execute, document, and cryptographically sign forensic commands during investigations — producing structured, auditable evidence records.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## What it does
|
|
8
|
+
|
|
9
|
+
When you run a command through `flt`, it:
|
|
10
|
+
|
|
11
|
+
- Executes the command via the system shell (bash or PowerShell)
|
|
12
|
+
- Logs the output, truncated to a configurable preview
|
|
13
|
+
- Attaches a formal legal explanation for the command (German, from `explanations.yaml`)
|
|
14
|
+
- Hashes the output with SHA256 for integrity verification
|
|
15
|
+
- Optionally signs the log file with your GPG key
|
|
16
|
+
- Organizes everything under a named case folder
|
|
17
|
+
|
|
18
|
+
All evidence is written as plain Markdown `.log` files alongside a `.meta.json` sidecar. Reports are generated as a single `case_report.md` per case.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Requirements
|
|
23
|
+
|
|
24
|
+
- Python 3.9+
|
|
25
|
+
- GPG (GNU Privacy Guard)
|
|
26
|
+
- Linux (tested on Kali) or Windows
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
### Linux
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
git clone https://github.com/mev0lent/forensic-log-tracker.git
|
|
36
|
+
cd forensic-log-tracker
|
|
37
|
+
chmod +x setup.sh
|
|
38
|
+
./setup.sh
|
|
39
|
+
source ~/.bashrc # or ~/.zshrc
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The setup script:
|
|
43
|
+
- Creates a virtual environment at `forensic-log-venv/`
|
|
44
|
+
- Installs all dependencies from `pyproject.toml`
|
|
45
|
+
- Registers the `flt` alias in your shell profile
|
|
46
|
+
- Prompts you to generate a GPG key if none exists
|
|
47
|
+
|
|
48
|
+
After setup, activate the environment before use:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
source forensic-log-venv/bin/activate
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Windows
|
|
55
|
+
|
|
56
|
+
```powershell
|
|
57
|
+
git clone https://github.com/mev0lent/forensic-log-tracker.git
|
|
58
|
+
cd forensic-log-tracker
|
|
59
|
+
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
|
|
60
|
+
.\setup.ps1
|
|
61
|
+
. $PROFILE
|
|
62
|
+
.\forensic-log-venv\Scripts\Activate.ps1
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Alternative (requirements.txt)
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
python3 -m venv alt-env
|
|
69
|
+
source alt-env/bin/activate
|
|
70
|
+
pip install -r requirements.txt
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Configuration
|
|
76
|
+
|
|
77
|
+
Edit `config/config.yaml` before first use:
|
|
78
|
+
|
|
79
|
+
```yaml
|
|
80
|
+
project:
|
|
81
|
+
analyst: "Your Name"
|
|
82
|
+
timezone: "Europe/Berlin" # Any IANA timezone string
|
|
83
|
+
|
|
84
|
+
output:
|
|
85
|
+
preview_lines: 20 # Lines shown in log preview
|
|
86
|
+
hash_algorithm: "sha256"
|
|
87
|
+
comment_type: "Comment" # "Comment" or "Callout" (Obsidian-style)
|
|
88
|
+
|
|
89
|
+
gpg:
|
|
90
|
+
enabled: true
|
|
91
|
+
auto_verify: true
|
|
92
|
+
default_key: "" # Optional: GPG key fingerprint
|
|
93
|
+
|
|
94
|
+
logging:
|
|
95
|
+
level: INFO # DEBUG, INFO, WARNING, ERROR, CRITICAL
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
To add or extend tool explanations, edit `config/explanations.yaml`. Each entry maps a command (and optional flags) to a formal explanation used in log output and reports.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Usage
|
|
103
|
+
|
|
104
|
+
### Create a case
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
flt new-case case001 --description "Investigating suspicious USB device"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Creates `logs/case001/` and writes a `description.txt`.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### Run a forensic command
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
flt run "strings /bin/ls" --case case001
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Produces:
|
|
121
|
+
- `logs/case001/<timestamp>_command.log` — Markdown log with output preview, explanation, and hash
|
|
122
|
+
- `logs/case001/<timestamp>_command.meta.json` — structured metadata (command, hash, timestamp)
|
|
123
|
+
- `logs/case001/<timestamp>_command.log.sig` — GPG detached signature (if enabled)
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### Dry-run mode
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
flt run "fdisk -l /dev/sdb" --case case001 --dry-run
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Logs the command with its explanation and timestamp but does not execute it. Useful for documenting intended actions before touching evidence.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
### Add a comment
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
flt comment --case case001 --text "Drive was write-protected before imaging."
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Creates a `_comment.log` file with the analyst name and timestamp. Signed with GPG if enabled.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
### List all cases
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
flt list-cases
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
### View case description
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
flt case-info --case case001
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
### Analyze a case
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
flt analyze --case case001
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Lists all log files and signatures present in the case folder.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
### Generate a report
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
flt report --case case001
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Writes `logs/case001/case001_report.md` containing:
|
|
180
|
+
- Case description
|
|
181
|
+
- Chronological timeline of all commands and comments
|
|
182
|
+
- Output excerpts, SHA256 hashes, legal context, and GPG signature status per entry
|
|
183
|
+
|
|
184
|
+
To skip GPG verification during report generation:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
flt report --case case001 --no-verify
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
### Verify output hashes
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
flt verify-output --case case001
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Recomputes the SHA256 hash of each log's output block and compares it against the stored value. Reports OK or Mismatch per file.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
### Verify a signature manually
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
gpg --verify logs/case001/<logfile>.log.sig
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Testing
|
|
211
|
+
|
|
212
|
+
Tests run inside Docker to ensure a clean, isolated environment.
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# Build and run tests separately
|
|
216
|
+
make build
|
|
217
|
+
make test
|
|
218
|
+
|
|
219
|
+
# Build and run in one step
|
|
220
|
+
make run_test
|
|
221
|
+
|
|
222
|
+
# Remove leftover Docker images
|
|
223
|
+
make clean
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## File structure
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
forensic-log-tracker/
|
|
232
|
+
├── core/ # Execution, logging, hashing, signing, legal explanations
|
|
233
|
+
├── utils/ # Config loading, path resolution, reporting, comments
|
|
234
|
+
├── config/
|
|
235
|
+
│ ├── config.yaml # Runtime configuration
|
|
236
|
+
│ └── explanations.yaml # Tool explanation database
|
|
237
|
+
├── templates/ # Jinja2 template for legal explanation rendering
|
|
238
|
+
├── forensic_log_tracker/
|
|
239
|
+
│ └── cli.py # CLI entry point
|
|
240
|
+
├── test/ # pytest test suite
|
|
241
|
+
├── setup.sh # Linux setup script
|
|
242
|
+
├── setup.ps1 # Windows setup script
|
|
243
|
+
└── Makefile # Docker test targets
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Logs are written to `logs/<case-id>/` and are excluded from version control by default.
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## .gitignore
|
|
251
|
+
|
|
252
|
+
Make sure your `.gitignore` includes the following to avoid committing evidence or keys:
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
logs/
|
|
256
|
+
*.sig
|
|
257
|
+
*.log
|
|
258
|
+
*.meta.json
|
|
259
|
+
forensic-log-venv/
|
|
260
|
+
__pycache__/
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## License
|
|
266
|
+
|
|
267
|
+
MIT — free to use, modify, and extend.
|
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from utils.pathing import get_case_log_path
|
|
2
|
+
from utils.log import logger
|
|
3
|
+
|
|
4
|
+
def create_case_folder(case: str, description: str):
|
|
5
|
+
base_path = get_case_log_path(case, create=True)
|
|
6
|
+
base_path.mkdir(parents=True, exist_ok=True)
|
|
7
|
+
desc_file = base_path / "description.txt"
|
|
8
|
+
|
|
9
|
+
with desc_file.open("w", encoding="utf-8") as f:
|
|
10
|
+
f.write(f"Case-ID: {case}\nDescription: {description}\n")
|
|
11
|
+
logger.info(f"New case created: {base_path}")
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import platform
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from core.hasher import compute_hash
|
|
6
|
+
from core.logger import write_log
|
|
7
|
+
from core.legalizer import get_legal_explanation
|
|
8
|
+
from utils.log import logger
|
|
9
|
+
from utils.shared_config import load_config
|
|
10
|
+
from utils.pathing import get_case_log_path
|
|
11
|
+
|
|
12
|
+
config = load_config()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def execute_command(cmd: str, case: str, dry_run: bool = False):
|
|
16
|
+
timestamp = datetime.now(config["TIMEZONE"]).isoformat()
|
|
17
|
+
case_dir = get_case_log_path(case, create=False)
|
|
18
|
+
|
|
19
|
+
logger.info(f"Executing command: {cmd}")
|
|
20
|
+
|
|
21
|
+
if dry_run:
|
|
22
|
+
output = "[!] DRY RUN: Command not executed."
|
|
23
|
+
else:
|
|
24
|
+
try:
|
|
25
|
+
if platform.system() == "Windows":
|
|
26
|
+
result = subprocess.run(
|
|
27
|
+
["powershell", "-Command", cmd],
|
|
28
|
+
capture_output=True,
|
|
29
|
+
text=True,
|
|
30
|
+
check=True
|
|
31
|
+
)
|
|
32
|
+
else:
|
|
33
|
+
result = subprocess.run(
|
|
34
|
+
["bash", "-c", cmd],
|
|
35
|
+
capture_output=True,
|
|
36
|
+
text=True,
|
|
37
|
+
check=True
|
|
38
|
+
)
|
|
39
|
+
output = f"[STDOUT]\n{result.stdout}\n[STDERR]\n{result.stderr}"
|
|
40
|
+
except subprocess.CalledProcessError as e:
|
|
41
|
+
output = f"[!] Command failed:\n{e.stderr}"
|
|
42
|
+
|
|
43
|
+
explanation = get_legal_explanation(" ".join(cmd.split()[:4]))
|
|
44
|
+
preview_lines = config.get("output", {}).get("preview_lines", 20)
|
|
45
|
+
hash_algo = config.get("output", {}).get("hash_algorithm", "sha256")
|
|
46
|
+
output_hash = compute_hash(output, hash_algo)
|
|
47
|
+
|
|
48
|
+
logfile = write_log(case_dir, cmd, output, explanation, timestamp, preview_lines, dry_run, output_hash)
|
|
49
|
+
return logfile, output
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from utils.log import logger
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def sign_file(log_path: Path) -> bool:
|
|
7
|
+
sig_path = log_path.with_suffix(log_path.suffix + ".sig")
|
|
8
|
+
try:
|
|
9
|
+
subprocess.run(
|
|
10
|
+
["gpg", "--batch", "--yes", "--output", str(sig_path), "--detach-sign", str(log_path)],
|
|
11
|
+
check=True
|
|
12
|
+
)
|
|
13
|
+
logger.info(f"Signed logfile: {sig_path.name}")
|
|
14
|
+
return True
|
|
15
|
+
except subprocess.CalledProcessError:
|
|
16
|
+
logger.warning("GPG signature failed – is a key configured?")
|
|
17
|
+
return False
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# core/hasher.py# core/hasher.py
|
|
2
|
+
import hashlib
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def compute_hash(data: str, algorithm: str = "sha256") -> str:
|
|
6
|
+
"""
|
|
7
|
+
Compute a hash for the given string using the specified algorithm.
|
|
8
|
+
|
|
9
|
+
Supported: sha256, md5, sha1, sha512, etc.
|
|
10
|
+
"""
|
|
11
|
+
try:
|
|
12
|
+
hasher = hashlib.new(algorithm)
|
|
13
|
+
hasher.update(data.encode("utf-8"))
|
|
14
|
+
return hasher.hexdigest()
|
|
15
|
+
except ValueError as e:
|
|
16
|
+
raise ValueError(f"[!] Unsupported hashing algorithm: {algorithm}") from e
|