Modifying Kali Packages

Kali has been built as a highly modular and customizable penetration testing framework and allows for some fairly advanced customization and usage. Customizations can happen at multiple levels, beginning at the source code level. The sources of all Kali packages are publicly available. In this chapter, we will show how you can retrieve packages, modify them, and build your own customized packages out of them. The Linux kernel is somewhat of a special case and as such, it is covered in a dedicated section (Section 9.2, "Recompiling the Linux Kernel"), where we will discuss where to find sources, how to configure the kernel build, and finally how to compile it and how to build the associated kernel packages.

The second level of customization is in the process of building live ISO images. We will show how the live-build tool offers plenty of hooks and configuration options to customize the resulting ISO image, including the possibility to use custom Debian packages in place of the packages available on mirrors.

We will also discuss how you can create a persistent live ISO built onto a USB key that will preserve files and operating system changes between reboots.

9.1. Modifying Kali Packages

Modifying Kali packages is usually a task for Kali contributors and developers: they update packages with new upstream versions, they tweak the default configuration for a better integration in the distribution, or they fix bugs reported by users. But you might have specific needs not fulfilled by the official packages and knowing how to build a modified package can thus be very valuable.

You might wonder why you need to bother with the package at all. After all, if you have to modify a piece of software, you can always grab its source code (usually with git) and run the modified version directly from the source checkout. This is fine when it is possible and when you use your home directory for this purpose, but if your application requires a system-wide setup (for example, with a make install step) then it will pollute your file system with files unknown to dpkg and will soon create problems that cannot be caught by package dependencies. Furthermore, with proper packages you will be able to share your changes and deploy them on multiple computers much more easily or revert the changes after having discovered that they were not working as well as you hoped.

So when would you want to modify a package? Let's take a look at a few examples. First, we will assume that you are a heavy user of SET and you noticed a new upstream release but the Kali developers are all busy for a conference and you want to try it out immediately. You want to update the package yourself. In another case, we will assume that you are struggling to get your MIFARE NFC card working and you want to rebuild "libfreefare" to enable debug messages in order to have actionable data to provide in a bug report that you are currently preparing. In a last case, we will assume that the "pyrit" program fails with a cryptic error message. After a web search, you find a commit that you expect to fix your problem in the upstream GitHub repository and you want to rebuild the package with this fix applied.

We will go through all those samples in the following sections. We will try to generalize the explanations so that you can better apply the instructions to other cases but it is impossible to cover all situations that you might encounter. If you hit problems, apply your best judgment to find a solution or go seek help on the most appropriate forums (see Chapter 6, Helping Yourself and Getting Help).

Whatever change you want to make, the general process is always the same: grab the source package, extract it, make your changes, then build the package. But for each step, there are often multiple tools that can handle the task. We picked the most relevant and most popular tools, but our review is not exhaustive.

9.1.1. Getting the Sources

Rebuilding a Kali package starts with getting its source code. A source package is composed of multiple files: the main file is the *.dsc (Debian Source Control) file as it lists the other accompanying files, which can be *.tar.{gz,bz2,xz}, sometimes *.diff.gz, or *.debian.tar.{gz,bz2,xz} files.

The source packages are stored on Kali mirrors that are available over HTTP. You could use your web browser to download all the required files but the easiest way to accomplish this is to use the apt source source_package_name command. This command requires a deb-src line in the /etc/apt/sources.list file and up-to-date index files (accomplished by running apt update). By default, Kali doesn't add the required line as few Kali users actually need to retrieve source packages but you can easily add it (see sample file in Section 8.1.3, "Kali Repositories" and the associated explanations in Section 8.1.2, "Understanding the sources.list File").

In this example, while we received the source package from a Kali mirror, the package is the same as in Debian since the version string doesn't contain "kali." This means that no kali-specific changes have been applied.

If you need a specific version of the source package, which is currently not available in the repositories listed in /etc/apt/sources.list, then the easiest way to download it is to find out the URL of its .dsc file by looking it up on http://pkg.kali.org and then handing that URL over to dget (from the devscripts package).

After having looked up the URL of the libreefare source package available in kali-bleeding-edge, you can download it with dget. It will first download the .dsc file, then parse it to know what other files are referenced, and then download those from the same location:

