Add unblob so REA can extract firmware
unblob 26.6.4 (the version REA is verified with) is installed from its PyPI wheel into /opt/unblob, with dependencies pinned to its uv.lock at the release commit. A wrapper puts that venv first on PATH, and REA_UNBLOB_COMMAND points REA's extract_firmware at it. Its extractors follow upstream's install-deps.sh: Ubuntu packages, sasquatch v4.5.1-6 (also used by binwalk) and onekey-sec's e2fsprogs fork, whose debugfs rdump options the ext2/3/4 handler needs. The build checks that unblob finds every extractor. The uv.lock converter moves to scripts/ and skips the locked project itself generically, since ghidra-mcp and unblob both use it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+62
-11
@@ -121,6 +121,28 @@ RUN python3 -m venv /opt/binwalk-py \
|
||||
&& /opt/esptool/bin/pip install --no-cache-dir --disable-pip-version-check \
|
||||
"esptool==${ESPTOOL_VERSION}"
|
||||
|
||||
# unblob (https://github.com/onekey-sec/unblob), the firmware extractor REA
|
||||
# uses for extract_firmware; REA is verified with 26.6.4. Installed from the
|
||||
# PyPI wheel (SHA-256 from PyPI) into its own venv, with every dependency
|
||||
# pinned to unblob's uv.lock at the release tag's commit, like ghidra-mcp.
|
||||
ARG UNBLOB_VERSION=26.6.4
|
||||
ARG UNBLOB_COMMIT=1fcc7a0a584a70a96c31f5a276c20944d199a089
|
||||
ARG UNBLOB_WHEEL_SHA256=0fc16e9c7dc92fcf86b8b61475700c9dd16e1dddacf34467574ea965a5d3584e
|
||||
ARG UNBLOB_UVLOCK_SHA256=0a88ed397d60e0624bdef34c7a0b7329a6d278dfdedb86f940c6ee25401c0317
|
||||
COPY scripts/uvlock-to-constraints.py /tmp/uvlock-to-constraints.py
|
||||
RUN set -e \
|
||||
&& whl="unblob-${UNBLOB_VERSION}-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl" \
|
||||
&& curl -fsSLo "/tmp/${whl}" "https://files.pythonhosted.org/packages/cp39/u/unblob/${whl}" \
|
||||
&& echo "${UNBLOB_WHEEL_SHA256} /tmp/${whl}" | sha256sum -c - \
|
||||
&& curl -fsSLo /tmp/uv.lock "https://raw.githubusercontent.com/onekey-sec/unblob/${UNBLOB_COMMIT}/uv.lock" \
|
||||
&& echo "${UNBLOB_UVLOCK_SHA256} /tmp/uv.lock" | sha256sum -c - \
|
||||
&& python3 -I /tmp/uvlock-to-constraints.py /tmp/uv.lock > /tmp/constraints.txt \
|
||||
&& python3 -m venv /opt/unblob \
|
||||
&& /opt/unblob/bin/pip install --no-cache-dir --disable-pip-version-check \
|
||||
--constraint /tmp/constraints.txt "/tmp/${whl}"
|
||||
# (unblob needs libmagic to start, which this stage lacks; the final stage
|
||||
# runs it.)
|
||||
|
||||
|
||||
# --- Final image -------------------------------------------------------------
|
||||
FROM ubuntu:24.04
|
||||
@@ -207,7 +229,7 @@ ARG GHIDRAMCP_VERSION=2.0
|
||||
ARG GHIDRAMCP_SHA256=ebf904fd6782e429e95a60a24fe0724b20c0acb2dedb304135a5281f6b5f2e72
|
||||
ARG GHIDRAMCP_COMMIT=1e980252087b2479a21b9ca6d82d5829538651a7
|
||||
ARG GHIDRAMCP_UVLOCK_SHA256=f80ffe8df8167535f253976a1dfb702a9a7f8836d884084017dd7c04e1444837
|
||||
COPY ghidra/uvlock-to-constraints.py /tmp/uvlock-to-constraints.py
|
||||
COPY scripts/uvlock-to-constraints.py /tmp/uvlock-to-constraints.py
|
||||
RUN set -e \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends python3 python3-venv \
|
||||
@@ -230,13 +252,23 @@ RUN set -e \
|
||||
&& /opt/ghidra-mcp/bin/ghidra-mcp --help >/dev/null \
|
||||
&& rm -rf /tmp/ghidramcp /tmp/ghidramcp.zip /tmp/uv.lock /tmp/constraints.txt /tmp/uvlock-to-constraints.py
|
||||
|
||||
# binwalk (built above) with the extraction tools its Dockerfile installs.
|
||||
# sasquatch (SquashFS variants) comes as a .deb from onekey-sec; the release
|
||||
# publishes no checksums, so the SHA-256 was taken when it was pinned.
|
||||
# binwalk and unblob (built above) with the extraction tools their install
|
||||
# scripts (binwalk's Dockerfile, unblob's install-deps.sh) put in place.
|
||||
# sasquatch (SquashFS variants) comes as a .deb from onekey-sec, at the
|
||||
# release unblob 26.6.4 uses. unblob's ext2/3/4 extraction needs the rdump
|
||||
# options from onekey-sec's e2fsprogs fork, so its .debs replace Ubuntu's
|
||||
# e2fsprogs (same upstream 1.47.0). These releases publish no checksums;
|
||||
# the SHA-256s were taken when pinned.
|
||||
# The Python tools' entry points are linked into /usr/local/bin; the venvs'
|
||||
# python/pip are not, so the system python3 isn't shadowed.
|
||||
ARG SASQUATCH_RELEASE=sasquatch-v4.5.1-5
|
||||
ARG SASQUATCH_SHA256_AMD64=23191cb530bed01e9f00b9a28a74d03db057fb111e13ce5fb383356c1fdf7e6c
|
||||
# python/pip are not, so the system python3 isn't shadowed. unblob gets a
|
||||
# wrapper that puts its own venv first on PATH, so it calls its own locked
|
||||
# jefferson/ubireader rather than binwalk's.
|
||||
ARG SASQUATCH_RELEASE=sasquatch-v4.5.1-6
|
||||
ARG SASQUATCH_SHA256_AMD64=efbc92bd27594e01211e1b582f105a463a0017360a0746a93de3f283906ade95
|
||||
ARG E2FSPROGS_OK_RELEASE=v1.47.0-3.ok2
|
||||
ARG LIBEXT2FS2_OK_SHA256_AMD64=4eaf27e79a570ec89e15d8851f7df693b8b3ae78ccbb5b2a4a7d3eee845f1beb
|
||||
ARG LIBSS2_OK_SHA256_AMD64=6dfc4612915d885607f36fcea2b851a947f9c73943494208ec48a0cbe9887427
|
||||
ARG E2FSPROGS_OK_SHA256_AMD64=360adf4aa996cc80bf39002775d39900ae207b591c105d12a8ad2a833eb536f4
|
||||
# binwalk -E -p (entropy graph as PNG) renders through Kaleido. binwalk's
|
||||
# build downloads it into the build stage's /root, which the image doesn't
|
||||
# have, so -p would crash; it's fetched here instead (same release the crate
|
||||
@@ -247,12 +279,23 @@ ARG KALEIDO_SHA256_AMD64=3eaa3efd41a00db05dd71add7f54ad4e9d4259552e3f7470ac4c1a8
|
||||
COPY --from=binwalk-build /out/bin/ /usr/local/bin/
|
||||
COPY --from=binwalk-build /opt/binwalk-py /opt/binwalk-py
|
||||
COPY --from=binwalk-build /opt/esptool /opt/esptool
|
||||
COPY --from=binwalk-build /opt/unblob /opt/unblob
|
||||
RUN set -e \
|
||||
&& arch="$(dpkg --print-architecture)" \
|
||||
&& [ "$arch" = amd64 ] || { echo "sasquatch checksum only pinned for amd64" >&2; exit 1; } \
|
||||
&& curl -fsSLo /tmp/sasquatch.deb \
|
||||
"https://github.com/onekey-sec/sasquatch/releases/download/${SASQUATCH_RELEASE}/sasquatch_1.0_${arch}.deb" \
|
||||
&& echo "${SASQUATCH_SHA256_AMD64} /tmp/sasquatch.deb" | sha256sum -c - \
|
||||
&& mkdir /tmp/e2fsprogs-ok && cd /tmp/e2fsprogs-ok \
|
||||
&& v="${E2FSPROGS_OK_RELEASE#v}" \
|
||||
&& printf '%s %s\n' \
|
||||
"${LIBEXT2FS2_OK_SHA256_AMD64}" "libext2fs2_${v}_${arch}.deb" \
|
||||
"${LIBSS2_OK_SHA256_AMD64}" "libss2_${v}_${arch}.deb" \
|
||||
"${E2FSPROGS_OK_SHA256_AMD64}" "e2fsprogs_${v}_${arch}.deb" > SHA256SUMS \
|
||||
&& for f in $(awk '{print $2}' SHA256SUMS); do \
|
||||
curl -fsSLO "https://github.com/onekey-sec/e2fsprogs/releases/download/${E2FSPROGS_OK_RELEASE}/$f"; \
|
||||
done \
|
||||
&& sha256sum -c SHA256SUMS && cd / \
|
||||
&& curl -fsSLo /tmp/kaleido.zip \
|
||||
"https://github.com/plotly/Kaleido/releases/download/v${KALEIDO_VERSION}/kaleido_linux_x64.zip" \
|
||||
&& echo "${KALEIDO_SHA256_AMD64} /tmp/kaleido.zip" | sha256sum -c - \
|
||||
@@ -260,16 +303,23 @@ RUN set -e \
|
||||
&& rm /tmp/kaleido.zip \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
/tmp/sasquatch.deb \
|
||||
/tmp/sasquatch.deb /tmp/e2fsprogs-ok/*.deb \
|
||||
7zip 7zip-standalone zstd srecord tar unzip sleuthkit cabextract \
|
||||
lz4 lzop unrar unyaffs cpio device-tree-compiler \
|
||||
liblzo2-2 libucl1 libfontconfig1 \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/sasquatch.deb \
|
||||
android-sdk-libsparse-utils erofs-utils lziprecover partclone unar \
|
||||
upx-ucl libmagic1t64 xz-utils \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/sasquatch.deb /tmp/e2fsprogs-ok \
|
||||
&& for f in /opt/binwalk-py/bin/* /opt/esptool/bin/*; do \
|
||||
case "$(basename "$f")" in python*|pip*|activate*|Activate*) continue ;; esac; \
|
||||
ln -s "$f" /usr/local/bin/; \
|
||||
done \
|
||||
&& binwalk --version && esptool version
|
||||
&& printf '%s\n' '#!/bin/sh' 'PATH="/opt/unblob/bin:$PATH" exec /opt/unblob/bin/unblob "$@"' \
|
||||
> /usr/local/bin/unblob \
|
||||
&& chmod 755 /usr/local/bin/unblob \
|
||||
&& binwalk --version && esptool version && unblob --version \
|
||||
&& debugfs -V 2>&1 | grep -q 1.47.0 \
|
||||
&& unblob --show-external-dependencies
|
||||
# Binwalk leaves a symlink to the input file in its extraction directory. The
|
||||
# target is a container path, which is dangling when viewed from the host.
|
||||
ENV BINWALK_RM_EXTRACTION_SYMLINK=1 \
|
||||
@@ -312,7 +362,8 @@ RUN set -e; cd /tmp \
|
||||
&& npm install --global --omit=optional --no-audit --no-fund "./rea-agents-${REA_VERSION}.tgz" \
|
||||
&& rm -rf "rea-agents-${REA_VERSION}.tgz" /root/.npm \
|
||||
&& [ "$(rea --version)" = "${REA_VERSION}" ]
|
||||
ENV REA_BINWALK_COMMAND=/usr/local/bin/binwalk
|
||||
ENV REA_BINWALK_COMMAND=/usr/local/bin/binwalk \
|
||||
REA_UNBLOB_COMMAND=/usr/local/bin/unblob
|
||||
|
||||
# stdio-to-HTTP bridge (mcp-remote) that Claude Desktop starts to reach REA's
|
||||
# HTTP endpoint in the other container. Installed from a committed lockfile.
|
||||
|
||||
Reference in New Issue
Block a user