feat: add wave 1 plugins (dns, encode, hash, defang, revshell, cidr)
All pure stdlib, zero external dependencies: - dns: raw UDP resolver with A/AAAA/MX/NS/TXT/CNAME/PTR/SOA - encode: base64, hex, URL, ROT13 encode/decode - hash: md5/sha1/sha256/sha512 generation + type identification - defang: IOC defanging/refanging for safe sharing - revshell: reverse shell one-liners for 11 languages - cidr: subnet calculator with IP membership check Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
75
plugins/encode.py
Normal file
75
plugins/encode.py
Normal file
@@ -0,0 +1,75 @@
|
||||
"""Plugin: encode and decode strings (base64, hex, URL, ROT13)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import urllib.parse
|
||||
|
||||
from derp.plugin import command
|
||||
|
||||
_ROT13 = str.maketrans(
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
||||
"NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm",
|
||||
)
|
||||
|
||||
_ENCODERS: dict[str, tuple[str, callable]] = {
|
||||
"b64": ("Base64", lambda t: base64.b64encode(t.encode()).decode()),
|
||||
"hex": ("Hex", lambda t: t.encode().hex()),
|
||||
"url": ("URL", lambda t: urllib.parse.quote(t, safe="")),
|
||||
"rot13": ("ROT13", lambda t: t.translate(_ROT13)),
|
||||
}
|
||||
|
||||
_DECODERS: dict[str, tuple[str, callable]] = {
|
||||
"b64": ("Base64", lambda t: base64.b64decode(t).decode("utf-8", errors="replace")),
|
||||
"hex": ("Hex", lambda t: bytes.fromhex(t).decode("utf-8", errors="replace")),
|
||||
"url": ("URL", lambda t: urllib.parse.unquote(t)),
|
||||
"rot13": ("ROT13", lambda t: t.translate(_ROT13)),
|
||||
}
|
||||
|
||||
_FORMATS = ", ".join(_ENCODERS)
|
||||
|
||||
|
||||
@command("encode", help=f"Encode text: !encode <{_FORMATS}> <text>")
|
||||
async def cmd_encode(bot, message):
|
||||
"""Encode text in the specified format."""
|
||||
parts = message.text.split(None, 2)
|
||||
if len(parts) < 3:
|
||||
await bot.reply(message, f"Usage: !encode <{_FORMATS}> <text>")
|
||||
return
|
||||
|
||||
fmt = parts[1].lower()
|
||||
text = parts[2]
|
||||
|
||||
entry = _ENCODERS.get(fmt)
|
||||
if entry is None:
|
||||
await bot.reply(message, f"Unknown format: {fmt} (valid: {_FORMATS})")
|
||||
return
|
||||
|
||||
try:
|
||||
result = entry[1](text)
|
||||
await bot.reply(message, result)
|
||||
except Exception as exc:
|
||||
await bot.reply(message, f"Encode error: {exc}")
|
||||
|
||||
|
||||
@command("decode", help=f"Decode text: !decode <{_FORMATS}> <text>")
|
||||
async def cmd_decode(bot, message):
|
||||
"""Decode text from the specified format."""
|
||||
parts = message.text.split(None, 2)
|
||||
if len(parts) < 3:
|
||||
await bot.reply(message, f"Usage: !decode <{_FORMATS}> <text>")
|
||||
return
|
||||
|
||||
fmt = parts[1].lower()
|
||||
text = parts[2]
|
||||
|
||||
entry = _DECODERS.get(fmt)
|
||||
if entry is None:
|
||||
await bot.reply(message, f"Unknown format: {fmt} (valid: {_FORMATS})")
|
||||
return
|
||||
|
||||
try:
|
||||
result = entry[1](text)
|
||||
await bot.reply(message, result)
|
||||
except Exception as exc:
|
||||
await bot.reply(message, f"Decode error: {exc}")
|
||||
Reference in New Issue
Block a user