File size: 2,191 Bytes
14b1bbe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
"""
Pwntools-based PoC assembler.

Produces a runnable Python script for every confirmed crash that a human
researcher (or downstream Bounty Gateway) can review and submit.  When
``pwntools`` isn't installed the assembler still emits a self-contained
Python file using the standard library that demonstrates the input.
"""

from __future__ import annotations

import os
import textwrap
from typing import Any

try:  # pragma: no cover
    from pwn import context  # type: ignore  # noqa: F401
    _PWN = True
except Exception:  # noqa: BLE001
    _PWN = False


class PwntoolsSynth:
    def assemble(self, crash: dict[str, Any], rop_chain: list[str]) -> dict[str, Any]:
        binary = crash.get("harness", "<binary>")
        crash_input = crash.get("path", "<input>")
        chain_lit = ", ".join(repr(g) for g in rop_chain) or "# no gadgets"
        if _PWN:
            template = textwrap.dedent(f"""\
                # Auto-generated by Rhodawk Mythos
                from pwn import *
                context.log_level = 'error'
                p = process({binary!r})
                rop = ROP({binary!r})
                gadgets = [{chain_lit}]
                with open({crash_input!r}, 'rb') as f:
                    payload = f.read()
                p.sendline(payload)
                print(p.recvall(timeout=2))
            """)
        else:
            template = textwrap.dedent(f"""\
                # Auto-generated by Rhodawk Mythos (no-pwntools fallback)
                import subprocess, sys
                with open({crash_input!r}, 'rb') as f:
                    payload = f.read()
                proc = subprocess.run([{binary!r}], input=payload,
                                      capture_output=True, timeout=5)
                sys.stdout.write(proc.stdout.decode(errors='replace'))
                sys.stderr.write(proc.stderr.decode(errors='replace'))
            """)
        out_path = os.path.join("/tmp", f"poc_{crash.get('id', 'x')}.py")
        try:
            with open(out_path, "w") as fh:
                fh.write(template)
        except OSError:
            pass
        return {"path": out_path, "code": template, "uses_pwntools": _PWN}