Add nmap command

This commit is contained in:
Nexus 2024-07-01 18:28:06 +01:00
parent c40c8294b3
commit 9d199f0102
Signed by: nex
GPG key ID: 0FA334385D0B689F
2 changed files with 131 additions and 0 deletions

View file

@ -20,3 +20,4 @@ python-magic~=0.4
aiofiles~=23.2
fuzzywuzzy[speedup]~=0.18
tortoise-orm[asyncpg]~=0.21
superpaste @ git+https://github.com/nexy7574/superpaste.git@e31eca6

View file

@ -3,8 +3,12 @@ import io
import json
import os
import re
import shlex
import shutil
import tempfile
import time
import typing
import warnings
from pathlib import Path
import discord
@ -14,6 +18,8 @@ from dns import asyncresolver
from rich.console import Console
from rich.tree import Tree
from conf import CONFIG
from superpaste import HstSHBackend
from superpaste.backends import GenericFile
class GetFilteredTextView(discord.ui.View):
@ -346,6 +352,130 @@ class NetworkCog(commands.Cog):
await ctx.respond(embed=embed)
@commands.slash_command()
@commands.max_concurrency(1, commands.BucketType.user)
async def nmap(
self,
ctx: discord.ApplicationContext,
target: str,
technique: typing.Annotated[
str,
discord.Option(
str,
choices=[
discord.OptionChoice(name="TCP SYN", value="S"),
discord.OptionChoice(name="TCP Connect", value="T"),
discord.OptionChoice(name="TCP ACK", value="A"),
discord.OptionChoice(name="TCP Window", value="W"),
discord.OptionChoice(name="TCP Maimon", value="M"),
discord.OptionChoice(name="UDP", value="U"),
discord.OptionChoice(name="TCP Null", value="N"),
discord.OptionChoice(name="TCP FIN", value="F"),
discord.OptionChoice(name="TCP XMAS", value="X"),
],
default="sT"
)
],
treat_all_hosts_online: bool = False,
service_scan: bool = False,
fast_mode: bool = False,
enable_os_detection: bool = False,
timing: typing.Annotated[
int,
discord.Option(
int,
description="Timing template to use 0 is slowest, 5 is fastest.",
choices=[0, 1, 2, 3, 4, 5],
default=3
)
] = 3,
ports: str = None
):
"""Runs nmap on a target. You cannot specify multiple targets."""
await ctx.defer()
if len(shlex.split(target)) > 1:
return await ctx.respond("You cannot specify multiple targets.")
if not shutil.which("nmap"):
warnings.warn(
"NMAP is not installed on this system, so the /nmap command is not enabled. "
"If you would like to enable it, install nmap, or mount the binary as a volume in docker."
)
return await ctx.respond("Nmap is not installed on this system.")
is_superuser = os.getuid() == 0
if technique != "T" and not is_superuser:
return await ctx.respond("Only `TCP Connect` can be used on this system.")
if enable_os_detection and not is_superuser:
return await ctx.respond("OS detection is not available on this system.")
with tempfile.TemporaryDirectory(prefix=f"nmap-{ctx.user.id}-{ctx.message.created_at.timestamp():.0f}") as tmp:
tmp_dir = Path(tmp)
args = [
"nmap",
"-oA",
str(tmp_dir.resolve() / target),
"-T",
str(timing),
"-s" + technique,
]
if treat_all_hosts_online:
args.append("-Pn")
if service_scan:
args.append("-sV")
if fast_mode:
args.append("-F")
if ports:
args.extend(("-p", ports))
if enable_os_detection:
args.append("-O")
args.append(target)
await ctx.respond(
embed=discord.Embed(
title="Running nmap...",
description="Command:\n"
"```{}```".format(shlex.join(args)),
)
)
process = await asyncio.create_subprocess_exec(
*args,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)
_, stderr = await process.communicate()
files = [discord.File(x, filename=x.name + ".txt") for x in tmp_dir.iterdir()]
if not files:
if len(stderr) <= 4089:
return await ctx.edit(
embed=discord.Embed(
title="Nmap failed.",
description="```\n" + stderr.decode() + "```",
color=discord.Color.red()
)
)
result = await HstSHBackend().async_create_paste(
GenericFile(stderr.decode())
)
return await ctx.edit(
embed=discord.Embed(
title="Nmap failed.",
description=f"Output was too long. [View full output]({result.url})",
color=discord.Color.red()
)
)
await ctx.edit(
embed=discord.Embed(
title="Nmap finished!",
description="Result files are attached.\n"
"* `gnmap` is 'greppable'\n"
"* `xml` is XML output\n"
"* `nmap` is normal output",
color=discord.Color.green()
),
files=files
)
def setup(bot):
bot.add_cog(NetworkCog(bot))