🔧 ProgrammierungVibe Coding Was Never Going to Be the Future. Architecture Is.(17.09.2026 um 01:55 Uhr)
🔧 ProgrammierungDIVING DEEPER INTO POWER BI(17.09.2026 um 01:58 Uhr)
🔧 ProgrammierungThe system lives in your files, not your prompts(17.09.2026 um 01:58 Uhr)
🔧 ProgrammierungSoftware Artifact Trust Starts At Package Registries(17.09.2026 um 01:58 Uhr)
🔧 ProgrammierungLandlock LSM: Secure Linux Apps ohne root-Rechte(17.09.2026 um 02:00 Uhr)
🔧 ProgrammierungDebugging Node.js Like a Pro(17.09.2026 um 02:00 Uhr)
🔧 ProgrammierungVibe Coding Was Never Going to Be the Future. Architecture Is.(17.09.2026 um 01:55 Uhr)
🔧 ProgrammierungDIVING DEEPER INTO POWER BI(17.09.2026 um 01:58 Uhr)
🔧 ProgrammierungThe system lives in your files, not your prompts(17.09.2026 um 01:58 Uhr)
🔧 ProgrammierungSoftware Artifact Trust Starts At Package Registries(17.09.2026 um 01:58 Uhr)
🔧 ProgrammierungLandlock LSM: Secure Linux Apps ohne root-Rechte(17.09.2026 um 02:00 Uhr)
🔧 ProgrammierungDebugging Node.js Like a Pro(17.09.2026 um 02:00 Uhr)
🔧 Programmierung 🕛 vor 5 Monaten 7 Min Lesezeit
0

Wrapping John the Ripper in a PyQt5 GUI on Windows: Architecture and Hard-Won Lessons

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht




Wrapping John the Ripper in a PyQt5 GUI on Windows



In the first article of this series, I introduced Kaloya PDF Cracker and explained the problem it solves. In this post, I want to go deeper into the technical decisions and the specific challenges I ran into while building it.



This is a walkthrough of three problems that took real effort to solve correctly:




  1. Keeping the GUI responsive while the cracking engine runs

  2. Getting automatic Administrator elevation without any user configuration

  3. Packaging everything into a single professional Windows installer









The Application Architecture



The codebase is split into three clean, independent layers. This separation is not just organisational — it is what allows the application to be extended, tested, and maintained without one layer breaking another.




CODE
+-----------------------------------------------+
| PyQt5 Presentation Layer |
| main_window.py + gui/styles.qss |
+-----------------------------------------------+
|
signals & slots
|
+-----------------------------------------------+
| Worker / Logic Layer |
| worker.py (runs inside QThread) |
+-----------------------------------------------+
|
subprocess calls
|
+-----------------------------------------------+
| John the Ripper Engine |
| john.exe + pdf2john.py (bundled) |
+-----------------------------------------------+






The GUI layer never calls John the Ripper directly. It communicates only with the Worker through PyQt5 signals and slots. This is the architectural decision that everything else builds on.









Problem 1 — Keeping the GUI Responsive



This is the most common mistake developers make when first integrating a subprocess into a Python GUI application.



If you call subprocess.run() directly inside a button click handler, the entire Qt event loop blocks. The window freezes. The progress bar does not move. The Cancel button stops working. The user sees a white rectangle and assumes the application crashed.



The correct solution is QThread.




CODE
# gui/worker.py

from PyQt5.QtCore import QThread, pyqtSignal
import subprocess
import os

class CrackingWorker(QThread):

# Signals communicate results back to the main thread safely
log_message = pyqtSignal(str)
finished = pyqtSignal(str)
error = pyqtSignal(str)

def __init__(self, pdf_path, wordlist_path, john_dir):
super().__init__()
self.pdf_path = pdf_path
self.wordlist_path = wordlist_path
self.john_dir = john_dir
self._stopped = False

def stop(self):
self._stopped = True

def run(self):
# Step 1 — Extract the encrypted hash from the PDF
self.log_message.emit("Extracting hash from PDF...")

pdf2john = os.path.join(self.john_dir, "pdf2john.py")
hash_file = os.path.join(self.john_dir, "hash.txt")

result = subprocess.run(
["python", pdf2john, self.pdf_path],
capture_output=True, text=True
)

if result.returncode != 0:
self.error.emit("Failed to extract hash from PDF.")
return

with open(hash_file, "w") as f:
f.write(result.stdout.strip())

# Step 2 — Feed the hash to John the Ripper
self.log_message.emit("Starting dictionary attack...")

john_exe = os.path.join(self.john_dir, "john.exe")
proc = subprocess.Popen(
[john_exe, f"--wordlist={self.wordlist_path}", hash_file],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
cwd=self.john_dir
)

for line in proc.stdout:
if self._stopped:
proc.terminate()
self.finished.emit("Cancelled.")
return
self.log_message.emit(line.strip())

