基于Python+协程+多进程的通用弱密码扫描器

听说不想扯淡的程序猿,不是一只好猿。所以今天来扯扯淡,不贴代码,只讲设计思想。

0x00 起 - 初始设计

我们的目标是设计一枚通用的弱密码扫描器,基本功能是针对不同类型的弱密码,可方便的扩展,比如添加SSH、SVN、phpmyadmin的弱密码扫描功能。我们设定启动方法是命令行,可以通过命令行指定扫描对象,以及扫描哪些弱密码。

既然是要求可扩展,那我们首先来编写一个通用的框架,然后通过添加POC的方法来实现扩展。在这个框架中,我们需要处理的事情包括:

  • 初始化扫描对象(格式化URL、从文件或数据库中读取URL)
  • 载入弱密码扫描脚本(载入一种或者多种扫描脚本)

同时为了易用性,框架还要提供一些额外的功能:

  • 提供一些公用的函数(如端口扫描、URL去格式化以及格式化等)
  • 显示当前可用的POC以及POC的相关信息

我们预期的调用方法应该是这样:

python base.py -p ssh_weak,mysql_weak -t test.txt --run

这样,让我们画个简图:

具体讲解一下:

base.py是扫描器的入口文件

  • poc处理流程:init_poc()将输入 ssh_weak,mysql_weak格式化,通过load_poc()加载到内存中。
  • target处理流程: init_target()将输入 test.txt 内容读取到内存中,同时应该支持直接指定参数,以及从数据库中读取参数。
  • POC管理: show_poc_info()调用load_poc(),载入所有POC,并print poc_info。

poc_base.py是所有POC的父类,POC通过继承poc_base,来实现常用函数的继承,以及POC引擎。

0x10 承 - 功能抽象

通过上述描述,我们得到了一个简单的框架,通过这个框架提供的功能,我们来试着写一个标准的POC:

from poc_base import PocBase

class MyPOC(PocBase):
    poc_info = {
        ‘author‘: ‘Friday‘,
        ‘title‘: ‘svn_weak‘,
    }

    def svn_burst(self, url, user, password):
        pass

    def save():        # 向数据库或文件中存储结果
        pass

    def verify(self, target):
        count = 0
        for url in target:
            for user in [‘root‘, ‘work‘]:
                for passwd in [‘test‘, ‘123456‘]:
                    count += 1
                    if port_open(22) and svn_burst():
                        print "Success"
                        save()    

                    if count % 10 == 0:
                        print "当前进度:%d" % count

有几个地方可以优化:

  1. 数据存储模块,每次扫描完存储一次,太浪费资源,有什么解决方法?
  2. 数据存储模块,是否能集成到框架中?
  3. 扫描数量较大的时候,应该有扫描成功的提醒,以及扫描进度的提醒,是否能集成到框架中?

这其实是一个问题,数据定时存储(扫描过程中多次存储)和进度提醒功能,如何集成到框架中?本来的逻辑是,调用一次POC,扫描多个URL,然后直接由POC输出结果。如果想实现数据存储和进度提醒,看起来要把更多的控制权交到框架手中。所以,将POC的功能简化到判断某一个URL是否存在弱密码,返回true or false。将POC的调用权限,交到Poc_Base中,多次调用POC,伪代码如下:

class Poc_Base(object):

    count = 0
    progress = 100              # 进度提醒的单位

    @ overide
    def verify():
        pass

    def run():
        for url in url_list:
            count += 1

            if count % progress == 0:
                save()                               # 数据存储
                print "progress %d " % (count)       # 进度提醒

            if self.verify():
                print "success"

经过优化之后,POC的基本模式,更简单了:

from poc_base import PocBase

class MyPOC(PocBase):
    poc_info = {
        ‘author‘: ‘Friday‘,
        ‘title‘: ‘svn_weak‘,
    }

    def svn_burst(self, url, user, password):
        pass

    def verify(self, url):
        for user in [‘root‘, ‘work‘]:
            for passwd in [‘test‘, ‘123456‘]:
                if port_open(22) and svn_burst():
                    return True

在beebeeto提交过POC的同学,应该惊呼了“除了结果自动存储的模块,这不和beebeeto的框架一样么!”,是的,在一开始写框架的时候,参考了beebeeto-frame,后来独立编写完成/优化完成后,发现殊途同归了 : )

0x20 转 - 性能提升

在实现基本功能之后,我又开始蠢蠢欲动了。作为一个有尊(xing)严(neng)的框架,怎么能满足于一条线的模式!所以,为了效率,我们要在框架层面添加协程和多进程支持,让多核CPU每个都能跑到100%是我们的目标!

但应该怎么添加进程和协程的支持呢?有之前添加数据存储和进度提醒的经验,实现不难想象。难点在于,在添加进程和协程支持的时候,不影响正常的数据存储和进度提醒。伪代码如下:

class Poc_Base(object):
    gevent_num = 100            # 协程数
    process_num = 4             # 进程数

    count = [0] * process_num   # 每个进程,单独计数
    progress = 100              # 进度提醒的单位

    @ overide
    def verify():
        pass

    def verify_count():
        count[progress_number] += 1

        if count[progress_number] % progress == 0:
            save()                                                # 数据存储
            print "progress %d " % (count[progress_number])       # 进度提醒

        if self.verify():
            print "success"

    # 协程调度函数,分配任务到协程
    def run_in_gevent(url_list):                    # url_list 每个进程分配到一定量的url
        pool = Pool(self.gevent_num)
        for target in url_list:
            pool.add(gevent.spawn(self.verify_count, url))

        pool.join()

    # 进程调度函数,分配任务到各个进程
    def run():
        url_each_process = len(url_list)/process_num

        for process_number in range(process_num):
            multiprocessing.Process(target=run_in_gevent, args=(url_list[*:*],)).start()

        multiprocessing.join()
        

