memlapse 0.1.1__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.
Files changed (77) hide show
  1. memlapse-0.1.1/CHANGELOG.md +59 -0
  2. memlapse-0.1.1/LICENSE +21 -0
  3. memlapse-0.1.1/MANIFEST.in +7 -0
  4. memlapse-0.1.1/PKG-INFO +154 -0
  5. memlapse-0.1.1/README.md +125 -0
  6. memlapse-0.1.1/memlapse/__init__.py +8 -0
  7. memlapse-0.1.1/memlapse/__main__.py +8 -0
  8. memlapse-0.1.1/memlapse/analytics.py +633 -0
  9. memlapse-0.1.1/memlapse/app.py +44 -0
  10. memlapse-0.1.1/memlapse/collectors/__init__.py +5 -0
  11. memlapse-0.1.1/memlapse/collectors/base.py +95 -0
  12. memlapse-0.1.1/memlapse/collectors/process.py +57 -0
  13. memlapse-0.1.1/memlapse/collectors/region.py +157 -0
  14. memlapse-0.1.1/memlapse/collectors/system.py +34 -0
  15. memlapse-0.1.1/memlapse/model/__init__.py +4 -0
  16. memlapse-0.1.1/memlapse/model/process.py +36 -0
  17. memlapse-0.1.1/memlapse/model/region.py +97 -0
  18. memlapse-0.1.1/memlapse/model/system.py +32 -0
  19. memlapse-0.1.1/memlapse/services/__init__.py +4 -0
  20. memlapse-0.1.1/memlapse/services/playback.py +516 -0
  21. memlapse-0.1.1/memlapse/services/recording.py +79 -0
  22. memlapse-0.1.1/memlapse/storage/__init__.py +3 -0
  23. memlapse-0.1.1/memlapse/storage/dao.py +449 -0
  24. memlapse-0.1.1/memlapse/storage/db.py +73 -0
  25. memlapse-0.1.1/memlapse/storage/schema.sql +118 -0
  26. memlapse-0.1.1/memlapse/ui/__init__.py +3 -0
  27. memlapse-0.1.1/memlapse/ui/dashboard.py +393 -0
  28. memlapse-0.1.1/memlapse/ui/gauges.py +113 -0
  29. memlapse-0.1.1/memlapse/ui/hexdump.py +16 -0
  30. memlapse-0.1.1/memlapse/ui/main_window.py +387 -0
  31. memlapse-0.1.1/memlapse/ui/process_view.py +175 -0
  32. memlapse-0.1.1/memlapse/ui/region_view.py +691 -0
  33. memlapse-0.1.1/memlapse/ui/theme.py +132 -0
  34. memlapse-0.1.1/memlapse/ui/timeline.py +181 -0
  35. memlapse-0.1.1/memlapse/win32/__init__.py +1 -0
  36. memlapse-0.1.1/memlapse/win32/memory.py +207 -0
  37. memlapse-0.1.1/memlapse/win32/privileges.py +136 -0
  38. memlapse-0.1.1/memlapse/win32/processes.py +142 -0
  39. memlapse-0.1.1/memlapse/win32/threads.py +146 -0
  40. memlapse-0.1.1/memlapse.egg-info/PKG-INFO +154 -0
  41. memlapse-0.1.1/memlapse.egg-info/SOURCES.txt +75 -0
  42. memlapse-0.1.1/memlapse.egg-info/dependency_links.txt +1 -0
  43. memlapse-0.1.1/memlapse.egg-info/entry_points.txt +2 -0
  44. memlapse-0.1.1/memlapse.egg-info/requires.txt +3 -0
  45. memlapse-0.1.1/memlapse.egg-info/top_level.txt +1 -0
  46. memlapse-0.1.1/pyproject.toml +89 -0
  47. memlapse-0.1.1/requirements-dev.txt +169 -0
  48. memlapse-0.1.1/requirements.txt +158 -0
  49. memlapse-0.1.1/setup.cfg +4 -0
  50. memlapse-0.1.1/tests/conftest.py +140 -0
  51. memlapse-0.1.1/tests/test_analytics.py +652 -0
  52. memlapse-0.1.1/tests/test_app.py +87 -0
  53. memlapse-0.1.1/tests/test_collector_base.py +86 -0
  54. memlapse-0.1.1/tests/test_dao.py +426 -0
  55. memlapse-0.1.1/tests/test_dashboard.py +250 -0
  56. memlapse-0.1.1/tests/test_gauges.py +64 -0
  57. memlapse-0.1.1/tests/test_hexdump.py +30 -0
  58. memlapse-0.1.1/tests/test_main_window.py +708 -0
  59. memlapse-0.1.1/tests/test_model.py +54 -0
  60. memlapse-0.1.1/tests/test_playback.py +1133 -0
  61. memlapse-0.1.1/tests/test_process_collector.py +91 -0
  62. memlapse-0.1.1/tests/test_process_view.py +161 -0
  63. memlapse-0.1.1/tests/test_recording_manager.py +181 -0
  64. memlapse-0.1.1/tests/test_region_sampler.py +265 -0
  65. memlapse-0.1.1/tests/test_region_view.py +1194 -0
  66. memlapse-0.1.1/tests/test_storage_db.py +153 -0
  67. memlapse-0.1.1/tests/test_system.py +49 -0
  68. memlapse-0.1.1/tests/test_system_collector.py +18 -0
  69. memlapse-0.1.1/tests/test_system_model.py +33 -0
  70. memlapse-0.1.1/tests/test_theme.py +30 -0
  71. memlapse-0.1.1/tests/test_timeline.py +179 -0
  72. memlapse-0.1.1/tests/test_version.py +72 -0
  73. memlapse-0.1.1/tests/test_win32_memory.py +167 -0
  74. memlapse-0.1.1/tests/test_win32_privileges.py +167 -0
  75. memlapse-0.1.1/tests/test_win32_processes.py +115 -0
  76. memlapse-0.1.1/tests/test_win32_threads.py +159 -0
  77. memlapse-0.1.1/tests/test_window_stats.py +20 -0