proc.wait()

# Step 3 — Read the result from john.pot
pot_file = os.path.join(self.john_dir, "john.pot")
if os.path.exists(pot_file):
with open(pot_file, "r") as f:
content = f.read().strip()
if content:
password = content.split(":")[-1]
self.finished.emit(password)
else:
self.finished.emit("Password not found in wordlist.")
else:
self.finished.emit("Attack complete. Check logs.")






In the main window, connecting to these signals is straightforward:




CODE
# gui/main_window.py (excerpt)

self.worker = CrackingWorker(pdf_path, wordlist_path, john_dir)
self.worker.log_message.connect(self.log_area.append)
self.worker.finished.connect(self.on_finished)
self.worker.error.connect(self.on_error)
self.worker.start()






Because QThread runs on a separate OS thread, the Qt event loop continues processing on the main thread. The progress bar animates. The Cancel button works. The log area updates in real time.









Problem 2 — Automatic Administrator Elevation



John the Ripper needs to write files — the .pot file that stores recovered passwords, and the .log and .rec files it uses for session management. On Windows 10 and 11, writing to C:\Program Files\ requires Administrator-level access.



Without elevation, John the Ripper fails silently. The GUI shows no error, the process exits cleanly, but no password is ever recovered.



There are two common approaches to handle this. The wrong way is calling ShellExecuteEx with runas at runtime from Python — this forces elevation on every subprocess launch and creates a visible UAC prompt mid-session which confuses users.



The correct way is embedding a UAC Application Manifest directly into the compiled executable.



uac_manifest.xml




CODE
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly
xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0">

<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="requireAdministrator"
uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>

</assembly>






This manifest tells Windows that the application must always run as Administrator. The UAC prompt appears exactly once — when the user double-clicks the application shortcut. After that, all subprocesses it spawns inherit the same elevated context automatically.



In the PyInstaller spec file, two settings activate this:




CODE
# build.spec (excerpt)

exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='KaloyaPDFCracker',
uac_admin=True, # tells PyInstaller to set the elevation flag
manifest='uac_manifest.xml', # embeds the XML into the EXE resources
...
)












Problem 3 — A Professional Windows Installer



PyInstaller produces a folder of files and a single .exe entry point. Distributing a folder to non-technical users who expect a standard Windows installer is a poor experience.



Inno Setup 6 solves this. It compresses the entire application directory and produces a single self-extracting installer executable that handles installation, shortcut creation, and uninstallation automatically.



The most important lesson from building the installer was about a single flag.



The bug: After installation, if the user ticked "Launch Kaloya PDF Cracker" on the final page, the application launched without Administrator elevation and crashed immediately.



The cause: The [Run] section had the runasoriginaluser flag set. This flag explicitly tells Inno Setup to drop the elevated context it holds during installation and launch the application as the original non-admin user. That directly contradicts the requireAdministrator manifest in the EXE.



The fix: Remove runasoriginaluser and add shellexec instead.




CODE
; WRONG — drops elevation, causes crash on first launch
[Run]
Filename: "{app}\KaloyaPDFCracker.exe"; \
Flags: nowait postinstall skipifsilent runasoriginaluser

; CORRECT — shellexec triggers a fresh UAC prompt, elevation is preserved
[Run]
Filename: "{app}\KaloyaPDFCracker.exe"; \
Flags: shellexec nowait postinstall skipifsilent






This single change fixed the post-installation launch error entirely.









The Lesson About Taskbar Pinning



One requested feature was programmatic pinning of the application shortcut to the Windows taskbar. This seemed straightforward. In practice, it is completely impossible.



Microsoft blocked all programmatic taskbar pinning in Windows 10 Build 1703 (the Creators Update, released April 2017). Any code, script, or installer that claims to do this is either detecting a specific older Windows version or simply does nothing silently on modern systems.



The correct solution is to tell the user to do it themselves. The installer finish page now contains a single clear line of instruction. This is not a limitation — it is the only honest approach available.









Source Code and Download



GitHub Repository:



If you have questions about the QThread implementation, the UAC manifest embedding, or the Inno Setup configuration, ask in the comments and I will answer in detail.

Vollständiger Original-Artikel
Den kompletten Beitrag mit allen Details direkt auf dev.to lesen.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
11 Quellen
CVE-2026-16794 | GitLab up to 19.1.7/19.2.5/19.3.1 Compliance Framework Management improper authorization (WID-SEC-2026-3315)
1 Quelle
Windows 11: Auto-Update-Installation, aber keine Einträge in Verlauf? - BornCity
1 Quelle
CVE-2026-76438 | Cisco BroadWorks Web-based Management Interface improper authorization (EUVD-2026-81161)
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Wrapping John the Ripper in a PyQt5 GUI on Windows: Architecture and Hard-Won Lessons

Thematisch verwandte Begriffe: Wrapping, John, Ripper, PyQt5 · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...