feat: integrate ghidra-cli v0.1
This commit is contained in:
commit
ffab80a1f2
52 changed files with 6689 additions and 126 deletions
306
flake.nix
Normal file
306
flake.nix
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
{
|
||||
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";
|
||||
};
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue