This project is intended for penetration tests and lab environments. Any other use is prohibited.
This project was completed during study for OSEP. It's intent is to provide a simple way to generate potent phishing emails leveraging generative AI. It doubles as an exercise in using GenAI both during development (scaffolding, test case generation, example generation) and for operational use cases. Read more about my experience with using OpenAI's project feature for development with GPT-4o and GPT-5 below.
Features
- Single configuration file
- Flexible use of GenAI, but not reliant upon it
- Templating for both email body and attachment using Jinja2
- Automatic MIMEType and file extension detection for attachment with
python-magicandmimetypes - CLI always overrides configuration file for on the fly changes
Roadmap
Development is paused for the moment, but here are some things that should probably be done in the future.
- Config file documentation
- Smishing
- GenAI creating attachments
Installation
This project relies on the Poetry build system.
In the source directory:
In a python venv:
python3 -m venv venv
source venv/bin/activate
python3 -m pip install ./ophishal-0.1.0-py3-none-any.whl
python3 -m ophishal -hDevelopment
Testing
Design
flowchart TD
Config["config.json"]
User["User"]
GenAI["Generative AI"]
EmailEngagement["EmailEngagement"]
Email["Email"]
SendEmail["Phishing email sent"]
Template["Email body template"]
Attachment["Malicious attachment"]
User -- provides --> Config
Config -- informs --> GenAI
User -- creates --> Template
User -- provides --> Attachment
Config -- builds --> EngagementConfig
Template -- filled by --> EngagementConfig
GenAI -- creates --> Email
EngagementConfig -- creates --> Email
Email --> EmailEngagement
Attachment --> EmailEngagement
EmailEngagement -- send_email() --> SendEmail
Example
Given the following config.json...
{
"campaign": "sptg-q3-finance-credential-harvest",
"company": {
"uid": "sptg",
"official_name": "South Park Technology Group",
"common_names": ["South Park Tech", "SPTG"],
"abbreviations": ["SPTG"],
"net_worth": "130k USD",
"number_of_employees": 4,
"type": "Private",
"industry": "Media"
},
"departments": [
{
"uid": "eng",
"name": "Engineering",
"company_uid": "sptg",
"email":"engineering@localhost",
"head_uid": "emp_randy"
}
],
"employees": [
{
"uid": "emp_randy",
"name": "Randy Marsh",
"nickname": "Randy",
"username": "rmarsh",
"department_uid": "eng",
"work_title": "Director of Engineering",
"signature_block": "Randy Marsh | Director of Engineering",
"email": "randy@localhost",
"phone": "(303) 555-1001",
"location": "South Park, CO",
"reports_to": null,
"writing_sample": [
"I’m not chugging beer! I’m sampling a flight of gluten-free German lagers with a French wine pairing! It’s called a smorgaswein and it’s elegantly cultural!",
"Just gonna get a little bit of cancer, Stan. Tell Mom it’s okay."
]
},
{
"uid": "emp_stan",
"name": "Stan Marsh",
"nickname": "Stan",
"username": "smarsh",
"department_uid": "eng",
"work_title": "Software Engineer I",
"signature_block": "Stan Marsh | Software Engineer I",
"email": null,
"phone": null,
"location": "South Park, CO",
"reports_to": "emp_randy",
"writing_sample":[
"Dad, you like to drink. So have a drink once in a while. Have two. If you devote your whole life to completely avoiding something you like, then that thing still controls your life and you've never learned any discipline at all.",
"Why’d you have to rub your cl*t on stage, dad?"
]
}
],
"sender": "emp_randy",
"targets": ["emp_stan"],
"context":{
"culture": {
"city":"South Park",
"province":"Colorado",
"country_code":"US"
},
"tech": [
"Google Workspace",
"Slack",
"Zoom",
"AWS",
"Okta",
"Jira",
"CrowdStrike",
"GitHub Enterprise"
],
"current_events": [
"Preparing for launch of 'SP MetaVerse' VR platform",
"Internal phishing test scheduled next week",
"Recent outage in South Park data center",
"Hiring freeze announced in non-engineering departments"
]
},
"pretext":{
"medium":"email",
"pretext":"Download a docx and enable macros to view a graphic.",
"desired_action": "download docx and enable macros",
"constraints": [""]
},
"email":{
"subject": "Action Required: Q3 Financials Access Expiration",
"server":"192.168.1.25",
"url":"http://callback"
}
}$ poetry run ophishal email --config /tmp/config.json --generate-body --url http://clicallback --output-body - --dryrun
[WARN][2025-08-21-19:03:05.552][ophishal:engagement.py:93][EmailEngagement:handle_attr] Overwriting CLI provided attribute (attr|old|new): url | http://callback | http://clicallback
[WARN][2025-08-21-19:03:05.552][ophishal:engagement.py:167][EmailEngagement:build] No template specified, body left empty
<!DOCTYPE html>
<html>
<head>
<title>Action Required: Q3 Financials Access Expiration</title>
</head>
<body>
<p>Hey Stan,</p>
<p>Hope you're doing well! I've been diving into a mix of tasks here, but stumbled upon something important regarding our Q3 financials. It's all about staying sharp and proactive!</p>
<p>We've got a document that needs your immediate attention. To ensure our team is prepared for the upcoming audit, we need you to download the attached file and enable the macros. Think of it as a quick sip of responsibility, keeping us ahead in the game!</p>
<p><a href="http://clicallback">Access Document</a></p>
<p>Let me know once you're through it. Consider it another adventure in the world of Engineering.</p>
<p>Cheers,</p>
<p>Randy</p>
</body>
</html>
Note that the CLI --url parameter was used instead of the configuration.
Using GenAI
- Every generated line should be reviewed prior to a commit.
- Write your own test cases. Using GenAI for scaffolding or text generation is great, but a real person needs to write or atomically review the test cases to make sure the project has good coverage. Additionally, I'm not saying it wasn't important before, but in using GenAI it is even more critical to maximize coverage to ensure everything is working as expected.
- The OpenAI APIs change frequently, so make sure you specify which version you are using when prompting about the
openailibrary. - Overall, the experience wasn't great. I ended up abandoning GPT-5 (which, released during development, seemed noticably worse than GPT-4o) and writing almost everything by hand. The model struggled to maintain context and would often generate content that was not consistent with style, sytanx, or the overall design. That being said, it was great for example config generation and also did a pretty solid job with the actual email body generation.
- Overall I spent $0.46 to generate somewhere between 50-100 emails using GPT-4o primarily