Customising recon scripts in Python, PowerShell and Bash
Listen to this lesson
This episode is a study companion for CompTIA PenTest+ PT0-003 and is not produced by or endorsed by CompTIA.
Objective 2.4 in this course covers script modification — CompTIA describes it as customising Python, PowerShell and Bash scripts for reconnaissance and enumeration. Note the verb: customising, not writing from scratch. This is the applied lab for the objective, and the Domain 2 capstone.
Why this matters
CompTIA's wording here is worth reading carefully. The objective is not "write tools"; it is customise existing ones. That reflects the job: you will spend far more time reading somebody else's script and adapting it than writing your own, and the exam tests whether you can read code and predict what it does.
It is also where scope discipline becomes mechanical rather than a matter of remembering. A script that cannot target something out of scope is better than a tester who remembers not to.
The lesson
Reading someone else's script before you run it
This is the same rule as lesson 12's scripting engine and lesson 24's exploit code, and it is the most important professional habit in this domain.
Before running anything you did not write, answer four questions:
- What does it send, and to where? Look for hardcoded addresses, domains and URLs. Tools downloaded from the internet have been known to report home.
- What does it write? To disk, to the target, to the console.
- Does it do anything intrusive? Authentication attempts, exploitation, configuration changes. Something described as an enumeration script can quietly include a login attempt, which is a different authorisation.
- What does it do with what it finds? Uploading results anywhere is a disclosure of the client's data.
A script you cannot read is a script you cannot run on a client's network, because you cannot answer the client's question about what you did.
Parsing tool output instead of re-typing it
The bulk of real customisation is joining tools together: taking one tool's output and shaping it into another's input.
- Prefer structured output. Lesson 12's XML exists so that this step is parsing rather than scraping. Same for JSON where a tool offers it.
- Scrape as a last resort, and when you do, pin the version — a scraper silently breaks when the format shifts, and produces an empty result that looks like a clean finding.
- Fail loudly on an empty parse. A pipeline that yields nothing because the format changed looks identical to one that yields nothing because the target is clean. This is the "not measured is a third result" problem, and the fix is for the script to say "I parsed 0 records from a 4MB file" rather than printing nothing.
Language choice follows the environment rather than preference: Bash where the tooling is command-line, Python where the parsing is real, PowerShell where the targets are Windows and you want structured objects.
Rate limiting and back-off you write yourself
Lessons 8, 10 and 11 all warned that scanning can take things down. A script makes that easier to do by accident, because it will happily issue a thousand requests a second without noticing anything is wrong.
So build in:
- A deliberate delay between requests, chosen rather than defaulted, and adjustable without editing the code.
- Concurrency you set explicitly.
- Back-off on errors. If responses start failing or slowing, slow down. A script that speeds up under errors — retrying immediately — turns a struggling service into an outage.
- A hard stop. A maximum request count or runtime, so a bug cannot run all night against a client.
Making a script refuse targets outside a scope file
This is the exercise that matters most, and it is the one that turns a rule into a property of the tool.
Write your scripts to take a scope file — the in-scope ranges and names from lesson 3 — and to refuse any target not in it. Not warn: refuse.
Details that make it real:
- Resolve names to addresses and check the address, because lesson 9's point was that names move. Checking only the name lets DNS carry you out of scope.
- Check every target at the moment of use, not once at startup. A script that expands its target list as it discovers hosts must re-check each one.
- Refuse by default on anything it cannot resolve or classify, rather than proceeding. Mutating tools must fail closed.
- Log every refusal, because a refusal is itself a finding: something in your input pointed outside the scope, and you want to know what and why.
This is the difference between remembering the rule at 2am on the third day of an engagement and not needing to.
Keeping scripts reproducible for the report
A finding has to be reproducible by the client's engineer (lesson 6), and a finding produced by a script you have since edited is not.
- Keep the exact script that produced each result, not the improved version.
- Record the invocation — arguments, scope file, timestamp — in the activity log from lesson 8.
- Make output self-describing: the script's own version or hash, the parameters, and when it ran, written into the output file itself. An output file that cannot say how it was produced is not evidence.
- Keep it deterministic where you can. A script that randomises its order makes two runs incomparable, which is exactly what you need when re-testing.
The test: could somebody else, given your repository and your notes, re-run this and get the same answer? If not, the finding rests on your word.
What to take into the exam
- The objective is customising existing scripts, not authoring tools — expect code-reading questions.
- Read before running: what it sends and where, what it writes, whether it does anything intrusive, what it does with results.
- Parse structured output; make an empty parse loud, because it looks like a clean result.
- Build rate limiting, back-off and a hard stop in deliberately.
- A scope file the script enforces beats a rule you have to remember; resolve names and check addresses at the moment of use, and fail closed.
Practise what you just read
1. What is the main professional reason to script reconnaissance rather than run tools by hand?
Select one
Show answer
A. Scripting makes recon reproducible and self-documenting: the script is the record of exactly what was run, so a finding can be reproduced. Speed is a side effect; the value is that the method is written down rather than remembered.
2. Why is parsing a tool's structured output safer than scraping its screen display?
Select one
Show answer
B. Screen output is formatted for a human and changes between versions, so a script that scrapes it breaks silently. Structured output such as XML or JSON is meant to be consumed by another program and is stable to parse, which is why tools emit it.
3. What is the single most dangerous mistake when scripting reconnaissance against a client?
Select one
Show answer
C. A loop over targets with no scope check inside it is the classic disaster: one wrong entry, or a range that is a character too wide, and the script touches hosts outside the engagement automatically. The scope test belongs in the code, not only in your head.
10 more questions on this objective are part of the full course.
Hands-on labs
Part of the free CompTIA PenTest+ PT0-003 course — 41 lessons and 62 hands-on labs.
This is an independent study companion for CompTIA PenTest+ PT0-003 and is not produced by or endorsed by CompTIA.