黑帽编程应用之Python1

时间:2022-07-28
本文章向大家介绍黑帽编程应用之Python1,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

[TOC]

0x00 前言

在安全工作者或者渗透测试中,我们常常需要自己造轮子来写自动化利用的脚本,所以Python脚本能更快的帮助我们编写响应扫描器以及可利用脚本;

扩展包:

0x01 IP地址处理模块

描述:在对很多业务进行扫描的时候,我们可能需要输入一个IP段对其扫描,在写Python脚本中免不了进行IP地址的计算包括网段/网络掩码/广播地址/子网数/IP类型等等;

因此Python给我们提供了一个强大的第三方模块IPy,安装模块执行pip install IPy即可;

(1) IP地址/网段基本处理

#/usr/bin/env python
from IPy import IP

#1.分辨IPv4还是IPv6以及IP类型
ipv4=IP('192.168.1.0/24').version()
ipv6=IP('::1').version()
#4 代表IPv4   6 代表IPv6
print(ipv4,"  ",ipv6)  # 4   6 
iptype = ip.iptype()  #'PRIVATE' 代表私有地址
IP('132.54.56.25').iptype()  #'PUBLIC'  代表公有地址
print(IP('::1').iptype())  #LOOPBACK
print(IP('2001:0658:022a:cafe:0200::1').iptype())  #ALLOCATED RIPE NCC

#2.网段IP数以及IP地址清单
ip=IP('192.168.10.0/24')
len(ip) #也是网络子网数
print(ip.len()) #输入该网段的IP数量 256
for x in ip:  #地址清单
    print(x)
print(str(ip[2]))
#打印结果
# 192.168.10.0
# ....
# 192.168.10.255


#3.IP反向解析名称
ip=IP('192.168.1.8')
revname = ip.reverseNames() #['8.1.168.192.in-addr.arpa.']


#4.IP转换
IP("192.168.1.1").int()  #3232235777  IP地址转整形
IP("192.168.1.1").strHex()  #'0xc0a80101'  #IP地址转十六进制
IP("192.168.1.1").strBin() #'11000000101010000000000100000001' #转二进制
print(IP(0xc0a80101))   #十六进制转成IP 192.168.1.1   | IP('192.168.1.1') 
print(IP(3232235777))   #十进制转成IP192.168.1.1


#5.网络地址子网掩码生成网段格式
IP('192.168.1.0').make_net('255.255.255.0')  #IP('192.168.1.0/24')
IP('192.168.1.0/255.255.0.0',make_net=True)  #IP('192.168.0.0/16')
IP('10.10.0.0/255.0.0.0',make_net=True)       #IP('10.0.0.0/8')
IP('10.10.0.0-10.10.255.255',make_net=True)   #IP('10.10.0.0/16')


#6.通过网络转换成IP以及子网掩码
IP('10.0.0.0/8').net() #IP('10.0.0.0')
IP('10.0.0.0/8').broadcast()  #IP('10.255.255.255') 根据网段求得子网掩码
#通过StrNormal方法指定不同的wantprefixlen参数值定制不同的输出类型的网段
#wantprefixlen取值
0 : 无返回,如192.168.1.0
1 :prefix格式 a.b.c.0/24 | 2001:658:22a:cafe::/64  #默认格式
2 :decimal netmask格式  a.b.c.d/255.255.255.0    
3 :lastIP格式  a.b.c.0-a.b.c.255 2001:658:22a:cafe::-2001:658:22a:cafe:ffff:ffff:ffff:ffff
#示例演示:
IP('192.168.1.0/30').strNormal(0)  #'192.168.1.0'   这里需要知道子网掩码的知识点
IP('192.168.1.4/30').strNormal(0)  #'192.168.1.4'   2 ^ (32-30 = 2) = 4 IP为一组
IP('192.168.1.0/30').strNormal(1)  #'192.168.1.0/30'
IP('192.168.1.0/30').strNormal()   #'192.168.1.0/30'
IP('192.168.1.0/30').strNormal(2)  #'192.168.1.0/255.255.255.252'
IP('192.168.1.0/30').strNormal(3)  #'192.168.1.0-192.168.1.3'  #根据子网掩码换算主机个数

