Ghidra: Difference between revisions

From NixOS Wiki
Klinger (talk | contribs)
install ghidra added
→‎Install Ghidra on NixOS: note that ghidra-bin doesn't support extensions earlier
 
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
[https://www.nsa.gov/ghidra Ghidra] is a software reverse engineering (SRE) framework created and maintained by the
American [https://en.wikipedia.org/wiki/National_Security_Agency National Security Agency] (NSA).


[https://www.nsa.gov/ghidra Ghidra] is a software reverse engineering (SRE) framework created and maintained by the American National Security Agency(NSA).j
=== Install Ghidra on NixOS ===
Ghidra can be installed from nixpkgs from source via the <code>ghidra</code> package or as a pre-packaged build using <code>ghidra-bin</code>.
 
There are a number of [https://github.com/NixOS/nixpkgs/tree/nixos-unstable/pkgs/tools/security/ghidra/extensions extensions] already supported in nixpkgs. Note that extensions ''cannot'' be used with the <code>ghidra-bin</code> package. If you want to build Ghidra with some extensions included, you can use the following:
 
<syntaxhighlight lang="nix">
      pkgs.ghidra.withExtensions (p: with p; [
        ret-sync
      ]);
</syntaxhighlight>
 
=== Ghidra overlays ===
 
Updating the <code>ghidra</code> package using an overlay is not as easy as most common packages in nixpkgs, due to it's
use of [https://gradle.org/ gradle] and how gradle-based packages are built on nix.
 
First you will need to generate a new gradle dependency (<code>deps.json</code>) file. which will
be be used to override the file specified in the <code>mitmCache</code> part of the <code>ghidra</code>
derivation.
 
In order to generate <code>deps.json</code>, you will need to git clone a copy of [https://github.com/NixOS/nixpkgs/ Nixpkgs] if you don't already have one. Inside of the clone you need modify the <code>rev</code> field of the attribute set passed to <code>mkDerivation</code> in [https://github.com/NixOS/nixpkgs/blob/nixos-unstable/pkgs/tools/security/ghidra/build.nix <code>pkgs/tools/security/ghidra/build.nix</code>] file, which used for building <code>ghidra</code>. The <code>rev</code> field should be set to whatever git commit you want to install.
 
Then from the root of your Nixpkgs folder run the command <code>$(nix-build -A
ghidra.mitmCache.updateScript)</code>. This command execute an update script to fetch the gradle
dependencies, and then stores the relevant information into <code>pkgs/tools/security/ghidra/deps.json</code>. Copy the
generated file over to your nix configuration and reference it in your overlays. In the example overlay
below, the <code>deps.json</code> file has been renamed to <code>ghidra-deps.json</code>.
 
<syntaxhighlight lang="nix">
        (final: prev: {
          ghidra = prev.ghidra.overrideAttrs (oldAttrs: {
            mitmCache = prev.gradle.fetchDeps {
              inherit (oldAttrs) pname;
              data = ./ghidra-deps.json;
            };
 
            src = prev.fetchFromGitHub {
              owner = "NationalSecurityAgency";
              repo = "Ghidra";
              rev = "7d5a514f25fe5bea52a0465c26ae5663855f79c9";
              hash = "sha256-PN5J2Wrr8RUF1UljG57bfw2lhlEqnmWwtZy5xQcrNsE=";
              # populate values that require us to use git. By doing this in postFetch we
              # can delete .git afterwards and maintain better reproducibility of the src.
              leaveDotGit = true;
              postFetch = ''
                cd "$out"
                git rev-parse HEAD > $out/COMMIT
                # 1970-Jan-01
                date -u -d "@$(git log -1 --pretty=%ct)" "+%Y-%b-%d" > $out/SOURCE_DATE_EPOCH
                # 19700101
                date -u -d "@$(git log -1 --pretty=%ct)" "+%Y%m%d" > $out/SOURCE_DATE_EPOCH_SHORT
                find "$out" -name .git -print0 | xargs -0 rm -rf
              '';
            };
</syntaxhighlight>
 
=== Declarative preferences ===
 
Although not built-in directly to the <code>ghidra</code> package, it's possible to create a declarative Ghidra <code>preferences</code> file. This does have the caveat that by making the file read-only, Ghidra will not be able to update it with new settings at runtime.  


=== Install Ghidra on NixOS ===
{{Note|If you prefer not to make the file read-only, you could optionally copy the read-only version from the [[Nix_package_manager#Nix_store|Nix store]] into the Ghidra settings
Ghidra can be installed from nixpkgs (ghidra, ghidra-bin). There are some extension packages available too.
folder, allowing you to then diff out settings you wish to make declarative. This is not currently shown.}}
 
The following is an example, using [[Home_Manager|Home Manager]], of how you might setup your Preferences file:


<syntaxhighlight lang="nix">
{
  lib,
  pkgs,
  config,
  ...
}:
let
  ghidra_pkg = pkgs.ghidra.withExtensions (
    exts:
    builtins.attrValues {
      # inherit (exts) <plugin-name>;
    }
  );
  ghidra_dir = ".config/ghidra/${pkgs.ghidra.distroPrefix}";
in
{
  home = {
    packages = [ ghidra_pkg ];
    file = {
      "${ghidra_dir}/preferences".text = ''
        GhidraShowWhatsNew=false
        SHOW.HELP.NAVIGATION.AID=true
        SHOW_TIPS=false
        TIP_INDEX=0
        G_FILE_CHOOSER.ShowDotFiles=true
        USER_AGREEMENT=ACCEPT
        LastExtensionImportDirectory=${config.home.homeDirectory}/.config/ghidra/scripts/
        LastNewProjectDirectory=${config.home.homeDirectory}/.config/ghidra/repos/
        ViewedProjects=
        RecentProjects=
      '';
    };
  };
}
// (lib.optionalAttrs pkgs.stdenv.isLinux {
  systemd.user.tmpfiles.rules = [
    # https://www.man7.org/linux/man-pages/man5/tmpfiles.d.5.html
    "d %h/${ghidra_dir} 0700 - - -"
    "L+ %h/.config/ghidra/latest - - - - %h/${ghidra_dir}"
    "d %h/.config/ghidra/scripts 0700 - - -"
    "d %h/.config/ghidra/repos 0700 - - -"
  ];
})
</syntaxhighlight>


=== Building Ghidra on NixOS ===
=== Building Ghidra on NixOS ===


Building Ghidra on NixOS can be a bit more finnicky than usual because of the gradle setup. This is an example shell.nix file.
Building Ghidra on NixOS can be a bit finicky because of the gradle setup. This is an example <code>shell.nix</code>
file to setup a development shell:
 
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
with import <nixpkgs> {};
with import <nixpkgs> {};
Line 14: Line 123:
pkgs.mkShell {
pkgs.mkShell {
   buildInputs = [
   buildInputs = [
     pkgs.jdk11
     pkgs.jdk21
     pkgs.gradle
     pkgs.gradle
     pkgs.gcc
     pkgs.gcc
Line 24: Line 133:
   shellHook = ''
   shellHook = ''
     rm -rf /tmp/gradle &> /dev/null
     rm -rf /tmp/gradle &> /dev/null
     mkdir /tmp/gradle  
     mkdir /tmp/gradle
     export GRADLE_USER_HOME="/tmp/gradle"  
     export GRADLE_USER_HOME="/tmp/gradle"
     echo "org.gradle.java.home=${pkgs.jdk11}/lib/openjdk" > /tmp/gradle/gradle.properties
     echo "org.gradle.java.home=${pkgs.jdk21}/lib/openjdk" > /tmp/gradle/gradle.properties
   '';
   '';
}
}
</syntaxhighlight>
</syntaxhighlight>
[[Category:Applications]]

Latest revision as of 04:33, 21 October 2024

Ghidra is a software reverse engineering (SRE) framework created and maintained by the American National Security Agency (NSA).

Install Ghidra on NixOS

Ghidra can be installed from nixpkgs from source via the ghidra package or as a pre-packaged build using ghidra-bin.

There are a number of extensions already supported in nixpkgs. Note that extensions cannot be used with the ghidra-bin package. If you want to build Ghidra with some extensions included, you can use the following:

      pkgs.ghidra.withExtensions (p: with p; [
        ret-sync
      ]);

Ghidra overlays

Updating the ghidra package using an overlay is not as easy as most common packages in nixpkgs, due to it's use of gradle and how gradle-based packages are built on nix.

First you will need to generate a new gradle dependency (deps.json) file. which will be be used to override the file specified in the mitmCache part of the ghidra derivation.

In order to generate deps.json, you will need to git clone a copy of Nixpkgs if you don't already have one. Inside of the clone you need modify the rev field of the attribute set passed to mkDerivation in pkgs/tools/security/ghidra/build.nix file, which used for building ghidra. The rev field should be set to whatever git commit you want to install.

Then from the root of your Nixpkgs folder run the command $(nix-build -A ghidra.mitmCache.updateScript). This command execute an update script to fetch the gradle dependencies, and then stores the relevant information into pkgs/tools/security/ghidra/deps.json. Copy the generated file over to your nix configuration and reference it in your overlays. In the example overlay below, the deps.json file has been renamed to ghidra-deps.json.

        (final: prev: {
          ghidra = prev.ghidra.overrideAttrs (oldAttrs: {
            mitmCache = prev.gradle.fetchDeps {
              inherit (oldAttrs) pname;
              data = ./ghidra-deps.json;
            };

            src = prev.fetchFromGitHub {
              owner = "NationalSecurityAgency";
              repo = "Ghidra";
              rev = "7d5a514f25fe5bea52a0465c26ae5663855f79c9";
              hash = "sha256-PN5J2Wrr8RUF1UljG57bfw2lhlEqnmWwtZy5xQcrNsE=";
              # populate values that require us to use git. By doing this in postFetch we
              # can delete .git afterwards and maintain better reproducibility of the src.
              leaveDotGit = true;
              postFetch = ''
                cd "$out"
                git rev-parse HEAD > $out/COMMIT
                # 1970-Jan-01
                date -u -d "@$(git log -1 --pretty=%ct)" "+%Y-%b-%d" > $out/SOURCE_DATE_EPOCH
                # 19700101
                date -u -d "@$(git log -1 --pretty=%ct)" "+%Y%m%d" > $out/SOURCE_DATE_EPOCH_SHORT
                find "$out" -name .git -print0 | xargs -0 rm -rf
              '';
            };

Declarative preferences

Although not built-in directly to the ghidra package, it's possible to create a declarative Ghidra preferences file. This does have the caveat that by making the file read-only, Ghidra will not be able to update it with new settings at runtime.

Note: If you prefer not to make the file read-only, you could optionally copy the read-only version from the Nix store into the Ghidra settings folder, allowing you to then diff out settings you wish to make declarative. This is not currently shown.

The following is an example, using Home Manager, of how you might setup your Preferences file:

{
  lib,
  pkgs,
  config,
  ...
}:
let
  ghidra_pkg = pkgs.ghidra.withExtensions (
    exts:
    builtins.attrValues {
      # inherit (exts) <plugin-name>;
    }
  );
  ghidra_dir = ".config/ghidra/${pkgs.ghidra.distroPrefix}";
in
{
  home = {
    packages = [ ghidra_pkg ];
    file = {
      "${ghidra_dir}/preferences".text = ''
        GhidraShowWhatsNew=false
        SHOW.HELP.NAVIGATION.AID=true
        SHOW_TIPS=false
        TIP_INDEX=0
        G_FILE_CHOOSER.ShowDotFiles=true
        USER_AGREEMENT=ACCEPT
        LastExtensionImportDirectory=${config.home.homeDirectory}/.config/ghidra/scripts/
        LastNewProjectDirectory=${config.home.homeDirectory}/.config/ghidra/repos/
        ViewedProjects=
        RecentProjects=
      '';
    };
  };
}
// (lib.optionalAttrs pkgs.stdenv.isLinux {
  systemd.user.tmpfiles.rules = [
    # https://www.man7.org/linux/man-pages/man5/tmpfiles.d.5.html
    "d %h/${ghidra_dir} 0700 - - -"
    "L+ %h/.config/ghidra/latest - - - - %h/${ghidra_dir}"
    "d %h/.config/ghidra/scripts 0700 - - -"
    "d %h/.config/ghidra/repos 0700 - - -"
  ];
})

Building Ghidra on NixOS

Building Ghidra on NixOS can be a bit finicky because of the gradle setup. This is an example shell.nix file to setup a development shell:

with import <nixpkgs> {};

pkgs.mkShell {
  buildInputs = [
    pkgs.jdk21
    pkgs.gradle
    pkgs.gcc
    pkgs.git
    pkgs.bison
    pkgs.flex
  ];

  shellHook = ''
    rm -rf /tmp/gradle &> /dev/null
    mkdir /tmp/gradle
    export GRADLE_USER_HOME="/tmp/gradle"
    echo "org.gradle.java.home=${pkgs.jdk21}/lib/openjdk" > /tmp/gradle/gradle.properties
  '';
}