Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Codebase complete rework #108

Merged
merged 16 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,9 @@ jobs:
- uses: actions/checkout@v1
- name: Install HatSploit
run: sudo pip3 install .
- name: Perform checks
run: hsf -c
macOS:
runs-on: macos-latest
steps:
- uses: actions/checkout@v1
- name: Install HatSploit
run: sudo pip3 install .
- name: Perform checks
run: hsf -c
run: sudo pip3 install . --break-system-packages
121 changes: 48 additions & 73 deletions hatsploit/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,15 @@
SOFTWARE.
"""

import argparse
import os
import sys
import yaml
import argparse

from hatasm import HatAsm
from typing import Any, Optional
from badges import Badges, Tables

from pex.platform.types import EXEC_FORMATS
from pex.platform import EXEC_FORMATS

from hatsploit.core.base.console import Console

Expand All @@ -43,34 +42,22 @@
from hatsploit.core.utils.update import Update

from hatsploit.lib.config import Config
from hatsploit.lib.jobs import Jobs
from hatsploit.lib.ui.jobs import Jobs
from hatsploit.lib.runtime import Runtime
from hatsploit.lib.payloads import Payloads
from hatsploit.lib.encoders import Encoders
from hatsploit.lib.show import Show
from hatsploit.lib.ui.payloads import Payloads
from hatsploit.lib.ui.encoders import Encoders
from hatsploit.lib.ui.show import Show


class HatSploit(object):
class HatSploit(Badges, Config):
""" Main class of hatsploit module.

This main class of hatsploit module is a representation of
HatSploit Framework CLI interface.
"""

def __init__(self) -> None:
super().__init__()

self.jobs = Jobs()
self.config = Config()
self.runtime = Runtime()

self.console = Console()
self.builder = Builder()
self.badges = Badges()
self.check = Check()
self.update = Update()

self.path_config = self.config.path_config
jobs = Jobs()
runtime = Runtime()

def policy(self) -> bool:
""" Print Terms of Service and ask for confirmation.
Expand All @@ -80,14 +67,14 @@ def policy(self) -> bool:
"""

if not os.path.exists(self.path_config['accept_path']):
self.badges.print_information("--( The HatSploit Terms of Service )--")
self.print_information("--( The HatSploit Terms of Service )--")

with open(
self.path_config['policy_path'] + 'terms_of_service.txt', 'r'
) as f:
self.badges.print_empty(f.read())
self.print_empty(f.read())

agree = self.badges.input_question(
agree = self.input_question(
"Accept HatSploit Framework Terms of Service? [y/n] "
)
if agree[0].lower() not in ['y', 'yes']:
Expand All @@ -113,8 +100,8 @@ def initialize(self, silent: bool = False) -> bool:

build = False

if not self.builder.check_base_built():
build = self.badges.input_question(
if not Builder().check_base_built():
build = self.input_question(
"Do you want to build and connect base databases? [y/n] "
)

Expand All @@ -141,9 +128,9 @@ def launch(self, shell: bool = True, scripts: list = [], rpc: list = []) -> None
if len(rpc) >= 2:
self.jobs.create_job(f"RPC on port {str(rpc[1])}", "", RPC(*rpc).run)

self.console.shell()
Console().shell()
else:
self.console.script(scripts, shell)
Console().script(scripts, shell)

def cli(self) -> None:
""" Main command-line arguments handler.
Expand Down Expand Up @@ -237,22 +224,22 @@ def cli(self) -> None:
rpc = (args.host or '127.0.0.1', args.port or 5000)

if args.check_all:
sys.exit(not self.check.check_all())
sys.exit(not Check().check_all())

elif args.check_modules:
sys.exit(self.check.check_modules())
sys.exit(Check().check_modules())

elif args.check_payloads:
sys.exit(self.check.check_payloads())
sys.exit(Check().check_payloads())

elif args.check_plugins:
sys.exit(self.check.check_plugins())
sys.exit(Check().check_plugins())

elif args.check_encoders:
sys.exit(self.check.check_encoders())
sys.exit(Check().check_encoders())

elif args.update:
self.update.update()
Update().update()
sys.exit(0)