(2) 多网络计算对比: 比较两个网段是否存在包含重叠等关系,IPy支持蕾仕于数值型数据的比较,可以帮助IP对象进行比较

#!/usr/bin/env python
#示例1.判断网段的区间
IP("192.168.0.0/16") < IP("192.168.1.0/24") #True
IP("192.168.0.0/16") > IP("192.168.1.0/24") #False


#判断IP地址或者网段是否包含在另外一个网段:
IP("192.168.0.0/16") in IP("192.168.1.0/24")  #False
IP("192.168.1.0/32") in IP("192.168.1.0/24")  #True


#判断两个网段是否重叠,采用IP提供的overlaps方法
IP("192.168.1.0/32").overlaps("192.168.1.0/24") #1 包含
IP("192.168.2.5").overlaps("192.168.1.0/24")    #0 不包含

实际案例:

+ IPy模块使用案例查看

Useage: > ipinfo.py -t/-m 192.168.1.1 
-t 指定IP类型地址进行相互转换二进制IP/整数IP/十六进制 
-m 指定IP类地址或者IP段查看信息
IP格式1:192.168.1.1 
IP格式2:192.168.1.0/24 
IP格式3:192.168.1.1-192.168.1.254

0x02 DNS处理模块

描述:Python中的dbspython是实现一个DNS工具包,支持所有的记录类型,用于查询/传输并动态更新ZONE信息,同时支持所有的记录类型; 模块安装:pip install dnspython

1.方法详解

dns提供一个DNS解析类-resolver,使用它的query方法来实现查询功能,query方法定义如下:

import dns.resolver

def query(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN,
          tcp=False, source=None, raise_on_no_answer=True,
          source_port=0, lifetime=None):

rdclass参数用于指定网络类型,可选值有IN,CH与HS,其中IN为默认; tcp参数表示是否启用TCP协议; 其中rdtype参数用来指定RR资源类型:

  • A 记录 : 将主机名转换成为IP地址
  • MX 记录 :邮件交换记录,定义邮件服务器的域名
  • CNAME 记录 : 指定别名记录,实现域名间的映射
  • NS 记录 : 标记区域的域名服务器及授权子域名
  • PTR 记录 :反向解析与A记录相反,将IP地址转换为主机名
  • SOA 记录 :SOA标记一个起始授权区的定义

示例演示:

#示例1.A记录 通过reponse.answer方法获取查询回应信息
for i in dns.resolver.query('www.qq.com.cn','A').response.answer:
  for j in i.items:
    print("A记录:%s" % j.address)  #A记录:61.129.226.218

for i in dns.resolver.query('qq.com','A').response.answer:
  for j in i.items:
    print("A记录:%s" % j.address)

# A记录:59.37.96.63
# A记录:58.60.9.21
# A记录:180.163.26.39


#示例2.MX记录
for i in dns.resolver.query('qq.com','MX'):
  print("MX preference = %s , mail exchanger = %s" %(i.preference,i.exchange))
#遍历出首选项以及邮件交换服务器  
# MX preference = 20 , mail exchanger = mx2.qq.com.
# MX preference = 30 , mail exchanger = mx1.qq.com.
# MX preference = 10 , mail exchanger = mx3.qq.com.


#示例3.NS记录 (输入根域名)
for i in dns.resolver.query('qq.com','NS').response.answer:
  for j in i.items:
    print("NS记录:%s" %j)

#执行结果
NS记录:ns2.qq.com.
NS记录:ns1.qq.com.
NS记录:ns4.qq.com.
NS记录:ns3.qq.com.


#示例4.CNAME记录
for i in dns.resolver.query('weiyigeek.github.io','CNAME').response.answer:
  for j in i.items:
    print("CNAME记录:%s" %j) #CNAME记录:www.weiyigeek.github.io.


