I used Putty most of the time. Once I discovered Kitty, I haven’t looked back as it is same as Putty but on steroids. In the world of secure shell (SSH) clients, Kitty stands out as a feature-rich and highly customizable option. While precompiled versions are readily available for different operating systems, I wanted to see how Kitty is compiled.
In this blog post, I will walk you through the process of compiling Kitty SSH client from source code.
Prerequisites
Before diving into the compilation process, ensure that you have the necessary tools and libraries installed on your system. I will use Ubuntu Linux virtual machine and will use docker image which comes with all necessary packages required for compiling.
Update the Installation
It is always a good approach to install latest updates
sudo apt-get update
sudo apt-get upgrade
Output:
Hit:1 http://us-central1.gce.archive.ubuntu.com/ubuntu jammy InRelease
Get:2 http://us-central1.gce.archive.ubuntu.com/ubuntu jammy-updates InRelease [119 kB]
Get:3 http://us-central1.gce.archive.ubuntu.com/ubuntu jammy-backports InRelease [108 kB]
Hit:4 http://security.ubuntu.com/ubuntu jammy-security InRelease
Fetched 226 kB in 0s (523 kB/s)
Reading package lists… Done
Install Docker
We will use Docker to download image which has all the compiling tools required
sudo apt-get install docker.io -y
Output:
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following package was automatically installed and is no longer required:
libnuma1
Use 'sudo apt autoremove' to remove it.
The following additional packages will be installed:
bridge-utils containerd dns-root-data dnsmasq-base pigz runc ubuntu-fan
Suggested packages:
ifupdown aufs-tools cgroupfs-mount | cgroup-lite debootstrap docker-doc rinse zfs-fuse
| zfsutils
The following NEW packages will be installed:
bridge-utils containerd dns-root-data dnsmasq-base docker.io pigz runc ubuntu-fan
0 upgraded, 8 newly installed, 0 to remove and 0 not upgraded.
Need to get 72.4 MB of archives.
After this operation, 287 MB of additional disk space will be used.
Get:1 http://us-central1.gce.archive.ubuntu.com/ubuntu jammy/universe amd64 pigz amd64 2.6-1 [63.6 kB]
... (truncated for length) ...
Create Working Directory
We will create directory which will be mounted inside the container to save the compiled binaries
mkdir builds && ls -l
Output:
total 4
drwxrwxr-x 2 wazeem wazeem 4096 Jul 1 12:36 builds
Download Docker Image
Download the docker image by cyd01 which has necessary components for compilation
sudo docker pull cyd01/cross-gcc
Output:
Using default tag: latest
latest: Pulling from cyd01/cross-gcc
d99de3d304f0: Pull complete
Digest: sha256:76e39c62686d0accda705b9f4b53bda43a08b15fbf1ceba54dc7620b347ed61a
Status: Downloaded newer image for cyd01/cross-gcc:latest
docker.io/cyd01/cross-gcc:latest
Run the Container
Now we will use a container from this image for code compilation. This command will drop us in container shell
sudo docker run --rm -it -v $(pwd)/builds:/builds cyd01/cross-gcc
Output:
user@cross-gcc:/sources$
Download Source Code
Pull the source code from Github repository
git clone https://github.com/cyd01/KiTTY.git
Output:
Cloning into 'KiTTY'...
remote: Enumerating objects: 4049, done.
remote: Counting objects: 100% (914/914), done.
remote: Compressing objects: 100% (281/281), done.
remote: Total 4049 (delta 641), reused 823 (delta 611), pack-reused 3135
Receiving objects: 100% (4049/4049), 10.02 MiB | 23.91 MiB/s, done.
Resolving deltas: 100% (2573/2573), done.
Modify the Code
Now we can make changes to code before compilation. For this demo, I will change the ssh client version. Using sed or vi, I am going to change ssh client version from “PuTTY-KiTTY” to “libssh_0.7.4“. Also make sure there is not spaces in the version name after “\0”
vi KiTTY/0.76b_My_PuTTY/utils/version.c
Save the changes and verify
cat KiTTY/0.76b_My_PuTTY/version.c |grep libssh
Output:
const char sshver[] = "libssh_0.7.4\0" ;
Compile the Code
Now, we will compile the windows binaries
cd KiTTY/0.76b_My_PuTTY/windows
make -f MAKEFILE.MINGW cross
Output:
sed -i ‘s#^typedef enum _WTS_VIRTUAL_CLASS #// typedef enum _WTS_VIRTUAL_CLASS #’ window.c
sed -i ‘s/0/999/’ version_major.txt
make -e TOOLPATH=/usr/bin/i686-w64-mingw32- -f MAKEFILE.MINGW putty.exe plink.exe pscp.exe psftp.exe pageant.exe puttygen.exe
… (truncated long compilation output) …
Packed 2 files.
mv putty.exe /builds/kitty.exe
mv putty_portable.exe /builds/kitty_portable.exe
mv putty_nocompress.exe /builds/kitty_nocompress.exe
mv plink.exe /builds/klink.exe
mv pscp.exe /builds/kscp.exe
mv psftp.exe /builds/ksftp.exe
mv pageant.exe /builds/kageant.exe
mv puttygen.exe /builds/kittygen.exe
rm *.o
Gather the Binary file
At the completion of compilation, we will have binary files in our build directory
exit
ls -l
Output:
total 6992
-rwxr-xr-x 1 wazeem wazeem 450560 Jul 1 13:43 kageant.exe
-rwxr-xr-x 1 wazeem wazeem 800256 Jul 1 13:42 kitty.exe
-rwxr-xr-x 1 wazeem wazeem 2028032 Jul 1 13:43 kitty_nocompress.exe
-rwxr-xr-x 1 wazeem wazeem 800256 Jul 1 13:43 kitty_portable.exe
-rwxr-xr-x 1 wazeem wazeem 539648 Jul 1 13:43 kittygen.exe
-rwxr-xr-x 1 wazeem wazeem 843776 Jul 1 13:43 klink.exe
-rwxr-xr-x 1 wazeem wazeem 839168 Jul 1 13:43 kscp.exe
-rwxr-xr-x 1 wazeem wazeem 845824 Jul 1 13:43 ksftp.exe
Verify the Changes
In the end, we will connect to ssh server using our compiled client and original client from vendor site to verify the modification using tcpdump/wireshark.
Tcpdump Output from Original Client

Tcpdump Output from Compiled Client

Download the Compiled Version
Here is the link to compiled version if you want to use. I highly recommend to use the official versions.