Every quarter I have to rebuild the scope for a black-box engagement: pull every live subdomain for the target, cut out anything already covered by other testing, and drop the known decoys. I was doing this by hand in Excel and it got old fast, so I wrote this.
It's a small script. You give it a list of root domains, a list of subdomains already covered elsewhere, and a list of decoys. It gives you back an Excel file with the final scope, ready to hand off or paste into your engagement doc.
Nothing clever going on inside — no AI, no guessing. It scrapes subdomains, checks which ones are actually alive, and filters against your two lists. That's it. Which is exactly why it's reliable.
- Runs
subfinderagainst each root domain you give it - Probes every subdomain it finds with
httpx, capturing the full redirect chain (so you can see301,200instead of just a final code) and the IP - Cross-checks each live subdomain against your "already covered" list and your decoy list
- Spits out an Excel file: everything it found on one sheet, the actual final scope on another, and a quick summary
You need Python 3, Go, and Git on the box first. Everything else — subfinder,
httpx, the Python packages — gets installed by the setup script.
git clone https://github.com/<your-username>/Blackbox_Scope_finalizer.git
cd Blackbox_Scope_finalizer
chmod +x setup_scope_tool.sh
./setup_scope_tool.shRun it again any time — it skips whatever's already installed.
One thing worth knowing: some distros (Kali included) ship an unrelated
package that also installs something called httpx at /usr/local/bin.
This script checks the version banner of whatever it finds before trusting
it, so it won't silently grab the wrong tool — but if you ever see a warning
about a binary "not identifying as a ProjectDiscovery tool," that's why.
Make three text files — one entry per line, no special formatting needed:
root_domains.txt # the root domains you're scoping
greybox_covered.txt # subdomains already covered under other testing
decoy.txt # known decoys/honeypots to exclude
Then:
source venv/bin/activate
python3 scope_builder.py --roots root_domains.txt \
--greybox greybox_covered.txt --decoy decoy.txt \
--out scope_report.xlsxIt auto-detects where subfinder/httpx live on your system. If it can't
find them, or finds the wrong one, override it directly:
python3 scope_builder.py --roots root_domains.txt \
--httpx-bin /full/path/to/httpx --subfinder-bin /full/path/to/subfinderscope_report.xlsx, three sheets:
- All Subdomains — everything found, status chain, IP, live/dead, flagged if covered or decoy
- Black-box Scope — just the final list: live, not covered, not a decoy
- Summary — the counts, so you can sanity-check the numbers at a glance
A domain counts as "live" if the last status code in its redirect chain is a
2xx — so 301,200 counts, 404 doesn't, no response doesn't.
- Large enterprise domains can easily return 500+ subdomains from passive enumeration, and a lot of them will be internal/VPN-only. Seeing those come back as "no response" from outside the network is expected, not a bug.
- Probing gets done in batches rather than one giant request — cleaner
output, easier to spot problems, and it sidesteps some flaky behavior I ran
into pushing hundreds of hosts through in a single call. Tune the batch
size with
--chunk-sizeif you need to. - If you're piping this into automation and results come back empty when they shouldn't, check whether the process invoking it is leaving stdin attached to something odd — that one cost me a good afternoon.
If something's in your greybox or decoy list, it has to match the subdomain exactly (case doesn't matter, but nothing is inferred). No wildcards. I'd rather be explicit here than have the tool guess wrong on something that affects scope.
Your root_domains.txt, greybox_covered.txt, and decoy.txt will likely
have real, sensitive information in them depending on what you're scoping.
They're excluded by .gitignore on purpose — don't commit them.
Only run this against domains you're actually authorized to enumerate and probe.
MIT. Do what you want with it.
— Suhel Kathi, OSCP / CEH