https://github.com/Matt1Up <~~~Source Code
Evidence-Capture Session Controller
A reproducible capture stack for browser/network activity and on-screen proof, orchestrated by a single controller. It couples mitmproxy, Firefox (custom profile), OBS Studio (virtual camera + recording control), and local viewers with a bundle-hash loop and dual timestamping (OpenTimestamps + Roughtime).
Main entrypoint:
control_all.py
Table of Contents
Overview
Key Features
Architecture
Prerequisites
Configuration
OBS Studio WebSocket & Virtual Camera
Firefox Profile & Downloads
PDF Signing Keys (Evidence Vaults)
Commands (via
control_all.py)ffoxhashvcammitmnetwatch-startwatch-clearws_dlws_bf1ws_bf2start_sessionstop_session
Quickstart: Typical Capture Flow
Local Web Viewers
Timestamping Method (OTS + Roughtime)
Safety Notes & Troubleshooting
Roadmap / Ideas
License
Overview
The system orchestrates a repeatable capture loop (“bundle” every X seconds) that:
Runs a Firefox session pinned to a mitmproxy proxy.
Records frame images via OBS virtual camera.
Writes JSON bundles to
RUN/bundles/(0000.json,0001.json, …) and shows the previous bundle SHA-256 in a narrow overlay window to create a visible hash-chain across time.Continuously monitors
~/downloadsto seal files into digitally signed “evidence vault” PDFs.Offers live viewers at
http://127.0.0.1:8050/
for the hash loop, state, and bundle cards.
Key Features
Isolated Firefox profile routed through mitmproxy
OBS virtual camera auto-enable + start/stop recording by command
Bundle hash-chain with visible on-screen previous-hash overlay
Download watcher: auto-hash,
pdfsig,exiftool, wrap into signed PDFsWireshark-like JSON lines stream (
network_stream.jsonl.zip)Local web viewers (Dash) for state, live hash, and bundle “cards”
Dual timestamping: OpenTimestamps (BTC) + Roughtime receipts
Architecture
control_all.py
├─ ffox -> custom-profile Firefox (proxy: mitm)
├─ mitm -> mitm_dump_control.py + httpstream_json.py
├─ vcam -> enable OBS Virtual Camera (via obs_studio_ctrl.py)
├─ hash -> overlay_json.py (1920x72, Liberation Mono 36, refresh 0.5s)
├─ net -> netstream_json.py (Wireshark-like stream; zipped on stop)
├─ watch-start / watch-clear -> download_watcher_json.py + housekeeping
├─ ws-dl, ws-bf1, ws-bf2 -> local web servers at http://127.0.0.1:8050/
├─ start_session “<name>” <interval> -> bin/start_json.py
└─ stop_session -> bin/stop_json.py (finalize .dump -> sanitized HAR)
Prerequisites
Ubuntu (tested) or comparable Linux environment
Python 3.x with typical CLI tooling
OBS Studio with:
OBS WebSocket enabled (Tools → WebSocket Server Settings)
OBS Virtual Camera available
mitmproxy
exiftool, pdfsig, zip
Firefox with custom profile (proxy set to mitm)
Font: Liberation Mono (for the overlay)
Some actions (e.g., turning on OBS Virtual Camera) may require passwordless
sudovia a small setup script.
Configuration
OBS Studio WebSocket & Virtual Camera
In OBS: Tools → WebSocket Server Settings → Show Connect Info → Copy Server IP/port.
Update
OBS_HOSTinobs_studio_ctrl.pywith that IP/port.Ensure the helper script to start the virtual camera has the right privileges (example):
/usr/local/sbin/obs_vcam_setup.sh(your working copy may be in/bin)Configure passwordless sudo as needed.
Firefox Profile & Downloads
The custom Firefox profile used by ffox must:
Route through the local mitmproxy.
Use
~/downloads(or your chosen path) as the default download folder.
PDF Signing Keys (Evidence Vaults)
signature/sign_pdfs.py must be configured with your signing materials:
DEFAULT_KEY_PEMDEFAULT_CERT_PEMDEFAULT_P12(if using a PKCS#12)
Commands (via control_all.py)
Command names below match the controller. Use the exact spellings wired in your
control_all.py.
ffox
Launches Firefox with a custom profile pre-configured to use mitmproxy.
This keeps capture browsing separate from your normal Firefox.
OBS should capture this window for the stream.
hash
Runs
overlay_json.pyto open a 1920×72 px overlay window with Liberation Mono Bold 36 pt, refreshing every 0.5 s.
Shows the last bundle hash so reviewers can visually verify the hash-chain in the OBS recording.
vcam
Turns on the OBS Virtual Camera.
RequiresOBS_HOSTto be set correctly inobs_studio_ctrl.py.
Remains active; start/stop recording is controlled by session start/stop.
mitm
Starts the mitmproxy stack (
mitm_dump_control.py+httpstream_json.py).
Provides internet to theffoxbrowser and writes a.dumpfor later HAR conversion.
net
Runs
netstream_json.py, creating a Wireshark-like TCP/IP stream (JSON lines).Included in each bundle
Also persisted as
RUN/bundles/network_stream.jsonl.zipon session stop
watch-start
Starts
download_watcher_json.py, monitoring the Downloads folder.
Each new file is:Hashed, run through pdfsig/exiftool
Logged into
RUN/downloaded_files.jsonEmbedded into a signed PDF “evidence vault” (via
signature/sign_pdfs.py)
Note: Only one watcher instance should run at a time.
watch-clear
One-shot cleanup: clears the downloads folder and logs, resets state for a fresh session, and updates
RUN/state.json.
Safe to run even ifwatch-startis active.
Destructive: move/archive any prior evidence first.
ws_dl
Starts
RUN/web-server/local_web_server_5.py.
Main viewer athttp://127.0.0.1:8050/
Uses config at
ws_dir/viewer.config.json.
ws_bf1
Runs
RUN/web-server/live_hash_loop.py.Watches
RUN/bundles/(default poll 0.5 s)Prepends updates to
--out RUN/web-server/live_hash_loop.txtDrives the Live Hash-Loop panel in the viewer
ws_bf2
Runs
RUN/web-server/combined.py.Watches
RUN/bundles/(default poll 0.5 s)Prepends to
--out RUN/web-server/combined.jsonBacks the Cards (collapsible bundles) view in the viewer
start_session
bin/start_json.pyUsage:
start_session “<Session Name Here>” 10.0
# i.e., start_session “<name>” <interval_sec>
What happens:
Initializes
RUN/state.jsonand writes0000.jsonfrom a 100-row system-time sample (start_time.json).SHA-256 of
start_time.jsonbecomes the initial nonce.The interval controls the loop that triggers
loop_json.py, which writes each subsequent bundle.The overlay shows previous bundle hash to maintain a visible hash-chain across captured frames.
mitm_dump_control.py --out-dirsets where the main.dumplives; the session name standardizes filenames for.dumpand derived HAR.
stop_session
bin/stop_json.py
What happens:
Gracefully stops
capture_randomized_save_json.py(waits up to one interval to finish the last loop).Stops all capture services and OBS recording.
Waits for
DEFAULT_OUT_DIR/<SESSION>.dump.ready.Converts the main
.dumpinto a sanitized/redacted HAR written toDEFAULT_HAR_OUTDIR.Zips the network stream (
network_stream.jsonl.zip).
Quickstart: Typical Capture Flow
Start virtual cam & overlay
vcam hash
Start proxy and browser
mitm ffox
(Optional) Start the download watcher
watch-start
(Optional) Launch local viewers
ws_dl ws_bf1 ws_bf2
Begin a capture session (every 10s)
start_session “Case Study – MCRO” 10.0
...perform your browsing / downloads / evidence capture / anything…
Stop the session (finalizes dump -> sanitized HAR; zips network stream)
stop_session
Cleanup: If preparing for a fresh run, use
watch-clear(destructive).
Local Web Viewers
Accessible at
http://127.0.0.1:8050/
when ws_dl (and optionally ws_bf1, ws_bf2) are running.
VIEW: JSON Viewer, PROFILE: File Downloads
VIEW LIVE DOWNLOADS +
pdfsig/exiftooldetails.
VIEW: Live Feed, PROFILE: File Downloads
LIVE HASH-LOOP VIEWER (Bundle → Frame → Bundle → Frame …).
VIEW: JSON Viewer, PROFILE: State
VIEW CONTENTS of RUN/state.json.
VIEW: Cards, PROFILE: Cards
Collapsible tiles for each bundle in
RUN/bundles.
Timestamping Method (OTS + Roughtime)
Every bundle (and key artifacts like start_time.json and frame PNGs) is timestamped by:
OpenTimestamps (.ots) — anchors to Bitcoin for immutability.
Roughtime — generates a JSON receipt binding the SHA-256 of the
.otsfile itself to a time-stamped proof.
Artifacts appear as:
xxxx.json.otsxxxx.json.ots__time-stamp.jsonxxxx.png.ots__time-stamp.json
Tools live under /time/ (e.g., time/roughtime_client.py).
Safety Notes & Troubleshooting
Single watcher instance: ensure only one
download_watcher_json.pyis running.OBS control: if
vcamor recording toggles fail, confirm:OBS_HOST(IP/port) inobs_studio_ctrl.pyOBS is running; WebSocket enabled; permissions set for virtual camera
Destructive cleanup:
watch-clearwipes downloads/logs — backup first.Firefox profile: proxy and default download folder must be correct; otherwise downloads won’t be captured/sealed.
Keys & certs:
signature/sign_pdfs.pymust point to valid signing materials.
Roadmap / Ideas
Replace visible 64-char hash string with a V1 QR code (21×21 px) anchored at a fixed pixel region in the frame.
Optionally encode entire bundles into QR tiles in a defined frame area, or hide bits via pixel-parity for invisible watermarking QR Codes. (Odd == 0, Even ==1..)
Lower capture frequency (e.g., 4× per minute) while keeping high verification value / high image capture quality
Add strict pixel-accuracy validation for the overlay region (useful for automated verification).
License
Specify your license here (e.g., MIT, Apache-2.0).
Notes
Designed to document and verify Mass Judicial Fraud and forged court records in the Minnesota Court Records Online system (e.g., MCRO) and cryptographically bind CourtListener archive states to a time-stamped, chain-verifiable capture.
The large overlayed hash promotes human-readable verification during review. For compact archives, consider QR or embedded bit-schemes later.