@@ -0,0 +1,59 @@
1
+ # Changelog
2
+
3
+ Notable changes to memlapse. Versions follow [semantic
4
+ versioning](https://semver.org/spec/v2.0.0.html): while the major version is 0
5
+ the interface may still change, and any such change is called out here under
6
+ **Changed** rather than assumed to be obvious from the version number.
7
+
8
+ What is versioned is the application: its command line, its window, and the
9
+ recordings it writes. The `memlapse` package is importable, but it is a
10
+ program rather than a library, and the names inside it may move without that
11
+ being a breaking change. A recording is the part with the longest life, so a
12
+ release after which an older recording no longer opens, or opens and scores
13
+ differently, says so here.
14
+
15
+ ## [0.1.1] - 2026-09-11
16
+
17
+ First release, and the first as a package: until now memlapse ran only from a
18
+ checkout with `python main.py`. It installs with `pip install memlapse` and
19
+ starts with `memlapse`, or `memlapse --elevate` to relaunch through UAC.
20
+ Windows only, Python 3.14.
21
+
22
+ The name is written in lower case throughout, in the window, the docs and the
23
+ repository, as it already was on PyPI. 0.1.0 below was tagged and never
24
+ published, which is why the first release is numbered 0.1.1.
25
+
26
+ ### Added
27
+
28
+ - A live process table, sortable and filterable, complete whether or not the
29
+ app is elevated.
30
+ - A memory map for the selected process, read with `VirtualQueryEx` and
31
+ refreshed once a second while it is on screen, with a hex preview of a
32
+ region's first bytes and a bounded save of a region's contents for a
33
+ disassembler or a YARA rule.
34
+ - Recording of a process's memory map over time to SQLite, and playback of a
35
+ recording on a timeline that can be scrubbed or played.
36
+ - A 0 to 100 injection score for each executable region, from unbacked
37
+ private or mapped executable memory, RWX protection, a PE header, a NOP
38
+ sled, high entropy, a thread starting in memory no image backs, and code
39
+ rewritten in place or unpacked from packed to code-like. Scores fall into
40
+ bands of low, review and likely injection, and the top band needs a signal
41
+ the memory map alone cannot give, so a private RWX page of the kind a JIT
42
+ compiler leaves stops at review.
43
+ - In playback, each region's rewrite history across the whole recording,
44
+ shown in its tooltip and as ticks on the timeline to scrub to. It is kept
45
+ beside the score rather than in it.
46
+ - A dashboard of system memory gauges, a scrolling usage timeline, a ranked
47
+ list of the processes using the most memory, and CSV and JSON export.
48
+
49
+ ## [0.1.0] - 2026-09-11
50
+
51
+ Tagged, never published. PyPI refused the upload because the repository was
52
+ then named `Memlapse` and the trusted publisher waiting for it named
53
+ `memlapse`, and a trusted publisher matches the repository name exactly. No
54
+ release was made anywhere, and the tag is left where it is so that the version
55
+ number is never used for anything else. 0.1.1 is the same program under the
56
+ lower case name.
57
+
58
+ [0.1.1]: https://github.com/mjaksn/memlapse/compare/v0.1.0...v0.1.1
59
+ [0.1.0]: https://github.com/mjaksn/memlapse/tree/v0.1.0
memlapse-0.1.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 mjaksn
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,7 @@
1
+ # What the sdist carries beyond the package. Left to itself setuptools takes
2
+ # tests/test_*.py and nothing else from tests/, so the source distribution
3
+ # would hold a suite without its conftest.py, and without the files
4
+ # test_version.py reads, that could not run. With these it can test itself.
5
+ graft tests
6
+ include CHANGELOG.md requirements.txt requirements-dev.txt
7
+ global-exclude *.py[cod]
@@ -0,0 +1,154 @@
1
+ Metadata-Version: 2.4
2
+ Name: memlapse
3
+ Version: 0.1.1
4
+ Summary: A Windows memory forensics tool that records a process's memory map over time, replays it, and scores each region for signs of code injection
5
+ Author: mjaksn
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/mjaksn/memlapse
8
+ Project-URL: Source, https://github.com/mjaksn/memlapse
9
+ Project-URL: Issues, https://github.com/mjaksn/memlapse/issues
10
+ Project-URL: Changelog, https://github.com/mjaksn/memlapse/blob/main/CHANGELOG.md
11
+ Keywords: memory-forensics,dfir,process-injection,malware-detection,windows,virtualqueryex,process-explorer,pyside6
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Win32 (MS Windows)
14
+ Classifier: Intended Audience :: Information Technology
15
+ Classifier: Intended Audience :: System Administrators
16
+ Classifier: Operating System :: Microsoft :: Windows
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Topic :: Security
21
+ Classifier: Topic :: System :: Monitoring
22
+ Requires-Python: >=3.14
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: PySide6<6.12,>=6.11.2
26
+ Requires-Dist: psutil<7.3,>=7.2.2
27
+ Requires-Dist: pyqtgraph<0.15,>=0.14.0
28
+ Dynamic: license-file
29
+
30
+ # memlapse
31
+
32
+ [![CI](https://github.com/mjaksn/memlapse/actions/workflows/ci.yml/badge.svg)](https://github.com/mjaksn/memlapse/actions/workflows/ci.yml)
33
+ [![Release](https://github.com/mjaksn/memlapse/actions/workflows/release.yml/badge.svg)](https://github.com/mjaksn/memlapse/actions/workflows/release.yml)
34
+ [![PyPI](https://img.shields.io/pypi/v/memlapse)](https://pypi.org/project/memlapse/)
35
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/mjaksn/memlapse/blob/main/LICENSE)
36
+
37
+ A Windows memory forensics tool, Process Explorer / System Informer-style
38
+ monitoring, that records a process's memory map over time and replays it.
39
+ Recording and playback of the memory activity of specific threads is the
40
+ planned next phase (Phase 5). See
41
+ [docs/ARCHITECTURE.md](https://github.com/mjaksn/memlapse/blob/main/docs/ARCHITECTURE.md)
42
+ for the design and
43
+ [docs/RESEARCH_NOTES.md](https://github.com/mjaksn/memlapse/blob/main/docs/RESEARCH_NOTES.md)
44
+ for the reference material behind the detection heuristics and the ideas
45
+ queued for later phases.
46
+
47
+ Antivirus checks are made mostly when a process starts, which leaves code
48
+ written into a process that is already running unscanned. Sampling a live
49
+ process on a timer covers exactly that gap, and recording the samples lets an
50
+ analyst scrub back to the moment the memory changed.
51
+
52
+ ## Status
53
+
54
+ - **Phase 1**, live process monitor (sortable, filterable table).
55
+ - **Phase 2**, memory-map view: select a process to see its VirtualQueryEx
56
+ region map, refreshed every second while on screen; click a region for a
57
+ hex preview of its bytes.
58
+ - **Phase 3**, record a process's memory map over time to SQLite.
59
+ - **Phase 4**, playback: scrub the recording with the timeline to replay how
60
+ its regions and footprint evolved.
61
+ - **Phase 6**, injection heuristics: each executable region gets a 0 to 100
62
+ score (unbacked private or mapped executable memory, RWX, PE header, NOP
63
+ sled, high entropy, and a thread whose start address lands in memory no
64
+ image backs) shown as a Score column with a heat tint and a reason tooltip
65
+ in the region view, banded low, review or likely injection. The top band
66
+ needs a signal the memory map alone cannot give, so a page that is merely
67
+ private and RWX, which is what a JIT compiler leaves behind, stops at
68
+ review. A fourth band, allowlisted, exists for a region whose every scoring
69
+ rule an entry has excused, but nothing in the app creates an entry yet, so
70
+ no run of it shows that band. The score also rises for a region whose code
71
+ was rewritten in place, and again if its entropy fell from packed to
72
+ code-like, the traces an injector leaves when it overwrites executable
73
+ memory that already exists and when a payload decrypts itself there. Both
74
+ work in playback, between consecutive samples, and in live mode, between
75
+ one refresh and the next. A replay then says more than a live watch can:
76
+ every score is still the answer for the sample being shown, but a region's
77
+ tooltip also says how many times the whole recording saw it rewritten and
78
+ when that last happened, and the timeline carries a tick at each of those
79
+ samples to scrub to. A region rewritten once, minutes ago, scores nothing
80
+ now and would otherwise pass for quiet.
81
+
82
+ - **Dashboard**, a vivid, near-live overview tab: system RAM/swap gauges, a
83
+ scrolling usage timeline, a heat-ranked top-process list (click to drill into
84
+ the monitor), leak/anomaly interpretation, and CSV/JSON export of the window.
85
+
86
+ Next: per-thread memory activity via ETW (Phase 5).
87
+
88
+ ## Use
89
+
90
+ 1. Open the **Forensic Monitor** tab (the app starts on the Dashboard; clicking
91
+ a process bar there also jumps to the monitor), then select a process (left)
92
+ to inspect its live memory map (right).
93
+ 2. Click **● Record** to sample it over time; **■ Stop** when done. Right-click
94
+ a region to save its bytes for a disassembler or a YARA rule.
95
+ 3. **Open Recording ▾** → pick a recording to enter playback, then drag the
96
+ timeline (or press ▶) to replay it. A tick on the timeline is a sample
97
+ where a region's executable bytes changed, which is where to scrub.
98
+ **Live** returns to real-time mode.
99
+
100
+ ## Install
101
+
102
+ Windows only, Python 3.14.
103
+
104
+ ```powershell
105
+ pip install memlapse
106
+
107
+ memlapse # live monitor
108
+ memlapse --elevate # relaunch elevated to read system and other users' processes
109
+ ```
110
+
111
+ `python -m memlapse` runs the same thing. Running elevated enables
112
+ `SeDebugPrivilege`, required to read most system and other-user processes.
113
+ The status bar reports the privilege state when the window opens.
114
+
115
+ The package accepts a range of versions of its three dependencies. For the
116
+ exact versions it is tested with, each checked against the hashes PyPI
117
+ publishes, install from a checkout instead:
118
+
119
+ ## Run from a checkout
120
+
121
+ ```powershell
122
+ python -m venv .venv
123
+ .venv\Scripts\Activate.ps1
124
+ pip install --require-hashes -r requirements.txt
125
+
126
+ python main.py # live monitor
127
+ python main.py --elevate # relaunch elevated
128
+ ```
129
+
130
+ VS Code and PyCharm each have a plain and an elevated launcher checked in, in
131
+ `.vscode/launch.json` and `.idea/runConfigurations/`. The elevated one takes
132
+ the same `--elevate` path as the command line above: Windows starts a separate
133
+ elevated process through UAC and the one the editor started exits immediately,
134
+ so nothing is left for a debugger to attach to. To debug with privileges,
135
+ start the editor elevated and use the plain launcher, which inherits them.
136
+
137
+ ## Test
138
+
139
+ ```powershell
140
+ pip install -r requirements-dev.txt
141
+ python -m pytest
142
+ ```
143
+
144
+ Dependencies are pinned by version and hash. The requirements files name every
145
+ package with an exact version, and `scripts/lock_hashes.py` writes the hashes
146
+ under each pin from the digests PyPI reports; the top of `requirements.txt`
147
+ says how to move a version.
148
+
149
+ ## Licence
150
+
151
+ MIT. See [LICENSE](https://github.com/mjaksn/memlapse/blob/main/LICENSE).
152
+
153
+ Changes are listed in
154
+ [CHANGELOG.md](https://github.com/mjaksn/memlapse/blob/main/CHANGELOG.md).
@@ -0,0 +1,125 @@
1
+ # memlapse
2
+
3
+ [![CI](https://github.com/mjaksn/memlapse/actions/workflows/ci.yml/badge.svg)](https://github.com/mjaksn/memlapse/actions/workflows/ci.yml)
4
+ [![Release](https://github.com/mjaksn/memlapse/actions/workflows/release.yml/badge.svg)](https://github.com/mjaksn/memlapse/actions/workflows/release.yml)
5
+ [![PyPI](https://img.shields.io/pypi/v/memlapse)](https://pypi.org/project/memlapse/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/mjaksn/memlapse/blob/main/LICENSE)
7
+
8
+ A Windows memory forensics tool, Process Explorer / System Informer-style
9
+ monitoring, that records a process's memory map over time and replays it.
10
+ Recording and playback of the memory activity of specific threads is the
11
+ planned next phase (Phase 5). See
12
+ [docs/ARCHITECTURE.md](https://github.com/mjaksn/memlapse/blob/main/docs/ARCHITECTURE.md)
13
+ for the design and
14
+ [docs/RESEARCH_NOTES.md](https://github.com/mjaksn/memlapse/blob/main/docs/RESEARCH_NOTES.md)
15
+ for the reference material behind the detection heuristics and the ideas
16
+ queued for later phases.
17
+
18
+ Antivirus checks are made mostly when a process starts, which leaves code
19
+ written into a process that is already running unscanned. Sampling a live
20
+ process on a timer covers exactly that gap, and recording the samples lets an
21
+ analyst scrub back to the moment the memory changed.
22
+
23
+ ## Status
24
+
25
+ - **Phase 1**, live process monitor (sortable, filterable table).
26
+ - **Phase 2**, memory-map view: select a process to see its VirtualQueryEx
27
+ region map, refreshed every second while on screen; click a region for a
28
+ hex preview of its bytes.
29
+ - **Phase 3**, record a process's memory map over time to SQLite.
30
+ - **Phase 4**, playback: scrub the recording with the timeline to replay how
31
+ its regions and footprint evolved.
32
+ - **Phase 6**, injection heuristics: each executable region gets a 0 to 100
33
+ score (unbacked private or mapped executable memory, RWX, PE header, NOP
34
+ sled, high entropy, and a thread whose start address lands in memory no
35
+ image backs) shown as a Score column with a heat tint and a reason tooltip
36
+ in the region view, banded low, review or likely injection. The top band
37
+ needs a signal the memory map alone cannot give, so a page that is merely
38
+ private and RWX, which is what a JIT compiler leaves behind, stops at
39
+ review. A fourth band, allowlisted, exists for a region whose every scoring
40
+ rule an entry has excused, but nothing in the app creates an entry yet, so
41
+ no run of it shows that band. The score also rises for a region whose code
42
+ was rewritten in place, and again if its entropy fell from packed to
43
+ code-like, the traces an injector leaves when it overwrites executable
44
+ memory that already exists and when a payload decrypts itself there. Both
45
+ work in playback, between consecutive samples, and in live mode, between
46
+ one refresh and the next. A replay then says more than a live watch can:
47
+ every score is still the answer for the sample being shown, but a region's
48
+ tooltip also says how many times the whole recording saw it rewritten and
49
+ when that last happened, and the timeline carries a tick at each of those
50
+ samples to scrub to. A region rewritten once, minutes ago, scores nothing
51
+ now and would otherwise pass for quiet.
52
+
53
+ - **Dashboard**, a vivid, near-live overview tab: system RAM/swap gauges, a
54
+ scrolling usage timeline, a heat-ranked top-process list (click to drill into
55
+ the monitor), leak/anomaly interpretation, and CSV/JSON export of the window.
56
+
57
+ Next: per-thread memory activity via ETW (Phase 5).
58
+
59
+ ## Use
60
+
61
+ 1. Open the **Forensic Monitor** tab (the app starts on the Dashboard; clicking
62
+ a process bar there also jumps to the monitor), then select a process (left)
63
+ to inspect its live memory map (right).
64
+ 2. Click **● Record** to sample it over time; **■ Stop** when done. Right-click
65
+ a region to save its bytes for a disassembler or a YARA rule.
66
+ 3. **Open Recording ▾** → pick a recording to enter playback, then drag the
67
+ timeline (or press ▶) to replay it. A tick on the timeline is a sample
68
+ where a region's executable bytes changed, which is where to scrub.
69
+ **Live** returns to real-time mode.
70
+
71
+ ## Install
72
+
73
+ Windows only, Python 3.14.
74
+
75
+ ```powershell
76
+ pip install memlapse
77
+
78
+ memlapse # live monitor
79
+ memlapse --elevate # relaunch elevated to read system and other users' processes
80
+ ```
81
+
82
+ `python -m memlapse` runs the same thing. Running elevated enables
83
+ `SeDebugPrivilege`, required to read most system and other-user processes.
84
+ The status bar reports the privilege state when the window opens.
85
+
86
+ The package accepts a range of versions of its three dependencies. For the
87
+ exact versions it is tested with, each checked against the hashes PyPI
88
+ publishes, install from a checkout instead:
89
+
90
+ ## Run from a checkout
91
+
92
+ ```powershell
93
+ python -m venv .venv
94
+ .venv\Scripts\Activate.ps1
95
+ pip install --require-hashes -r requirements.txt
96
+
97
+ python main.py # live monitor
98
+ python main.py --elevate # relaunch elevated
99
+ ```
100
+
101
+ VS Code and PyCharm each have a plain and an elevated launcher checked in, in
102
+ `.vscode/launch.json` and `.idea/runConfigurations/`. The elevated one takes
103
+ the same `--elevate` path as the command line above: Windows starts a separate
104
+ elevated process through UAC and the one the editor started exits immediately,
105
+ so nothing is left for a debugger to attach to. To debug with privileges,
106
+ start the editor elevated and use the plain launcher, which inherits them.
107
+
108
+ ## Test
109
+
110
+ ```powershell
111
+ pip install -r requirements-dev.txt
112
+ python -m pytest
113
+ ```
114
+
115
+ Dependencies are pinned by version and hash. The requirements files name every
116
+ package with an exact version, and `scripts/lock_hashes.py` writes the hashes
117
+ under each pin from the digests PyPI reports; the top of `requirements.txt`
118
+ says how to move a version.
119
+
120
+ ## Licence
121
+
122
+ MIT. See [LICENSE](https://github.com/mjaksn/memlapse/blob/main/LICENSE).
123
+
124
+ Changes are listed in
125
+ [CHANGELOG.md](https://github.com/mjaksn/memlapse/blob/main/CHANGELOG.md).
@@ -0,0 +1,8 @@
1
+ """memlapse, a Windows memory forensics tool.
2
+
3
+ Process Explorer / System Informer-style monitoring with recording and
4
+ playback of a process's memory map over time, and a per-region injection
5
+ score. Per-thread attribution via ETW is planned (see docs/ARCHITECTURE.md).
6
+ """
7
+
8
+ __version__ = "0.1.1"
@@ -0,0 +1,8 @@
1
+ """Run memlapse with ``python -m memlapse`` (add --elevate for admin)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from .app import main
6
+
7
+ if __name__ == "__main__":
8
+ raise SystemExit(main())