ntfsdump 3.1.0__tar.gz → 3.2.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.
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/.github/workflows/publish-binary-pypi.yaml +2 -2
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/.github/workflows/publish-release.yaml +45 -20
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/.github/workflows/test.yaml +5 -4
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/.gitignore +8 -1
- ntfsdump-3.2.0/PKG-INFO +283 -0
- ntfsdump-3.2.0/README.md +267 -0
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/pyproject.toml +9 -9
- ntfsdump-3.2.0/src/ntfsdump/__about__.py +2 -0
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/src/ntfsdump/__main__.py +3 -1
- ntfsdump-3.2.0/src/ntfsdump/cli.py +271 -0
- ntfsdump-3.2.0/src/ntfsdump/core.py +41 -0
- ntfsdump-3.2.0/src/ntfsdump/errors.py +3 -0
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/src/ntfsdump/formats/__init__.py +14 -4
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/src/ntfsdump/formats/base.py +12 -2
- ntfsdump-3.2.0/src/ntfsdump/formats/detect.py +63 -0
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/src/ntfsdump/formats/e01.py +1 -1
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/src/ntfsdump/formats/vhd.py +1 -1
- ntfsdump-3.2.0/src/ntfsdump/formats/vmdk.py +100 -0
- ntfsdump-3.2.0/src/ntfsdump/image.py +116 -0
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/src/ntfsdump/logger.py +42 -16
- ntfsdump-3.2.0/src/ntfsdump/sources/__init__.py +9 -0
- ntfsdump-3.2.0/src/ntfsdump/sources/resolver.py +135 -0
- ntfsdump-3.2.0/src/ntfsdump/vmware/__init__.py +26 -0
- ntfsdump-3.2.0/src/ntfsdump/vmware/metadata.py +354 -0
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/tests/ntfsdump/conftest.py +11 -0
- ntfsdump-3.2.0/tests/ntfsdump/fixtures/vmware/SingleVM/SingleVM.vmx +15 -0
- ntfsdump-3.2.0/tests/ntfsdump/fixtures/vmware/WindowsVM/WindowsVM.vmsd +38 -0
- ntfsdump-3.2.0/tests/ntfsdump/fixtures/vmware/WindowsVM/WindowsVM.vmx +21 -0
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/tests/ntfsdump/test__init__.py +1 -1
- ntfsdump-3.2.0/tests/ntfsdump/test_cli.py +160 -0
- ntfsdump-3.2.0/tests/ntfsdump/test_detect.py +69 -0
- ntfsdump-3.2.0/tests/ntfsdump/test_source.py +151 -0
- ntfsdump-3.2.0/tests/ntfsdump/test_vmdk_chain.py +129 -0
- ntfsdump-3.2.0/tests/ntfsdump/test_vmware.py +146 -0
- ntfsdump-3.2.0/uv.lock +527 -0
- ntfsdump-3.1.0/PKG-INFO +0 -172
- ntfsdump-3.1.0/README.md +0 -156
- ntfsdump-3.1.0/src/ntfsdump/__about__.py +0 -2
- ntfsdump-3.1.0/src/ntfsdump/cli.py +0 -89
- ntfsdump-3.1.0/src/ntfsdump/core.py +0 -29
- ntfsdump-3.1.0/src/ntfsdump/formats/vmdk.py +0 -14
- ntfsdump-3.1.0/src/ntfsdump/image.py +0 -64
- ntfsdump-3.1.0/uv.lock +0 -423
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/.devcontainer/Dockerfile +0 -0
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/.devcontainer/devcontainer.json +0 -0
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/.devcontainer/postCreateCommands.fish +0 -0
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/Dockerfile +0 -0
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/LICENSE +0 -0
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/docker-compose.yml +0 -0
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/src/ntfsdump/__init__.py +0 -0
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/src/ntfsdump/formats/raw.py +0 -0
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/src/ntfsdump/volume.py +0 -0
- {ntfsdump-3.1.0 → ntfsdump-3.2.0}/tests/ntfsdump/cache/.gitkeep +0 -0
|
@@ -9,9 +9,9 @@ jobs:
|
|
|
9
9
|
publish:
|
|
10
10
|
runs-on: ubuntu-latest
|
|
11
11
|
steps:
|
|
12
|
-
- uses: actions/checkout@
|
|
12
|
+
- uses: actions/checkout@v6
|
|
13
13
|
- name: Set up Python
|
|
14
|
-
uses: actions/setup-python@
|
|
14
|
+
uses: actions/setup-python@v6
|
|
15
15
|
with:
|
|
16
16
|
python-version: '3.13'
|
|
17
17
|
- name: Install dependencies
|
|
@@ -15,13 +15,13 @@ jobs:
|
|
|
15
15
|
python-version: ['3.13']
|
|
16
16
|
steps:
|
|
17
17
|
- name: checkout
|
|
18
|
-
uses: actions/checkout@
|
|
18
|
+
uses: actions/checkout@v6
|
|
19
19
|
|
|
20
20
|
- name: install python ${{ matrix.python-version }}
|
|
21
|
-
uses: actions/setup-python@
|
|
21
|
+
uses: actions/setup-python@v6
|
|
22
22
|
with:
|
|
23
23
|
python-version: ${{ matrix.python-version }}
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
- name: Install dependencies
|
|
26
26
|
run: |
|
|
27
27
|
pip install uv
|
|
@@ -30,17 +30,26 @@ jobs:
|
|
|
30
30
|
- name: run python
|
|
31
31
|
run: |
|
|
32
32
|
uv run ntfsdump -h
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
- name: build
|
|
35
35
|
run: |
|
|
36
36
|
uv run python -m nuitka --standalone --onefile --follow-imports --include-distribution-metadata=ntfsdump -o ntfsdump.exe --output-dir=dist --assume-yes-for-downloads src/ntfsdump/cli.py
|
|
37
37
|
|
|
38
|
-
|
|
39
38
|
- name: verify
|
|
40
39
|
run: |
|
|
41
40
|
dist/ntfsdump.exe -h
|
|
42
41
|
dist/ntfsdump.exe --version
|
|
43
|
-
|
|
42
|
+
|
|
43
|
+
- name: collect third-party licenses
|
|
44
|
+
run: |
|
|
45
|
+
mkdir -p dist/third-party-licenses
|
|
46
|
+
curl -fsSL -o dist/third-party-licenses/COPYING.LESSER-libewf.txt https://raw.githubusercontent.com/libyal/libewf/main/COPYING.LESSER
|
|
47
|
+
curl -fsSL -o dist/third-party-licenses/COPYING.LESSER-libvhdi.txt https://raw.githubusercontent.com/libyal/libvhdi/main/COPYING.LESSER
|
|
48
|
+
curl -fsSL -o dist/third-party-licenses/COPYING.LESSER-libvmdk.txt https://raw.githubusercontent.com/libyal/libvmdk/main/COPYING.LESSER
|
|
49
|
+
curl -fsSL -o dist/third-party-licenses/LICENSE-pytsk3-apache-2.0.txt https://raw.githubusercontent.com/py4n6/pytsk/master/LICENSE
|
|
50
|
+
cp LICENSE dist/third-party-licenses/LICENSE-ntfsdump-mit.txt
|
|
51
|
+
shell: bash
|
|
52
|
+
|
|
44
53
|
- name: create tag
|
|
45
54
|
id: create_tag
|
|
46
55
|
if: startsWith(github.ref, 'refs/heads/master')
|
|
@@ -53,17 +62,22 @@ jobs:
|
|
|
53
62
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
54
63
|
shell: bash
|
|
55
64
|
|
|
56
|
-
- name:
|
|
65
|
+
- name: package release zip
|
|
57
66
|
if: startsWith(github.ref, 'refs/heads/master')
|
|
58
|
-
run:
|
|
67
|
+
run: |
|
|
68
|
+
mkdir -p dist/stage
|
|
69
|
+
cp dist/ntfsdump.exe dist/stage/
|
|
70
|
+
cp -r dist/third-party-licenses dist/stage/
|
|
71
|
+
cd dist/stage
|
|
72
|
+
uv run python -m zipfile -c ../ntfsdump-windows-x64-v${{ steps.create_tag.outputs.version }}.zip ntfsdump.exe third-party-licenses/
|
|
59
73
|
shell: bash
|
|
60
74
|
|
|
61
75
|
- name: create release
|
|
62
|
-
uses: softprops/action-gh-release@
|
|
76
|
+
uses: softprops/action-gh-release@v2
|
|
63
77
|
if: startsWith(github.ref, 'refs/heads/master')
|
|
64
78
|
with:
|
|
65
79
|
tag_name: v${{ steps.create_tag.outputs.version }}
|
|
66
|
-
files: dist/ntfsdump-windows-x64-v${{ steps.create_tag.outputs.version }}.
|
|
80
|
+
files: dist/ntfsdump-windows-x64-v${{ steps.create_tag.outputs.version }}.zip
|
|
67
81
|
name: Release v${{ steps.create_tag.outputs.version }}
|
|
68
82
|
body: 'This release was automatically created by GitHub Actions.'
|
|
69
83
|
env:
|
|
@@ -77,14 +91,12 @@ jobs:
|
|
|
77
91
|
python-version: ['3.13']
|
|
78
92
|
steps:
|
|
79
93
|
- name: checkout
|
|
80
|
-
uses: actions/checkout@
|
|
94
|
+
uses: actions/checkout@v6
|
|
81
95
|
|
|
82
96
|
- name: install python ${{ matrix.python-version }}
|
|
83
|
-
uses: actions/setup-python@
|
|
97
|
+
uses: actions/setup-python@v6
|
|
84
98
|
with:
|
|
85
99
|
python-version: ${{ matrix.python-version }}
|
|
86
|
-
|
|
87
|
-
|
|
88
100
|
|
|
89
101
|
- name: Install dependencies
|
|
90
102
|
run: |
|
|
@@ -99,22 +111,35 @@ jobs:
|
|
|
99
111
|
- name: build
|
|
100
112
|
run: |
|
|
101
113
|
uv run python -m nuitka --standalone --onefile --follow-imports --include-distribution-metadata=ntfsdump -o ntfsdump --output-dir=dist --assume-yes-for-downloads src/ntfsdump/cli.py
|
|
102
|
-
|
|
114
|
+
|
|
103
115
|
- name: verify
|
|
104
116
|
run: |
|
|
105
117
|
dist/ntfsdump -h
|
|
106
118
|
dist/ntfsdump --version
|
|
107
119
|
|
|
108
|
-
- name:
|
|
120
|
+
- name: collect third-party licenses
|
|
121
|
+
run: |
|
|
122
|
+
mkdir -p dist/third-party-licenses
|
|
123
|
+
curl -fsSL -o dist/third-party-licenses/COPYING.LESSER-libewf.txt https://raw.githubusercontent.com/libyal/libewf/main/COPYING.LESSER
|
|
124
|
+
curl -fsSL -o dist/third-party-licenses/COPYING.LESSER-libvhdi.txt https://raw.githubusercontent.com/libyal/libvhdi/main/COPYING.LESSER
|
|
125
|
+
curl -fsSL -o dist/third-party-licenses/COPYING.LESSER-libvmdk.txt https://raw.githubusercontent.com/libyal/libvmdk/main/COPYING.LESSER
|
|
126
|
+
curl -fsSL -o dist/third-party-licenses/LICENSE-pytsk3-apache-2.0.txt https://raw.githubusercontent.com/py4n6/pytsk/master/LICENSE
|
|
127
|
+
cp LICENSE dist/third-party-licenses/LICENSE-ntfsdump-mit.txt
|
|
128
|
+
|
|
129
|
+
- name: package release zip
|
|
109
130
|
if: startsWith(github.ref, 'refs/heads/master')
|
|
110
|
-
run:
|
|
111
|
-
|
|
131
|
+
run: |
|
|
132
|
+
mkdir -p dist/stage
|
|
133
|
+
cp dist/ntfsdump dist/stage/
|
|
134
|
+
cp -r dist/third-party-licenses dist/stage/
|
|
135
|
+
cd dist/stage
|
|
136
|
+
uv run python -m zipfile -c ../ntfsdump-linux-x64-v${{ needs.build-windows.outputs.version }}.zip ntfsdump third-party-licenses/
|
|
112
137
|
|
|
113
138
|
- name: upload asset to release
|
|
114
139
|
if: startsWith(github.ref, 'refs/heads/master')
|
|
115
|
-
uses: softprops/action-gh-release@
|
|
140
|
+
uses: softprops/action-gh-release@v2
|
|
116
141
|
with:
|
|
117
142
|
tag_name: v${{ needs.build-windows.outputs.version }}
|
|
118
|
-
files: dist/ntfsdump-linux-x64-v${{ needs.build-windows.outputs.version }}
|
|
143
|
+
files: dist/ntfsdump-linux-x64-v${{ needs.build-windows.outputs.version }}.zip
|
|
119
144
|
env:
|
|
120
145
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -3,8 +3,9 @@ name: pytest
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
5
|
branches:
|
|
6
|
+
- master
|
|
6
7
|
- develop
|
|
7
|
-
|
|
8
|
+
pull_request:
|
|
8
9
|
|
|
9
10
|
jobs:
|
|
10
11
|
pytest:
|
|
@@ -12,13 +13,13 @@ jobs:
|
|
|
12
13
|
runs-on: ubuntu-latest
|
|
13
14
|
strategy:
|
|
14
15
|
matrix:
|
|
15
|
-
python-version: ['3.13']
|
|
16
|
+
python-version: ['3.13', '3.14']
|
|
16
17
|
steps:
|
|
17
18
|
- name: checkout
|
|
18
|
-
uses: actions/checkout@
|
|
19
|
+
uses: actions/checkout@v6
|
|
19
20
|
|
|
20
21
|
- name: install python ${{ matrix.python-version }}
|
|
21
|
-
uses: actions/setup-python@
|
|
22
|
+
uses: actions/setup-python@v6
|
|
22
23
|
with:
|
|
23
24
|
python-version: ${{ matrix.python-version }}
|
|
24
25
|
|
ntfsdump-3.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: ntfsdump
|
|
3
|
+
Version: 3.2.0
|
|
4
|
+
Summary: A command-line tool for efficiently extracting files, directories, and alternate data streams directly from NTFS image files.
|
|
5
|
+
Project-URL: Homepage, https://github.com/sumeshi/ntfsdump
|
|
6
|
+
Project-URL: Repository, https://github.com/sumeshi/ntfsdump
|
|
7
|
+
Author-email: sumeshi <sum3sh1@protonmail.com>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Python: >=3.13
|
|
11
|
+
Requires-Dist: libewf-python==20240506
|
|
12
|
+
Requires-Dist: libvhdi-python==20260901
|
|
13
|
+
Requires-Dist: libvmdk-python==20260714
|
|
14
|
+
Requires-Dist: pytsk3==20260715
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# ntfsdump
|
|
18
|
+
|
|
19
|
+
[](LICENSE)
|
|
20
|
+
[](https://pypi.org/project/ntfsdump/)
|
|
21
|
+
[](https://github.com/sumeshi/ntfsdump/blob/master/.github/workflows/test.yaml)
|
|
22
|
+
|
|
23
|
+

|
|
24
|
+
|
|
25
|
+
A command-line tool for efficiently extracting files, directories, and alternate data streams directly from NTFS image files.
|
|
26
|
+
|
|
27
|
+
## Overview
|
|
28
|
+
|
|
29
|
+
`ntfsdump` is a command-line tool and Python library for extracting files, directories, and alternate data streams from NTFS volumes in disk images without mounting them.
|
|
30
|
+
|
|
31
|
+
It supports common forensic image formats such as RAW, E01, VHD/VHDX, and VMDK through `pytsk3` and libraries from the `libyal` project.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
## Features
|
|
35
|
+
|
|
36
|
+
- Extract files directly from NTFS volumes in disk images
|
|
37
|
+
- Dump a single file, multiple files, or an entire directory recursively
|
|
38
|
+
- Extract alternate data streams (ADS)
|
|
39
|
+
- Reconstruct the original directory structure in the output directory
|
|
40
|
+
- Supports `RAW`, `E01`, `VHD`, `VHDX`, and `VMDK ` image formats
|
|
41
|
+
- Automatically detects the input image format by signature
|
|
42
|
+
- Accepts a VMware VM directory, VMX or VMSD directly, without converting images
|
|
43
|
+
- Lists and reads VMware snapshots (`--list-snapshots`, `--snapshot`)
|
|
44
|
+
- Selects a virtual disk when a VM has more than one (`--list-disks`, `--disk`)
|
|
45
|
+
- Reads split VMDK extents and VMDK snapshot/delta chains without merging them
|
|
46
|
+
- Read paths from standard input for integration with tools such as `ntfsfind`
|
|
47
|
+
- Use as a command-line tool or Python library
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# From PyPI
|
|
54
|
+
pip install ntfsdump
|
|
55
|
+
|
|
56
|
+
# From GitHub Releases (Precompiled Binaries)
|
|
57
|
+
chmod +x ./ntfsdump
|
|
58
|
+
./ntfsdump --help
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
## Supported Input
|
|
63
|
+
|
|
64
|
+
- Image formats: `RAW`, `E01`, `VHD`, `VHDX`, `VMDK` (auto-detected), plus VMware VM directories, VMX and VMSD
|
|
65
|
+
- File system: `NTFS`
|
|
66
|
+
- Partition tables: GPT and MBR are both supported
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
## Usage
|
|
70
|
+
|
|
71
|
+
### Command Line Interface
|
|
72
|
+
|
|
73
|
+
You can pass arguments directly to the CLI. The output path can be either a file path or a directory path.
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
ntfsdump [OPTIONS] SOURCE [PATH...]
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`SOURCE` may be an image file, a VMware VM directory, a VMX or a VMSD:
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
disk.raw
|
|
83
|
+
evidence.E01
|
|
84
|
+
disk.vhd
|
|
85
|
+
disk.vhdx
|
|
86
|
+
disk.vmdk
|
|
87
|
+
vm.vmsd
|
|
88
|
+
/path/to/vm/
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Options**:
|
|
92
|
+
- `--help`, `-h`: Show help message.
|
|
93
|
+
- `--version`, `-V`: Display program version.
|
|
94
|
+
- `--quiet`, `-q`: Suppress normal stdout output. Errors are still written to stderr.
|
|
95
|
+
- `--flat`: Extract all artifacts purely into a single folder without reconstructing directories.
|
|
96
|
+
- `--volume`, `-n`: Target specific NTFS volume number (default: auto-detects main OS volume).
|
|
97
|
+
- `--snapshot`, `-s`: Read the NTFS as it was at the given VMware snapshot. The ID is the snapshot UID shown by `--list-snapshots`. Without it, the VM's current state is read.
|
|
98
|
+
- `--disk`, `-d`: Read a specific VMware virtual disk by ID (default: auto-select when unique).
|
|
99
|
+
- `--list-snapshots`: List VMware snapshots found in the SOURCE and exit.
|
|
100
|
+
- `--list-disks`: List VMware virtual disks found in the SOURCE and exit.
|
|
101
|
+
- `--image-format`: Force the image format instead of auto-detection. Options: `raw`, `e01`, `vhd`, `vhdx`, `vmdk`.
|
|
102
|
+
- `--log [FILE]`: Enable logging. Optionally specify a log file path.
|
|
103
|
+
- `--output`, `-o`: Directory or file to save exported outputs.
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
#### Examples
|
|
107
|
+
|
|
108
|
+
Dump a single file (format is auto-detected):
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
ntfsdump -o ./dump /path/to/your/image.raw /$MFT
|
|
112
|
+
ntfsdump -o ./dump /path/to/your/evidence.E01 /Windows/System32/config/SYSTEM
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Dump an entire directory recursively:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
ntfsdump -o ./dump /path/to/your/image.raw /Windows/System32/winevt/Logs
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Force the format for a file without a recognizable signature:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
ntfsdump --image-format raw /path/to/your/evidence.bin /$MFT
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
#### VMware Snapshots (`--list-snapshots`, `-s/--snapshot`)
|
|
128
|
+
|
|
129
|
+
`ntfsdump` can read the NTFS volume **as it was at a specific VMware snapshot**, directly from the delta VMDK chain — without reverting the VM, cloning disks, or merging snapshots.
|
|
130
|
+
|
|
131
|
+
First, list the snapshots recorded in the VM's `VMSD` metadata:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
ntfsdump ./WindowsVM --list-snapshots
|
|
135
|
+
ID NAME CREATED PARENT
|
|
136
|
+
1 Initialized 2026-09-01 12:33:43 -
|
|
137
|
+
5 NetConnect 2026-09-02 02:25:08 1
|
|
138
|
+
6 PrepareTools 2026-09-10 17:46:35 5
|
|
139
|
+
7 SetConfigs 2026-09-25 00:51:39 5
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
- `ID` is VMware's own snapshot UID. Always take it from this listing — it is the only valid identifier.
|
|
143
|
+
- `PARENT` shows the snapshot lineage, so you can follow the history of the VM.
|
|
144
|
+
|
|
145
|
+
Then pass the ID with `-s` / `--snapshot` to read any point in time:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# Read the SYSTEM registry hive as it was at snapshot 5.
|
|
149
|
+
ntfsdump ./WindowsVM -s 5 /Windows/System32/config/SYSTEM
|
|
150
|
+
|
|
151
|
+
# Snapshot 5, second virtual disk (see disk selection below).
|
|
152
|
+
ntfsdump ./WindowsVM -s 5 -d 1 /Evidence
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Notes:
|
|
156
|
+
|
|
157
|
+
- Without `-s`, the VM's **current state** is read (which may itself already be a delta chain after taking a snapshot).
|
|
158
|
+
- Only snapshot **IDs** are accepted; selecting by display name is not supported.
|
|
159
|
+
- If the VM directory has no `VMSD` (no snapshot metadata), a plain `--list-snapshots` reports `No VMware snapshot metadata was found.` rather than pretending the VMDK chain is a snapshot list.
|
|
160
|
+
|
|
161
|
+
#### Virtual Disk Selection (`--list-disks`, `-d/--disk`)
|
|
162
|
+
|
|
163
|
+
For VMs with more than one virtual disk, list them first:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
ntfsdump ./WindowsVM --list-disks
|
|
167
|
+
ID NODE SIZE VMDK
|
|
168
|
+
0 nvme0:0 100 GiB Windows10_22H2(x64).vmdk
|
|
169
|
+
1 scsi0:1 500 GiB Data.vmdk
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Then select a disk with `-d` / `--disk`:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# Read the second virtual disk.
|
|
176
|
+
ntfsdump ./WindowsVM -d 1 /Evidence
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
- With a **single** disk, it is selected automatically.
|
|
180
|
+
- With **multiple** disks, `ntfsdump` refuses to guess and asks you to choose with `--list-disks` + `-d`.
|
|
181
|
+
|
|
182
|
+
#### Snapshot Delta VMDK Chains
|
|
183
|
+
|
|
184
|
+
Even a bare VMDK inside the VM directory is understood: parents are resolved automatically from the descriptors, so pointing at a delta file reads the whole chain (base + deltas) as one logical disk:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
ntfsdump ./WindowsVM/Windows-000003.vmdk /$MFT
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Using with [ntfsfind](https://github.com/sumeshi/ntfsfind) over standard input (pipe):
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
ntfsfind '.*\.evtx' ./image.raw | ntfsdump -o ./dump ./image.raw
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
*Note: Any absolute path (starting with `/` or `\`) passed over stdin via tools like `ntfsfind` will automatically be cleaned, and the folder hierarchy will be rebuilt faithfully inside your local output directory (`./dump/Windows/System32/winevt/Logs/System.evtx`).*
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
### Python Module
|
|
200
|
+
|
|
201
|
+
You can incorporate `ntfsdump` logic into your own scripts.
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
from ntfsdump import ntfsdump
|
|
205
|
+
|
|
206
|
+
# Image format is auto-detected. Pass image_format='raw' to force it.
|
|
207
|
+
ntfsdump(
|
|
208
|
+
source='./path/to/your/image.raw',
|
|
209
|
+
paths=['/Windows/System32/winevt/Logs'],
|
|
210
|
+
output='./dump',
|
|
211
|
+
volume=2,
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
# VMware VM directory, snapshot and disk selection.
|
|
215
|
+
ntfsdump(
|
|
216
|
+
source='./WindowsVM',
|
|
217
|
+
paths=['/Windows/System32/config/SYSTEM'],
|
|
218
|
+
output='./dump',
|
|
219
|
+
snapshot='3',
|
|
220
|
+
disk=1,
|
|
221
|
+
)
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
## Query Syntax
|
|
226
|
+
|
|
227
|
+
`ntfsdump` uses UNIX-like path separators (`/`) for queries. Depending on the image and backend behavior, path matching may be case-sensitive.
|
|
228
|
+
|
|
229
|
+
- **File**: `/$MFT` -> extracts `$MFT`
|
|
230
|
+
- **ADS**: `/$Extend/$UsnJrnl:$J` -> extracts the `$J` ADS file from `$UsnJrnl`.
|
|
231
|
+
- **Directory**: `/Windows/System32/winevt/Logs` -> extracts all event logs recursively.
|
|
232
|
+
- **Prefix Expansion**: `/Windows/Prefetch/.*` -> extracts all files located in the `Prefetch` directory.
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
## Logs
|
|
236
|
+
|
|
237
|
+
Logging is disabled by default and no log file is created. To record which files were successfully dumped or failed, enable it explicitly:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
# Auto-generated name in the current directory (e.g. ntfsdump_20260921_153000.log)
|
|
241
|
+
ntfsdump image.raw /$MFT --log
|
|
242
|
+
|
|
243
|
+
# Explicit log path
|
|
244
|
+
ntfsdump image.raw /$MFT --log ./case.log
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
## Contributing
|
|
249
|
+
|
|
250
|
+
We welcome bug reports, issues, and feature requests. Please submit them on the [GitHub repository](https://github.com/sumeshi/ntfsdump). :sushi: :sushi: :sushi:
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
## License
|
|
254
|
+
|
|
255
|
+
ntfsdump is released under the [MIT](LICENSE) License.
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
### Third-party licenses
|
|
259
|
+
|
|
260
|
+
The standalone binaries distributed via GitHub Releases bundle the following third-party libraries.
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
#### LGPL-3.0-or-later
|
|
264
|
+
|
|
265
|
+
The following libyal libraries are licensed under the [GNU Lesser General Public License v3.0 or later (LGPL-3.0-or-later)](https://www.gnu.org/licenses/lgpl-3.0.html).
|
|
266
|
+
You may obtain, modify, and rebuild them from their upstream sources in accordance with the LGPL.
|
|
267
|
+
|
|
268
|
+
- [libewf / libewf-python](https://github.com/libyal/libewf)
|
|
269
|
+
- Bundled version: [`libewf-python==20240506`](https://pypi.org/project/libewf-python/20240506/) (source: https://github.com/libyal/libewf/releases/tag/20240506)
|
|
270
|
+
- License text: https://github.com/libyal/libewf/blob/main/COPYING.LESSER
|
|
271
|
+
- [libvhdi / libvhdi-python](https://github.com/libyal/libvhdi)
|
|
272
|
+
- Bundled version: [`libvhdi-python==20260901`](https://pypi.org/project/libvhdi-python/20260901/) (source: https://github.com/libyal/libvhdi/releases/tag/20260901)
|
|
273
|
+
- License text: https://github.com/libyal/libvhdi/blob/main/COPYING.LESSER
|
|
274
|
+
- [libvmdk / libvmdk-python](https://github.com/libyal/libvmdk)
|
|
275
|
+
- Bundled version: [`libvmdk-python==20260714`](https://pypi.org/project/libvmdk-python/20260714/) (source: https://github.com/libyal/libvmdk/releases/tag/20260714)
|
|
276
|
+
- License text: https://github.com/libyal/libvmdk/blob/main/COPYING.LESSER
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
#### Apache-2.0
|
|
280
|
+
|
|
281
|
+
- [pytsk / pytsk3](https://github.com/py4n6/pytsk) — licensed under the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0).
|
|
282
|
+
- Bundled version: [`pytsk3==20260715`](https://pypi.org/project/pytsk3/20260715/)
|
|
283
|
+
- License text: https://github.com/py4n6/pytsk/blob/master/LICENSE
|