python黑帽子——搭建扫描器入门介绍

Posted Demo不是emo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python黑帽子——搭建扫描器入门介绍相关的知识,希望对你有一定的参考价值。

作者名:Demo不是emo 

主页面链接:主页传送门
创作初心:舞台再大,你不上台,永远是观众,没人会关心你努不努力,摔的痛不痛,他们只会看你最后站在什么位置,然后羡慕或鄙夷
座右铭:不要让时代的悲哀成为你的悲哀
专研方向:网络安全,数据结构

每日emo:总想把自己变得更好再来找你,却不知你已越走越远

 如果你以前没有 Python 编程经验,这篇博客将带你浏览一下 Python 的背景,语 法,函数,迭代器等语法问题,如果你已经有 Python 的编程经验,可以跳过这 一章。以后的章节将不会介绍更多的语言细节,你可以根据兴趣自行学习。

目录

一、建立 Python 开发环境

1、下载环境 

2、安装第三方库

3、解释型 python与交互型 python 

[1]、解释型 

[2]、交互型

二、Python 语言简介

三、变量,字符串,列表,字典介绍

1、变量

2、字符串

3、列表

4、字典

四、使用用网络,迭代器,异常处理,模块等 

1、网络

2、条件选择

3、异常处理

4、函数

5、迭代 

6、文件I/O

7、SYS 模块 

8、OS模块 


一、建立 Python 开发环境

1、下载环境 

