mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-02 17:29:37 +02:00
GP-3579 Added docker image generation to Ghidra distribution. Use from development source repo is not supported.
This commit is contained in:
parent
397a814f5f
commit
fbdcd1c709
7 changed files with 354 additions and 0 deletions
62
docker/Dockerfile
Normal file
62
docker/Dockerfile
Normal file
|
@ -0,0 +1,62 @@
|
|||
###############################################################
|
||||
# Dockerfile
|
||||
# This is the Dockerfile for a release of Ghidra.
|
||||
# It should be built from the root directory of
|
||||
# a ghidra release using the command
|
||||
# docker build -f docker/Dockerfile -t <image-name>
|
||||
###############################################################
|
||||
FROM alpine:3.20 as base
|
||||
|
||||
LABEL org.opencontainers.image.title="ghidra" \
|
||||
org.opencontainers.image.description="Docker image for Ghidra" \
|
||||
org.opencontainers.image.source="https://github.com/NationalSecurityAgency/ghidra" \
|
||||
org.opencontainers.image.licenses="Apache 2.0"
|
||||
|
||||
# Configure user, entrypoint, and some env vars first, before making the image larger with dependencies
|
||||
# so that we can keep the image size as small as possible.
|
||||
RUN addgroup -g 1001 -S ghidra && adduser -u 1001 -S ghidra -G ghidra
|
||||
ENTRYPOINT ["/bin/bash", "/ghidra/docker/entrypoint.sh"]
|
||||
# Set JAVA_HOME so that we don't need to do this manually when Ghidra is first started.
|
||||
ENV JAVA_HOME /usr/lib/jvm/java-21-openjdk
|
||||
ENV LD_LIBRARY_PATH /usr/lib/jvm/java-21-openjdk/lib/:/usr/lib/jvm/java-21-openjdk/lib/server/
|
||||
WORKDIR /ghidra
|
||||
|
||||
# validate build context is correct. an error will happen if this file is not present.
|
||||
COPY ./ghidraRun ./ghidraRun
|
||||
|
||||
# update and install dependencies used to both build and run ghidra
|
||||
RUN apk update \
|
||||
&& apk add openjdk21 python3 \
|
||||
bash gcompat \
|
||||
fontconfig msttcorefonts-installer \
|
||||
linux-headers libressl-dev \
|
||||
&& update-ms-fonts
|
||||
|
||||
FROM base as build
|
||||
|
||||
# install additional dependencies used to build ghidra
|
||||
RUN apk add gradle \
|
||||
python3-dev py-pip \
|
||||
alpine-sdk \
|
||||
build-base \
|
||||
gcc g++ make libc-dev zlib-dev musl-dev \
|
||||
zip readline-dev
|
||||
# copy the contents of the release into the current working dir.
|
||||
COPY . .
|
||||
|
||||
# build postgres and install pyghidra
|
||||
RUN /ghidra/Ghidra/Features/BSim/support/make-postgres.sh \
|
||||
&& python3 -m venv /ghidra/venv \
|
||||
&& /ghidra/venv/bin/python3 -m pip install --no-index -f /ghidra/Ghidra/Features/PyGhidra/pypkg/dist pyghidra \
|
||||
&& mkdir /ghidra/repositories && mkdir /ghidra/bsim_datadir
|
||||
|
||||
|
||||
FROM base as runtime
|
||||
|
||||
# install additional dependencies needed for running ghidra
|
||||
RUN apk add openssl openssh-client \
|
||||
xhost musl-locales musl-locales-lang
|
||||
|
||||
USER ghidra
|
||||
WORKDIR /ghidra
|
||||
COPY --chown=ghidra:ghidra --from=build /ghidra /ghidra
|
1
docker/Dockerfile.dockerignore
Normal file
1
docker/Dockerfile.dockerignore
Normal file
|
@ -0,0 +1 @@
|
|||
docker/Dockerfile*
|
203
docker/README.md
Normal file
203
docker/README.md
Normal file
|
@ -0,0 +1,203 @@
|
|||
# Dockerized Ghidra
|
||||
|
||||
## Build
|
||||
|
||||
From the root directory of your Ghidra release, run the following command with the correct version for your release.
|
||||
|
||||
```
|
||||
docker build -f docker/Dockerfile -t ghidra/ghidra[:<version>] .
|
||||
```
|
||||
|
||||
The image tag is optional, but highly recommended.
|
||||
|
||||
|
||||
## The MODE environment variable
|
||||
|
||||
The Ghidra Docker Container supports the following `MODE`'s of execution:
|
||||
- gui
|
||||
- headless
|
||||
- ghidra-server
|
||||
- bsim
|
||||
- bsim-server
|
||||
- pyghidra
|
||||
|
||||
The `MODE` environment variable designates which entrypoint of Ghidra to execute.
|
||||
|
||||
The `entrypoint.sh` script is executed upon container startup.
|
||||
|
||||
## Configuring a Container
|
||||
|
||||
Configuration of a container is done just as any other docker container would be configured.
|
||||
Volumes can be mounted, environment variables can be set, ports can be mapped from container to the host, and so on.
|
||||
Configuration steps vary a lot based on what MODE the container is started with.
|
||||
|
||||
The base directory for Ghidra within the container is located at `/ghidra`.
|
||||
All of ghidra's default locations for files, configs, etc., are the same within that.
|
||||
Ghidra is run as the user `ghidra` within the container.
|
||||
|
||||
The `ghidra` user only has permissions to the following directories inside the container:
|
||||
- `/ghidra`
|
||||
- `/home/ghidra`
|
||||
|
||||
|
||||
When a container does not receive any arguments passed to it with the `docker run` command,
|
||||
the corresponding Command Line Interface (CLI) for the `MODE` executed will display it's usage statement.
|
||||
|
||||
### Mapping Local Volumes to a Container
|
||||
|
||||
Volumes within the container may run into permission issues if the volumes are not accessible by users in the group id `1001`.
|
||||
|
||||
The default uid and guid for the container is `1001:1001`. Volumes that get mapped to the container should be accessible by this uid/guid.
|
||||
|
||||
Adding the host machine's user to the group `1001` on the host helps manage volumes that will be used in the container.
|
||||
This can easily be done by executing `sudo usermod -aG 1001 <user>` on Linux.
|
||||
|
||||
### Example of Headless Mode
|
||||
|
||||
```
|
||||
docker run \
|
||||
--env MODE=headless \
|
||||
--rm \
|
||||
--volume /path/to/myproject:/home/ghidra/myproject \
|
||||
--volume /path/to/mybinary:/home/ghidra/mybinary \
|
||||
ghidra/ghidra:<version> \
|
||||
/myproject programFolder -import /mybinary
|
||||
```
|
||||
|
||||
Breaking this down line by line:
|
||||
- `docker run` is going to start a docker container using the image `ghidra/ghidra<:<version>`
|
||||
- `--env MODE=headless` configures the environment variable `MODE` within the container to be the value `headless`
|
||||
- `--rm` removes the container after the command is complete
|
||||
- `--volume /path/to/myproject:/myproject` mounts the local volume `/path/to/myproject` on the host to `/myproject` within the container
|
||||
- `--volume /path/to/mybinary:/mybinary` mounts the local volume `/path/to/mybinary` on the host to `/mybinary` within the container
|
||||
- `ghidra/ghidra:<version>` is the full reference for the docker image, where `ghidra/ghidra` is the group and name of the image, and `<version>` is the tag.
|
||||
- `/myproject programFolder -import /mybinary` are arguments being passed to Ghidra's headless analyzer's command line interface
|
||||
|
||||
Passing no arguments will result in the usage of the headless analyzer being displayed.
|
||||
|
||||
### Example of Gui Mode
|
||||
|
||||
Running Ghidra's Graphical User Interface (GUI) in the docker container is not a recommended method for running Ghidra.
|
||||
GUI's are not a typical use case for dockerized applications.
|
||||
|
||||
```
|
||||
docker run \
|
||||
--env MODE=gui \
|
||||
-it \
|
||||
--rm \
|
||||
--net host \
|
||||
--env DISPLAY \
|
||||
--volume="$HOME/.Xauthority:/home/ghidra/.Xauthority" \
|
||||
ghidra/ghidra:<version>
|
||||
```
|
||||
|
||||
In this mode, the container relies on X11 forwarding to display the GUI. Configuration of X11 can vary, but in this case,
|
||||
the host's Xauthority file is mounted into the container, the container is configured to use the host's network, and the DISPLAY
|
||||
environment variable is passed to the container. This enables forwarding the GUI back to the host machine's display. Volumes
|
||||
containing binaries would still need to be mounted to the container as well as volumes for ghidra projects.
|
||||
|
||||
The host's `.Xauthority` file must have appropriate permissions - assigned the group`:1001` with `rw` group permissions.
|
||||
|
||||
|
||||
### Example of Ghidra Server Mode
|
||||
|
||||
```
|
||||
docker run \
|
||||
--env MODE=ghidra-server \
|
||||
--rm \
|
||||
-it \
|
||||
--volume /path/to/my/repositories:/ghidra/repositories \
|
||||
--volume /path/to/my/configs/server.conf:/ghidra/server/server.conf \
|
||||
-p 13100:13100 \
|
||||
-p 13101:13101 \
|
||||
-p 13102:13102 \
|
||||
ghidra/ghidra:<version>
|
||||
```
|
||||
|
||||
Volumes would need to be mounted to the server container to save the repositories, users, and also to configure the server as well.
|
||||
|
||||
To utilize svrAdmin, exec into the running ghidra server container (`docker exec -it <container-id> bash`) for a bash shell in the container.
|
||||
After exec'ing into the container, administration and management of the Ghidra server is the same as outside of a containerized environment.
|
||||
|
||||
To stop the container, execute the command `docker stop <container-id>`.
|
||||
|
||||
## Example of BSIM Server Mode
|
||||
|
||||
```
|
||||
export DATADIR_PATH=/home/ghidrausr/datadir
|
||||
docker run \
|
||||
--env MODE=bsim-server \
|
||||
--rm \
|
||||
-it \
|
||||
--volume /path/to/my/datadir:/ghidra/bsim_datadir \
|
||||
-p 5432:5432 \
|
||||
ghidra/ghidra:<version> \
|
||||
/ghidra/bsim_datadir
|
||||
```
|
||||
|
||||
`/ghidra/bsim_datadir` is the directory used to store bsim's data in the container. Other directories could be used on the container,
|
||||
but make sure that the folder on the host machine has appropriate permissions, assigned the group `:1001`.
|
||||
|
||||
This example simply starts a bsim server. Configuring the bsim server and populating it with data
|
||||
could be done post start within the container in a similar way that ghidra server administration is done.
|
||||
An administrator would have to exec into the running bsim server container (`docker exec -it <container-id> bash`),
|
||||
and after exec'ing into the container, administration and management of the Bsim server is the same as outside of a containerized environment.
|
||||
|
||||
To stop the container, execute the command `docker stop <container-id>`.
|
||||
|
||||
## Example of BSIM CLI Mode
|
||||
```
|
||||
docker run \
|
||||
--env MODE=bsim \
|
||||
--rm \
|
||||
-it \
|
||||
ghidra/ghidra:RELEASE \
|
||||
generatesigs ghidra://ghidrasvr/demo /home/ghidra \
|
||||
--bsim postgresql://bsimsvr/demo \
|
||||
--commit --overwrite \
|
||||
--user ghidra
|
||||
```
|
||||
|
||||
In this example, the bsim CLI is used to connect to a ghidra server hosted on `ghidrasvr`,
|
||||
generate signatures for the `demo` repository in that ghidra server and save them to `/home/ghidra`.
|
||||
and then commit the signatures to the BSIM server hosted on `bsimsvr` in the `demo` database.
|
||||
|
||||
|
||||
## Example of Pyghidra Gui Mode
|
||||
|
||||
Running Ghidra's Graphical User Interface (GUI) in the docker container is not a recommended method for running Ghidra.
|
||||
GUI's are not a typical use case for dockerized applications.
|
||||
|
||||
```
|
||||
docker run \
|
||||
--env MODE=pyghidra \
|
||||
-it \
|
||||
--rm \
|
||||
--net host \
|
||||
--env DISPLAY \
|
||||
--volume="$HOME/.Xauthority:/home/ghidra/.Xauthority:rw" \
|
||||
ghidra/ghidra:<version> -c
|
||||
```
|
||||
In this mode, the container relies on X11 forwarding to display the GUI. Configuration of X11 can vary, but in this case,
|
||||
the host's Xauthority file is mounted into the container, the container is configured to use the host's network, and the DISPLAY
|
||||
environment variable is passed to the container. This enables forwarding the GUI back to the host machine's display. Volumes
|
||||
containing binaries would still need to be mounted to the container as well as volumes for ghidra projects.
|
||||
|
||||
The host's `.Xauthority` file must have appropriate permissions - owned by `:1001` with `rw` group permissions.
|
||||
|
||||
|
||||
## Example of Pyghidra Headless Mode
|
||||
|
||||
```
|
||||
docker run \
|
||||
--env MODE=pyghidra \
|
||||
--rm \
|
||||
--volume /path/to/myproject:/myproject \
|
||||
--volume /path/to/mybinary:/mybinary \
|
||||
ghidra/ghidra:<version> -H \
|
||||
/myproject programFolder -import /mybinary
|
||||
```
|
||||
Passing no arguments to the pyghidra headless analyzer will result in the help menu being displayed, just like the headless analyzer.
|
||||
|
||||
This use case is very similar to the headless mode's example with the added benefit of being able to utilize python3 for Ghidra Scripts.
|
||||
|
28
docker/build.gradle
Normal file
28
docker/build.gradle
Normal file
|
@ -0,0 +1,28 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
rootProject.assembleDistribution {
|
||||
from (ROOT_PROJECT_DIR + "/docker") {
|
||||
into "docker"
|
||||
exclude "build.gradle"
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.assembleMarkdownToHtml {
|
||||
from ("${this.projectDir}/README.md") {
|
||||
into "."
|
||||
}
|
||||
}
|
4
docker/certification.manifest
Normal file
4
docker/certification.manifest
Normal file
|
@ -0,0 +1,4 @@
|
|||
##VERSION: 2.0
|
||||
Dockerfile||GHIDRA||||END|
|
||||
Dockerfile.dockerignore||GHIDRA||||END|
|
||||
README.md||GHIDRA||||END|
|
55
docker/entrypoint.sh
Executable file
55
docker/entrypoint.sh
Executable file
|
@ -0,0 +1,55 @@
|
|||
#!/bin/bash
|
||||
## ###
|
||||
# IP: GHIDRA
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
##
|
||||
|
||||
MODE=${MODE:="gui"}
|
||||
|
||||
echo "$@"
|
||||
MAXMEM=${MAXMEM:=2G}
|
||||
|
||||
if [[ $MODE == "gui" ]] then
|
||||
/ghidra/support/launch.sh bg jdk Ghidra "${MAXMEM}" "" ghidra.GhidraRun "$@"
|
||||
# need to do this since the launched process is not blocking terminal exit
|
||||
while ! tail -f ~/.config/ghidra/ghidra_*/application.log; do sleep 1 ; done
|
||||
elif [[ $MODE == "headless" ]] then
|
||||
LAUNCH_MODE=${LAUNCH_MODE:=fg}
|
||||
DEBUG_ADDRESS=${DEBUG_ADDRESS:=127.0.0.1:13002}
|
||||
VMARG_LIST=${VMARG_LIST:="-XX:ParallelGCThreads=2 -XX:CICompilerCount=2 -Djava.awt.headless=true "}
|
||||
DEBUG_ADDRESS=${DEBUG_ADDRESS} /ghidra/support/launch.sh "${LAUNCH_MODE}" jdk Ghidra-Headless "${MAXMEM}" "${VMARG_LIST}" ghidra.app.util.headless.AnalyzeHeadless "$@"
|
||||
elif [[ $MODE == "ghidra-server" ]] then
|
||||
# Note, for svrAdmin, you will need to exec into the container running the ghidra server and use the CLI there.
|
||||
/ghidra/server/ghidraSvr console
|
||||
elif [[ $MODE == "bsim" ]] then
|
||||
LAUNCH_MODE=${LAUNCH_MODE:=fg}
|
||||
VMARG_LIST=${VMARG_LIST:="-Djava.awt.headless=true "}
|
||||
/ghidra/support/launch.sh $LAUNCH_MODE jdk "BSim" "${MAXMEM}" "" ghidra.features.bsim.query.ingest.BSimLaunchable "$@"
|
||||
elif [[ $MODE == "bsim-server" ]] then
|
||||
LAUNCH_MODE=${LAUNCH_MODE:=fg}
|
||||
VMARG_LIST=${VMARG_LIST:="-Djava.awt.headless=true -Xshare:off"}
|
||||
mkdir -p $DATADIR_PATH
|
||||
/ghidra/support/launch.sh "$LAUNCH_MODE" jdk BSimControl "$MAXMEM" "$VMARG_LIST" ghidra.features.bsim.query.BSimControlLaunchable start $@
|
||||
# need to do this since the launched process is not blocking terminal exit
|
||||
while ! tail -f $DATADIR_PATH/logfile; do sleep 1 ; done
|
||||
elif [[ $MODE == "pyghidra" ]] then
|
||||
# Add optional JVM args inside the quotes
|
||||
VMARG_LIST=${VMARG_LIST:=""}
|
||||
PYGHIDRA_LAUNCHER="/ghidra/Ghidra/Features/PyGhidra/support/pyghidra_launcher.py"
|
||||
set -e
|
||||
source /ghidra/venv/bin/activate
|
||||
/ghidra/venv/bin/python3 "${PYGHIDRA_LAUNCHER}" "/ghidra" ${VMARG_LIST} "$@"
|
||||
else
|
||||
echo "Unknown MODE: $MODE. Valid MODE's are gui, headless, ghidra-server, bsim, bsim_ctl, or pyghidra."
|
||||
fi
|
|
@ -33,6 +33,7 @@ includeProjects('GPL')
|
|||
/*******************************************************************************************
|
||||
* Include miscellaneous support modules
|
||||
*******************************************************************************************/
|
||||
includeProject('docker', '.', true)
|
||||
includeProject('Doclets', 'GhidraBuild/BuildFiles', true)
|
||||
includeProject('LaunchSupport', 'GhidraBuild', true)
|
||||
includeProject('MarkdownSupport', 'GhidraBuild', true)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue