【python黑帽子】——(一)搭建扫描器入门介绍

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

作者名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 在 WindowsMac OS X 和 Linux 上的安装包。

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

安装包为程序开发者提供 了 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上更新

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: python