#示例5.SOA授权区域定义
for i in dns.resolver.query('baidu.com','SOA'):
    print(i)
#dns.baidu.com. sa.baidu.com. 2012141218 300 300 2592000 7200

实际案例: + Github查看

WeiyiGeek.dnsinfo信息查看

0x01 web探测模块

pycurl 模块

描述:pycurl是一个用C语言写的libcurl Python实现,功能强大支持多种通信协议,类似于linux下Curl命令功能的Python封装简单易用; 模块安装:

#安装
pip install pycurl  #可能会报错 Please specify --curl-dir=/path/to/built/libcurl (安装后重新执行)
#如果报错访问:https://www.lfd.uci.edu/~gohlke/pythonlibs/#pycurl 下载pycurl-7.43.0.3-cp37-cp37m-win32.whl (根据您Python版本位数)
Processing c:usersweiyigeekdownloadspycurl-7.43.0.3-cp37-cp37m-win32.whl
Installing collected packages: pycurl
Successfully installed pycurl-7.43.0.3

#查看版本
python -c "import pycurl;print(pycurl.version)"
'PycURL/7.43.0.3 libcurl/7.64.1 OpenSSL/1.1.1c zlib/1.2.11 c-ares/1.15.0 libssh2/1.8.2'

主要功能:

  • web服务质量探测:HTTP状态码/请求延时/HTTP头信息/下载速度等等
  • 探测服务的可用性以及服务响应速度

模块常用方法:

pcurl = pycurl.Curl #创建对象
pcurl.setopt(option,value)  #curl_easy_setopt 方法,value值会依赖option
pcurl.perform() #实现pycurl对象的请求提交
pcurl.getinfo(option) #获取pycurl对象请求响应信息
pcurl.close()

利用libcurl包提供的常量值来达到探测Web服务质量的目的:

