---
title: 'KiTTY Password Decryptor'
url: 'https://kvc.pl/repositories/kittypassworddecryptor'
markdown: 'https://kvc.pl/repositories/kittypassworddecryptor.md'
date: '2026-08-29'
description: 'KiTTY Password Decryptor (dp.exe): Modern C++23 Win32 utility for decrypting KiTTY session passwords using custom Blowfish/nbcrypt algorithm. Features GUI with dark mode and MICA support, CLI mode for scripting, CSV/JSON export, recursive session scanning, and zero external dependencies. Statically linked with /MT — no VC++ Redistributable required.'
---

> KiTTY Password Decryptor (dp.exe): Modern C++23 Win32 utility for decrypting KiTTY session passwords using custom Blowfish/nbcrypt algorithm.

 [ Download dp.zip](https://kvc.pl/repositories/kittypassworddecryptor/dp.zip) [ Source on GitHub](https://github.com/wesmar/KittyPasswordDecryptor)

# dp.exe — KiTTY Password Decryptor

![KiTTY Password Decryptor](https://kvc.pl/user/pages/04.repositories/16.kittypassworddecryptor/images/KittyPasswordDecryptor.jpg)

**Version 1.0.0** — Modern C++23 Win32 utility for decrypting KiTTY session passwords *Standalone Win32 utility that reads KiTTY `Sessions` directories, decrypts stored passwords using KiTTY's custom Blowfish/nbcrypt algorithm, and displays results in a sortable, filterable GUI.* *Operates in two modes: a full Win32 dialog interface with dark-mode and MICA support, and a headless CLI mode for scripting. Exports to CSV or JSON. Zero external dependencies — pure Win32, statically linked, no VC++ Redistributable required.* 

---

## 📚 Table of Contents

- [Feature Overview](#feature-overview)
- [Architecture](#architecture)
- [Usage](#usage)
    - [GUI Mode](#gui-mode)
    - [CLI Mode](#cli-mode)
- [Crypto Engine](#crypto-engine)
- [Session Scanner](#session-scanner)
- [Export](#export)
- [UI and Dark Mode](#ui-and-dark-mode)
- [Module Map](#module-map-for-maintainers)
- [Source Tree](#source-tree-local-repo)
- [Build System](#build-system)
- [System Requirements](#system-requirements)

---

## Feature Overview

This is a standalone Win32 utility written in modern C++23 that provides comprehensive KiTTY password decryption capabilities:

### Core Capabilities

- **Password decryption** — KiTTY custom base64 + Fisher-Yates scramble seeded by ciphertext prefix; two key derivation modes tried automatically
- **Session scanning** — Recursive directory walker (max depth 4) searches for `Sessions` folders; percent-decodes filenames; skips `Default Settings`
- **GUI** — Win32 dialog, sortable/filterable `SysListView32`, double-click / right-click clipboard copy
- **CLI** — Headless single-password decrypt; two argument orderings; attaches to parent console for pipeline use
- **Export CSV** — RFC 4180, semicolon-separated, double-quote escaping, UTF-8 no BOM
- **Export JSON** — Pretty-printed JSON array, full Unicode escape for control characters, UTF-8 no BOM
- **Dark mode** — Auto-detects Windows dark/light theme; MICA backdrop on Win11 (build ≥ 22000); rounded corners via DWM; reacts to `WM_SETTINGCHANGE` live
- **DPI** — Per-Monitor DPI v2 (manifest); `Segoe UI Variable` on Win11, `Segoe UI` fallback; font scaled via `GetDpiForWindow`
- **No dependencies** — Pure Win32; no external DLLs; no VC++ Redistributable; statically linked CRT (`/MT`)

### Design Priorities

1. Zero external dependencies — pure Win32 API surface
2. Modern C++23 architecture with RAII and `std::format`
3. Deterministic behavior with fail-fast crypto fallback
4. Native Windows UX with dark mode, MICA, and DPI awareness

---

## Architecture

### Layered Structure

flowchart TD A[wmain Entry Point] --> B[dp::app::Run] B --> C{CLI Args?} C -->|Yes| D[CLI Mode] C -->|No| E[GUI Mode] D --> F[dp::core::DecryptPassword] E --> G[dp::ui::MainDialog] F --> H[KittyDecryptBase64] G --> I[OnScan] G --> J[OnExportCsv] G --> K[OnExportJson] I --> L[dp::core::LoadSessionsFromRoot] L --> M[ScanDir Walker] L --> N[ReadKeyValues Parser] L --> O[BuildSession] O --> H J --> P[dp::core::ExportCsv] K --> Q[dp::core::ExportJson] 

```
wmain (dp.cpp)
  ↓
dp::app::Run (App.cpp)
  ├─ CLI path  ──► dp::core::DecryptPassword ──► KittyDecryptBase64
  │                                               └─ KiTTY base64 engine
  └─ GUI path  ──► dp::ui::MainDialog::Show
                        ├─ OnScan ──► dp::core::LoadSessionsFromRoot
                        │             ├─ ScanDir (recursive walker)
                        │             ├─ ReadKeyValues (kv parser)
                        │             └─ BuildSession ──► DecryptPassword
                        ├─ OnExportCsv  ──► dp::core::ExportCsv
                        ├─ OnExportJson ──► dp::core::ExportJson
                        └─ ApplyTheme ──► DWM + uxtheme dark-mode stack
```

### Namespace Map

| Namespace | Directory | Responsibility |
|---|---|---|
| `dp::app` | `src/app/` | CLI/GUI dispatch, COM init, console attach |
| `dp::core` | `src/core/` | Crypto, scan, export, string utilities |
| `dp::ui` | `src/ui/` | Win32 dialog, dark mode, ListView |
| `dp::ui::dark` | `src/ui/DarkMode.h` | Undocumented uxtheme wrappers |

---

## Usage

### GUI Mode

Launch `dp.exe` with no arguments. The main dialog opens:

1. Click **Browse…** to select a root folder (e.g. your KiTTY Portable directory or `%APPDATA%\KiTTY`).
2. Click **Scan** — the tool recursively finds all `Sessions` subdirectories and decrypts every stored password.
3. Use the **Filter** box to search across session name, host, user, terminal type and password simultaneously (case-insensitive).
4. Click any column header to sort; click again to reverse.
5. Double-click a row or right-click → **Copy selected** to copy tab-separated fields to the clipboard.
6. **Export CSV** / **Export JSON** — save the currently shown (filtered) set via a standard Save dialog.

Rows with a failed decrypt are rendered in red. The status bar shows total / shown / decrypted counts.

### CLI Mode

```
dp.exe <password> <host> <term> [0|1]
dp.exe <0|1>      <host> <term> <password>
```

Two argument orderings are accepted — mode flag first or password first. The mode flag is optional; when omitted the engine tries both key derivation modes automatically.

**Example (from `build.ps1` smoke test):**

```
dp.exe 1633bGXSgBnT4I wesmar.wp.pl xterm 0
Expected output: bc107!+
```

On success the plaintext is written to stdout followed by a newline and the process exits with code `0`. On failure `ERR:DECRYPT` is printed and the exit code is `1`. When launched from a terminal the process auto-attaches to the parent console and sets UTF-8 output.

**Help:**

```
dp.exe --help
dp.exe -h
dp.exe /?
```

---

## Crypto Engine

KiTTY stores passwords as a custom base64-encoded ciphertext. The decryption algorithm implemented in `KittyBcrypt.cpp` works as follows:

### Base Alphabet

A shuffled 64-character set distinct from standard Base64:

```
AZERTYUIOPQSDFGHJKLMWXCVBNazertyuiopqsdfghjklmwxcvbn0123456789+/
```

### Key Derivation

Two modes, both attempted automatically:

| Mode | Key |
|---|---|
| 0 (default) | `host + term + "KiTTY"` |
| 1 (portable) | `"KiTTY"` (password-only variant) |

### Decryption Steps

\[mermaid\]
flowchart LR
A\[Ciphertext\] --> B\[Seed Alphabet
≤5 bytes\]
B --> C\[Advance Past
Seed Prefix\]
C --> D{Marker Byte?}
D -->|Yes| E\[Accumulate Offset
Re-scramble Alphabet\]
D -->|No| F\[Locate in Alphabet\]
E --> G\[Output
offset + index\]
F --> G
G --> H{Every pattern.size()?}
H -->|Yes| I\[Key Re-scramble\]
H -->|No| J{More Bytes?}
I --> J
J -->|Yes| D
J -->|No| K\[Plaintext Output\]

```

1. **Seed the alphabet** with the first ≤ 5 bytes of the ciphertext (Fisher-Yates scramble driven by ciphertext bytes).
2. **Advance past** the 5-byte seed prefix.
3. **For each remaining ciphertext byte:**
   - Detect **marker bytes** (equal to the last character of the current alphabet)
   - Each marker accumulates an offset and re-scrambles the alphabet using the key
4. **Locate the non-marker byte** in the current alphabet; output `offset + index` as the plaintext byte.
5. **Every `pattern.size()` decoded bytes** trigger another key-driven re-scramble.
6. **Skip silently:** embedded newlines and characters absent from the current alphabet.

`DecryptPassword` tries mode 0 first; falls back to mode 1 if mode 0 yields no output.

---

## Session Scanner {#session-scanner}

`Scan.cpp` — `LoadSessionsFromRoot(root, out)`

### Scanning Process

[mermaid]
flowchart TD
    A[Root Directory] --> B[Recursive Walk<br/>Max Depth 4]
    B --> C{Directory =<br/>'Sessions'?}
    C -->|No| B
    C -->|Yes| D[Read All Files<br/>in Sessions]
    D --> E[Parse Key-Value<br/>KeyName\Value\n]
    E --> F[Percent-Decode<br/>Filename]
    F --> G{Default Settings?}
    G -->|Yes| H[Skip]
    G -->|No| I[Extract Fields]
    I --> J[Decrypt Password]
    J --> K[Build Session Struct]
    K --> L[Add to Output]
```

### Scanner Characteristics

- Recursively walks subdirectories up to **depth 4**
- When a directory named `Sessions` (case-insensitive) is found, all files inside it are treated as session files
- Subdirectories of `Sessions` are **not** descended
- Each session file is parsed as `KeyName\Value\n` key-value pairs (KiTTY's native storage format)
- The filename is percent-decoded (`%XX` → byte) and widened to UTF-16 for the session name
- `Default Settings` (and its percent-encoded form) is silently skipped

### Fields Extracted Per Session

| Field | Registry key |
|---|---|
| Session name | filename (percent-decoded) |
| Host | `HostName` |
| User | `UserName` |
| Terminal | `TerminalType` (default: `xterm`) |
| Port | `PortNumber` |
| Encrypted password | `Password` |

- Files are read in a single `ReadFile` call (capped at 64 MiB)
- Zero-copy `string_view` slicing is used for line parsing

---

## Export

Both exporters build the entire output in a `std::string` buffer before writing in a single `fwrite` call (RAII `unique_ptr<FILE>`).

### CSV Export (`ExportCsv`)

- Semicolon-separated, UTF-8 no BOM
- RFC 4180 double-quote escaping
- Columns: `Session;Host;User;Port;Term;Password;Source`

### JSON Export (`ExportJson`)

- Pretty-printed JSON array, one object per line
- `std::format` used for field serialisation
- All control characters (`< 0x20`) emitted as `\uXXXX`
- Special characters (`"`, `\`, `\n`, `\r`, `\t`) escaped per JSON spec

---

## UI and Dark Mode

`MainDialog` is a single modal Win32 dialog (`DIALOGEX`, resource `IDD_MAIN`). All Windows API surface uses Unicode (`W` variants). The dialog owns one `SysListView32` with full-row select, double-buffer, and grid lines.

### Dark Mode Detection

Reads `HKCU\...\Themes\Personalize\AppsUseLightTheme`. Theme is applied on `WM_INITDIALOG` and refreshed live on `WM_SETTINGCHANGE / ImmersiveColorSet`.

### DWM Attributes Applied at Runtime

| Attribute | Effect |
|---|---|
| `DWMWA_USE_IMMERSIVE_DARK_MODE` (20) | Dark title bar |
| `DWMWA_SYSTEMBACKDROP_TYPE` (38) = `DWMSBT_MAINWINDOW` | MICA backdrop (Win11 only) |
| `DWMWA_WINDOW_CORNER_PREFERENCE` (33) = `DWMWCP_ROUND` | Rounded window corners |

### Undocumented uxtheme.dll Ordinals

Loaded dynamically; all calls are no-ops on older Windows:

| Ordinal | Function | Purpose |
|---|---|---|
| 133 | `AllowDarkModeForWindow` | Opts a specific HWND into dark rendering |
| 135 | `SetPreferredAppMode(1)` | Allows dark menus and scrollbars process-wide |
| 136 | `FlushMenuThemes` | Forces menu renderer to pick up dark preference |
| 137 | `RefreshImmersiveColorPolicyState` | Tells DWM color system to re-read user preference |

### ListView Styling

`SetWindowTheme(list_, L"DarkMode_Explorer", nullptr)` applied to the `SysListView32` and its header in dark mode. The `NM_CUSTOMDRAW` handler:

- Colours failed-decrypt rows **red**
- Highlights filtered rows with a **tinted background**

### Font

`Segoe UI Variable` (Win11) / `Segoe UI` (Win10), height scaled with `GetDpiForWindow` and `MulDiv(9, dpi, 72)`, `CLEARTYPE_QUALITY`.

---

## Module Map (for Maintainers)

| File | Purpose |
|---|---|
| `src/dp.cpp` | `wmain` — Unicode entry point |
| `src/app/App.cpp` | `Run()` — argument parsing, CLI decrypt, GUI bootstrap |
| `src/app/App.h` | `Run()` declaration |
| `src/core/Crypto.cpp` | `DecryptPassword` — tries both key derivation modes |
| `src/core/Crypto.h` | Public decrypt API |
| `src/core/KittyBcrypt.cpp` | `KittyDecryptBase64` — full KiTTY nbcrypt algorithm |
| `src/core/KittyBcrypt.h` | Decrypt function declaration |
| `src/core/Scan.cpp` | `LoadSessionsFromRoot` — walker, parser, session builder |
| `src/core/Scan.h` | Scanner API |
| `src/core/Export.cpp` | `ExportCsv`, `ExportJson` |
| `src/core/Export.h` | Export API |
| `src/core/Session.h` | `Session` struct (name, host, user, term, port, password, source) |
| `src/core/StringUtil.cpp` | `WidenUtf8Fallback`, `NarrowUtf8`, `BaseName`, `PercentDecode`, `IEquals`, `ContainsInsensitive` |
| `src/core/StringUtil.h` | String utility declarations |
| `src/ui/MainDialog.cpp` | Win32 dialog — all message handling, theming, ListView, export |
| `src/ui/MainDialog.h` | `MainDialog` class declaration |
| `src/ui/DarkMode.h` | Inline dark-mode wrappers over undocumented uxtheme ordinals |
| `src/WinCommon.h` | Windows targeting macros, lean headers |
| `src/Resource.h` | Dialog and control resource IDs |
| `src/LinkerDeps.cpp` | `#pragma comment(lib, …)` for comctl32, dwmapi, ole32, shell32, uxtheme |
| `src/dp.manifest` | Per-Monitor DPI v2, long-path aware, CC v6, Win10/11 compat |
| `src/dp.rc` | Dialog template and version resource |
| `dp.vcxproj` | MSBuild project — Debug/Release × Win32/x64, C++23, `/MT` release |
| `build.ps1` | PowerShell build script — clean, build both arches, strip intermediates, reproducible timestamps |

---

## Source Tree (Local Repo)

Current local layout:

```
dp/
├─ src/
│   ├─ dp.cpp                  wmain
│   ├─ WinCommon.h             Windows targeting + lean headers
│   ├─ Resource.h              Control and dialog IDs
│   ├─ LinkerDeps.cpp          Pragma-lib dependencies
│   ├─ dp.manifest             DPI v2 / CC v6 / Win11 compat manifest
│   ├─ dp.rc                   Dialog template + version resource
│   ├─ app/
│   │   ├─ App.cpp             CLI/GUI dispatch
│   │   └─ App.h
│   ├─ core/
│   │   ├─ Session.h           Session data struct
│   │   ├─ Crypto.cpp/h        DecryptPassword (dual-mode key derivation)
│   │   ├─ KittyBcrypt.cpp/h   KittyDecryptBase64 (nbcrypt engine)
│   │   ├─ Scan.cpp/h          Session directory walker and parser
│   │   ├─ Export.cpp/h        CSV and JSON export
│   │   └─ StringUtil.cpp/h    UTF-8/wide conversions, percent-decode, search
│   └─ ui/
│       ├─ DarkMode.h          Uxtheme ordinal wrappers (header-only)
│       ├─ MainDialog.cpp      Full Win32 dialog implementation
│       └─ MainDialog.h
├─ dp.vcxproj                  MSBuild project
├─ dp.vcxproj.filters          Solution Explorer filter layout
├─ dp.slnx                     Solution file
└─ build.ps1                   Build + clean + smoke test script
```

Build output:

```
bin/
├─ x86/dp.exe
└─ x64/dp.exe
```

---

## Build System

**Requirements:** Visual Studio 2026 with C++ Desktop workload (MSVC v145 toolset).

```powershell
.\build.ps1
```

The script performs the following steps:

1. **Locate VS 2026** via `vswhere.exe`
2. **Kill any running `dp.exe`** from the repo directory (avoids file-lock on clean)
3. **Remove `bin\` and `obj\`** directories
4. **Build Release|Win32 and Release|x64** via MSBuild
5. **Strip all intermediates** (`obj\` and everything in `bin\` except `dp.exe`)
6. **Stamp both binaries** with a reproducible timestamp of `2030-01-01`

### Compiler Flags (Release)

| Flag | Purpose |
|---|---|
| `/std:c++latest` | C++23 features (`std::format`, `std::ranges`, designated initialisers) |
| `/utf-8` | Source and execution charset = UTF-8 |
| `/W4 /permissive- /sdl` | High warning level, strict conformance, security checks |
| `/Zc:__cplusplus /Zc:preprocessor` | Correct `__cplusplus` value, conformant preprocessor |
| `/MT` | Static CRT — no VC++ Redistributable on target |
| `/O2 /GL /LTCG` | Max speed, whole-program optimisation, link-time code generation |
| `/BREPRO` | Reproducible builds |

### Linker Entry Point

`wmainCRTStartup` — Unicode wide-char `wmain`; no narrow-string codec risk for path arguments.

### Smoke Test

Printed by `build.ps1` on completion:

```powershell
cd test
..\bin\x86\dp.exe 1633bGXSgBnT4I wesmar.wp.pl xterm 0
# Expected: bc107!+
```

---

## System Requirements

| Component | Requirement |
|---|---|
| **Operating System** | Windows 10 or later (Windows 11 recommended for MICA and rounded corners) |
| **Architecture** | x64 (`bin\x64\dp.exe`) and x86 (`bin\x86\dp.exe`) |
| **Compiler (build)** | Visual Studio 2026, MSVC v145 toolset, C++23 |
| **Runtime dependencies** | None — static CRT (`/MT`), pure Win32; no VC++ Redistributable required |
| **Windows APIs** | comctl32, dwmapi, ole32 (IFileDialog), shell32, uxtheme |

---

*dp.exe v1.0.0 — KiTTY Password Decryptor — Modern C++23 Win32 implementation.*

[wesmar (Marek Wesolowski)](mailto:marek@kvc.pl) | [kvc.pl](https://kvc.pl)

### Add a comment

---

## Navigation

- Parent: [Repositories](https://kvc.pl/repositories.md)
- Previous: [Secure FTP Plugin](https://kvc.pl/repositories/sftpplug.md)
- Next: [xtbrep — Analizator portfela XTB](https://kvc.pl/repositories/xtbrep.md)