这样,我们就能在跑POC的时候,用到高端的协程和进程了。

0x30 合

实际运行过程中,协程开了150,进程开了2(8核CPU),可以把两个核的CPU都跑到90+%。

虽然一开始说,不会贴代码,但还是贴了不少伪代码。内容并不深奥,如果你看过beebeeto-frame和beehive的源码,觉得这是简化版的beehive,是高度定制版的beebeeto-frame,我也会觉得很开心: ) ,学习借鉴就是开源软件对于我的意义。

因为涉及公司的一些制度,不方便公开源码,但感兴趣的同学,或者想自己实现一个简单的扫描器的同学,可以参考上文提到的两种开源软件,在github上可以搜到。

时间: 2024-10-08 13:50:00

基于Python+协程+多进程的通用弱密码扫描器的相关文章

Python核心技术与实战——十五|Python协程

我们在上一章将生成器的时候最后写了,在Python2中生成器还扮演了一个重要的角色——实现Python的协程.那什么是协程呢? 协程 协程是实现并发编程的一种方式.提到并发,肯很多人都会想到多线程/多进程模型,这就是解决并发问题的经典模型之一.在最初的互联网世界中,多线程/多进程就在服务器并发中起到举足轻重的作用. 但是随着互联网的发展,慢慢很多场合都会遇到C10K瓶颈,也就是同时连接到服务器的客户达到1W,于是,很多代码就跑崩溃,因为进程的上下文切换占用了大量的资源,线程也顶不住如此巨大的压力

Python 协程总结

Python 协程总结 理解 协程,又称为微线程,看上去像是子程序,但是它和子程序又不太一样,它在执行的过程中,可以在中断当前的子程序后去执行别的子程序,再返回来执行之前的子程序,但是它的相关信息还是之前的. 优点: 极高的执行效率,因为子程序切换而不是线程切换,没有了线程切换的开销: 不需要多线程的锁机制,因为只有一个线程在执行: 如果要充分利用CPU多核,可以通过使用多进程+协程的方式 使用 打开asyncio的源代码,可以发现asyncio中的需要用到的文件如下: 下面的则是接下来要总结的

python协程:yield的使用

本文和大家分享的主要是python协程yield相关内容,一起来看看吧,希望对大家学习python有所帮助. 协程定义 协程的底层架构是在pep342 中定义,并在python2.5 实现的. python2.5 中,yield关键字可以在表达式中使用,而且生成器API中增加了 .send(value)方法.生成器可以使用.send(...)方法发送数据,发送的数据会成为生成器函数中yield表达式的值. 协程是指一个过程,这个过程与调用方协作,产出有调用方提供的值.因此,生成器可以作为协程使用

从python协程理解tornado异步

博客原文地址:http://www.v2steve.com/py_tornado_async.html 刚接触tornado时候最疑惑的问题就是tornado.gen.coroutine是怎么实现的.如何在代码中用同步格式实现异步效果.看了几次源码发现其实就是python协程的一个具体应用.下面从生成器开始,说说tornado的异步. python协程 python利用yield关键字实现生成器,yield就像生化危机里的T病毒,被yield感染的函数都不仅仅是函数,而是一个函数生成器.函数生成

00.用 yield 实现 Python 协程

来源:Python与数据分析 链接: https://mp.weixin.qq.com/s/GrU6C-x4K0WBNPYNJBCrMw 什么是协程 引用官方的说法: 协程是一种用户态的轻量级线程,协程的调度完全由用户控制.协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快. 与线程相比,协程更轻量.一个Python线程大概占用8M内

python协程的理解

一.介绍 什么是并发?并发的本质就是切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去执行其他的任务(切换由操作系统强制控制):1.任务发生阻塞2.计算任务时间过长,需要让出cpu给高优先级的程序 协程,又称微线程,是一种用户态的轻量级线程.协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置,当程序中存在大量不需要CPU的操作时(IO),适用于协程.协程本质上就是一个线程,以前线程任务的切换是由操作系统控制的,遇到I/

python协程--asyncio模块(基础并发测试)

在高并发的场景下,python提供了一个多线程的模块threading,但似乎这个模块并不近人如意,原因在于cpython本身的全局解析锁(GIL)问题,在一段时间片内实际上的执行是单线程的.同时还存在着资源争夺的问题.python3.4之后引入了基于生成器对象的协程概念.也就是asyncio模块.除了asyncio模块,python在高并发这一问题还提出了另外一些解决方案,例如tornado和gevent都实现了类似的功能.由此,在方案选择上提供了更多的可能性.以下是threading模块和a

python协程,线程的其他方法

OK 这一篇主要是协程的,还落下了点线程的方法,先说线程, 线程池 线程池回调函数 协程 一. 线程池   线程池顾名思义就是跟是跟进程池一样的 到这里就差我们的线程池没有讲了,我们用一个新的模块给大家讲,早期的时候我们没有线程池,现在python提供了一个新的标准或者说内置的模块,这个模块里面提供了新的线程池和进程池,之前我们说的进程池是在multiprocessing里面的,现在这个在这个新的模块里面,他俩用法上是一样的. 为什么要将进程池和线程池放到一起呢,是为了统一使用方式,使用thre

理解Python协程:从yield/send到yield from再到async/await

Python中的协程大概经历了如下三个阶段: 1. 最初的生成器变形yield/send 2. 引入@asyncio.coroutine和yield from 3. 在最近的Python3.5版本中引入async/await关键字 一.生成器变形yield/send def mygen(alist): while len(alist) > 0: c = randint(0, len(alist)-1) yield alist.pop(c) a = ["aa","bb&q