#setopt
pc.setopt(pycurl.URL, URL) #定义请求的URL
pc.setopt(pycurl.USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0") #设置http请求头USERAGENT
pc.setopt(pycurl.CONNECTTIMEOUT, 5) #连接等待时间,0为不等待
pc.setopt(pycurl.TIMEOUT, 5)  #请求超时时间
pc.setopt(pycurl.MAXREDIRS, 1)  #最大的重定向数
pc.setopt(pycurl.NOPROGRESS, 1)  #是否屏蔽下载进度条 非0则屏蔽
pc.setopt(pycurl.MAXREDIRS, 1)   #指定HTTP重定向的最大数为1
pc.setopt(pycurl.DNS_CACHE_TIMEOUT, 30)  #报错DNS信息为30s
pc.setopt(pycurl.FORBID_REUSE, 1) #完成交互后断开连接不重用
pc.setopt(pycurl.FERSH_CONNECT, 1) #强制获取新的连接,即代替缓存中的连接
pc.setopt(pycurl.HEADERFUNCTION, getheader) #将返回的HTTP HEADER定向到回调环境getheader
pc.setopt(pycurl.WRITEFUNCTION, getbody) #将返回的HTTP BOBY定向到回调环境getboby
pc.setopt(pycurl.WRITEHEADER, index)  #将返回HTTP HEADER定向到indexfile文件对象
pc.setopt(pycurl.WRITEDATA, index)  #将返回的HTML内容定向到indexfile文件对象中

#getinfo
print("HTTP状态码: %s" %(pc.getinfo(pc.HTTP_CODE)))
print("DNS解析时间: %.2f ms" %(pc.getinfo(pc.NAMELOOKUP_TIME)*1000))

print("建立连接时间: %.2f ms" %(pc.getinfo(pc.CONNECT_TIME)*1000))
print("准备传输时间: %.2f ms" %(pc.getinfo(pc.PRETRANSFER_TIME)*1000))
print("传输开始时间: %.2f ms" %(pc.getinfo(pc.STARTTRANSFER_TIME)*1000))
print("传输结束总时间: %.2f ms" %(pc.getinfo(pc.TOTAL_TIME)*1000))
print("重定向消耗的时间: %.2f ms" %(pc.getinfo(pc.REDIRECT_TIME)*1000))

print("下载数据包大小: %d bytes/s" %(pc.getinfo(pc.SIZE_DOWNLOAD)))
print("上传数据包大小: %d bytes/s" %(pc.getinfo(pc.SIZE_UPLOAD)))
print("平均下载速度: %d bytes/s" %(pc.getinfo(pc.SPEED_DOWNLOAD)))
print("平均上传速度: %d bytes/s" %(pc.getinfo(pc.SPEED_UPLAOD)))

print("HTTP头部大小: %d byte" %(pc.getinfo(pc.HEADER_SIZE)))

实际案例:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : pycurldemo.py
# @CreateTime : 2019/7/31 15:23
# @Author : WeiyiGeek
# @Function : 实现探测Web服务质量与网页截图
# @Software: PyCharm


import sys, time
import pycurl

URL="http://www.weiyigeek.github.io"


def request():
    """
     构建请求
    :return:
    """
    pc = pycurl.Curl()  #构建一个Curl对象
    pc.setopt(pycurl.URL, URL) #定义请求的URL
    pc.setopt(pycurl.CONNECTTIMEOUT, 5) #连接等待时间,0为不等待
    pc.setopt(pycurl.TIMEOUT, 5)  #请求超时时间
    pc.setopt(pycurl.NOPROGRESS, 1)  #疲敝下载进度条 与 curl 相似
    pc.setopt(pycurl.FORBID_REUSE, 1) #完成交互后断开连接不重用
    pc.setopt(pycurl.MAXREDIRS, 1)   #指定HTTP重定向的最大数为1
    pc.setopt(pycurl.DNS_CACHE_TIMEOUT, 30)  #报错DNS信息为30s
    pc.setopt(pycurl.USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0")

    #创建一个文件对象以'wb'方式打开,存储返回的http头部信息以及页面内容;
    with open('content.txt', 'wb') as index:
        pc.setopt(pycurl.WRITEHEADER, index)  #将返回HTTP HEADER定向到indexfile文件对象
        pc.setopt(pycurl.WRITEDATA, index)  #将返回的HTML内容定向到indexfile文件对象中
        try:
            pc.perform()  #提交请求
        except Exception as e:
            print("connect Error:" + str(e))
            sys.exit()

    return pc


def reponse(pc):
    """
    返回请求响应数据解析
    :param pc:
    :return:
    """
    print("HTTP状态码: %s" %(pc.getinfo(pc.HTTP_CODE)))
    print("DNS解析时间: %.2f ms" %(pc.getinfo(pc.NAMELOOKUP_TIME)*1000))
    print("建立连接时间: %.2f ms" %(pc.getinfo(pc.CONNECT_TIME)*1000))
    print("准备传输时间: %.2f ms" %(pc.getinfo(pc.PRETRANSFER_TIME)*1000))
    print("传输开始时间: %.2f ms" %(pc.getinfo(pc.STARTTRANSFER_TIME)*1000))
    print("传输结束总时间: %.2f ms" %(pc.getinfo(pc.TOTAL_TIME)*1000))
    print("下载数据包大小: %d bytes/s" %(pc.getinfo(pc.SIZE_DOWNLOAD)))
    print("HTTP头部大小: %d byte" %(pc.getinfo(pc.HEADER_SIZE)))
    print("平均下载速度: %d bytes/s" %(pc.getinfo(pc.SPEED_DOWNLOAD)))
    print("重定向消耗的时间: %.2f ms" % (pc.getinfo(pc.REDIRECT_TIME) * 1000))
    pc.close()

def main():
    """
    请求函数调用
    响应函数调用
    :return:
    """
    pcurl = request()
    reponse(pcurl)
    return 0

if __name__ == '__main__':
    main()

WeiyiGeek.pycurl模块