306 lines
9.9 KiB
Nix
306 lines
9.9 KiB
Nix
{
|
|
description = "ghidr 0.1: pinned read-only Ghidra analysis CLI";
|
|
|
|
inputs.nixpkgs.url = "github:NixOS/nixpkgs/62e0f05ede1da0d54515d4ea8ce9c733f12d9f08";
|
|
|
|
outputs =
|
|
{ self, nixpkgs }:
|
|
let
|
|
system = "x86_64-linux";
|
|
pkgs = import nixpkgs { inherit system; };
|
|
inherit (pkgs) lib;
|
|
jdk = pkgs.jdk21_headless;
|
|
|
|
ghidra = pkgs.stdenvNoCC.mkDerivation {
|
|
pname = "ghidra";
|
|
version = "12.1.2";
|
|
src = pkgs.fetchurl {
|
|
url = "https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_12.1.2_build/ghidra_12.1.2_PUBLIC_20260605.zip";
|
|
hash = "sha256-ti6BoDkGGEZsAZxg2ML3ls7SUJxMGupKN2RKdycs+Z0=";
|
|
};
|
|
nativeBuildInputs = [
|
|
pkgs.autoPatchelfHook
|
|
pkgs.makeWrapper
|
|
pkgs.unzip
|
|
];
|
|
buildInputs = [ pkgs.stdenv.cc.cc.lib ];
|
|
dontConfigure = true;
|
|
dontBuild = true;
|
|
unpackPhase = ''
|
|
runHook preUnpack
|
|
unzip -q "$src"
|
|
sourceRoot=ghidra_12.1.2_PUBLIC
|
|
runHook postUnpack
|
|
'';
|
|
installPhase = ''
|
|
runHook preInstall
|
|
mkdir -p "$out/lib/ghidra" "$out/bin"
|
|
cp -a . "$out/lib/ghidra/"
|
|
patchShebangs "$out/lib/ghidra/support"
|
|
makeWrapper "$out/lib/ghidra/support/analyzeHeadless" "$out/bin/ghidra-analyzeHeadless" \
|
|
--set JAVA_HOME "${jdk}" \
|
|
--prefix PATH : "${
|
|
lib.makeBinPath [
|
|
jdk
|
|
pkgs.bash
|
|
pkgs.coreutils
|
|
pkgs.findutils
|
|
pkgs.gnugrep
|
|
pkgs.gnused
|
|
]
|
|
}"
|
|
runHook postInstall
|
|
'';
|
|
passthru = { inherit jdk; };
|
|
meta = {
|
|
description = "Ghidra 12.1.2 headless analysis distribution";
|
|
homepage = "https://github.com/NationalSecurityAgency/ghidra";
|
|
license = lib.licenses.asl20;
|
|
platforms = [ system ];
|
|
sourceProvenance = [ lib.sourceTypes.binaryBytecode ];
|
|
};
|
|
};
|
|
|
|
adapter = pkgs.stdenvNoCC.mkDerivation {
|
|
pname = "ghidr-java-adapter";
|
|
version = "0.1.0";
|
|
src = ./java;
|
|
nativeBuildInputs = [
|
|
jdk
|
|
pkgs.clang-tools
|
|
];
|
|
dontConfigure = true;
|
|
buildPhase = ''
|
|
runHook preBuild
|
|
clang-format --dry-run --Werror --style=Google GhidrAdapter.java
|
|
classpath="$(find ${ghidra}/lib/ghidra -type f -name '*.jar' -print | LC_ALL=C sort | paste -sd: -)"
|
|
# Ghidra's release JAR manifests reference optional JARs that are not
|
|
# shipped in the distribution. Keep adapter source warnings fatal,
|
|
# while excluding those upstream class-path warnings and preventing
|
|
# processors discovered in Ghidra's dependency closure from running.
|
|
javac -encoding UTF-8 -source 21 -target 21 -proc:none \
|
|
-Xlint:all,-path -Werror -cp "$classpath" GhidrAdapter.java
|
|
runHook postBuild
|
|
'';
|
|
installPhase = ''
|
|
runHook preInstall
|
|
mkdir -p "$out/share/ghidr/java"
|
|
install -m 0444 GhidrAdapter.java dispatch.txt "$out/share/ghidr/java/"
|
|
install -m 0444 ./*.class "$out/share/ghidr/java/"
|
|
runHook postInstall
|
|
'';
|
|
};
|
|
|
|
elfFixture = pkgs.stdenv.mkDerivation {
|
|
pname = "ghidr-fixture-elf-x86-64";
|
|
version = "0.1.0";
|
|
src = ./fixtures/src/known.c;
|
|
dontUnpack = true;
|
|
SOURCE_DATE_EPOCH = "1";
|
|
buildPhase = ''
|
|
runHook preBuild
|
|
$CC -x c "$src" -Os -ffreestanding -fno-ident -fno-stack-protector \
|
|
-fno-asynchronous-unwind-tables -fno-unwind-tables -nostdlib -static \
|
|
-no-pie -Wl,--build-id=none,-e,_start -o known.elf
|
|
runHook postBuild
|
|
'';
|
|
installPhase = ''
|
|
mkdir -p "$out/elf-x86_64"
|
|
install -m 0555 known.elf "$out/elf-x86_64/known.elf"
|
|
'';
|
|
};
|
|
|
|
peFixture = pkgs.pkgsCross.mingwW64.stdenv.mkDerivation {
|
|
pname = "ghidr-fixture-pe32plus-x86-64";
|
|
version = "0.1.0";
|
|
src = ./fixtures/src/known.c;
|
|
dontUnpack = true;
|
|
SOURCE_DATE_EPOCH = "1";
|
|
buildPhase = ''
|
|
runHook preBuild
|
|
$CC -x c "$src" -Os -ffreestanding -fno-ident -fno-stack-protector \
|
|
-nostdlib -Wl,--no-insert-timestamp,--entry,mainCRTStartup,--subsystem,console \
|
|
-o known.exe
|
|
runHook postBuild
|
|
'';
|
|
installPhase = ''
|
|
mkdir -p "$out/pe32plus-x86_64"
|
|
install -m 0555 known.exe "$out/pe32plus-x86_64/known.exe"
|
|
'';
|
|
};
|
|
|
|
fixtures = pkgs.symlinkJoin {
|
|
name = "ghidr-fixtures-0.1.0";
|
|
paths = [
|
|
elfFixture
|
|
peFixture
|
|
];
|
|
};
|
|
|
|
rustPackage = pkgs.rustPlatform.buildRustPackage {
|
|
pname = "ghidra-cli";
|
|
version = "0.1.0";
|
|
src = lib.cleanSource self;
|
|
cargoLock.lockFile = ./Cargo.lock;
|
|
doCheck = true;
|
|
cargoTestFlags = [ "--features=test-support" ];
|
|
nativeBuildInputs = [ pkgs.installShellFiles ];
|
|
};
|
|
|
|
ghidr =
|
|
pkgs.runCommand "ghidr-0.1.0"
|
|
{
|
|
nativeBuildInputs = [ pkgs.makeWrapper ];
|
|
meta.mainProgram = "ghidr";
|
|
}
|
|
''
|
|
mkdir -p "$out/bin" "$out/share/ghidr"
|
|
ln -s ${adapter}/share/ghidr/java "$out/share/ghidr/java"
|
|
makeWrapper ${rustPackage}/bin/ghidr "$out/bin/ghidr" \
|
|
--set GHIDR_GHIDRA_VERSION 12.1.2 \
|
|
--set GHIDR_JAVA_HOME ${jdk} \
|
|
--set GHIDR_ANALYZE_HEADLESS ${ghidra}/bin/ghidra-analyzeHeadless \
|
|
--set GHIDR_ADAPTER_PATH "$out/share/ghidr/java" \
|
|
--set GHIDR_BUBBLEWRAP ${pkgs.bubblewrap}/bin/bwrap \
|
|
--prefix PATH : ${
|
|
lib.makeBinPath [
|
|
ghidra
|
|
jdk
|
|
pkgs.bubblewrap
|
|
]
|
|
}
|
|
'';
|
|
|
|
realGhidraE2e =
|
|
pkgs.runCommand "ghidr-real-ghidra-e2e"
|
|
{
|
|
nativeBuildInputs = [
|
|
ghidr
|
|
pkgs.jq
|
|
];
|
|
}
|
|
''
|
|
export HOME="$TMPDIR/home"
|
|
mkdir -p "$HOME" "$TMPDIR/store"
|
|
${ghidr}/bin/ghidr --sandbox off --store "$TMPDIR/store" inspect \
|
|
${fixtures}/elf-x86_64/known.elf > elf.json
|
|
jq -e '
|
|
.kind == "inspection"
|
|
and .provenance.ghidr_version == "0.1.0"
|
|
and .provenance.ghidra_version == "12.1.2"
|
|
' elf.json
|
|
${ghidr}/bin/ghidr --sandbox off --store "$TMPDIR/store" functions \
|
|
${fixtures}/pe32plus-x86_64/known.exe --all > pe.json
|
|
jq -e '.kind == "functions" and (.data.items | length) > 0' pe.json
|
|
${ghidr}/bin/ghidr --sandbox off --store "$TMPDIR/store" decompile \
|
|
${fixtures}/elf-x86_64/known.elf --name fixture_add > decompile.json
|
|
jq -e '.data.function.name == "fixture_add"' decompile.json
|
|
touch "$out"
|
|
'';
|
|
|
|
adapterE2e =
|
|
pkgs.runCommand "ghidr-java-adapter-e2e"
|
|
{
|
|
nativeBuildInputs = [
|
|
ghidra
|
|
jdk
|
|
pkgs.bash
|
|
pkgs.jq
|
|
];
|
|
}
|
|
''
|
|
export HOME="$TMPDIR/home"
|
|
export GHIDR_ANALYZE_HEADLESS=${ghidra}/bin/ghidra-analyzeHeadless
|
|
export GHIDR_ADAPTER_PATH=${adapter}/share/ghidr/java
|
|
export GHIDR_FIXTURES=${fixtures}
|
|
mkdir -p "$HOME"
|
|
cp -R ${./tests} tests
|
|
chmod +x tests/real_ghidra_adapter.sh
|
|
patchShebangs tests/real_ghidra_adapter.sh
|
|
./tests/real_ghidra_adapter.sh
|
|
touch "$out"
|
|
'';
|
|
in
|
|
{
|
|
packages.${system} = {
|
|
default = ghidr;
|
|
inherit
|
|
ghidr
|
|
ghidra
|
|
adapter
|
|
fixtures
|
|
;
|
|
real-ghidra-e2e = realGhidraE2e;
|
|
};
|
|
|
|
apps.${system}.default = {
|
|
type = "app";
|
|
program = "${ghidr}/bin/ghidr";
|
|
meta.description = "Run ghidr with its pinned Ghidra runtime";
|
|
};
|
|
|
|
checks.${system} = {
|
|
rust = rustPackage;
|
|
java-adapter = adapter;
|
|
java-adapter-e2e = adapterE2e;
|
|
inherit fixtures;
|
|
real-ghidra-e2e = realGhidraE2e;
|
|
cargo-deny = pkgs.stdenvNoCC.mkDerivation {
|
|
pname = "ghidr-cargo-deny";
|
|
version = "0.1.0";
|
|
src = lib.cleanSource self;
|
|
inherit (rustPackage) cargoDeps;
|
|
nativeBuildInputs = [
|
|
pkgs.cargo
|
|
pkgs.cargo-deny
|
|
pkgs.rustPlatform.cargoSetupHook
|
|
];
|
|
dontConfigure = true;
|
|
CARGO_NET_OFFLINE = "true";
|
|
buildPhase = ''
|
|
runHook preBuild
|
|
cargo deny check bans licenses sources
|
|
runHook postBuild
|
|
'';
|
|
installPhase = ''
|
|
touch "$out"
|
|
'';
|
|
};
|
|
nix-style =
|
|
pkgs.runCommand "ghidr-nix-style"
|
|
{
|
|
nativeBuildInputs = [
|
|
pkgs.nixfmt-rfc-style
|
|
pkgs.statix
|
|
];
|
|
}
|
|
''
|
|
cp ${./flake.nix} flake.nix
|
|
nixfmt --check flake.nix
|
|
statix check flake.nix
|
|
touch "$out"
|
|
'';
|
|
};
|
|
|
|
devShells.${system}.default = pkgs.mkShell {
|
|
packages = [
|
|
pkgs.rustc
|
|
pkgs.cargo
|
|
pkgs.clippy
|
|
pkgs.rustfmt
|
|
pkgs.cargo-deny
|
|
pkgs.bubblewrap
|
|
pkgs.clang-tools
|
|
pkgs.nixfmt-rfc-style
|
|
pkgs.statix
|
|
pkgs.jq
|
|
jdk
|
|
ghidra
|
|
];
|
|
GHIDR_GHIDRA_VERSION = "12.1.2";
|
|
GHIDR_JAVA_HOME = "${jdk}";
|
|
GHIDR_ANALYZE_HEADLESS = "${ghidra}/bin/ghidra-analyzeHeadless";
|
|
GHIDR_ADAPTER_PATH = "${adapter}/share/ghidr/java";
|
|
};
|
|
};
|
|
}
|