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 aiofiles~=23.2
fuzzywuzzy[speedup]~=0.18 fuzzywuzzy[speedup]~=0.18
tortoise-orm[asyncpg]~=0.21 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 json
import os import os
import re import re
import shlex
import shutil
import tempfile
import time import time
import typing import typing
import warnings
from pathlib import Path from pathlib import Path
import discord import discord
@ -14,6 +18,8 @@ from dns import asyncresolver
from rich.console import Console from rich.console import Console
from rich.tree import Tree from rich.tree import Tree
from conf import CONFIG from conf import CONFIG
from superpaste import HstSHBackend
from superpaste.backends import GenericFile
class GetFilteredTextView(discord.ui.View): class GetFilteredTextView(discord.ui.View):
@ -346,6 +352,130 @@ class NetworkCog(commands.Cog):
await ctx.respond(embed=embed) 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): def setup(bot):
bot.add_cog(NetworkCog(bot)) bot.add_cog(NetworkCog(bot))