mirror of
https://github.com/p0dalirius/Coercer
synced 2026-08-09 13:01:12 +00:00
added shell completion support via argcomplete (#98)
furthermore, added missing psutil dependency to pyproject.toml
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# PYTHON_ARGCOMPLETE_OK
|
||||
# File name : Coercer.py
|
||||
# Author : Podalirius (@podalirius_)
|
||||
# Date created : 20 Sep 2022
|
||||
|
||||
@@ -38,6 +38,11 @@ You can now install it from pypi (latest version is <img alt="PyPI" src="https:/
|
||||
sudo python3 -m pip install coercer
|
||||
```
|
||||
|
||||
### Shell Completions
|
||||
|
||||
Coercer uses [argcomplete](https://github.com/kislyuk/argcomplete) to autogenerate tab completions for your shell (bash, zsh, fish, ...).
|
||||
See the `argcomplete` README for how to enable tab completions.
|
||||
|
||||
## Quick start
|
||||
|
||||
- You want to **assess** the Remote Procedure Calls listening on a machine to see if they can be leveraged to coerce an authentication?
|
||||
@@ -49,7 +54,7 @@ sudo python3 -m pip install coercer
|
||||
+ Use [**coerce** mode](./documentation/Coerce-mode.md), example:
|
||||
|
||||
https://user-images.githubusercontent.com/79218792/204372851-4ba461ed-6812-4057-829d-0af6a06b0ecc.mp4
|
||||
|
||||
|
||||
- You are doing **research** and want to fuzz Remote Procedure Calls listening on a machine with various paths?
|
||||
+ Use [**fuzz** mode](./documentation/Fuzz-mode.md), example:
|
||||
|
||||
|
||||
+15
-12
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# PYTHON_ARGCOMPLETE_OK
|
||||
# File name : __main__.py
|
||||
# Author : Podalirius (@podalirius_)
|
||||
# Date created : 17 Sep 2022
|
||||
@@ -9,6 +10,7 @@ import argparse
|
||||
import os
|
||||
import sys
|
||||
import threading
|
||||
import argcomplete
|
||||
from sectools.network.domains import is_fqdn
|
||||
from sectools.network.ip import is_ipv4_cidr, is_ipv4_addr, is_ipv6_addr, expand_cidr, expand_port_range
|
||||
|
||||
@@ -46,7 +48,7 @@ def parseArgs():
|
||||
mode_scan_advanced_config.add_argument("--smb-port", default=445, type=int, help="SMB port (default: 445)")
|
||||
mode_scan_advanced_config.add_argument("--dce-port", default=135, type=int, help="DCERPC port (default: 135)")
|
||||
mode_scan_advanced_config.add_argument("--dce-ports", default=[], nargs='+', type=int, help="DCERPC ports")
|
||||
mode_scan_advanced_config.add_argument("--auth-type", default=None, type=str, help="Desired authentication type ('smb' or 'http').")
|
||||
mode_scan_advanced_config.add_argument("--auth-type", default=None, type=str, choices=('smb', 'http'), help="Desired authentication type.")
|
||||
mode_scan_advanced_config.add_argument("--stop-on-ntlm-auth", default=False, action="store_true", help="Move on to next target on successful NTLM authentication.")
|
||||
# Filters
|
||||
mode_scan_filters = mode_scan.add_argument_group("Filtering")
|
||||
@@ -93,7 +95,7 @@ def parseArgs():
|
||||
mode_fuzz_advanced_config.add_argument("--smb-port", default=445, type=int, help="SMB port (default: 445)")
|
||||
mode_fuzz_advanced_config.add_argument("--dce-port", default=135, type=int, help="DCERPC port (default: 135)")
|
||||
mode_fuzz_advanced_config.add_argument("--dce-ports", default=[], nargs='+', type=int, help="DCERPC ports")
|
||||
mode_fuzz_advanced_config.add_argument("--auth-type", default=None, type=str, help="Desired authentication type ('smb' or 'http').")
|
||||
mode_fuzz_advanced_config.add_argument("--auth-type", default=None, type=str, choices=('smb', 'http'), help="Desired authentication type.")
|
||||
# Filters
|
||||
mode_fuzz_filters = mode_fuzz.add_argument_group("Filtering")
|
||||
mode_fuzz_filters.add_argument("--filter-method-name", default=[], action='append', type=str, help="Filter by method name")
|
||||
@@ -122,7 +124,7 @@ def parseArgs():
|
||||
mode_fuzz_logging = mode_fuzz.add_argument_group("Logging")
|
||||
mode_fuzz_logging.add_argument("--minimum-log-level", default=0, help="Minimum logging level (integer).")
|
||||
mode_fuzz_logging.add_argument("--log-file", default=None, help="Path for the file to log to (enables logging).")
|
||||
|
||||
|
||||
# Creating the "coerce" subparser ==============================================================================================================
|
||||
mode_coerce = argparse.ArgumentParser(add_help=False)
|
||||
mode_coerce.add_argument("-v", "--verbose", default=False, action="store_true", help="Verbose mode (default: False)")
|
||||
@@ -136,7 +138,7 @@ def parseArgs():
|
||||
mode_coerce_advanced_config.add_argument("--dce-port", default=135, type=int, help="DCERPC port (default: 135)")
|
||||
mode_coerce_advanced_config.add_argument("--dce-ports", default=[], nargs='+', type=int, help="DCERPC ports")
|
||||
mode_coerce_advanced_config.add_argument("--always-continue", default=False, action="store_true", help="Always continue to coerce")
|
||||
mode_coerce_advanced_config.add_argument("--auth-type", default=None, type=str, help="Desired authentication type ('smb' or 'http').")
|
||||
mode_coerce_advanced_config.add_argument("--auth-type", default=None, type=str, choices=('smb', 'http'), help="Desired authentication type.")
|
||||
# Filters
|
||||
mode_coerce_filters = mode_coerce.add_argument_group("Filtering")
|
||||
mode_coerce_filters.add_argument("--filter-method-name", default=[], action='append', type=str, help="Filter by method name")
|
||||
@@ -165,13 +167,14 @@ def parseArgs():
|
||||
mode_coerce_logging = mode_coerce.add_argument_group("Logging")
|
||||
mode_coerce_logging.add_argument("--minimum-log-level", default=0, help="Minimum logging level (integer).")
|
||||
mode_coerce_logging.add_argument("--log-file", default=None, help="Path for the file to log to (enables logging).")
|
||||
|
||||
|
||||
# Adding the subparsers to the base parser
|
||||
subparsers = parser.add_subparsers(help="Mode", dest="mode", required=True)
|
||||
mode_scan_parser = subparsers.add_parser("scan", parents=[mode_scan], help="Tests known methods with known working paths on all methods, and report when an authentication is received.")
|
||||
mode_coerce_parser = subparsers.add_parser("coerce", parents=[mode_coerce], help="Trigger authentications through all known methods with known working paths")
|
||||
mode_coerce_parser = subparsers.add_parser("coerce", parents=[mode_coerce], help="Trigger authentications through all known methods with known working paths.")
|
||||
mode_fuzz_parser = subparsers.add_parser("fuzz", parents=[mode_fuzz], help="Tests every method with a list of exploit paths, and report when an authentication is received.")
|
||||
|
||||
argcomplete.autocomplete(parser, always_complete_options=False)
|
||||
options = parser.parse_args()
|
||||
|
||||
# Parsing hashes
|
||||
@@ -245,15 +248,15 @@ def main():
|
||||
final_targets.append(target)
|
||||
else:
|
||||
reporter.print_warn("Target '%s' was not added." % target, debug=True)
|
||||
|
||||
# Sort
|
||||
|
||||
# Sort
|
||||
targets = sorted(list(set(final_targets)))
|
||||
|
||||
credentials = Credentials(
|
||||
username=options.username,
|
||||
password=options.password,
|
||||
domain=options.domain,
|
||||
lmhash=lmhash,
|
||||
username=options.username,
|
||||
password=options.password,
|
||||
domain=options.domain,
|
||||
lmhash=lmhash,
|
||||
nthash=nthash
|
||||
)
|
||||
|
||||
|
||||
Generated
+47
-5
@@ -1,4 +1,22 @@
|
||||
# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "argcomplete"
|
||||
version = "3.1.2"
|
||||
description = "Bash tab completion for argparse"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "argcomplete-3.1.2-py3-none-any.whl", hash = "sha256:d97c036d12a752d1079f190bc1521c545b941fda89ad85d15afa909b4d1b9a99"},
|
||||
{file = "argcomplete-3.1.2.tar.gz", hash = "sha256:d5d1e5efd41435260b8f85673b74ea2e883affcbec9f4230c582689e8e78251b"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
importlib-metadata = {version = ">=0.23,<7", markers = "python_version < \"3.8\""}
|
||||
|
||||
[package.extras]
|
||||
test = ["coverage", "mypy", "pexpect", "ruff", "wheel"]
|
||||
|
||||
[[package]]
|
||||
name = "cffi"
|
||||
@@ -260,7 +278,7 @@ zipp = ">=0.5"
|
||||
[package.extras]
|
||||
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"]
|
||||
perf = ["ipython"]
|
||||
testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
|
||||
testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3) ; python_version < \"3.9\"", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7) ; platform_python_implementation != \"PyPy\"", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8 ; python_version < \"3.12\"", "pytest-mypy (>=0.9.1) ; platform_python_implementation != \"PyPy\"", "pytest-perf (>=0.9.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "itsdangerous"
|
||||
@@ -415,6 +433,30 @@ files = [
|
||||
{file = "netifaces-0.11.0.tar.gz", hash = "sha256:043a79146eb2907edf439899f262b3dfe41717d34124298ed281139a8b93ca32"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psutil"
|
||||
version = "7.0.0"
|
||||
description = "Cross-platform lib for process and system monitoring in Python. NOTE: the syntax of this script MUST be kept compatible with Python 2.7."
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "psutil-7.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:101d71dc322e3cffd7cea0650b09b3d08b8e7c4109dd6809fe452dfd00e58b25"},
|
||||
{file = "psutil-7.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:39db632f6bb862eeccf56660871433e111b6ea58f2caea825571951d4b6aa3da"},
|
||||
{file = "psutil-7.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fcee592b4c6f146991ca55919ea3d1f8926497a713ed7faaf8225e174581e91"},
|
||||
{file = "psutil-7.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b1388a4f6875d7e2aff5c4ca1cc16c545ed41dd8bb596cefea80111db353a34"},
|
||||
{file = "psutil-7.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5f098451abc2828f7dc6b58d44b532b22f2088f4999a937557b603ce72b1993"},
|
||||
{file = "psutil-7.0.0-cp36-cp36m-win32.whl", hash = "sha256:84df4eb63e16849689f76b1ffcb36db7b8de703d1bc1fe41773db487621b6c17"},
|
||||
{file = "psutil-7.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:1e744154a6580bc968a0195fd25e80432d3afec619daf145b9e5ba16cc1d688e"},
|
||||
{file = "psutil-7.0.0-cp37-abi3-win32.whl", hash = "sha256:ba3fcef7523064a6c9da440fc4d6bd07da93ac726b5733c29027d7dc95b39d99"},
|
||||
{file = "psutil-7.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:4cf3d4eb1aa9b348dec30105c55cd9b7d4629285735a102beb4441e38db90553"},
|
||||
{file = "psutil-7.0.0.tar.gz", hash = "sha256:7be9c3eba38beccb6495ea33afd982a44074b78f28c434a1f51cc07fd315c456"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
dev = ["abi3audit", "black (==24.10.0)", "check-manifest", "coverage", "packaging", "pylint", "pyperf", "pypinfo", "pytest", "pytest-cov", "pytest-xdist", "requests", "rstcheck", "ruff", "setuptools", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "virtualenv", "vulture", "wheel"]
|
||||
test = ["pytest", "pytest-xdist", "setuptools"]
|
||||
|
||||
[[package]]
|
||||
name = "pyasn1"
|
||||
version = "0.4.8"
|
||||
@@ -528,7 +570,7 @@ description = "Backported and Experimental Type Hints for Python 3.7+"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
markers = "python_version < \"3.8\""
|
||||
markers = "python_version == \"3.7\""
|
||||
files = [
|
||||
{file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"},
|
||||
{file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"},
|
||||
@@ -579,9 +621,9 @@ files = [
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"]
|
||||
testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
|
||||
testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7) ; platform_python_implementation != \"PyPy\"", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8 ; python_version < \"3.12\"", "pytest-mypy (>=0.9.1) ; platform_python_implementation != \"PyPy\""]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = ">=3.7"
|
||||
content-hash = "09f656769a2b2da2b0baf09bd564e97ff7fb39375b519002bc112ba608144d0e"
|
||||
content-hash = "0ac25becbd61fd064883187452230ba4b3fde74458501a1453b7d7899923feff"
|
||||
|
||||
+3
-1
@@ -9,11 +9,13 @@ authors = [
|
||||
{ name = "p0dalirius" }
|
||||
]
|
||||
dependencies = [
|
||||
"argcomplete",
|
||||
"impacket>=0.10.0",
|
||||
"xlsxwriter>=3.0.0",
|
||||
"jinja2>=3.1.3",
|
||||
"sectools>=1.4.3",
|
||||
"netifaces>=0.11.0"
|
||||
"netifaces>=0.11.0",
|
||||
"psutil",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
|
||||
+2
-1
@@ -1,7 +1,8 @@
|
||||
argcomplete
|
||||
impacket
|
||||
xlsxwriter
|
||||
jinja2
|
||||
sectools
|
||||
netifaces
|
||||
psutil
|
||||
pydivert; sys_platform == "win32"
|
||||
pydivert; sys_platform == "win32"
|
||||
|
||||
Reference in New Issue
Block a user