Skip to content
designformatllm

Attacks as data: why a plain text format beats a script

Attacks as data: why a plain text format beats a script plasma
######%%%%%%%%%%%%%%%%%#######*****+++++=====-------::::::::::::::::-------======+++++++************
##%%%%%%%%%%%%%%%%%%%%%%%%######*****+++++=====------:::::::::::::::::--------======++++++*********#
%%%%%%%@@@@@@@@@@@@@@@%%%%%%%######****+++++=====-------::::::::::::::::--------======++++++*******#
%%%%@@@@@@@@@@@@@@@@@@@@@@%%%%%%#####*****++++=====--------:::::::::::::---------======++++++******#
%%%@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%%####*****+++++=====------------:::------------=======++++++******
%%%%@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%#####****+++++======-------------------------========++++++*****
%%%%%%@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%%####*****+++++=======-----------------------========+++++++****
##%%%%%%%%%@@@@@@@@@@@@@@@@@@@%%%%%%####*****+++++=======-----------------------==========+++++++***
########%%%%%%%%%%%%@@@%%%%%%%%%%#####****+++++======--------------------------============++++++++*
******##########%%%%%%%%%%%#######****++++=====-------:::::::::-----------------============++++++++
+++++**********############*******++++====----::::::....::::::::::::------------==============++++++
=====++++++++++++*********++++++++====---::::...       ........:::::::------------===============+++
----================++++=========-----::::...              ......:::::::----------==================
----------------------------------:::::.....               ......:::::::-----------=================
:::::::::::::::::::::::::::::::::::........                .......::::::----------==================
::...........::::::::::::::.............                  .......:::::::--------================++++
....................................                     .......:::::::-------==========++++++++++++
::............................                         ........::::::-------=======+++++++++++++++++
:::::::.......................                       ........:::::::-----======++++++++*************
---::::::::::::::....................           ...........::::::------=====+++++********###########
==-------------::::::::::::::..........................:::::::------====+++++******#######%%%%%%%%%%
+++===============-----------:::::::::::::::::::::::::::::------=====++++*****#####%%%%%%%%@@@@@@@@@
*******+++++++++++++++==========---------------------------======+++++****#####%%%%%@@@@@@@@@@@@@@@@
################***********++++++++=========================+++++*****#####%%%%@@@@@@@@@@@@@@@@@@@@@

Security teams already build lightweight replay scripts for specific exploits. Most of them by hand, and none of them alike. Exploitmatic formalizes that idea with a grammar: an attack becomes a plain text file that chains steps, captures values, and evaluates an assert on each response.

The important move is that the file is data, not code. That one decision drives everything else.

Data, never code

A solution is bytes in, bytes out, and a set of tests over the response. The runtime never executes anything from a solution. It replays the steps and reports what the asserts found.

That means the corpus has no arbitrary-code supply chain. There is no template engine and no injected interpreter. When you run a solution you are not running someone else’s program; you are running your own runtime against a payload that is just bytes and tests. The blast radius of a bad file is a failed assert, not code execution on your machine.

A human can read it, an LLM can write it

The format is plain text on purpose. A step block reads like a checklist:

tls malformed-heartbeat
  send: 1803030003014000
  recv: 70000
  assert: regex "18030[123]40"

A human sees the identity, the bytes, and the test. An LLM sees the same grammar, and because the runtime is deterministic, a file an LLM writes is exactly what runs. The result lines give it a clean signal to fix and retry.

That is the loop: describe the attack in your own words, let an LLM draft the file, review it, then run it. Natural language is an authoring aid, never a runtime input.

The result is derived, never stored

The runtime prints what was sent, what came back, and the test that ran on each step. One line per step, then a result line. There is no artifact file; the console output is the result.

The result comes from the tests, never from the file. A solution cannot claim a success it did not earn, because the report only repeats what the asserts found on this run.

Plain text, no YAML

Line-based, one instruction per line, comments with #, validated at load. No aliases, no anchors, no YAML CVEs. The strictness lives in the loader, not in a second language to learn.

That is the trade we wanted: a format with no syntax to remember, and a runtime that refuses to run a bad file.

The grammar is the contract

The formal grammar, the parser, and the validator are open. A solution either parses or it does not, and the error says which line and why. That makes the corpus reviewable by machines and humans alike, and it makes authoring something an LLM can be coached to do well.

Exploitation comes first, and the verification is what proves it worked. The format is how both stay honest.

Write attacks down. Verify them.

Download the binary, point it at a target you own, and get a verified result. The corpus is open and the format is plain text.