精华内容
下载资源
问答
  • 欢迎访问系列文章Linux 二进制漏洞挖掘入门系列之(二)堆溢出:off-by-oneLinux 二进制漏洞挖掘入门系列之(三)整数溢出Linux 二进制漏洞挖掘入门系列之(四)格式化字符串漏洞Linux 二进制漏洞挖掘入门系列之(五)UAF ...

    欢迎访问系列文章

    Linux 二进制漏洞挖掘入门系列之(二)堆溢出:off-by-one

    Linux 二进制漏洞挖掘入门系列之(三)整数溢出

    Linux 二进制漏洞挖掘入门系列之(四)格式化字符串漏洞

    Linux 二进制漏洞挖掘入门系列之(五)UAF 漏洞分析与利用

    0x10 环境

    gdb-peda 插件,用来调试程序时,高亮不同寄存器,堆栈的地址和数据

    Windows 环境下的 IDA Pro,强大的交互式反汇编工具

    测试程序(即带有栈溢出漏洞的二进制可执行文件)

    虚拟机装有 Linux 发行版,例如 Ubuntu、Kali,用来运行测试程序

    pwntools,如果要写 POC,会用到此 python 包

    测试程序下载地址

    1

    链接:https://pan.baidu.com/s/1U3ktIz-veMuktutss-oGuA

    提取码:9sn2

    2

    下面文件下载后,放在linux下的 /home/pwn/pwn0/

    链接:https://pan.baidu.com/s/11lm17lllPZ5A8rrcuCELAg

    提取码:knpf

    gdb-peda 插件安装终端输入以下命令,即可安装成功

    git clone https://github.com/longld/peda.git ~/peda

    echo "source ~/peda/peda.py" >> ~/.gdbinit

    对于非 Kali 的 Linux 发行版,我们还需要安装 checksec,一个用来检查 ELF 二进制可执行文件的保护措施的小程序

    apt-get install checksec

    0x20 漏洞分析

    首先当然是运行目标程序,亲手体验一下程序的作用,然后再反编译代码,进行静态分析,找到其中可能存在的 bug,最后进行利用

    0x21 初步分析

    在 linux 环境下检测之前下载好的文件类型。从结果不难看出,文件类型是 ELF 32 位的可执行程序,架构是 Intel x86,也就是说该程序无法在 ARM 架构的处理器上运行。

    c2a54f22bb7c472664346c1a37997663.png

    检查以下目标程序有没有保护措施,如果是自己安装的 checksec ,需要加入 -f 参数,即 checksec -f pwn0

    7efd194d5129c8ec2e5ba62d1db775e5.png

    Arch,即我们刚刚说的架构,32 位

    Stack / CANNARY (栈保护),类似于cookie, 防止利用栈溢出覆盖和篡改

    FORTIFY,对字符串格式化漏洞的保护,一般在 gcc 编译时考虑

    NX 即 No-eXecute(不可执行),栈数据没有可执行权限

    RELRO 分为RELRO会有Partial RELRO和FULL RELRO,如果开启FULL RELRO,意味着我们无法修改got表

    在 linux 环境下运行下载好的测试程序 pwn0

    adbf3a840617b7de95dbe62c52ecd632.png

    这个程序比较简单,就是你输入什么,屏幕会打印什么,至于有没有漏洞存在,需要使用工具来进行分析源码

    0x22 静态分析

    使用 IDA Pro 打开目标程序 pwn0,由于测试程序是 32 位的,需要使用 32 位 IDA 打开。打开之后,给我们呈现的是反汇编代码,如果你不习惯使用汇编,可以按 F5,得到 IDA 反编译的伪码(C语言),接近源码,这也是 IDA 强大的原因之一

    88b2e619559a54c320cbda1c474eda51.png

    我们发现,foo() 函数传递的 a1 参数值是固定的,也就是 foo 函数第 8 行的判断永远不成立,导致 getFlag() 函数无法运行,我们也就拿不到里面的值

    这里存在的问题就是,gets() 函数不会限制用户输入的数据长度,而变量 s 的大小不是无限的,它在栈中,分配一个固定的地址,并且大小有限制。

    93c6fb27081475e552a319e91e902475.png

    上图是一个典型的函数调用栈的示意图,由于没有对用户的输入做判断,我们可以写入大量的值到 s,直到 s 覆盖到函数形参 a1,将 a1 改写为 0x61616161,那么就可以使得 if 条件判断成立,从而得到 flag。现在只需要知道变量 s 离栈底的距离即可

    这里,穿插一下基本概念

    ESP寄存器用来记录栈顶的地址。随着数据项的入栈和出栈,其值在不断变化

    EBP寄存器用于引用当前栈帧中的变量。

    事实上 IDA 已经给出答案,在上面静态分析截图的代码中,foo() 函数第 4 行后面,IDA 已给出注释,s 的地址是,ebp - 1Ch,也就是距离 EBP 1C个字节的距离。为了了解 IDA 的计算过程,我们使用 gdb 调试来分析

    0x23 gdb 调试分析

    我们需要在内存给变量 s 分配地址时,查看栈空间,并观察各个寄存器的状态,这就需要在分配给变量 s 的代码处,设置断点

    在 IDA Pro 中,点击 Options > General > Disassembly,勾选下面的选项,这样就能够查看代码段的相关地址,才能根据地址设置断点

    d8962426509d560570df47395c58ccab.png

    查看定义变量 s 的代码

    3d9d40dc8d1cd86cce10bf829857a52d.png

    这是 foo() 函数的汇编代码,不难看出,在 0x080485AB 处,开始给变量 s 分配内存。也就是说,需要利用 gdb 调试,在该地址处设置断点,并查看此时的寄存器和函数栈分配情况

    6e2a7ec87bd7353ad221033eabdb2fe9.png

    如上图,此时栈顶位置就是分配给 s 变量的位置,即 EAX 寄存器存放的数据,它与 EBP 的距离为 0xffffd328 - 0xffffd30c = 0x1c,与 IDA 分析的一致

    所以,最终,变量 s 距离栈底,形参 a1

    (EBP - EAX)+ EBP + EIP

    0xffffd328 - 0xffffd30c + 0x4 + 0x4 # 寄存器存放 32 位数据,即 4 字节

    (上述结果为十进制数 36)

    0x30 验证

    运行 pwn0,输入 36 个 A(也可以是其他填充数据),再输入1234(也是测试数据),那么填充数据理论上覆盖了 s 以下的栈空间,1234 刚好覆盖形参 a1,还是用 gdb 来验证吧

    0x31 gdb 验证

    接着 0x23 节设置的断点(s 赋值前),我们再在后面设置一个断点,断点位置不用太固定,从下图随便选一个地址作为点(s 赋值后)即可,重要的是,必须是在 s 赋值后

    8d453411e9973b457db4d6e541122eba.png

    首先观察 s 赋值前,栈空间的数据,此时形参 a1 仍然是 0x12345678

    b8a231fcaf5b643f3c2d981251ef8773.png

    然后设置第二个断点,在 gdb 中输入 c,继续第一个断点后运行程序,此时程序提示输入,我们按照 0x20 的分析,输入以下数据

    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2222

    数据来源:

    payload = A' * (0xffffd328 - 0xffffd30c) + 'A' * 0x4 + 'A' * 0x4

    payload += 2222 # 字符 A 用来填充,可以随意更换,字符 1234 用来覆盖形参 a1

    print payload

    此时,再用 gdb 查看栈空间

    a76f298544296bf82d42c51f38ad6282.png

    达到相应效果,形参 a1 的值被替换

    0x32 编写代码验证

    注意事项:内存存储数字可能未必是我们输入的数字,可能需要转换为字符串,然后输入

    # -*- coding: utf-8 -*-

    import pwn

    pwn_object = pwn.process("./pwn0")

    print pwn_object.recvline()# 读取一行程序输出后,print打印出来(so,can you find flag?)

    payload = 'A' * (0xffffd328 - 0xffffd30c) + 'A' * 0x4 + 'A' * 0x4

    payload += pwn.p32(0x61616161)

    pwn_object.sendline(payload)# 用p32转换字符,加在payload末尾

    print pwn_object.recvline()

    print pwn_object.recvline()

    程序输出结果:

    5e2db09fe3870862c3eaf43071276ca5.png

    至此,我们已经成功的让程序运行到,它原本不可能执行的地方了

    ——————————————————————————————

    原创文章,转载请注明出处!

    展开全文
  • 主要介绍了浅谈D-Link系列路由器漏洞挖掘入门,详细的介绍了D-Link系列的各种漏洞,具有一定的参考价值,有兴趣的可以了解一下
  • 入门快速使用3.1.实例化`Session`对象3.2.定义消息(Request)3.3.构建协议树(Protocol-Tree)3.4.Fuzz3.5.查看结果4.必备知识汇总4.1.会话,Session4.2.目标,Target4.2.1.Repeater4.2.2.TimeRepeater4

    文章目录


    本文主要涉及到对Boofuzz的简单介绍,以及基于Boofuzz官方文档/网上资料的学习、整理和翻译相关内容,希望对想要入门的Boofuzz的朋友有所帮助,谢谢~

    1.简介

    模糊技术主要的两种形式:

    • 基于变异的模糊化,mutation-based fuzzing,该技术主要包括以下:
      1. 收集已知的良好数据,如文件或网络流量;
      2. 通过随机/启发式等方式方法,对数据进行稍微地修改;
    • 基于生成的模糊化,generation-based fuzzing,从描述特定格式或网络协议报文格式规范或RFC开始,生成具有一定差异的有效测试用例数据,以便在测试的应用程序中造成崩溃。

    模糊测试中,应该避免过度转换数据,否则应用程序可能会很快将输入作为无效输入拒绝。

    接下来我们提到的Sulley和Boofuzz都是属于基于生成的模糊化fuzzer。

    1.1.从Sulley说起

    Sulley不仅具有令人印象深刻的数据生成能力,而且还朝着更进一步的方向迈进了一步,其中还包括现代模糊器应提供的许多其他重要方面。Sulley监视网络并有条不紊地维护记录。Sulley可以检测和监视目标的运行状况,并可以使用多种方法将其恢复到已知的良好状态。Sulley对检测到的故障进行检测,跟踪和分类。Sulley可以并行进行测试,从而显着提高测试速度。Sulley可以自动确定哪些独特的测试用例序列会触发故障。Sulley可以自动完成所有这些工作。
    请添加图片描述

    上图是Sulley的整体框架图,来源于BlackHat。Sulley主要包括四大组件

    • Data Generation,数据生成
    • Session,会话管理
    • Agents,代理
    • Utilities,独立单元工具

    其中,数据生成和会话管理是比较重要的两个模块。Sulley数据生成方式是基于generation-based的方式,需要对协议或者文件进行建模。数据生成的特点:

    • 一个数据报文由基元(Primitives)、块(Blocks组成);
    • 多个基元可以组成块,块可以相互嵌套;
    • 在基元的基础上我们可以创建自定义的特殊的复杂基元(Legos,数据积木,暂且这么翻译吧),例如Email的地址,IP地址等;
    • 最后还有一些有用的工具,例如算length长度、校验和、加密模块等;

    1.2.Boofuzz

    Boofuzz是一个基于生成(generation-based)的协议Fuzz工具,它通过python语言来描述协议的格式。

    Boofuzz是经典模糊测试框架Sulley的继承者,除了众多的bug修复之外,boofuzz还致力于扩展性。Boofuzz对协议的模糊测试有着良好的支持,且其代码开源,目前被广泛使用,但Boofuzz无法直接获取协议相关知识,需人工定义协议模型.

    Boofuzz架构

    请添加图片描述

    2.Dev环境部署

    2.1.使用pip安装部署

    强烈建议在虚拟环境(venv)中设置boofuzz。首先,创建一个目录来保存boofuzz安装:

    $ mkdir boofuzz && cd boofuzz
    $ python3 -m venv env
    

    这将在当前文件夹中创建一个新的虚拟环境env。请注意,虚拟环境中的Python版本是固定的,并在创建时选择。与全局安装不同,在虚拟环境中,python被别名为虚拟环境的python版本。

    接下来,激活虚拟环境:

    source env/bin/activate
    

    如果在windows平台上,使用命令:

    env\Scripts\activate.bat
    

    使用一下命令更pipsetuptools

    (env) $ pip install -U pip setuptools
    

    最后安装boofuzz

    (env) $ pip install boofuzz
    

    要运行和测试模糊脚本,请确保始终事先激活虚拟环境

    2.2.从源码部署boofuzz

    #!/bin/bash
    sudo echo
    
    if [ ! -d ~/work_dir/boofuzz-F ];then
        mv ~/Downloads/boofuzz-F ~/work_dir
    fi
    
    sudo apt-get install -y python3-pip \
        python3-venv \
        build-essential
    
    pip install -U pip setuptools
    
    pip install pcapy impacket wheel
    
    cd ~/work_dir/boofuzz-F
    python3 -m venv env
    source env/bin/activate
    pip install -e .[dev]
    

    使用HTTP代理时,需要设置环境变量:

    set HTTPS_PROXY=http://your.proxy.com:port
    

    2.3.进程监控

    process monitor是在Windows或Linux上检测崩溃和重新启动应用程序的工具。虽然boofuzz通常在与目标不同的机器上运行,但进程监视器必须在目标机器本身上运行。

    注意:windows平台使用process_monitor.py,*nix平台使用process_monitor_unix.py

    2.4.网络监控,network_monitor.py

    网络监视器是Sulley记录测试数据的主要工具,已经被boofuzz的记录机制所取代。然而,有些人仍然更喜欢PCAP方法。

    注意:

    网络监视器需要Pcapy和Impacket,它们不会随着boofuzz自动安装。

    您可以使用pip install pcapy impacket手动安装它们。

    如果遇到错误,请查看Pcapy项目(https://github.com/helpsystems/pcapy)页面上的要求。

    3.入门快速使用

    一般fuzz的流程为:

    • 实例化Session对象
    • 定义消息(Request)
    • 构建协议树(Protocol-Tree)
    • Fuzz
    • 查看结果

    3.1.实例化Session对象

    Session对象是fuzz会话的中心。创建时,将向其传递一个Target对象,该对象本身将接收一个Connection对象。例如:

    session = Session(
        target=Target(
            connection=TCPSocketConnection("127.0.0.1", 8021)))
    

    Connection对象实现ITargetConnection接口。可用的子类包括:

    3.2.定义消息(Request)

    会话对象就绪后,接下来需要在协议中定义消息。

    每个消息都是一个请求对象,其子对象定义该消息的结构。

    以下是FTP协议中的几个消息定义:

    user = Request("user", children=(
        String("key", "USER"),
        Delim("space", " "),
        String("val", "anonymous"),
        Static("end", "\r\n"),
    ))
    
    passw = Request("pass", children=(
        String("key", "PASS"),
        Delim("space", " "),
        String("val", "james"),
        Static("end", "\r\n"),
    ))
    
    stor = Request("stor", children=(
        String("key", "STOR"),
        Delim("space", " "),
        String("val", "AAAA"),
        Static("end", "\r\n"),
    ))
    
    retr = Request("retr", children=(
        String("key", "RETR"),
        Delim("space", " "),
        String("val", "AAAA"),
        Static("end", "\r\n"),
    ))
    

    3.3.构建协议树(Protocol-Tree)

    定义消息后,您将使用刚才创建的会话对象将消息(Request)连接到图形(graph)中,构建协议树(Protocol-Tree):

    session.connect(user)
    session.connect(user, passw)
    session.connect(passw, stor)
    session.connect(passw, retr)
    

    当模糊化时,boofuzz将在模糊化passw之前发送user,在模糊化stor或retr之前发送user和passw。

    从以上的表述可以看出,构建协议树(Protocol-Tree),其实是Session对象组织维护了以root为根节点的消息(Request)状态转移图(graph)。

    若要绘制Session构建的消息(Request)状态转移图(graph),使用以下代码

     with open('somefile.png', 'wb') as file: 
         file.write(session.render_graph_graphviz().create_png())
    

    需要注意,绘图前请确保系统中已经安装好了graphviz,如果没有,使用命令sudo apt install graphviz -y进行安装。

    将上述例子中的协议树(Protocol-Tree)画出来,如下所示:

    请添加图片描述

    3.4.Fuzz

    最后即可开始模糊测试

    session.fuzz()
    

    请注意,此时您只有一个非常基本的模糊器。

    项目中的examples目录中有一些示例和请求定义可能有助于您进一步了解。

    3.5.查看结果

    每次运行的日志数据将保存到当前工作目录中boofuzz results目录中的SQLite数据库中。您可以随时使用重新打开这些数据库上的web界面

    $ boo open <run-*.db>
    

    检查响应,您需要使用Session.post_test_case_callbacks回调函数。要在请求中使用响应中的数据,请参阅ProtocolSessionReference

    4.必备知识汇总

    我在这里罗列了几个值得重点关注的点:

    • s_*系列函数;
    • 很多s_*系列函数都有一个bool类型的参数fuzzable,它是控制是否对某个字段进行fuzz的开关;
    • Session.connect函数;
    • Session.fuzz函数;

    4.1.会话,Session

    Session几乎提供了整个Boofuzz功能的设定,同时通过查看Session类初始化的参数可以了解到Boofuzz提供了那些功能。Session类的初始化参数如下:

    参数:
    session_filename (str): 序列化持久数据到的文件名. Default None.
    
    index_start (int);      设置从哪个索引(index)开始启动testcase.
    
    index_end (int);        设置到哪个索引(index)结束testcase.
    
    sleep_time (float):     运行testcase之间的时间间隔,单位为秒. Default 0.
    
    restart_interval (int): 间隔几个testcase就重启一次目标, 设置为0时表示从不重启目标. Default 0.
    
    console_gui (bool):     在终端使用光标生产一个类似于web界面的静态控制台。未在Windows下测试. Default False.
    
    crash_threshold_request (int):  请求(request)耗尽前允许的最大崩溃数. Default 12.
    
    crash_threshold_element (int):  元素(element)耗尽前允许的最大崩溃数. Default 3.
    
    restart_sleep_time (int):       目标不能被重启时,休眠的时间,单位为秒. Default 5.
    
    restart_callbacks (list of method): 在回调post_test_case_callback失败后,这些注册调用(restart_callbacks)会执行. Default None.
    
    restart_threshold (int):    丢失目标连接时的最大重试次数. Default None(indefinitely).
    
    restart_timeout (float):    重试连接尝试的时间(秒). Default None(indefinitely).
    
    pre_send_callbacks (list of method): 注册的方法将在每个模糊测试用例之前被调用. Default None.
    
    post_test_case_callbacks (list of method): 注册的方法将在每个模糊测试用例之后调用. Default None.
    
    post_start_target_callbacks (list of method): 方法将在目标启动或重新启动后调用,例如,由进程监视器调用。
    
    web_port (int):             通过web浏览器监视模糊测试的端口. Default 26000.
    
    keep_web_open (bool):       会话完成后保持webinterface打开. Default True.
    
    fuzz_loggers (list of ifuzz_logger.IFuzzLogger): 用于保存测试数据和结果。默认日志到标准输出。
    
    fuzz_db_keep_only_n_pass_cases (int): 为了最大限度地减少磁盘使用量,仅保存位于故障或错误之前的n个测试用例的数据。设置为0,表示保存每个测试用例(高磁盘I/O!). Default 0.
    
    receive_data_after_each_request (bool): 如果为True,会话将在发送每个非模糊节点后尝试接收应答. Default True.
    
    check_data_received_each_request (bool): 如果为True,会话将验证在传输每个非模糊节点后是否已接收到一些数据,如果未接收到待验证的数据,则注册失败。如果为False,则不会执行此检查。默认为False。除非receive_data_after_each_request为假,否则仍会进行接收尝试。
    
    receive_data_after_fuzz (bool): 如果为True,会话将在发送模糊消息后尝试接收回复. Default False.
    
    ignore_connection_reset (bool): Log ECONNRESET errors ("Target connection reset") as "info" instead of failures.
    
    ignore_connection_aborted (bool): Log ECONNABORTED errors as "info" instead of failures.
    
    ignore_connection_issues_when_sending_fuzz_data (bool): 忽略模糊数据传输故障。默认为True。这通常是一个有用的启用设置,因为一旦消息明显无效,目标可能会断开连接。
    
    ignore_connection_ssl_errors (bool): Log SSL related errors as "info" instead of failures. Default False.
    
    reuse_target_connection (bool): If True, only use one target connection instead of reconnecting each test case. Default False.
    

    从以上Session提供的入参可以看出,其大致提供了几个功能:

    • 通过session_filename进行实例对象数据序列化并保持到本地;
    • 通过index_startindex_end手动指定模糊测试testcase的起始和结束索引;
    • 指定时间间隔(发送请求,重启目标等),超时(发送请求等),阈值等;
    • 指定回调函数(pre,post,重启目标等);
    • 监视模糊测试的web-service设置;
    • 其他;

    Session继承扩展了pgraph.graph类,pgraph是操纵有向图和无向图的python库,Session在graph类基础上提供用于架构协议会话的容器。

    常用函数包括:

    • connect,构建协议树时,用来连接消息节点;

    • add_target,添加目标;

    • example_test_case_callback;

    • register_post_test_case_callback,注册一个测试后用例方法。注册的方法将在每个模糊测试用例之后调用。调用的顺序:

      pre_send()
      ↓
      req
      ↓
      callback
      ↓
      ...
      ↓
      req
      ↓
      callback
      ↓
      post-test-case-callback
      
    • fuzz,模糊整个协议树(Protocol-Tree)。迭代并模糊所有情况,根据self.skip跳过并根据self.restart_interval重新启动。

      如果希望模糊测试结束后,web服务器仍然可用,则程序必须在结尾调用boofuzz.helpers.pause_for_signal()

    • import_file,导入session序列化的本地配置文件;

    • num_mutations,图中的总突变数。此函数会更新成员变量self.total_num_mutations

    • transmit_fuzz,发送模糊测试请求;

    • transmit_normal,发送正常的请求;

    • render_graph_graphviz,渲染图。使用代码:

      with open('somefile.png', 'wb') as file:
          file.write(session.render_graph_graphviz().create_png())
      

    4.2.目标,Target

    目标描述符容器。

    常用函数包括:

    • set_fuzz_data_logger,设置此对象的模糊数据记录器——用于发送和接收的模糊数据;

    4.2.1.Repeater

    基础的重复器类

    4.2.2.TimeRepeater

    基于时间的重复器类。启动计时器,并重复,直到超过持续时间秒。

    4.2.3.CountRepeater

    基于数量的重复器。重复固定的次数。

    4.3.连接,Connection

    连接对象,网络层连接描述类。

    4.3.1.ITargetConnection

    用于连接模糊目标的接口。

    4.3.2.BaseSocketConnection

    该类是套接字(socket)上许多连接的基础类。

    4.3.3.TCPSocketConnection

    用于TCP套接字的BaseSocketConnection实现。

    4.3.4.UDPSocketConnection

    用于UDP套接字的BaseSocketConnection实现。

    4.3.5.SSLSocketConnection

    用于SSL套接字的BaseSocketConnection实现。

    4.3.6.RawL2SocketConnection

    用于网络L2层的BaseSocketConnection实现。

    4.3.7.RawL3SocketConnection

    用于网络L3层的BaseSocketConnection实现。

    4.3.8.SocketConnection

    ITargetConnection使用套接字实现。

    4.3.9.SerialConnection

    ITargetConnection实现通用串行端口。

    4.4.监视器,Monitors

    监控器是针对特定行为监控目标的组件。监视器可以是被动的,只是观察和提供数据,或者更主动地与目标直接交互。某些监控器还具有启动、停止和重新启动目标的功能。

    根据您在目标主机上可用的工具,检测目标的崩溃或不当行为可能是一个复杂、非直接的过程;这尤其适用于嵌入式设备。Boofuzz提供了三种主要的监视器实现:

    • ProcessMonitor,在Windows和Unix上从进程收集调试信息的监视器。它还可以重新启动目标进程并检测故障。

    • NetworkMonitor,一种通过PCAP被动捕获网络流量并将其附加到测试用例日志的监视器。

    • CallbackMonitor,用于实现可提供给会话类的回调。

    4.4.1BaseMonitor

    目标监视器的接口。所有监视器必须遵守本规范。

    4.4.2.ProcessMonitor

    进程监视器由两部分组成:

    • ProcessMonitor类,实现BaseMonitor;
    • 要在目标主机上运行的模块,windows平台使用process_monitor.py,*nix平台使用process_monitor_unix.py

    4.4.3.NetworkMonitor

    网络监视器由两部分组成:

    • NetworkMonitor类,它实现BaseMonitor;

    • 要在目标主机上运行的模块,使用network_monitor.py

    4.4.4.CallbackMonitor

    Session中用于提供回调数组的新型回调监视器。它的目的是在会话类中保留*_callbacks参数,同时通过将这些回调转发到监视器基础结构来简化会话的实现。

    参数到此类的方法实现的映射关系,如下所示:

    • restart_callbacks –> target_restart
    • pre_send_callbacks –> pre_send
    • post_test_case_callbacks –> post_send
    • post_start_target_callbacks –> post_start_target

    所有其他实现的接口成员都只是存根(stubs),因为会话中不存在相应的参数。在任何情况下,实现自定义监视器可能比使用回调函数更明智。

    4.5.日志,Logging

    Boofuzz提供了灵活的日志记录。所有日志类都实现IFuzzLogger。下面详细介绍了内置日志类。

    要同时使用多个记录器,请参阅 FuzzLogger

    4.5.1.IFuzzLogger

    用于记录模糊数据的抽象类。

    IFuzzLogger为Sulley框架和测试编写器提供了日志接口。

    提供的方法旨在反映功能测试动作。IFuzzLogger提供了一种记录测试用例、通过、失败、测试步骤等的方法,而不是一般的调试/信息/警告方法。

    这个假设的示例输出给出了如何使用记录器的想法:

    • Test Case: UDP.Header.Address 3300

      Test Step: Fuzzing

      ​ Send: 45 00 13 ab 00 01 40 00 40 11 c9 …

      Test Step: Process monitor

      ​ checkCheck OK

      Test Step: DNP

      ​ CheckSend: ff ff ff ff ff ff 00 0c 29 d1 10 …

      ​ Recv: 00 0c 29 d1 10 81 00 30 a7 05 6e …

      ​ Check: Reply is as expected. Check OK

    • Test Case: UDP.Header.Address 3301

      Test Step: Fuzzing

      ​ Send: 45 00 13 ab 00 01 40 00 40 11 c9 …

      Test Step: Process monitor check

      ​ Check Failed: “Process returned exit code 1”

      Test Step: DNP Check

      ​ Send: ff ff ff ff ff ff 00 0c 29 d1 10 …

      ​ Recv: None

      ​ Check: Reply is as expected. Check Failed

    为每个模糊案例打开一个测试案例。为每个高级测试步骤打开一个测试步骤。测试步骤可以包括,例如:

    • Fuzzing
    • Set up (pre-fuzzing)
    • Post-test cleanup
    • Instrumentation checks
    • Reset due to failure

    在测试步骤中,测试可以记录发送的数据、接收的数据、检查、检查结果和其他信息。

    4.5.2.IFuzzLoggerBackend

    IFuzzLogger的别名

    4.5.3.FuzzLoggerText

    此类格式化FuzzLogger数据以用于文本显示。可以将其配置为输出到标准输出或命名文件。

    使用两个FuzzLoggerText,可以将FuzzLogger实例配置为输出到控制台和文件。

    4.5.4.FuzzLoggerCsv

    此类为pcap文件格式化FuzzLogger数据。可以将其配置为输出到命名文件。

    4.5.5.FuzzLoggerCurses

    此类使用curses为控制台GUI格式化FuzzLogger数据。这还没有在Windows上测试过。

    4.5.6.FuzzLogger

    获取IFuzzLogger对象的列表,并将记录的数据多路传输到每个对象。

    FuzzLogger还维护概要故障和错误数据。

    4.6.协议定义,Protocol Definition

    有关老式Spike样式的静态协议定义格式,请参阅静态协议定义函数。这里描述的非静态协议定义是较新的(但仍有些实验性)方法。

    请求是消息,消息中包含了块,原语(Primitives)是块/请求的组成(bytes, strings, numbers, checksums等)。

    下面是一个HTTP消息的示例。它演示了如何使用请求、块和几个原语:

    req = Request("HTTP-Request",children=(
        Block("Request-Line", children=(
            Group("Method", values= ["GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE"]),
            Delim("space-1", " "),
            String("URI", "/index.html"),
            Delim("space-2", " "),
            String("HTTP-Version", "HTTP/1.1"),
            Static("CRLF", "\r\n"),
        )),
        Block("Host-Line", children=(
            String("Host-Key", "Host:"),
            Delim("space", " "),
            String("Host-Value", "example.com"),
            Static("CRLF", "\r\n"),
        )),
        Static("CRLF", "\r\n"),
    ))
    

    4.6.1.Request

    顶层容器。可以保存任何块结构或原语(Primitives)。

    这基本上可以被认为是超级块、根块、父块等别名。

    4.6.2.Blocks

    基本构建块。可以包含primitives, sizers, checksums或其他blocks。

    4.6.3.Primitives

    • Static

      静态原语是固定的,在模糊化时不会发生变化。

    • Simple

      只能通过简单手动指定的,模糊字节值。

    • Delim

      分隔符,它的突变包括重复、替换和排除。分隔符包括:,\r,\n, ,=,>,<等等;

    • Group

      此原语表示,在突变时将便利一个指定的静态值列表的每个元素。

      可以将块绑定到组原语,以指定块应循环遍历组中每个值的所有可能突变。例如,group原语在表示有效操作码列表时非常有用。

      下面是Group原语表示HTTP请求方法的所有突变的可能。

          with s_block("Request-Line"):
              s_group("Method", ["GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE"])
              s_delim(" ", name="space-1")
              s_string("/index.html", name="Request-URI")
              s_delim(" ", name="space-2")
              s_string("HTTP/1.1", name="HTTP-Version")
              s_static("\r\n", name="Request-Line-CRLF")
              s_string("Host:", name="Host-Line")
              s_delim(" ", name="space-3")
              s_string("example.com", name="Host-Line-Value")
              s_static("\r\n", name="Host-Line-CRLF")
          s_static("\r\n", "Request-CRLF")
      
    • RandomData

      生成随机数据块,同时保留原始数据的副本。
      可以指定随机长度范围。对于静态长度,请将最小/最大长度设置为相同。

    • String

      在“坏”字符串库中循环的基元。
      类变量“fuzz_library”包含所有实例的全局智能模糊值列表。当前我使用的代码中的_fuzz_library如下:

          _fuzz_library = [
              "!@#$%%^#$%#$@#$%$$@#$%^^**(()",
              "",  # strings ripped from spike (and some others I added)
              "$(reboot)",
              "$;reboot",
              "%00",
              "%00/",
      .........
              '%0DCMD=$"reboot";$CMD',
              "%0Dreboot",
              "%n" * 500,
              "%s" * 100,
              "%s" * 500,
              "%u0000",
              "& reboot &",
              "& reboot",
              "&&CMD=$'reboot';$CMD",
              '&&CMD=$"reboot";$CMD',
              "&&reboot",
              "&&reboot&&",
              "..:..:..:..:..:..:..:..:..:..:..:..:..:",
              "/%00/",
              "/." * 5000,
              "/.../" + "B" * 5000 + "\x00\x00",
              "/.../.../.../.../.../.../.../.../.../.../",
              "/../../../../../../../../../../../../boot.ini",
              "/../../../../../../../../../../../../etc/passwd",
              "/.:/" + "A" * 5000 + "\x00\x00",
              "/\\" * 5000,
              "/index.html|reboot|",
              "; reboot",
              ";CMD=$'reboot';$CMD",
              ';CMD=$"reboot";$CMD',
              ";id",
      .........
          ]
      

      _fuzz_library库变量包含特定于实例化原语的模糊值。这允许我们避免在每个实例化的原语中复制大约70MB的_fuzz_library数据结构。

    • FromFile

      循环浏览文件中的“坏”值列表。
      获取文件名并打开文件以读取模糊化过程中使用的值。文件名可能包含通配符(glob characters)。

    • Mirror

      原语用于使用另一个原语保持更新。

    • BitField

      位字段原语表示许多可变长度,用于定义所有其他整数类型。

    • Byte

      1个字节大小的位字段原语。

    • Bytes

      将任意长度的二进制字节字符串模糊化的原语。

    • Word

      2个字节大小的位字段原语。

    • DWord

      4个字节大小的位字段原语。

    • QWord

      8个字节大小的位字段原语。

    4.6.4.制作自己的块/原语

    要创建自己的块/基本体,请执行以下操作:

    Overload,Override,Overwrite区别

    • Overload重载,同一个作用域中,语义功能相似,仅函数名相同;
    • Override覆盖,继承关系中,Override一般用于多态技术,函数必须实现基类的统一接口;
    • Overwrite重写,继承关系中,子类函数名与父类相同。
    • 可选:创建附带的静态原语函数。示例,请参见boofuzz的__init__.py文件。

    如果您的块依赖于对其他块的引用,那么校验和或长度字段依赖于消息的其他部分的方式,请参阅Size源代码以获取如何避免递归问题,并小心。

    Fuzzable

    自定义块/原语时,需要继承此类。它是所有块/原语的基类。

    FuzzableBlock

    设计为具有子元素的可模糊类型。

    FuzzableBlock重写以下方法,更改基于FuzzableBlock的任何类型的默认行为:

    1. mutations() ,遍历所有子节点产生的突变。
    2. num_mutations() ,对每个子节点表示的突变求和。
    3. encode() ,调用函数 get_child_data().

    FuzzableBlock添加了以下方法:

    1. get_child_data(),渲染并连接所有子节点。
    2. push() ,添加额外的子节点;通常只在内部使用。

    4.7.静态协议定义,Static Protocol Definition

    老式Spike样式的静态协议定义格式,请参阅静态协议定义函数。不在赘述了,推荐使用新的Protocol Definition,见4.6节。

    4.8.其他模块,Other Modules

    4.8.1.测试用例会话引用,ProtocolSessionReference

    指在单个测试用例的上下文中接收或生成的动态值。

    将此对象作为原语的default_value参数传递,并确保使用回调设置引用的值,例如,post_test_case_callbacks(请参阅Session

    4.8.2.ProtocolSession

    包含一个session_variables字典,用于存储特定于单个模糊测试用例的数据。

    通常,session_variables中的值将在回调函数中设置,例如,post_test_case_callbacks(请参阅Session)。

    变量可以在以后的回调函数中使用,也可以由ProtocolSessionReference对象使用。

    4.8.3.Helpers

    该类包含了许多助手函授和小工具,熟悉它们,让你更加得心应手。

    4.8.4.IP Constants

    此文件包含IPv4协议的常量。

    在版本0.2.0中更改:ip_constants已移动到connections子包中。完整路径现在是boofuzz.connections.ip_constants

    4.8.5.PED-RPC

    Boofuzz提供了一个RPC原语来在远程机器上托管监控器。主boofuzz实例充当连接到(远程)运行的RPC服务器实例的客户端,透明地调用在服务器实例的客户端实例上调用的函数,并将其结果作为python对象返回。一般来说,通过RPC接口传递的数据需要能够被pickle。

    请注意,PED-RPC不提供任何形式的身份验证或授权。建议仅在受信任的网络上运行它。

    4.8.6.DCE-RPC

    期待更新…

    4.8.7.Crash binning

    期待更新…

    4.8.8.EventHook

    期待更新…

    5.Boofuzz功能探究与源码走读

    5.1.Session功能探究

    前面4.1章节我们已经大概了梳理了Session类提供的功能,以及常用的函数方法。

    接下来我们会逐个尝试Session的不同参数设置,对fuzz过程的影响;

    5.1.1.session_filename,序列化持久数据到的文件

    测试代码使用了example/http_simple.py。修改如下:

    def main():
        session = Session(
    +++        session_filename = r'to_specify_path\http_simple.session',
            target=Target(connection=TCPSocketConnection("127.0.0.1", 80)),
        )
    

    当指定了session_filename参数后,在fuzz过程中,会产生如下调用栈:

    export_file, sessions.py:691 # 将session对象的各个变量dump到本地
        ↑
    _fuzz_current_case, sessions.py:1775 # 模糊测试当前用例
        ↑
    _main_fuzz_loop, sessions.py:1388 # 模糊测试用例主循环
        ↑
    fuzz, sessions.py:1264 # 模糊测试主入口
        ↑
    main, http_simple.py:20<module>, http_simple.py:78execfile, _pydev_execfile.py:18
        ↑
    run, pydevd.py:1068
        ↑
    main, pydevd.py:1658<module>, pydevd.py:1664
    

    5.1.2.index_startindex_end,指定模糊测试testcase开始和结束的索引

    测试代码使用了example/http_simple.py。修改如下:

    def main():
        session = Session(
    +++        index_start=5,
    +++        index_end=10,
            target=Target(connection=TCPSocketConnection("127.0.0.1", 80)),
        )
    

    通过调试和走读源码可以发现index_startindex_end主要在_main_fuzz_loop函数中起作用,控制着模糊测试testcase开始和结束。

    如下:

    # file: boofuzz\sessions.py
    # 其中self.total_mutant_index的值是在生成testcase迭代器过程中而增加的。
    def _main_fuzz_loop(self, fuzz_case_iterator):
    	...
    	try:
    		...
    		for mutation_context in fuzz_case_iterator:
    			if self.total_mutant_index < self._index_start: # 如果小于index_start则忽略
    				continue
    			# Check restart interval
    			...
    			self._fuzz_current_case(mutation_context)
    
    			self.num_cases_actually_fuzzed += 1
    
    			if self._index_end is not None and self.total_mutant_index >= self._index_end: # 如果大于等于index_end则退出Fuzz
    				break
    		...
    	except KeyboardInterrupt:
    		...
    	finally:
    		...
    

    5.1.3.回调函数

    • restart_callbacks (list of method),在回调post_test_case_callback失败后,这些调用会执行. Default None.
    • pre_send_callbacks (list of method),注册的方法将在每个模糊测试用例之前被调用. Default None.
    • post_test_case_callbacks (list of method),注册的方法将在每个模糊测试用例之后调用. Default None.
    • post_start_arget_callbacks (list of method),方法将在目标启动或重新启动后调用,例如,由进程监视器调用。

    boofuzz中与回调函数主要的相关代码,如下:

    # file: boofuzz\sessions.py
    class Session(pgraph.Graph):
        def __init__(
            self,
            ...
            restart_callbacks=None,
    		...
            pre_send_callbacks=None,
            post_test_case_callbacks=None,
            post_start_target_callbacks=None,
            ...
            target=None,
        ):
    		...
            if pre_send_callbacks is None:
                pre_send_methods = []
            else:
                pre_send_methods = pre_send_callbacks
    
            if post_test_case_callbacks is None:
                post_test_case_methods = []
            else:
                post_test_case_methods = post_test_case_callbacks
    
            if post_start_target_callbacks is None:
                post_start_target_methods = []
            else:
                post_start_target_methods = post_start_target_callbacks
    
            if restart_callbacks is None:
                restart_methods = []
            else:
                restart_methods = restart_callbacks
    
            self._callback_monitor = CallbackMonitor(
                on_pre_send=pre_send_methods,
                on_post_send=post_test_case_methods,
                on_restart_target=restart_methods,
                on_post_start_target=post_start_target_methods,
            )
    		...
    

    如上Session构造函数中初始化时,创建了一个CallbackMonitor类型的成员变量,CallbackMonitor是Session中用于提供回调数组的回调监视器。它的目的是在Session类中保留*_callbacks的回调参数,同时通过将这些回调转发到监视器基础结构来简化会话的实现。

    所有其他实现的接口成员都只是存根(Stub),因为会话中不存在相应的参数。在任何情况下,实现自定义监视器可能比使用回调函数更好一点。

    # file: boofuzz\sessions.py
    def _fuzz_current_case(self, mutation_context):
    	target = self.targets[0]
    	...
    	try:
    		self._open_connection_keep_trying(target)
    
    		self._pre_send(target) # 这里会调用Session的pre_send_callbacks
    
    		for e in mutation_context.message_path[:-1]:
    			prev_node = self.nodes[e.src]
    			node = self.nodes[e.dst]
    			protocol_session = ProtocolSession(
    				previous_message=prev_node,
    				current_message=node,
    			)
    			mutation_context.protocol_session = protocol_session
    			callback_data = self._callback_current_node(node=node, edge=e, test_case_context=protocol_session) # 这里调用edge的callback
    			self._fuzz_data_logger.open_test_step("Transmit Prep Node '{0}'".format(node.name))
    			self.transmit_normal(target, node, e, callback_data=callback_data, mutation_context=mutation_context)
    
    		prev_node = self.nodes[mutation_context.message_path[-1].src]
    		node = self.nodes[mutation_context.message_path[-1].dst]
    		protocol_session = ProtocolSession(
    			previous_message=prev_node,
    			current_message=node,
    		)
    		mutation_context.protocol_session = protocol_session
    		callback_data = self._callback_current_node(
    			node=self.fuzz_node, edge=mutation_context.message_path[-1], test_case_context=protocol_session
    		) # 这里调用edge的callback
    		self._fuzz_data_logger.open_test_step("Fuzzing Node '{0}'".format(self.fuzz_node.name))
    		self.transmit_fuzz(
    			target,
    			self.fuzz_node,
    			mutation_context.message_path[-1],
    			callback_data=callback_data,
    			mutation_context=mutation_context,
    		)
    
    		self._check_for_passively_detected_failures(target=target) # 这里会调用Session的post_test_case_callbacks
    		...
    

    注意:除了Session有回调函数,使用Session.connect函数也可以对edge定义调用回调。

    5.1.4.其他的略

    参考

    项目github地址,https://github.com/jtpereyda/boofuzz

    boofuzz手册,https://boofuzz.readthedocs.io/en/stable/

    IoT 设备网络协议模糊测试工具boofuzz实战,https://blog.csdn.net/song_lee/article/details/104334096

    Practical Modbus Fuzzing with boofuzz,https://64k.space/practical-modbus-fuzzing-with-boofuzz.html

    展开全文
  • IOT漏洞挖掘入门

    2020-06-01 10:57:15
    看评论是乌云 14年8月提交的漏洞。 于是进一步分析一下。 首先拿到 http://地址/.htpasswd admin:$1$$xAjuh7utDUp3xXVqThWzp/ 在hashcat中进行破解 Session..........: hashcat Status...........: ...

    一日无聊,发现一篇文章

    https://www.52pojie.cn/thread-367479-1-1.html

    看评论是乌云 14年8月提交的漏洞。

     

    于是进一步分析一下。

    首先拿到

    http://地址/.htpasswd

    admin:$1$$xAjuh7utDUp3xXVqThWzp/

    在hashcat中进行破解

    
    Session..........: hashcat
    Status...........: Running
    Hash.Type........: md5crypt, MD5 (Unix), Cisco-IOS $1$ (MD5)
    Hash.Target......: $1$$xAjuh7utDUp3xXVqThWzp/
    


    嗯,跑了几分钟,没有跑出来。反正跑出来也没啥用。

    于是上zoomeye关键词volans又找到一枚新的

    hashcat  -m 500 '$1$$U6YTLx/HR47ETGUJalT/f/'  xxxx

    $1$$U6YTLx/HR47ETGUJalT/f/:fan1314520

    不错,已经可以登陆进去了。

     

    修改元素属性,删除input中的id值,即可绕过检测。

    展开全文
  • 介绍二进制漏洞挖掘的一个方法思路,用IDA解析二进制代码,取得程序的函数,栈帧,数据流,控制流;取得程序的界面资源,取得资源对应的函数代码,综合分析程序的堆溢、栈溢、同步问题、线程安全问题、 逻辑漏洞分析...
  • Boofuzz实战 进行漏洞挖掘 入门

    千次阅读 2021-09-17 15:04:07
    参考搭建环境:Boofuzz协议漏洞挖掘入门教程与使用心得 教程2 参考跑个例子:使用boofuzz进行漏洞挖掘(一) 例子解析:使用boofuzz进行漏洞挖掘(二) 一、环境搭建 从源码部署boofuzz 创建目录 mkdir ~/work_dir/...

    参考搭建环境:Boofuzz协议漏洞挖掘入门教程与使用心得

    教程2

    参考跑个例子:使用boofuzz进行漏洞挖掘(一)

    例子解析:使用boofuzz进行漏洞挖掘(二)

    一、环境搭建

    从源码部署boofuzz

    创建目录

    mkdir ~/work_dir/boofuzz-F
    git clone http://www.github.com/jtpereyda/boofuzz
    cd boofuzz
    

    shell脚本,或者手动执行命令进行安装,安装虚拟环境env

    #!/bin/bash
    sudo echo
    
    sudo apt-get install -y python3-pip \
        python3-venv \
        build-essential
    
    pip install -U pip setuptools
    
    pip install pcapy impacket wheel
    
    cd ~/work_dir/boofuzz-F
    python3 -m venv env
    source env/bin/activate
    pip install -e .[dev]
    

    image-20210917150203481

    二、跑个例子

    进入examples中我们先编辑和运行第一个例子(FUZZ ftp服务)就像你第一次写代码那样hello world!那样。 vim ftp-simple.py

    cd boofuzz/examples
    
    vim ftp-example.py
    
    from boofuzz import *
    
    def main():
      session = Session(target= Target(connection=SocketConnection("127.0.0.1", 21, proto='tcp')))
      s_initialize("user")
      s_string("USER")
      s_delim(" ")
      S_string("anonymous")
      s_static("lrln")
      s_initialize("pass")
      s_string("PASS")
      s_delim(" ")
      S_string("james")
      s_static("lrln")
      s_initialize("stor")
      s_string("STOR")
      s_delim(" ")
      s_string("AAAA")
      S_static("lrln")
      s_initialize("retr")
      s_string( "RETR")
      s_delim(" ")
      s_string("AAAA")
      s_static("\r\n")
      session.connect(s_get("user"))
      session.connect(s_get("user"), s_get("pass"))
      session.connect(s_get("pass"), s_get("stor") )
      session.connect(s_get("pass"), s_get("retr") )
      session.fuzz()
    if __name__ == "__main__":
    	main()
      
    
    展开全文
  • Web逻辑漏洞挖掘 身份认证安全、业务一致性安全、业务数据篡改、密码找回等各种漏洞案例。
  • ActiveX控件漏洞挖掘入门,非常容易使用的COMRaider工具挖掘ActiveX控件的漏洞。
  • 得到明文的响应体,然后还是使用fehelper将其格式化: 与Android页面上对一下,由此石锤Android端也是存在此漏洞: Android端与web端并不是同一个接口,猜测接口应该只是个后端靠前的代理,调用的更后端的业务应该...
  • web漏洞挖掘快速入门,涵盖完整的漏洞挖掘流程,从前期的信息搜集一直到后渗透测试,是新手入门挖洞的理想指南。
  • ActiveX漏洞挖掘入门

    2011-09-11 23:03:03
    ActiveX是微软在1996年引入,是基于COM组件和OLE的。...但由于现在有的第三方开发人员编程方面的原因,控件出现越来越多的漏洞能被恶意的网站来利用,通过溢出或者是功能代码的注入来侵害个人电脑。
  • 0x10 UAF(Use After Free) 漏洞原理 这里,需要先介绍一下堆分配内存的原则。ptmalloc 是 glibc 的堆管理器,前身是 dlmalloc,Linux 中进程分配内存的两种方式:brk 和 mmap。当程序使用 malloc 申请内存的时候,...
  • 如何入门漏洞挖掘,以及提高自己的挖掘能力

    万次阅读 多人点赞 2018-07-17 16:57:52
     大家好我是米斯特团队的一员,我的id香瓜,我们团队在这次i春秋第二次漏洞挖掘大赛中,包揽了前五名,我key表哥一不小心拿了一个第一,导致很多人来加他好友问他,如何修炼漏洞挖掘能力,我今天帮大家解答一下这个...
  • D-Link系列路由器漏洞挖掘入门 前言 前几天去上海参加了geekpwn,看着大神们一个个破解成功各种硬件,我只能在下面喊 6666,特别羡慕那些大神们。所以回来就决定好好研究一下路由器,争取跟上大神们的步伐。看网上...
  • 这个栈溢出的原因是由于cookie的值过长导致的栈溢出。服务端取得客户端请求的HTTP头中Cookie字段中uid的值,格式...通过对漏洞点进行分析,搭建模拟环境并完成整个漏洞利用过程。 (文章中有不足之处,还请各位...
  • 关于格式化字符串漏洞的利用,可参见:ASIS CTF 2020_full_protection: 格式化字符串与栈溢出的利用 0x40 总结 对于格式化字符串漏洞,32 位和 64 位的程序是有所不同的。借助于先知社区上的一张图片,32 位程序 ...
  • 所以,此类漏洞,最大困难往往并不是发现漏洞点,怎么样利用漏洞达到getshell的效果。 在程序运行中,堆是可以提供动态分配的内存,允许程序申请未知大小的内存。堆其实就是程序虚拟地址空间的一块连续的线性区域,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,273
精华内容 1,309
关键字:

漏洞挖掘入门