elif args.script:
Expand Down Expand Up @@ -315,28 +302,15 @@ def __call__(self, parser: Any, namespace: Any, values: str,
setattr(namespace, self.dest, options)


class HatSploitGen(HatSploit):
class HatSploitGen(HatSploit, Tables, HatAsm):
""" Main class of hatsploit module.

This main class of hatsploit module is a payload generator
CLI interface.
"""

def __init__(self) -> None:
super().__init__()

self.hatasm = HatAsm()
self.payloads = Payloads()
self.encoders = Encoders()

self.show = Show()

self.badges = Badges()
self.tables = Tables()
self.config = Config()

self.builder = Builder()
self.db = DB()
payloads = Payloads()
encoders = Encoders()

def cli(self) -> None:
""" Main command-line arguments handler.
Expand Down Expand Up @@ -431,6 +405,7 @@ def cli(self) -> None:
'-a',
'--assembly',
dest='assembly',
action='store_true',
help='Show assembly for payloads. (requires --arch)'
)
parser.add_argument(
Expand All @@ -448,12 +423,12 @@ def cli(self) -> None:
args = parser.parse_args()

if args.custom:
self.badges.print_process(f"Using {args.custom} as custom payload path...")
self.print_process(f"Using {args.custom} as custom payload path...")

self.builder.build_payload_database(
args.custom, self.config.path_config['db_path'] + 'custom.json')
self.db.connect_payload_database(
'custom', self.config.path_config['db_path'] + 'custom.json')
Builder().build_payload_database(
args.custom, self.path_config['db_path'] + 'custom.json')
DB().connect_payload_database(
'custom', self.path_config['db_path'] + 'custom.json')

if args.payloads or args.encoders:
query = ''
Expand All @@ -464,10 +439,10 @@ def cli(self) -> None:
query += '/' + args.arch

if args.payloads:
self.show.show_search_payloads(
Show().show_search_payloads(
self.payloads.get_payloads(), query)
elif args.encoders:
self.show.show_search_encoders(
Show().show_search_encoders(
self.encoders.get_encoders(), query)

elif args.formats:
Expand All @@ -478,7 +453,7 @@ def cli(self) -> None:
platforms = ', '.join([str(p) for p in EXEC_FORMATS[format]])
data.append((format, platforms))

self.tables.print_table("Formats", ('Format', 'Platforms'), *data)
self.print_table("Formats", ('Format', 'Platforms'), *data)

else:
formats = []
Expand All @@ -488,33 +463,33 @@ def cli(self) -> None:
formats.append(format)

data = [(args.platform, ', '.join(formats))]
self.tables.print_table("Formats", ('Platform', 'Formats'), *data)
self.print_table("Formats", ('Platform', 'Formats'), *data)

elif args.payload:
self.badges.print_process(f"Attempting to generate {args.payload}...")
self.print_process(f"Attempting to generate {args.payload}...")

options = {}

if args.options:
options = args.options

if args.encoder and args.iterations:
self.badges.print_information(f"Using {str(args.iterations)} as a number of times to encode.")
self.print_information(f"Using {str(args.iterations)} as a number of times to encode.")
options['iterations'] = args.iterations

if args.badchars:
self.badges.print_information(f"Trying to avoid these bad characters: {args.badchars}")
self.print_information(f"Trying to avoid these bad characters: {args.badchars}")
options['badchars'] = args.badchars

if args.encoder:
self.badges.print_information(f"Payload will be encoded with {args.encoder}")
self.print_information(f"Payload will be encoded with {args.encoder}")

payload = self.payloads.get_payload(args.payload)
if not payload:
self.badges.print_error(f"Invalid payload: {args.payload}!")
self.print_error(f"Invalid payload: {args.payload}!")
return

details = payload.details
details = payload.info
payload = self.payloads.generate_payload(
args.payload, options, args.encoder, 'implant' if args.implant else 'run')

Expand All @@ -523,26 +498,26 @@ def cli(self) -> None:
payload, details['Platform'], details['Arch'], args.format)

if not payload:
self.badges.print_error(f"Invalid format: {args.format}!")
self.print_error(f"Invalid format: {args.format}!")
return

if not args.output:
self.badges.print_process("Writing raw payload...")
self.print_process(f"Writing raw payload ({str(len(payload))} bytes)...")

if isinstance(payload, bytes):
if args.assembly:
hexdump = self.hatasm.hexdump_asm(str(details['Arch']), code=payload)
hexdump = self.hexdump_asm(str(details['Arch']), code=payload)
else:
hexdump = self.hatasm.hexdump(payload)
hexdump = self.hexdump(payload)

for line in hexdump:
self.badges.print_empty(line)
self.print_empty(line)
else:
self.badges.print_empty(payload)
self.print_empty(payload)

else:
with open(args.output, 'wb') as f:
self.badges.print_process(f"Saving payload to {args.output}...")
self.print_process(f"Saving payload to {args.output} ({str(len(payload))} bytes)...")
f.write(payload)

else:
Expand Down
24 changes: 11 additions & 13 deletions hatsploit/commands/advanced.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,15 @@
Current source: https://github.com/EntySec/HatSploit
"""

from hatsploit.lib.command import Command
from hatsploit.lib.modules import Modules
from hatsploit.lib.show import Show
from badges.cmd import Command

from hatsploit.lib.ui.modules import Modules
from hatsploit.lib.ui.show import Show

class HatSploitCommand(Command):
def __init__(self):
super().__init__()

self.show = Show()
self.modules = Modules()

self.details.update({
class ExternalCommand(Command):
def __init__(self):
super().__init__({
'Category': "modules",
'Name': "advanced",
'Authors': [
Expand All @@ -26,8 +22,10 @@ def __init__(self):
'MinArgs': 0,
})

def rpc(self, *args):
self.modules = Modules()

def rpc(self, *_):
return self.modules.get_current_advanced()

def run(self, argc, argv):
self.show.show_advanced(self.modules.get_current_module())
def run(self, _):
Show().show_advanced(self.modules.get_current_module())
40 changes: 29 additions & 11 deletions hatsploit/commands/back.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,13 @@
Current source: https://github.com/EntySec/HatSploit
"""

from hatsploit.lib.command import Command
from hatsploit.lib.modules import Modules
from badges.cmd import Command
from hatsploit.lib.ui.modules import Modules


class HatSploitCommand(Command):
class ExternalCommand(Command):
def __init__(self):
super().__init__()

self.modules = Modules()

self.details.update({
super().__init__({
'Category': "modules",
'Name': "back",
'Authors': [
Expand All @@ -24,8 +20,30 @@ def __init__(self):
'MinArgs': 0,
})

def rpc(self, *args):
self.run(0, [])
self.modules = Modules()

def run(self, argc, argv):
def rpc(self, *_):
self.modules.go_back()

def run(self, _):
module = self.modules.get_current_module()

if not module:
return

for command in module.commands:
self.console.delete_external(command)

self.modules.go_back()

module = self.modules.get_current_module()

if module:
commands = {}

for command in module.commands:
commands[command] = module.commands[command]
commands[command]['Method'] = getattr(module, command)
commands[command]['Category'] = 'module'

self.console.add_external(commands)
Loading