• Python攻防之多线程、C段扫描和数据库编程


    [网络安全自学篇] 十五.Python攻防之多线程、C段扫描和数据库编程(二)

    2019-10-05 11:44:11 Eastmount 阅读数 91更多

    分类专栏: 网络安全 Web安全 Python学习系列

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    本文链接:https://blog.csdn.net/Eastmount/article/details/102138329

    这是作者的系列网络安全自学教程,主要是关于网安工具和实践操作的在线笔记,特分享出来与博友共勉,希望您们喜欢,一起进步。前文分享了Python网络攻防相关基础知识,包括正则表达式、Web编程和套接字通信,本文将继续分析Python攻防之多线程、C段扫描和数据库编程。本文参考了爱春秋ADO老师的课程内容,这里也推荐大家观看他Bilibili和ichunqiu的课程,同时也结合了作者之前的经验进行讲解。

    作者作为网络安全的小白,分享一些自学基础教程给大家,希望你们喜欢。同时,更希望你能与我一起操作深入进步,后续也将深入学习网络安全和系统安全知识并分享相关实验。总之,希望该系列文章对博友有所帮助,写文不容易,大神请飘过,不喜勿喷,谢谢!

    下载地址:https://github.com/eastmountyxz/NetworkSecuritySelf-study
    百度网盘:

    文章目录

    前文学习:
    [网络安全自学篇] 一.入门笔记之看雪Web安全学习及异或解密示例
    [网络安全自学篇] 二.Chrome浏览器保留密码功能渗透解析及登录加密入门笔记
    [网络安全自学篇] 三.Burp Suite工具安装配置、Proxy基础用法及暴库示例
    [网络安全自学篇] 四.实验吧CTF实战之WEB渗透和隐写术解密
    [网络安全自学篇] 五.IDA Pro反汇编工具初识及逆向工程解密实战
    [网络安全自学篇] 六.OllyDbg动态分析工具基础用法及Crakeme逆向破解
    [网络安全自学篇] 七.快手视频下载之Chrome浏览器Network分析及Python爬虫探讨
    [网络安全自学篇] 八.Web漏洞及端口扫描之Nmap、ThreatScan和DirBuster工具
    [网络安全自学篇] 九.社会工程学之基础概念、IP获取、IP物理定位、文件属性
    [网络安全自学篇] 十.论文之基于机器学习算法的主机恶意代码
    [网络安全自学篇] 十一.虚拟机VMware+Kali安装入门及Sqlmap基本用法
    [网络安全自学篇] 十二.Wireshark安装入门及抓取网站用户名密码(一)
    [网络安全自学篇] 十三.Wireshark抓包原理(ARP劫持、MAC泛洪)及数据流追踪和图像抓取(二)
    [网络安全自学篇] 十四.Python攻防之基础常识、正则表达式、Web编程和套接字通信(一)

    前文欣赏:
    [渗透&攻防] 一.从数据库原理学习网络攻防及防止SQL注入
    [渗透&攻防] 二.SQL MAP工具从零解读数据库及基础用法
    [渗透&攻防] 三.数据库之差异备份及Caidao利器
    [渗透&攻防] 四.详解MySQL数据库攻防及Fiddler神器分析数据包

    [python] 专题七.网络编程之套接字Socket、TCP和UDP通信实例
    [python] 专题八.多线程编程之thread和threading
    [python] 专题九.Mysql数据库编程基础知识

    参考文献:
    《安全之路Web渗透技术及实战案例解析》陈小兵老师
    《Wireshark数据包分析实战》第二版 Chris Sanders
    《TCP/IP协议栈详解卷一》 W.Richard Stevens

    《Wireshark协议分析从入门到精通》-51cto老师
    https://www.bilibili.com/video/av29479068
    2019 Python黑客编程:安全工具开发 - bilibili 白帽黑客教程
    http://www.heibanke.com/lesson/crawler_ex00/
    python subprocess模块使用总结

    声明:本人坚决反对利用社会工程学方法进行犯罪的行为,一切犯罪行为必将受到严惩,绿色网络需要我们共同维护,更推荐大家了解它们背后的原理,更好地进行防护。


    一.Python多线程

    1.进程和线程

    进程: 是程序的一次执行,每个进程都有自己的地址空间、内存、数据栈及其他记录运行轨迹的辅助数据。
    线程: 所有的线程都运行在同一个进程当中,共享相同的运行环境。线程有开始、顺序执行和结束三个部分。

    由于单线程效率低,这里引入了多线程编程。
    计算机的核心是CPU,它承担了所有的计算任务,它就像一座工厂,时刻运行着。假定工厂的电力有限,一次只能供给一个车间使用。也就是说,一个车间开工的时候,其他车间都必须停工。背后的含义就是,单个CPU一次只能运行一个任务。
    进程就好比工厂的车间,它代表CPU所能处理的单个任务。任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。一个车间里,可以有很多工人。他们协同完成一个任务。线程就好比车间里的工人,一个进程可以包括多个线程。

    2.thread模块

    Python thread模块可以调用下述函数实现多线程开启。它将产生一个新线程,在新的线程中用指定的参数和可选的kwargs来调用这个函数。
    start_new_thread(function, args kwargs=None)

    注意:使用这个方法时,一定要加time.sleep()函数,否则每个线程都可能不执行。此方法还有一个缺点,遇到较复杂的问题时,线程数不易控制。

    # -*- coding: utf-8 -*-
    # By:CSDN Eastmount 2019-10-05
    import thread
    import time
    
    def fun1():
        print "hello world %s" % time.ctime()
        
    #多线程
    def main():
        thread.start_new_thread(fun1, ()) #无参数
        thread.start_new_thread(fun1, ())
        time.sleep(2)
        print "over"
    
    #程序成功在同一时刻运行两个函数
    if __name__ == '__main__':
        main()
    

    输出结果如下图所示:

    在这里插入图片描述

    上面的代码简单讲述了thread模块的多线程使用。但实际应用中这种例子遇到比较少,而哪一种情况比较多呢?假如说所有C段的地址ping探测其是否存活,代码如下。

    # -*- coding: utf-8 -*-
    # By:CSDN Eastmount 2019-10-05
    import thread
    import time
    from subprocess import Popen, PIPE
    
    def ping_check():
        #check = Popen(['/bin/bash', '-c', 'ping -c 2 ' + '127.0.0.1'], stdin=PIPE, stdout=PIPE)
        ip = '127.0.0.1'
        #ping指定次数后停止ping 但报错访问被拒绝,选项 -c 需要具有管理权限。
        #check = Popen("ping -c 3 {0} \n".format(ip), stdin=PIPE, stdout=PIPE,  shell=True)
        check = Popen("ping {0} \n".format(ip), stdin=PIPE, stdout=PIPE,  shell=True)
        data = check.stdout.read() #数据
        print data
    
    #程序成功在同一时刻运行两个函数
    if __name__ == '__main__':
        ping_check()
    

    如果输入的ip地址为本机127.0.0.1,则输出正常连通结果,如下所示。

    在这里插入图片描述

    如果输入的ip地址为本机220.0.0.1,则提示超时,如下图所示。

    在这里插入图片描述

    接着思考:如何对一个C段网址进行ping探测呢?
    设计一个循环,如果主机不存在,返回的是timeout;如果主机存在,则包含TTL字样,这里以TTL为判断标准,从而判断存活的数据。

    # -*- coding: utf-8 -*-
    # By:CSDN Eastmount 2019-10-05
    import thread
    import time
    from subprocess import Popen, PIPE
    
    def ping_check():
        ip = '127.0.0.1'
        check = Popen("ping {0} \n".format(ip), stdin=PIPE, stdout=PIPE,  shell=True)
        data = check.stdout.read() #数据
        if 'TTL' in data: #存活
            print 'UP'
    
    #程序成功在同一时刻运行两个函数
    if __name__ == '__main__':
        ping_check()
    

    输出结果为“UP”。

    3.检测ichunqiu地址

    接下来我们尝试检测ichunqiu网站的ip地址存活情况。首先,调用ping命令检测该网站的ip地址,即:1.31.128.240。

    在这里插入图片描述

    这里将ping_check()函数设置一个传递参数,对应ip地址,对它进行探测;通过thread线程实现ip地址存活性探测,能探测到很多存活的主机。

    # -*- coding: utf-8 -*-
    # By:CSDN Eastmount 2019-10-05
    import thread
    import time
    from subprocess import Popen, PIPE
    
    def ping_check(ip):
        check = Popen("ping {0} \n".format(ip), stdin=PIPE, stdout=PIPE, shell=True)
        data = check.stdout.read() #数据
        if 'TTL' in data: #存活
            print '%s is UP' % ip
    
    #主函数
    if __name__ == '__main__':
        #寻找目标 ichunqiu  1.31.128.240
        for i in range(1,255):
            ip = '1.31.128.' + str(i)
            #多线程方法
            thread.start_new_thread(ping_check, (ip, ))
            time.sleep(0.1)
    

    输出结果如下图所示:

    在这里插入图片描述

    问题:
    在多线程编程中,几个线程是同时启动,所以输出也是输出在一行,那怎么才能换行输出呢?这里使用系统输出。

    # -*- coding: utf-8 -*-
    # By:CSDN Eastmount 2019-10-05
    import thread
    import time
    from subprocess import Popen, PIPE
    import sys
    
    def ping_check(ip):
        check = Popen("ping {0} \n".format(ip), stdin=PIPE, stdout=PIPE, shell=True)
        data = check.stdout.read() #数据
        if 'TTL' in data: #存活
            sys.stdout.write('%s is UP \n' % ip)
    
    #主函数
    if __name__ == '__main__':
        #寻找目标 ichunqiu  1.31.128.240
        for i in range(1,255):
            ip = '1.31.128.' + str(i)
            #多线程方法
            thread.start_new_thread(ping_check, (ip, ))
            time.sleep(0.1)
    

    按行输出结果,如下图所示:

    在这里插入图片描述

    4.threading模块

    thread模块存在一些缺点,尤其是线程数不能被控制。下面使用threading解决线程数可控制的问题。

    • 使用threading模块
    • 子类化Thread类
    # -*- coding: utf-8 -*-
    import threading
    import time
    import sys
    
    def fun1(key):
        sys.stdout.write('hello %s:%s \n'%(key, time.ctime()))
    
    def main():
        threads = []
        keys = ['a', 'b', 'c']
    
        #线程数
        threads_count = len(keys)
    
        for i in range(threads_count):
            t = threading.Thread(target=fun1,  args=(keys[i],))
            threads.append(t)
    
        for i in range(threads_count):
            threads[i].start()
    
        for i in range(threads_count):
            threads[i].join()
    
    if __name__ == '__main__':
        main()
    

    输出结果如下图所示,三个线程同时发生。

    在这里插入图片描述

    多线程threading方法实现了我们想要的功能,能够控制线程数,例如想写成requests模块,获取网站的status_code状态码。

    # -*- coding: utf-8 -*-
    import threading
    import time
    import requests
    import sys
    
    def fun1():
        time_start = time.time()
        r = requests.get(url="http://www.eastmountyxz.com/")
        times = time.time() - time_start
        #print('Status:%s--%s--%s'%(r.status_code, times, time.strftime('%H:%M:%S')))
        sys.stdout.write('Status:%s--%s--%s\n'%(r.status_code, times, time.strftime('%H:%M:%S')))
        
    def main():
        threads = []
        #线程数 网页访问10次
        threads_count = 10
    
        for i in range(threads_count):
            t = threading.Thread(target=fun1,  args=())
            threads.append(t)
    
        for i in range(threads_count):
            threads[i].start()
    
        for i in range(threads_count):
            threads[i].join()
    
    if __name__ == '__main__':
        main()
    

    输出结果如下图所示:

    在这里插入图片描述


    二.多线程+Queue实现C段扫描

    生产者-消费者问题和Queue模块:

    • Queue模块:qsize()、empty()、full()、put()、get()
    • 完美搭配,Queue+Thread

    虽然threading解决了线程数可控问题,但是面对复杂问题的时候,比如生产者和消费者问题,仍然不能很好地解决。

    生产者和消费者问题
    生产者生产货物,将货物放到队列数据中,生产者在生产这些货物时,它的时间是不确定的;当生存着将货物交给消费者,消耗的时间也是不确定的;由于两个时间都不确定,多线程编程存在一定问题。

    这里引入Queue模块解决该问题。

    import Queue
    
    queue = Queue.Queue()
    
    for i in range(10):
        queue.put(i)
    print(queue.empty())
    print(queue.qsize())
    
    #取数据 get依次取出里面的数据
    print(queue.get())
    print(queue.get())
    

    输出结果如下所示:

    在这里插入图片描述

    生产者利用Queue将所有数据货物按顺序放入Queue,接着消费者依次取出Queue中的数据。接着实现C段扫描。

    # -*- coding: utf-8 -*-
    # By:CSDN Eastmount 2019-10-05
    import threading
    import Queue
    import sys
    from subprocess import Popen, PIPE
    
    #定义一个类 传入参数queue
    class DoRun(threading.Thread):
        def __init__(self, queue):
            threading.Thread.__init__(self)
            self._queue = queue
    
        def run(self):
            #非空取数据
            while not self._queue.empty():
                ip = self._queue.get()
                #print ip
                check_ping = Popen("ping {0} \n".format(ip), stdin=PIPE, stdout=PIPE,  shell=True)
                data = check_ping.stdout.read()
                if 'TTL' in data:
                    sys.stdout.write(ip+' is UP.\n')
                
    def main():
        threads = []
        threads_count = 100
        queue = Queue.Queue()
        
        #放入ip地址
        for i in range(1, 255):
            queue.put('1.31.128.' + str(i))
    
        for i in range(threads_count):
            threads.append(DoRun(queue))
    
        for i in threads:
            i.start()
    
        for i in threads:
            i.join()
    
    if __name__ == '__main__':
        main() 
    

    最终输出结果如下图所示,通过该代码可以实现检测某网站ip段的存活情况。

    在这里插入图片描述


    三.数据库编程

    1.基础概念

    Python数据库编程,这里直接引入核心代码即可,更多参考前文:[python] 专题九.Mysql数据库编程基础知识

    • Python DB API
    • Python MySQL 开发环境
    • Python数据库编程实例

    早期每个数据库和Python建立连接时,都需要有对应的接口程序,这样导致数据库比较混乱,需要学习很多新的接口程序并修改大量代码。

    在这里插入图片描述

    后来为了解决该问题,我们定义了相关的接口规范,所有数据库接入其中即可编程。我们只要学会Python DB API,就能实现对不同版本数据库的操作,这样更加方便快捷,更改的代码较少。

    在这里插入图片描述
    Python访问数据库的基本流程如下图所示:
    在这里插入图片描述

    在这里插入图片描述

    2.MySQLdb

    Python调用MsSQL需要导入MySQLdb库,如下:

    import MySQLdb

    connect()函数
    主要使用的方法是connect对象。connect()方法生成一个connect对象,用于访问数据库,其参数如下:

    user:Username
    password:Password
    host:Hostname
    database:DatabaseName
    dsn:Data source name

    注意并非所有的接口程序都严格按照这种格式,如MySQLdb。

    import MySQLdb
    conn = MySQLdb.connect(host='localhost', db='test01', user='root', passwd='123456', port=3306, charset='utf8')
    

    connect()对象方法如下:

    lose():关闭数据库连接,或者关闭游标对象
    commit():提交当前事务
    rollback():取消当前事务
    cursor():创建游标或类游标对象
    errorhandler(cxn,errcls,errval):作为已给游标的句柄

    注意,执行close()方法则上述的连接对象方法不能再使用,否则发生异常。commit()、rollback()、cursor()或许更对于支持事务的数据库更有意义。数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完整地执行,要么完全地不执行。 一旦你完成了数据库连接,关闭了游标对象,然后在执行commit()提交你的操作,然后关闭连接。

    游标对象
    上面说了connect()方法用于提供连接数据库的接口,如果要对数据库操作那么还需要使用游标对象。游标对象的属性和方法:

    fetchone():可以看作fetch(取出) one(一个),也就是得到结果集的下一行(一行)。
    fetchmany(size):可以看作fetch(取出)many(多个),这里的参数是界限,得到结果集的下几行(几行)
    fetchall():顾名思义,取得所有。
    execute(sql):执行数据库操作,参数为sql语句。
    close():不需要游标时尽可能的关闭

    下面是一个获取MySQL数据库版本的代码,它覆盖了Python链接数据库的基本过程。

    # -*- coding: utf-8 -*-
    import MySQLdb
    
    #建立连接
    conn = MySQLdb.connect(
        host = '127.0.0.1',
        port = 3306,
        user = 'root',
        passwd = '123456'
        )
    
    #执行最简单的语句
    cus = conn.cursor()
    
    #查看MySQL的版本
    sql = 'select version()'
    
    cus.execute(sql)
    
    #查看返回结果
    print(cus.fetchone())
    
    #关闭连接和对象
    cus.close()
    conn.close()
    

    输出结果如下图所示:

    在这里插入图片描述

    Python网络爬虫和MySQL数据库结合的文章参考作者前文:
    [python爬虫] 招聘信息定时系统 (一).BeautifulSoup爬取信息并存储MySQL
    [python爬虫] Selenium爬取内容并存储至MySQL数据库


    四.总结

    希望这篇文章对你有所帮助,这是Python网络攻防非常基础的一篇博客,后续作者也将继续深入学习,制作一些常用的小工具供大家交流。

  • 相关阅读:
    Dreamweaver CS4无法启动:xml parsing fatal error..Designer.xml错误解决方法
    strcpy() strcat() strcmp() gets() puts()
    使用友元,编译出错fatal error C1001: INTERNAL COMPILER ERROR (compiler file 'msc1.cpp', line 1786) 的解决
    HashMap按key排序
    转Oracle数据类型及存储方式【E】
    JAVA_java.util.Date与java.sql.Date相互转换
    Oracle_复制表跟往表插数据
    java_Struts学习例子
    ORA01033: ORACLE initialization or shutdown in progressORACLE
    dorado勾选修改的时候总是选择第一条记录解决办法.
  • 原文地址:https://www.cnblogs.com/grj001/p/12223879.html
Copyright © 2020-2023  润新知