It is worth noting that dget did not automatically extract the source package because it could not verify the PGP signature on the source package. Thus we did that step manually with dpkg-source -x dsc-file. You can also force the source package extraction by passing the --allow-unauthenticated or -u option. Inversely, you can use --download-only to skip the source package extraction step.

Retrieving Sources from Git


You might have noticed that the apt source invocation tells you about a possible Git repository used to maintain the package. It might point to a Debian Git repository or to a Kali Git repository.

All Kali-specific packages are maintained in Git repositories hosted on git.kali.org. You can retrieve the sources from those repositories with git clone git://git.kali.org/packages/source-package. If the operation doesn't yield the expected sources, try switching to the kali/master branch with git checkout kali/master.

Contrary to what you get with apt source, the obtained tree will not have patches automatically applied. Have a look at debian/patches/ to learn about the possible changes made by Kali.

You can use the git repositories as another way to retrieve the sources and thus (mostly) follow the other instructions from this section. But when Kali developers work with those repositories, they use another packaging workflow and use tools from the git-buildpackage package that we will not cover here. You can learn more about those tools here:

https://honk.sigxcpu.org/piki/projects/git-buildpackage/

9.1.2. Installing Build Dependencies

Now that you have the sources, you still need to install build dependencies. They will be necessary to build the desired binary packages but are also likely required for partial builds that you might want to run to test the changes while you make them.

Each source package declares its build dependencies in the Build-Depends field of the debian/control file. Let's instruct apt to install those (assuming that you are in a directory containing an unpacked source package):

In this sample, all build dependencies can be satisfied with packages available to APT. This might not always be the case as the tool building kali-rolling does not ensure installability of build dependencies (only dependencies of binary packages are taken into account). In practice, binary dependencies and build dependencies are often tightly coupled and most packages will have their build dependencies satisfiable.

9.1.3. Making Changes

We can't cover all the possible changes that you might want to make to a given package in this section. This would amount to teaching you all the nitty gritty details of Debian packaging. However, we will cover the three common use cases presented earlier and we will explain some of the unavoidable parts (like maintaining the changelog file).

The first thing to do is to change the package version number so that the rebuilt packages can be distinguished from the original packages provided by Kali or Debian. To achieve this, we usually add a suffix identifying the entity (person or company) applying the changes. Since buxy is my IRC nickname, I will use it as a suffix. Such a change is best effected with the dch command (Debian CHangelog) from the devscripts package, with a command such as dch --local buxy. This invokes a text editor (sensible-editor, which runs the editor assigned in the VISUAL or EDITOR environment variables, or /usr/bin/editor otherwise), which allows you to document the differences introduced by this rebuild. This editor shows that dch really did change the debian/changelog file:

If you do such changes regularly, you might want to set the DEBFULLNAME and DEBEMAIL environment variables to your full name and your email, respectively. Their values will be used by many packaging tools, including dch, which will embed them on the trailer line shown above (starting with " -- ").

9.1.3.1. Applying a Patch

In one of our use cases, we have downloaded the pyrit source package and we want to apply a patch that we found in the upstream git repository. This is a common operation and it should always be simple. Unfortunately, patches can be handled in different ways depending on the source package format and on the Git packaging workflow in use (when Git is used to maintain the package).

9.1.3.1.1. With an Unpacked Source Package

You have run apt source pyrit and you have a pyrit-0.4.0 directory. You can apply your patch directly with patch -p1< patch-file:

At this point, you have manually patched the source code and you can already build binary packages of your modified version (see Section 9.1.4, "Starting the Build"). But if you try to build an updated source package, it will fail, complaining about "unexpected upstream changes." This is because pyrit (like a majority of the source packages) uses the source format (see debian/source/format file) known as 3.0 (quilt), where changes to the upstream code must be recorded in separate patches stored in debian/patches/ and where the debian/patches/series file indicates the order in which patches must be applied. You can register your changes in a new patch by running dpkg-source --commit:

Quilt Patch Series


This patch management convention has been popularized by a tool named quilt and the "3.0 (quilt)" source package format is thus compatible with this tool—with the small deviation that it uses debian/patches instead of patches. This tool is available in the package of the same name and you can find a nice tutorial here:

https://raphaelhertzog.com/2012/08/08/how-to-use-quilt-to-manage-patches-in-debian-packages/

