Initial import — ntdsextract2 Docker build context
Cargo-installs --locked from crates.io on rust:1.96-alpine3.21 with build-base + linux-headers + gettext-dev (libesedb's bundled C tree needs all three). Final image is ~26MB on alpine:3.21.
This commit is contained in:
+32
@@ -0,0 +1,32 @@
|
|||||||
|
# tabledevil/ntdsextract2 — Jan Starke's NTDS.DIT forensic analyser, Rust.
|
||||||
|
#
|
||||||
|
# Modern replacement for the old Python ntdsxtract; pulls users/groups/
|
||||||
|
# computers from an offline NTDS.DIT (and the matching SYSTEM hive for
|
||||||
|
# secret-decryption), emits a bodyfile timeline, walks the AD DIT tree.
|
||||||
|
#
|
||||||
|
# Upstream moved off GitHub to https://codeberg.org/janstarke/ntdsextract2
|
||||||
|
# (still on crates.io; we install from there to keep the build hermetic).
|
||||||
|
#
|
||||||
|
# docker run --rm -v /evidence:/data:ro tabledevil/ntdsextract2 \
|
||||||
|
# user /data/ntds.dit
|
||||||
|
# docker run --rm -v /evidence:/data:ro tabledevil/ntdsextract2 \
|
||||||
|
# timeline /data/ntds.dit --bodyfile > /tmp/timeline.body
|
||||||
|
|
||||||
|
FROM rust:1.96-alpine3.21 AS build
|
||||||
|
# build-base brings gcc + libc-dev + binutils + make (libesedb's bundled C
|
||||||
|
# tree fails to compile without them); linux-headers + gettext-dev are
|
||||||
|
# libyal-on-musl prerequisites (bindtextdomain etc.).
|
||||||
|
RUN apk add --no-cache --virtual .build build-base clang pkgconf linux-headers gettext-dev
|
||||||
|
|
||||||
|
# Crates.io build pulls upstream + embedded C code; takes ~5 min cold.
|
||||||
|
# --locked uses the upstream Cargo.lock (otherwise resolved transitive deps
|
||||||
|
# can demand newer rustc than the base image ships).
|
||||||
|
RUN cargo install --locked --root /opt/ntdsextract2 ntdsextract2
|
||||||
|
|
||||||
|
FROM alpine:3.21
|
||||||
|
RUN apk add --no-cache libgcc
|
||||||
|
COPY --from=build /opt/ntdsextract2/bin/ntdsextract2 /usr/local/bin/ntdsextract2
|
||||||
|
COPY start.sh /start.sh
|
||||||
|
RUN chmod +x /start.sh && mkdir -p /data
|
||||||
|
WORKDIR /data
|
||||||
|
ENTRYPOINT ["/start.sh"]
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# docker_ntdsextract2
|
||||||
|
|
||||||
|
Build context for `tabledevil/ntdsextract2` — Jan Starke's Rust NTDS.DIT
|
||||||
|
forensic analyser.
|
||||||
|
|
||||||
|
Upstream: <https://codeberg.org/janstarke/ntdsextract2> (the GitHub
|
||||||
|
mirror at <https://github.com/janstarke/ntdsextract2> is archived; same
|
||||||
|
author, same code).
|
||||||
|
|
||||||
|
## What it does
|
||||||
|
|
||||||
|
Offline analysis of an extracted Active Directory database:
|
||||||
|
|
||||||
|
| subcommand | output |
|
||||||
|
|---|---|
|
||||||
|
| `user` | account list with SID, RID, status, last logon, password timestamps |
|
||||||
|
| `group` | groups + members |
|
||||||
|
| `computer` | joined hosts with last-logon and OS strings |
|
||||||
|
| `timeline` | bodyfile-format timeline (feed `mactime`) |
|
||||||
|
| `tree` | the DIT hierarchy |
|
||||||
|
| `entry` | dump a single entry by DN |
|
||||||
|
| `search` | regex search over entries |
|
||||||
|
| `types` | list the AD schema's defined types |
|
||||||
|
|
||||||
|
## Getting the input
|
||||||
|
|
||||||
|
`NTDS.DIT` is locked while AD is running. You need to extract it (and the
|
||||||
|
matching `SYSTEM` registry hive) via vshadow / a forensic acquisition.
|
||||||
|
`tabledevil/vhdi` or `tabledevil/libewf` handle E01/VHDX mounts so you can
|
||||||
|
pull the file off cleanly.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run --rm -v /evidence:/data:ro tabledevil/ntdsextract2 user /data/ntds.dit
|
||||||
|
docker run --rm -v /evidence:/data:ro tabledevil/ntdsextract2 timeline /data/ntds.dit > timeline.body
|
||||||
|
```
|
||||||
|
|
||||||
|
Run with no args for the in-image quick-reference banner.
|
||||||
|
|
||||||
|
## Build context
|
||||||
|
|
||||||
|
The image installs from crates.io (`cargo install ntdsextract2`) so the
|
||||||
|
build always picks up Jan's latest release. To refresh the published
|
||||||
|
image with a newer version, just rebuild — no Dockerfile edits required.
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Banner on bare run; pass-through to ntdsextract2 otherwise.
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
cat >&2 <<'EOF'
|
||||||
|
============================================================
|
||||||
|
ntdsextract2 — Active Directory database analyser (Jan Starke)
|
||||||
|
------------------------------------------------------------
|
||||||
|
Mount your NTDS.DIT at /data, then pick a subcommand:
|
||||||
|
|
||||||
|
docker run --rm -v /evidence:/data:ro tabledevil/ntdsextract2 \
|
||||||
|
user /data/ntds.dit # account list
|
||||||
|
docker run --rm -v /evidence:/data:ro tabledevil/ntdsextract2 \
|
||||||
|
group /data/ntds.dit # group membership
|
||||||
|
docker run --rm -v /evidence:/data:ro tabledevil/ntdsextract2 \
|
||||||
|
computer /data/ntds.dit # joined hosts
|
||||||
|
docker run --rm -v /evidence:/data:ro tabledevil/ntdsextract2 \
|
||||||
|
timeline /data/ntds.dit > timeline.body # bodyfile for mactime
|
||||||
|
docker run --rm -v /evidence:/data:ro tabledevil/ntdsextract2 \
|
||||||
|
tree /data/ntds.dit # DIT hierarchy
|
||||||
|
docker run --rm -v /evidence:/data:ro tabledevil/ntdsextract2 \
|
||||||
|
search '<regex>' /data/ntds.dit # entry search
|
||||||
|
|
||||||
|
NTDS.DIT files are normally locked while AD runs — extract with
|
||||||
|
vshadow / volume shadow copy first; ntdsextract2 reads the offline
|
||||||
|
copy directly.
|
||||||
|
============================================================
|
||||||
|
EOF
|
||||||
|
ntdsextract2 --help 2>&1 | head -20 >&2
|
||||||
|
exit 64
|
||||||
|
fi
|
||||||
|
exec ntdsextract2 "$@"
|
||||||
Reference in New Issue
Block a user