Edit on GitHub

#  Custom Burp Editors

Scalpel’s main killer feature is the ability to program your own editors using Python.

#  Table of content

#  Event hooks

#  1. Edit a request

E.g: A simple script to edit a fully URL encoded query string parameter in a request:

from pyscalpel import Request
from pyscalpel.utils import urldecode, urlencode_all


# Hook to initialize the editor's content
def req_edit_in(req: Request) -> bytes | None:
    param = req.query.get("filename")
    if param is not None:
        return urldecode(param)

    # Do not modify the request
    return None

# Hook to update the request from the editor's modified content
def req_edit_out(req: Request, modified_content: bytes) -> Request:
    req.query["filename"] = urlencode_all(modified_content)
    return req

#  2. Edit a response

It is the same process for editing responses:

def res_edit_in(res: Response) -> bytes | None:
    # Displays an additional header in the editor
    res.headers["X-Python-In-Response-Editor"] = "res_edit_in"
    return bytes(res)


def res_edit_out(_: Response, text: bytes) -> Response | None:
    # Recreate a response from the editor's content
    res = Response.from_raw(text)
    return res

#  3. Multiple tabs example

You can have multiple tabs open at the same time. Just suffix your function names:

E.g: Same script as above but for two parameters: “filename” and “directory”.

from pyscalpel import Request
from pyscalpel.utils import urldecode, urlencode_all

def req_edit_in_filename(req: Request):
    param = req.query.get("filename")
    if param is not None:
        return urldecode(param)

def req_edit_out_filename(req: Request, text: bytes):
    req.query["filename"] = urlencode_all(text)
    return req


def req_edit_in_directory(req: Request):
    param = req.query.get("directory")
    if param is not None:
        return urldecode(param)


def req_edit_out_directory(req: Request, text: bytes):
    req.query["directory"] = urlencode_all(text)
    return req

This will result in two open tabs. One for the filename parameter and one for the directory parameter (see the second image below).


#  Binary editors

editors

To display the contents of your tab in a hexadecimal, binary, octal or decimal editor, the user can apply the editor decorator to the req_edit_in / res_edit_in hook:

1"""
2    To display the contents of your tab in a hexadecimal, binary, octal or decimal editor,
3    the user can apply the `editor` decorator to the `req_edit_in` / `res_edit_in` hook:
4"""
5from pyscalpel.edit import editor
6
7
8__all__ = ["editor"]
def editor(mode: Literal['raw', 'hex', 'octal', 'binary', 'decimal']):
12def editor(mode: EditorMode):
13    """Decorator to specify the editor type for a given hook
14
15    This can be applied to a req_edit_in / res_edit_in hook declaration to specify the editor that should be displayed in Burp
16
17    Example:
18    ```py
19        @editor("hex")
20        def req_edit_in(req: Request) -> bytes | None:
21            return bytes(req)
22    ```
23    This displays the request in an hex editor.
24
25    Currently, the only modes supported are `"raw"`, `"hex"`, `"octal"`, `"binary"` and `"decimal"`.
26
27
28    Args:
29        mode (EDITOR_MODE): The editor mode (raw, hex,...)
30    """
31
32    if mode not in EDITOR_MODES:
33        raise ValueError(f"Argument must be one of {EDITOR_MODES}")
34
35    def decorator(hook: Callable):
36        hook.__annotations__["scalpel_editor_mode"] = mode
37        return hook
38
39    return decorator

Decorator to specify the editor type for a given hook

This can be applied to a req_edit_in / res_edit_in hook declaration to specify the editor that should be displayed in Burp

Example:

    @editor("hex")
    def req_edit_in(req: Request) -> bytes | None:
        return bytes(req)

This displays the request in an hex editor.

Currently, the only modes supported are "raw", "hex", "octal", "binary" and "decimal".

Args: mode (EDITOR_MODE): The editor mode (raw, hex,...)

#  Example

E.g.: A simple script displaying requests in a hexadecimal editor and responses in a binary editor:

from pyscalpel import Request, Response, editor


@editor("hex")
def req_edit_in(req: Request) -> bytes | None:
    return bytes(req)

@editor("binary")
def res_edit_in(res: Response) -> bytes | None:
    return bytes(res)

The hexadecimal editor:

The binary editor:


#  Further reading

Learn more about the available hooks in the technical documentation’s Event Hooks & API section.