Skip to main content
My helper modules for writing OSWE exploit scripts. Feel free pull what you need into your script for each target. The full toolkit lives in my GitHub repo here:

hkm67/OSWE-Notes

Exploit template plus helper modules for blind SQLi, reverse shells, web callbacks, and WebSocket interfaces.

Files

exploit.py is a barebone skeleton: session setup, argument parsing, and an empty exploit chain. Paste in the helpers the target needs from the other files, then fill in the stage functions.

exploit.py – Flags

-u and -P exist because some stages are slow. Brute-forcing a token can take a few minutes. Once you have the credentials, pass them directly and skip to the stage you’re actually working on.

Helpers

utils.py

Console output:
Random generators:
generate_password() always satisfies strict validation policies. It avoids shell-breaking characters (quotes, backslashes) so you can safely embed it in payloads. Regex extraction – pull values out of HTML responses:
Uses re.DOTALL, so it works on values that span multiple lines. PowerShell encoder – avoids quoting issues when injecting PS1 through a webshell:
-EncodedCommand expects UTF-16LE base64. Encoding it in Python ensures the command arrives intact regardless of how it’s passed through the delivery mechanism.

shell_listener.py

Paste start_listener() into your script, run it in a background thread, then trigger the shell:
Two threads: one reads from the socket and prints, the other reads your input and sends. This way neither side blocks the other. Uncomment conn.send(b"\n") inside the function for PowerShell. It kicks the PS1 prompt on connect so you see output immediately. Reverse shell payloads:

web_callback_server.py

One server that does two things: serves files to the victim and captures whatever the victim sends back. Hardcode your payloads as constants at the top of the script, using .replace() for LHOST/LPORT (full credits to rizemon/exploit-writing-for-oswe for this neat trick!):
Then register and start:
GET callbacks store query params in EXFIL_DATA[path]. POST callbacks parse JSON or form-encoded bodies into the same dict. CORS headers are set on every response so fetch() in the victim browser works cross-origin. XSS cookie theft:
If the session cookie is HttpOnly, cookie theft won’t work. Go after browser storage, scrape the CSRF token, or force admin actions directly instead. Steal tokens from storage (JWT / SPA sessions):
Scrape a CSRF token from an admin page (then replay it server-side):
Force an admin action with the victim’s session (e.g. create an admin user):

sqli_parallel.py

Paste extract_string_blind() into your script. The only thing you write is one function, is_correct_char(index, char) -> bool, that returns True when char is correct at position index (1-based). Pass it in and the extractor pulls the whole string:
All (position, character) combinations are submitted at once. The thread pool caps concurrency at max_workers=30. For a 32-char string over a 62-char charset, that’s ~2000 tasks, done in roughly the time it takes to test a single character sequentially. Tune max_workers down if you’re hitting rate limits, up if the target handles the load.

websocket_helper.py

For targets that expose a command interface over WebSocket. Paste ws_recv_all() into your script:
If the app sends typed frames (e.g. {"type": "response", "payload": "..."}), filter on the type to skip heartbeats:
Increase the timeout if large outputs are being cut off.

requests Cheatsheet

Sending requests:
Reading responses:
Persist headers or cookies across all requests:
Auth bypass check – inspect the 302 before following it:
Scrape a CSRF token and persist it:
Sanity-check every critical step:
Many apps return HTTP 200 even on failure, so check the response body, not just the status code. Print the outgoing request (useful when something isn’t behaving as expected):

Development Tips

Skip slow stages while iterating – hardcode a known-good cookie and comment out the early steps:
Route through Burp for a specific request without touching the rest:
Or set it globally for the session via --proxy, or as an env var:

Common Patterns

Avoid f-string hell with payloads that contain lots of {} (SSTI):
b64-encode a shell command to avoid quoting issues:
Wait for an async callback (XSS, SSRF, XXE):

Decompilation

After exporting, open the folder as a workspace in VS Code or Notepad++ for multi-file search.

Database Debugging

PostgreSQL – log all queries in real time: Enable in postgresql.conf:
Reload without restart:
Tail the log and filter for SQLi signatures:
Useful when developing a blind SQLi payload. It confirms whether your syntax is actually reaching the database or getting rejected earlier in the stack.
Last modified on May 26, 2026