If the source package uses the 1.0 or 3.0 (native) source format, then there is no requirement to register your upstream changes in a patch. They are automatically bundled in the resulting source package.

9.1.3.1.2. With a Git Repository

If you have used Git to retrieve the source package, the situation is even more complicated. There are multiple Git workflows and associated tools, and obviously not all Debian packages are using the same workflows and tools. The distinction already explained about source format is still relevant but you must also check whether patches are pre-applied in the source tree or whether they are only stored in debian/patches (in this case, they are then applied at build time).

The most popular tool is git-buildpackage. It is what we use to manage all repositories on git.kali.org. When you use it, patches are not pre-applied in the source tree but they are stored in debian/patches. You can manually add patches in that directory and list them in debian/patches/series but users of git-buildpackage tend to use gbp pq to edit the entire patch series as a single branch that you can extend or rebase to your liking. Check gbp-pq(1) to learn how to invoke it.

git-dpm (with associated command of the same name) is another git packaging tool that you can find in use. It records metadata in debian/.git-dpm and keeps patches applied in the source tree by merging a constantly-rebased branch that it builds out of the content of debian/patches.

9.1.3.2. Tweaking Build Options

You usually have to tweak build options when you want to enable an optional feature or behaviour that is not activated in the official package, or when you want to customize parameters that are set at build time through a ./configure option or through variables set in the build environment.

In those cases, the changes are usually limited to debian/rules, which drives the steps in the package build process. In the simplest cases, the lines concerning the initial configuration (./configure …) or the actual build ($(MAKE) … or make …) are easy to spot. If these commands are not explicitly called, they are probably a side effect of another explicit command, in which case, please refer to their documentation to learn more about how to change the default behaviour. With packages using dh, you might need to add an override for the dh_auto_configure or dh_auto_build commands (see their respective manual pages for explanations on how to achieve this).

To make those explanations more concrete, let's apply them to our sample use case. You decided to modify libfreefare to pass the --enable-debug option to the ./configure script so that you could get a more verbose output from your near field communication (NFC) tools and file a better bug report about your non-recognized Mifare NFC card. Since the package uses dh to drive the build process, you add (or in this case modify) the override_dh_auto_configure target. Here is the corresponding extract of libfreefare's debian/rules file:

9.1.3.3. Packaging a New Upstream Version

Let's take a look at an example at this point, as we discuss packaging upstream versions. Let's say you are a SET power-user and you noticed a new upstream release (7.4.5) that is not yet available in Kali (which only has version 7.4.4). You want to build an updated package and try it out. This is a minor version bump and you thus don't expect the update to require any change at the packaging level.

To update the source package, you extract the new source tarball next to the current source package and you copy the debian directory from the current source package to the new one. Then you bump the version in debian/changelog.

That's it. You can now build the updated package.

Depending on the kind of changes that the new upstream version introduces, you may also need to change build dependencies and run-time dependencies, and install new files. Those are much more involved operations that are not covered by this book.

9.1.4. Starting the Build

When all the needed changes have been applied to the sources, you can start generating the actual binary package or .deb file. The whole process is managed by the dpkg-buildpackage command and it looks like this:

The -us -uc options disable signatures on some of the generated files (.dsc, .changes) because this operation will fail if you do not have a GnuPG key associated with the identity you have put in the changelog file. The -boption asks for a "binary-only build." In this case, the source package (.dsc) will not be created, only the binary (.deb) packages will. Use this option to avoid failures during the source package build: if you haven't properly recorded your changes in the patch management system, it might complain and interrupt the build process.

As suggested by dpkg-deb's messages, the generated binary packages are now available in the parent directory (the one that hosts the directory of the source package). You can install them with dpkg -i or apt install.

We prefer apt install over dpkg -i as it will deal with missing dependencies gracefully. But not so long ago, you had to use dpkg as apt was not able to deal with .deb files outside of any repository.

dpkg-buildpackage wrappers


More often than not, Debian developers use a higher-level program such as debuild; this runs dpkg-buildpackage as usual, but it also adds an invocation of a program (lintian) that runs many checks to validate the generated package against the Debian policy. This script also cleans up the environment so that local environment variables do not pollute the package build. The debuild command is one of the tools in the devscripts suite, which share some consistency and configuration to make the maintainers' task easier.