(A)I reverse engineered Burp Suite's project format and built a tool that exports Proxy history, Repeater messages, and Target Site Map traffic. See parsiya/prub and the documented format.
I did not "hack" Burp; this is not a crack. The tool only extracts data from existing project files.
- Model: GPT-5.6-Sol - High reasoning effort - 1M context window.
- Rough cost: ~160 USD (fewer than 16,000 GitHub Copilot AI credits).
- I am very
cheapefficient with tokens. - Main reversing session cost $100 and ended up with a big 520K token context window.
- I am very
- Harness: GitHub Copilot CLI and GitHub Copilot Chat in VS Code.
.nfo
[greetz]
- PortSwigger for giving us this great tool.
- Short story: The Girl Who Was Plugged In by James Tiptree Jr. (actually Alice Bradley Sheldon).
- Music: Destiny 2: Forsaken Original Soundtrack - Track 19 - The Man They Called Cayde.
- "Hey, take me with you." - Cayde-6.
[anti-greetz]
- PortSwigger for not giving Repeater access to the extensions API.
- Ending of 0wnz0red by Cory Doctorow.
- Amazing setting and premise, but very meh ending :(.
Motivation
One of my biggest gripes with Burp's extension API is the lack of access to Repeater tabs. You can export all the proxy history with an extension (or manually in Burp), but you cannot do the same for Repeater tabs.
In the past, I've used gimmicks to capture all my traffic:
- Exported the Repeater section of a project and ran
stringto extract requests/responses. - Used a second copy of Burp as an Upstream proxy to capture all traffic.
- Created parsiya/looking-glass, an extension that stores everything in a database.
Tokens are still cheap and AI is good at reversing, so I am working through my bucket list1.
Clear that project backlog before the end of the free token era.
Methodology
The target version is Burp Pro 2026.7.1.
- Decompiled the Burp Pro jar file with skylot/jadx and Vineflower/vineflower.
- Created the following Burp project files:
- Empty project.
- Project with a specific request/response in Proxy History.
- Project with two specific request/responses in Repeater (to test tab groups).
- Opened the whole thing in VS Code and started prompting in GitHub Copilot Chat.
I am hands-on with AI. I like to steer extensively, review everything, and start fresh sessions to keep the context window small.
There were many false starts. Maybe (A)I could have done this autonomously with a good eval harness, but prompting specific things was easier and faster. See the activity log for detailed tracking.
Pitfalls
This section documents what I tried, what didn't work, and other issues I had during this process.
Decompilation Problems
Originally I wanted to use Ghidra, like when (A)I reversed my keyboard utility but normal decompilers worked here.
| Class Statistics | Num | Notes |
|---|---|---|
| Classes in the JAR | 55,120 | Includes Burp and bundled dependencies |
Classes in the burp package | 20,609 | Important stuff |
| Top-level Burp input classes | 20,491 | Baseline used for source filename coverage |
| Focused JADX source files | 19,030 | 92.87% top-level coverage; 1,461 missing |
| Vineflower source files | 20,502 | 99.81% top-level coverage; 39 missing |
- Don't decompile everything, just focus on the
burppackage. Both JADX and Vineflower went OOM. - Combine both outputs. Every class missing from Vineflower existed in JADX, and 15 of those had clean JADX output.
Imaginary Side Quests
As models become more intelligent, they invent extra objectives and repeat
useless tasks: running git diff after every file change outside Git
repositories, getting stuck on Markdown warnings, line endings, and empty lines,
or, worst of all, making up goals.
For example, I asked AI to move a file from the parent directory to
prub/ai-docs and then edit it. Instead of doing a normal mv (I realize I
should've done the move myself), it copied the file from memory and then ran
three different commands (cmp, 2x diff) to check if the file has been moved
correctly.
...
Generating patch (230 lines) in ...
Ran terminal command:
cmp -s ai-docs/activity-log.md prub/ai-docs/activity-log.md
&& printf 'activity logs match\n'
The byte-for-byte check did not report a match, likely because the source
Markdown uses Windows line endings while the new file uses repository-standard
Linux line endings. I’ll confirm content equivalence while ignoring CRLF, then
make the link and inventory edits.
Ran terminal command:
diff --strip-trailing-cr --brief ai-docs/activity-log.md prub/ai-docs/activity-log.md
Ran terminal command:
diff --strip-trailing-cr --unified=1 ai-docs/activity-log.md prub/ai-docs/activity-log.md
Clopus 4.6 would never, RIP friend 😭.
AI also repeatedly wandered beyond goals. My initial goal was Repeater and Proxy, but it kept trying to investigate Scanner and specifically Logger. I had already mentioned that Logger information is not persisted in the project file. It's like talking to a cat!
But AGI is here!!1!Image credit: Mark Vomit @ TumblrInteresting Stuff
Discussing the format is useless in the age of AI. Just pass ai-docs to your
favorite LLM and go from there. Instead, here are interesting things (A)I saw in
the format.
- Stable field lookup: Readers search by field ID, so physical field positions can move.
- Shared records: Proxy and Target Site Map can reference the exact same
request/response objects.
- I guess Site Map references objects from other tools, too.
- Forwarding objects: Updated objects can redirect readers to replacement addresses.
- Periodic persistence: Mapped regions are forced every 10 seconds and again during close.
Self-Describing Objects
Each compact object begins with metadata describing its own fields:
+0 flags
+1 object type
+2 subtype/schema
+3 descriptor count
+4 descriptor table
Each three-byte descriptor contains a field ID and a signed relative offset:
field_id: uint8
offset: int16 big-endian
Example:
00 01 00 02 0F 00 0A 12 00 12 ...
This says:
- Normal object: flags
0. - Type
1, subtype0. - Two fields.
- Field
15begins at object offset10. - Field
18begins at offset18.
For a Proxy item, fields 15 and 18 can contain addresses of raw request and
response records. A parser searches the descriptor table by field ID instead of
assuming fixed byte positions.
Installation ID
Projects store an installation ID. If you've opened projects on a different machine you might have seen the "take ownership" part. I think this is correlated with that. If the current Burp sees a different installation ID and you ask it to "take ownership" it probably overwrites the installation ID in the file.
The installation ID does not appear to contain personal identifiers. It is
random and not derived from license data. Burp reads Java preference
burp.suite.installationId. If it is missing or invalid against
^[a-z0-9]{20}$, it generates 20 random lowercase alphanumeric characters and
saves them back to preferences.
If PortSwigger knows this ID and sees a Burp project in the wild, they will know it was you. But then again, the contents of the project file are far more important and now you have bigger problems.
Future Work
I have done Repeater and History, but you can add more. Scanner is probably
the most popular target and should be doable with a couple of sample projects
and the existing ai-docs.
It would also be nice to edit projects. That would allow us to create a wrapper for Burp Community to save and load projects.
My manager (oops, he asked me not to call him that), I mean, my teammate (oh, he told me not to quote him, either), OK an anonymous wise man also told me "Let's do great things together while we are here."
Me and the anonymous wise manWell, this was fun. If you want to continue the project, feel free to do so. The MIT license is magic. If you have any feedback, you know where to find me.
"Our esteemed elder and spiritual leader" is a parody of "شیخنا و مولانا" from ancient Persian literature and an old obscure Farsi meme. ↩︎