Back to Articles

ssTaker: When Your Screenshot Tool Needs to Just Work on Parrot OS

[ View on GitHub ]

ssTaker: When Your Screenshot Tool Needs to Just Work on Parrot OS

Hook

Sometimes the best tool is the one that actually runs on your pentesting distro. ssTaker exists because a more sophisticated tool kept breaking, and that story tells us everything about pragmatic software design.

Context

Security researchers doing reconnaissance need to visually survey dozens or hundreds of web services quickly. Tools like EyeWitness pioneered the "screenshot all the things" approach, generating HTML galleries that let pentesters rapidly identify interesting targets without manually visiting each URL. But dependency management in security distributions can be fragile—different Python versions, conflicting libraries, and distribution-specific quirks break tools at the worst moments.

ssTaker emerged from a specific frustration: EyeWitness compatibility issues on Parrot OS, a popular Debian-based pentesting distribution. Rather than debug complex Python dependency chains or wait for upstream fixes, the author built a minimal bash wrapper around CutyCapt, a Qt-based screenshot utility that's been in Debian repositories since 2010. It's not the fastest or most feature-rich solution, but it solves the immediate problem with tools already installed on most pentesting systems.

Technical Insight

Output

Read line by line

Extract domain + port

Formatted URL

Rendered PNG

Screenshot path

Gallery HTML

Next domain

Domain List File

Bash Loop Controller

URL Parser

CutyCapt WebKit

Timestamped Directory

HTML Report Generator

report.html

System architecture — auto-generated

The architecture is deliberately simple: read domain list, loop through entries, invoke CutyCapt for each, collect screenshots in a timestamped directory, and generate an HTML report. This simplicity is the entire design philosophy. Let's examine the core workflow:

#!/bin/bash
# Simplified ssTaker core logic

domain_list=$1
timestamp=$(date +%Y%m%d_%H%M%S)
output_dir="screenshots_${timestamp}"
mkdir -p "${output_dir}"

while IFS= read -r domain; do
    # Strip protocols if accidentally included
    domain=$(echo "${domain}" | sed 's|http[s]*://||')
    
    # Handle optional port specification
    if [[ "${domain}" =~ :[0-9]+$ ]]; then
        url="http://${domain}"
    else
        url="http://${domain}"
    fi
    
    output_file="${output_dir}/${domain//[:.\/]/_}.png"
    
    # CutyCapt invocation with timeout and size parameters
    cutycapt --url="${url}" \
             --out="${output_file}" \
             --max-wait=10000 \
             --min-width=1024 \
             --min-height=768
             
    # Build HTML report incrementally
    echo "<div class='screenshot'>" >> "${output_dir}/report.html"
    echo "<h3>${domain}</h3>" >> "${output_dir}/report.html"
    echo "<img src='${output_file}' />" >> "${output_dir}/report.html"
    echo "</div>" >> "${output_dir}/report.html"
done < "${domain_list}"

The input format expects newline-delimited domains without protocols: example.com, target.local:8080, or 192.168.1.100:8443. This is both a strength and weakness—it's simple to generate from tools like nmap or masscan, but requires preprocessing if you're working with full URLs from other reconnaissance tools.

CutyCapt does the heavy lifting through Qt's WebKit rendering engine. The --max-wait parameter tells it to wait up to 10 seconds for JavaScript and resources to load before capturing. The --min-width and --min-height settings ensure responsive designs render at desktop dimensions rather than mobile views. CutyCapt outputs directly to PNG files, avoiding any image format conversion overhead.

The HTML report generation is basic but functional—a single file with inline CSS creating a responsive grid of screenshots. Each image links to the original PNG for full-resolution viewing. There's no JavaScript, no external dependencies, just HTML and CSS that renders in any browser:

<!DOCTYPE html>
<html>
<head>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        .screenshot { 
            display: inline-block; 
            margin: 15px;
            border: 1px solid #ccc;
            padding: 10px;
        }
        .screenshot img { 
            max-width: 400px; 
            cursor: pointer;
        }
    </style>
</head>
<body>
    <h1>Screenshot Report - 20231215_143022</h1>
    <!-- Screenshot divs inserted here -->
</body>
</html>

The timestamp-based directory naming prevents overwrites and creates a natural audit trail. When you're doing reconnaissance over several days or weeks, you can compare how targets change over time by diffing directories.

What ssTaker intentionally doesn't do reveals its design priorities: no parallel processing, no headless Chrome, no authentication handling, no custom headers, no proxy support. Every additional feature would add complexity, dependencies, and potential failure points. For the target use case—quick visual reconnaissance on Parrot OS—these omissions are defensible trade-offs.

Gotcha

The sequential processing model becomes painful with large domain lists. Capturing 200 screenshots at 10-15 seconds each means 30-50 minutes of runtime. Modern alternatives like GoWitness parallelize across dozens of workers, completing the same job in minutes. You'll feel this limitation acutely during time-sensitive engagements.

CutyCapt's WebKit version is frozen in time—it uses Qt4 or Qt5's WebKit, which stopped receiving updates years ago. Modern web applications using recent JavaScript features, CSS Grid, or WebAssembly may not render correctly. You're essentially viewing websites through a 2015-era browser. For reconnaissance this might be acceptable, but don't expect screenshots to match what targets see in current Chrome or Firefox. Additionally, CutyCapt requires X11 or Xvfb (virtual framebuffer), adding deployment complexity in truly headless environments like Docker containers or cloud instances without GUI support. The script doesn't handle CutyCapt failures gracefully—if one domain hangs or crashes the renderer, you'll need to manually intervene rather than having the script continue with remaining domains.

Verdict

Use if: You're on Parrot OS or similar Debian-based pentesting distributions where EyeWitness breaks, you have under 100 domains to screenshot, you need something that works right now without debugging Python environments, and you're doing basic reconnaissance where outdated WebKit rendering is acceptable. The simplicity is genuinely valuable when you're in the middle of an engagement and just need screenshots.

Skip if: You have hundreds of domains (the sequential processing will kill you), you need modern browser rendering for JavaScript-heavy applications, you're working in containerized or cloud environments without X11, or you require authentication, custom headers, or proxy support. In those cases, invest the setup time in GoWitness or Aquatone—the performance and feature differences are worth it. Also skip if you're building this into automated pipelines where CutyCapt's lack of active maintenance becomes a security concern.

// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/developer-tools/bugbaba-sstaker.svg)](https://starlog.is/api/badge-click/developer-tools/bugbaba-sstaker)