Python 的下载网站(http://www.python.org/download/)提供了 Python 在 Windows,Mac OS X 和 Linux 上的安装包。

如果您运行的是 Mac OS X 或 Linux,Python 的解释器已经预先安装在了系统上。

安装包为程序开发者提供 了 Python 解释器,标准库和几个内置模块。 Python 标准库和内置模块提供的 功能范围广泛,包括内建的数据类型,异常处理,数字和数学模块,文件处理 功能,如

加密服务,与操作系统互操作性,网络数据处理,并与 IP 协议交互,还包括许 多其他有用模块。同时,程序开发者可以很容易地安装任何第三方软件包。 第三方软件包的完整列表可在(http://pypi.python.org/pypi/) 上看到

2、安装第三方库

 在后面,我们将利用 python 的 python-nmap 包来处理 NMAP扫描工具 的结果。 下面的例子描述了如何下载和安装 python-nmap 包,这种方法也适用与安装其他包

因为这里我用的是kali系统,就用kali系统来演示了,也推荐大家使用kali系统,毕竟是渗透测试专用系统,后续我们编写的脚本很多都需要配合里面的渗透测试工具。

kali系统会预安装pip,所以我们直接执行下面这个代码就可以了

pip install python-nmap

结果如下就是安装成功了

后续在编写脚本时有需要安装的包我都会提前说,大家现在只要知道怎么安装就可以了。 

最近几年 python 源代码已经延伸成了 2.x 和 3.x 两个分支。一般情况我用的都是python3.10,如果有特别的情况我会提前说,(版本不用跟我相同,都是3.x即可)。

3、解释型 python与交互型 python 

 解释型交互型的区别就是非交互式交互式的区别,简单举个例子

[1]、解释型 

其实就相当于文件生成后再调用解释器来解释,即执行里面的代码

例如我们新建一个hello.py文件,内容如下

print("hello world!")

此时文件已经生成,再在该目录终端下执行下面这个命令,就可以调动解释器执行其中的代码

python hello.py

 此时终端就会呈现出输出结果,输出“hello world!”,

[2]、交互型

 此外,python 具有交互能力,程序设计师可以调用 python 解释器,并直接与解释 器“交流”。就相当于一直调用解释器,每输入一次命令后交互解释器就会立即执行

在终端输入python即可进入交互型python,此时输入的命令就会被直接执行,效果如下

二、Python 语言简介

 在以后的内容中,我们会讲解变量,数据类型,字符串,复杂的数据结构,网络, 选择,循环,文件处理,异常处理,与操作系统进行交互。为了显示这一点,我们将构建一个简单的 TCP 类型的漏洞扫描器,读取来自服务的提示消息,并把他们与已知的存在漏洞的服务版本做比较,作为一个有经验的程序设计师,你可能会发现一些最 初的示例代码的设计非常难看,事实上,我们希望你能在代码基础上进行发展, 使他变得优雅。

三、变量,字符串,列表,字典介绍

那么,让我们从任何编程语言的基础——变量开始吧! 

1、变量

 在 python 中,变量对应的数据存储在内存中,这种在内存中的位置可以存储不同 的值,如整型,实数,布尔值,字符串,或更复杂的数据结构,例如列表或字典。在 下面的代码中,我们定义一个存储整形的变量和一个存储字符串的提示消息。

port = 21
banner = "FreeFloat FTP Server"
print("[+] Checking for "+banner+" on port "+str(port))

为了把 这两个变量连接到一个字符串中,我们必须用 str()函数将port转换为字符型 ,结果如下

[+] Checking for FreeFloat FTP Server on port 21

怎么样,这个语句相信渗透的小伙伴都不会陌生吧,就是在这样来的,我们后面呢还会用到。 

此外python定义变量与其他语言不同,它不必声明变量的类型,相反,python 解释器决定了变量类型何在内存中为他保留的空间的 大小

思考下面的例子,我们正确的声明了一个字符串,一个整数,一个列表和一个 布尔值,解释器都自动的正确的识别了每个变量的类型(type函数用于返回变量的类型)。

banner = "FreeFloat FTP Server" # 字符串类型
type(banner)
# <type 'str'>

port = 21 # 整型
type(port)
# <type 'int'>

portList=[21,22,80,110] # 列表类型
type(portList)
# <type 'list'>

portOpen = True # 布尔类型
type(portOpen)
# <type 'bool'>

2、字符串

 在 python 中字符串模块提供了一系列非常强大的字符串操作方法。阅读 http://docs.python.org/library/string.html 可以查看完整的用法。

让我们来看几个常用的函数。思考下面这些函数的用法,

upper() 方法将字符串中 的小写字母转为大写字母,

lower()方法转换字符串中所有大写字母为小写,

replace(old,new)方法把字符串中的 old(旧字符串) 替换成 new(新字符串),

find()方法 检测字符串中是否包含指定的子字符串。

 比如下面的代码

banner = "FreeFloat FTP Server"
print(banner.upper())
# FREEFLOAT FTP SERVER

print(banner.lower())
# freefloat ftp server

print(banner.replace('FreeFloat','Ability'))
# Ability FTP Server

print(banner.find('FTP'))
# 10

3、列表

 Python 的数据结构——列表,提供了一种存储一组数据的方式。这组数据里的元素可以是任意数据类型。另外,有一些内置的操作列表的方法,例如元素的添加,删除,插入,弹出,获取索引,排序,计数,排序和反转

请看下面的例子,一个程序通过使用 append()添加元素来建立一个列表,打印项目,然后在 再次输出前给他们排序。程序设计师可以找到特殊元素的索引(例如样例中的 80),此外,指定的元素也可以被移动。

portList = []
portList.append(21)
portList.append(80)
portList.append(443)
portList.append(25)
print(portList)
# [21, 80, 443, 25]

portList.sort()
print(portList)
# [21, 25, 80, 443]

pos = portList.index(80)
print("[+] There are "+str(pos)+" ports to scan before 80.")
# [+] There are 2 ports to scan before 80.

portList.remove(443)
print(portList)
# [21, 25, 80]

cnt = len(portList)
print("[+] Scanning "+str(cnt)+" Total Ports.")
# [+] Scanning 3 Total Ports.

4、字典

Python 的数据结构——字典,提供了一个可以存储任何数量 python 对象的哈希表。 字典的元素由键和值组成,让我们继续用我们的漏洞扫描器的例子来讲解 python 的字 典。当扫描指定的 TCP 端口时,用字典包含每个端口对应的常见的服务名会很有用。 建立一个字典,我们能查找像 ftp 这样的键并返回端口关联的值 21。

当我们建立一个字典时,每一个键和他的值被冒号隔开,同时,我们用逗号分隔元素。 注意,.keys()这个函数将返回字典的所有键的列表,.items()这个方法将返回字典的元素的列表。接下来,我们验证字典是否包含了指定的键(ftp),伴随着键,值 21 返回了。 

services = 'ftp':21,'ssh':22,'smtp':25,'http':80
services.keys()
# ['ftp', 'smtp', 'ssh', 'http']

services.items()
# [('ftp', 21), ('smtp', 25), ('ssh', 22), ('http', 80)]

services.has_key('ftp')
# True

services['ftp']
# 21

print("[+] Found vuln with FTP on port "+str(services['ftp']))
#Found vuln with FTP on port 21

四、使用用网络,迭代器,异常处理,模块等 

1、网络

套接字模块(socket)提供了一个可以使 python 建立网络连接的库,用于在客户端程序和服务器程序之间创建连接.

让我们快速的编写一个获取目标端口信息的脚本,连接到特定 IP 地址和端口后,我们的脚本将打印提示信息,之后, 我们使用 connect()函数连接到 IP 地址端口。一旦连接成功,就可以通过套接字进行读写。我们把获取的结果存到一个变量中,然后打印到服务器。

import socket                              # 引入套接字模块
socket.setdefaulttimeout(2)                # 经过两秒还未连接到,就进入下一操作
s = socket.socket()                        # 创建套接字
s.connect(("192.168.95.148",21))           # 初始化tcp连接
ans = str(s.recv(1024))                    # 接收tcp数据,字节型数据返回,每次最多接收1024字节
print(ans)                                
# 220 FreeFloat Ftp Server (Version 1.00).

 上面这段代码就可以实现一个简单的21端口服务探测功能,将ip换成你想探测的目标,就可以探测到目标的21端口的具体服务信息。

2、条件选择

像大多数编程语言一样,python 提供了条件选择的方式,通过 if 语句,建立一个逻辑表达式来判断选择的结果。继续写我们的脚本,我们想知道,是否指定的 FTP 服务 器是容易受到攻击的。要做到这一点,我们要拿我们的结果和已知的易受攻击的 FTP 服务器版本作比较。

这里给出了四个易受攻击的ftp服务版本,修改后的代码如下

import socket
socket.setdefaulttimeout(2)
s = socket.socket()
s.connect(("192.168.95.148",21))
ans = str(s.recv(1024))
if "FreeFloat Ftp Server (Version 1.00)" in ans:
    print("[+] FreeFloat FTP Server is vulnerable.")
elif "3Com 3CDaemon FTP Server Version 2.0" in ans:
    print("[+] 3CDaemon FTP Server is vulnerable.")
elif "Ability Server 2.34" in ans:
    print("[+] Ability FTP Server is vulnerable.")
elif "Sami FTP Server 2.0.2" in ans:
    print("[+] Sami FTP Server is vulnerable.")
else:
    print("[-] FTP Server is not vulnerable.\\n")

3、异常处理

 即使一个程序设计师编写的程序语法正确,该程序仍然可能在运行或执行时发生错误。 考虑经典的一种运行错误——除以零。因为零不能做除数,所以 python 解释器显示一 条消息,把错误信息告诉程序设计师:该错误使程序停止执行。如下

可以看到程序直接结束了,并出现了报错内容,但是我们不想让程序结束,想让他报错后继续执行就应该引入我们的捕捉异常操作

捕捉异常可以使用try/except语句

以下为简单的try....except...else的语法:

try:
<语句>        #运行别的代码
except <名字>:
<语句>        #如果在try部份引发了'name'异常
except <名字>,<数据>:
<语句>        #如果引发了'name'异常,获得附加的数据
else:
<语句>        #如果没有异常发生

 例如下面这段代码,就能成功捕捉到异常,这样就可以起到程序错误但是

try:
    print("1237/0=" + str(1237 / 0))
except:
    print("error")
else:
    print("right")

 这样的话当1237/0仍然会被识别出错误,但是不会直接结束程序输出报错信息,而是会输出我们定义的error。

现在我们继续更新我们的脚本

import socket
socket.setdefaulttimeout(2)
s = socket.socket()
try:
    s.connect(("192.168.95.149", 21))
except Exception as e:
    print("[-] Error = "+str(e))

4、函数

在 python 中,函数提供了组建好的,可反复使用的代码片段。通常,这允许程序设 计师写代码来执行单独或关联的行为。

尽管 python 提供了许多内置函数,程序设计师仍然可以创建自定义的函数。关键字 def()开始了一个函数,程序设计师可以把任何变量放到括号里。这些变量随后被传递, 这意味着在函数内部对这些变量的任何变化,都将影响调用的函数的值。继续以我们 的 FTP 漏洞扫描器为例,让我们创建一个函数来执行只连接到 FTP 服务器的操作返回提示信息 

import socket


def retBanner(ip, port):
    try:
        socket.setdefaulttimeout(2)
        s = socket.socket()
        s.connect((ip, port))
        banner = s.recv(1024)
        return banner
    except:
        return


def main():
    ip1 = '192.168.95.148'
    ip2 = '192.168.95.149'
    port = 21
    banner1 = retBanner(ip1, port)
    if banner1:
        print('[+] ' + ip1 + ': ' + banner1)
    banner2 = retBanner(ip2, port)
    if banner2:
        print('[+] ' + ip2 + ': ' + banner2)


if __name__ == '__main__':
    main()

在返回信息后,我们的脚本需要与已知存在漏洞的程序进行核对。这也反映了函数 的单一性和相关性。该函数 checkVulns()用获得的信息来对服务器存在的漏洞进行判断

def checkVulns(banner):
    if 'FreeFloat Ftp Server (Version 1.00)' in banner:
        print('[+] FreeFloat FTP Server is vulnerable.')
    elif '3Com 3CDaemon FTP Server Version 2.0' in banner:
        print('[+] 3CDaemon FTP Server is vulnerable.')
    elif 'Ability Server 2.34' in banner:
        print('[+] Ability FTP Server is vulnerable.')
    elif 'Sami FTP Server 2.0.2' in banner:
        print('[+] Sami FTP Server is vulnerable.')
    else:
        print('[-] FTP Server is not vulnerable.')
    return

5、迭代 

上一章中,你可能会发现我们几乎重复三次写了相同的代码,来检测三个不同的 IP 地 址。

代替反复做一件事,使用 for 循环便利多个元素会更加容易。举个例子:如果我们想便利整个整个 IP 地址从 192.168.98.1 到 192.168.95.254 的子网,我们要用一个 for 循 环从 1 到 255 进行遍历,来打印出子网内的信息。 

for x in range(1,255):
    print("192.168.95."+str(x))

同样,我们可能需要遍历已知的端口列表来检查漏洞。代替一系列的数字,我们可以通过一个元素列表遍历他们。

portList = [21,22,25,80,110]
for port in portList:
    print(port)

继续更新我们的脚本,更新后代码如下,随着程序有了遍历 IP 和端口的能力,我们也将个更新我们的漏洞检测脚本,现在, 我们的脚本将测试全部 254 个 IP 地址所提供的 telnet, SSH, smtp, http,

import socket


def retBanner(ip, port):
    try:
        socket.setdefaulttimeout(2)
        s = socket.socket()
        s.connect((ip, port))
        banners = s.recv(1024)
        return str(banners)
    except Exception as e:
        print("扫描错误: ", e)
        return


def checkVulns(banners):
    if 'FreeFloat Ftp Server (Version 1.00)' in banners:
        print('[+] FreeFloat FTP Server is vulnerable.')
    elif '3Com 3CDaemon FTP Server Version 2.0' in banners:
        print('[+] 3CDaemon FTP Server is vulnerable.')
    elif 'Ability Server 2.34' in banners:
        print('[+] Ability FTP Server is vulnerable.')
    elif 'Sami FTP Server 2.0.2' in banners:
        print('[+] Sami FTP Server is vulnerable.')
    else:
        print('[-] FTP Server is not vulnerable.')
    return


def main():
    portList = [21, 22, 25, 80, 110, 443]
    for x in range(106, 107):
        ip = '192.168.1.' + str(x)
        for port in portList:
            banner = retBanner(ip, port)
            if banner:
                print('[+] ' + ip + ':' + str(port) + banner)
                checkVulns(banner)
            else:
                print('[+] ' + ip + ":" + str(port) + " :do not have vuln")


if __name__ == '__main__':
    main()

6、文件I/O

虽然我们的脚本已有了一些能帮助检测漏洞信息的 if 语句,但加进一个漏洞列表会更好,举个例子,假设我们有一个叫做 vuln_banners.txt 的文本文件。

在每一行该文件列出了具体的服务版本和已知的之前的漏洞,我们不需要构建一个庞大的 if 语句, 让我们读取这个文本文件,并用他来判断是否我们的提示信息存在漏洞

就是下面这样包含很多历史漏洞的txt文件 

我们将会把我们更新后的代码放到函数 checkVulns()中。在这里我们将用只读模式 (’r’)打开文本文件。然后使用函数 readlines()遍历文件的每一行,对每一行,我们把他 与我们的提示信息作比较,注意我们必须用方法.strip(‘\\r’)去掉每行的回车符,如果发现一对匹配了,我们打印出有漏洞的服务信息。 更新后的checkVulns函数代码如下(此时历史漏洞文件在同一目录下)

def checkVulns(banner):
    f = open("vuln_banners.txt", 'r')
    for line in f.readlines():
        if line.strip('\\n') in banner:
            print("[+] Server is vulnerable: " + banner.strip('\\n'))

7、SYS 模块 

内置的 sys 模块提供访问和维护 python 解释器的能力。这包括了提示信息,版本, 整数的最大值,可用模块,路径钩子,标准错误,标准输入输出的定位和解释器调用 的命令行参数。你能够在 python 的在线模块文档上找到更多与此相关的信息 (http://docs.python.org/library/sys)。

在创建 python 脚本时与 sys 模块交互会十分 有用。我们可以,例如,想在程序运行时解析命令行参数。思考下我们的漏洞扫描器,

如果我们想要把文本文件的名字作为命令行参数传递会怎么样呢?领标 sys.argv 包含了全部的命令含参数。第一个索引 sys.argv[0]包含了 python 脚本解释器的名称。列表中剩余的元素包含了以下全部的命令行参数。因此,如果我们只想传递附加的参数, sys.argv 应该包含两个元素。

 来看下面这个例子

import sys
    if len(sys.argv)==2:
        filename = sys.argv[1]
        print "[+] Reading Vulnerabilities From: "+filename

我们使用命令行执行

 简单理解就是

sys.argv[1]就是demo2.py

sys.argv[2]就是第一个参数a.txt

依次类推

8、OS模块 

 内置的 OS 模块提供了丰富的与 MAC,NT,Posix 等操作系统进行交互的能力。这个模 块允许程序独立的与操作系统环境。文件系统,用户数据库和权限进行交互。

思考一 下,比如,上一章中,用户把文件名作为命令行参数来传递。他可以验证文件是否存 在以及当前用户是否有权限处理这个文件。如果失败,他将显示一条信息,来显示一个适当的错误信息给用户。

import sys
import os

if len(sys.argv) == 2:  # 命令行传入了一个参数
    filename = sys.argv[1]  # 提取第一个参数
    if not os.path.isfile(filename):  # 路径不存在
        print('[-] ' + filename + ' does not exist.')
        exit(0)
    if not os.access(filename, os.R_OK):  # 没有访问权限
        print('[-] ' + filename + ' access denied.')
        exit(0)
    print('[+] Reading Vulnerabilities From: ' + filename)  # 正常读取文件

现在我们可以重新组合漏洞扫描程序的各个零件。不用担心他会错误终止或是在执 行时缺少使用线程的能力或是更好的分析命令行的能力,我们将会在后面的博客继续改进这个脚本,博主后续的脚本成品都会在github上更新

以上是关于python黑帽子——搭建扫描器入门介绍的主要内容,如果未能解决你的问题,请参考以下文章

厉害了,Python也能操作注册表黑帽子入门必看

厉害了,Python也能操作注册表黑帽子入门必看

python灰帽子讲的啥

python3黑帽子mbp版(第2章:网络基础)

《Python黑帽子:黑客与渗透测试编程之道》读书笔记:web攻击

《Python黑帽子:黑客与渗透测试编程之道》读书笔记:web攻击