使用Qiling分析Dlink DIR-645中的缓冲区溢出(part I)
字数 1555 2025-08-22 12:22:48

Dlink DIR-645 缓冲区溢出漏洞分析教学文档 (Part I)

1. 漏洞概述

本教学文档将详细分析 Dlink DIR-645 路由器中的缓冲区溢出漏洞 (CVE-2013-7389),该漏洞存在于 hedwig.cgi 程序中,影响多个 Dlink 路由器型号。

漏洞基本信息

  • 漏洞编号: CVE-2013-7389
  • 影响组件: hedwig.cgi (实际为 cgibin 二进制文件)
  • 漏洞类型: 缓冲区溢出
  • 攻击向量: 通过特制的 HTTP Cookie 头触发

2. 环境准备

2.1 所需工具

  • Qiling 框架 (用于模拟执行和漏洞分析)
  • Ghidra (反汇编和逆向工程)
  • binwalk (固件提取)
  • gdb-multiarch (调试)

2.2 固件获取与提取

  1. 下载存在漏洞的固件版本
  2. 使用 binwalk 提取固件:
    binwalk -e DIR645A1_FW103RUB08.bin
    

3. 漏洞定位

3.1 关键文件定位

  • hedwig.cgi 是一个符号链接,指向 /htdocs/cgibin 二进制文件
  • 实际漏洞存在于 cgibin 程序中

3.2 关键函数定位

  1. 使用 Ghidra 分析 cgibin 二进制文件
  2. 搜索字符串 "hedwig.cgi" 找到相关函数
  3. 定位到 hedwigcgi_main 函数

4. 漏洞触发条件分析

4.1 必要条件

  • HTTP 请求方法必须为 POST
  • HTTP Cookie 头必须包含 uid= 参数
  • uid= 参数值需要足够长以触发溢出

4.2 环境变量设置

使用 Qiling 框架时需要设置的环境变量:

required_env = {
    "REQUEST_METHOD": "POST",
    "HTTP_COOKIE": "uid=" + "A"*1041 + "1111"
}

5. 漏洞详细分析

5.1 漏洞触发流程

  1. 程序检查 REQUEST_METHOD 环境变量是否为 "POST"
  2. HTTP_COOKIE 环境变量中提取 uid= 参数值
  3. 使用 strcpyuid= 值复制到堆缓冲区
  4. 使用 sprintf 格式化字符串,将堆缓冲区内容复制到栈变量
  5. 过长的输入导致栈上保存的寄存器值被覆盖

5.2 关键代码片段

// 从环境变量获取 Cookie
cookie_value = getenv("HTTP_COOKIE");

// 查找 uid= 参数
// 使用 strcpy 复制到堆缓冲区
strcpy(heap_buffer, uid_value);

// 使用 sprintf 格式化字符串到栈缓冲区
sprintf(stack_buffer, "%s/%s/postxml", "/runtime/session", heap_buffer);

5.3 内存布局

  • 堆缓冲区地址: 0x437898
  • 栈缓冲区地址: 0x7ff3c1e0
  • 关键寄存器覆盖:
    • $ra (返回地址) 被覆盖为 0x41414141
    • 多个保存的寄存器 ($s0-$s8) 被覆盖

6. 动态分析技术

6.1 使用 Qiling 进行模拟

from qiling import *

def redirect_to_hedwigcgi_main(ql):
    ql.reg.arch_pc = HEDWIGCGI_MAIN  # 重定向到目标函数

ql = Qiling(path, rootfs, output="debug", env=required_env)
ql.hook_address(redirect_to_hedwigcgi_main, MAIN_ADDR)

6.2 函数 Hook 技术

def hook_sess_get_uid(ql):
    ql.hook_code(print_asm)  # 打印执行的汇编指令

ql.hook_address(hook_sess_get_uid, SESS_GET_UID)

6.3 关键函数 Hook

def strcpy_hook(ql):
    print("dst:", hex(ql.os.function_arg[0]))
    print("src:", ql.mem.string(ql.os.function_arg[1]))
    return 2

ql.set_api('strcpy', strcpy_hook, QL_INTERCEPT.ENTER)

7. 调试技巧

7.1 启用调试模式

ql.debugger = True  # 启用GDB调试服务器

7.2 GDB 连接

gdb-multiarch
(gdb) set remotetimeout 100
(gdb) target remote 127.0.0.1:9999

7.3 指令级跟踪

def print_asm(ql, address, size):
    buf = ql.mem.read(address, size)
    for i in md.disasm(buf, address):
        print(f":: {hex(i.address)}: {i.mnemonic} {i.op_str}")

8. 漏洞验证

8.1 崩溃验证

发送特制的 HTTP 请求:

POST /hedwig.cgi
Cookie: uid=AAAAAAAA...[1041 bytes]...1111

8.2 崩溃现象

  • 程序计数器 PC 被覆盖为 0x41414140
  • 多个寄存器被覆盖为 0x41414141
  • 错误信息: Invalid memory read (UC_ERR_READ_UNMAPPED)

9. 漏洞总结

9.1 根本原因

  • 不安全的 strcpy 使用导致堆缓冲区溢出
  • 后续的 sprintf 将超长数据复制到栈缓冲区
  • 缺乏输入长度检查导致关键寄存器被覆盖

9.2 利用思路

  1. 控制 uid= 参数的内容
  2. 精心构造溢出数据覆盖返回地址
  3. 实现任意代码执行

10. 后续步骤

在 Part II 中,我们将:

  1. 精确计算偏移量
  2. 构造 ROP 链
  3. 开发完整的漏洞利用代码
  4. 实现远程代码执行

11. 参考资料

  1. Dlink 安全公告
  2. Qiling 框架文档
  3. HITB 会议材料

本教学文档详细介绍了 Dlink DIR-645 缓冲区溢出漏洞的分析过程,包括环境准备、漏洞定位、动态分析和调试技巧。在 Part II 中,我们将深入探讨如何利用此漏洞实现代码执行。

Dlink DIR-645 缓冲区溢出漏洞分析教学文档 (Part I) 1. 漏洞概述 本教学文档将详细分析 Dlink DIR-645 路由器中的缓冲区溢出漏洞 (CVE-2013-7389),该漏洞存在于 hedwig.cgi 程序中,影响多个 Dlink 路由器型号。 漏洞基本信息 漏洞编号 : CVE-2013-7389 影响组件 : hedwig.cgi (实际为 cgibin 二进制文件) 漏洞类型 : 缓冲区溢出 攻击向量 : 通过特制的 HTTP Cookie 头触发 2. 环境准备 2.1 所需工具 Qiling 框架 (用于模拟执行和漏洞分析) Ghidra (反汇编和逆向工程) binwalk (固件提取) gdb-multiarch (调试) 2.2 固件获取与提取 下载存在漏洞的固件版本 使用 binwalk 提取固件: 3. 漏洞定位 3.1 关键文件定位 hedwig.cgi 是一个符号链接,指向 /htdocs/cgibin 二进制文件 实际漏洞存在于 cgibin 程序中 3.2 关键函数定位 使用 Ghidra 分析 cgibin 二进制文件 搜索字符串 "hedwig.cgi" 找到相关函数 定位到 hedwigcgi_main 函数 4. 漏洞触发条件分析 4.1 必要条件 HTTP 请求方法必须为 POST HTTP Cookie 头必须包含 uid= 参数 uid= 参数值需要足够长以触发溢出 4.2 环境变量设置 使用 Qiling 框架时需要设置的环境变量: 5. 漏洞详细分析 5.1 漏洞触发流程 程序检查 REQUEST_METHOD 环境变量是否为 "POST" 从 HTTP_COOKIE 环境变量中提取 uid= 参数值 使用 strcpy 将 uid= 值复制到堆缓冲区 使用 sprintf 格式化字符串,将堆缓冲区内容复制到栈变量 过长的输入导致栈上保存的寄存器值被覆盖 5.2 关键代码片段 5.3 内存布局 堆缓冲区地址 : 0x437898 栈缓冲区地址 : 0x7ff3c1e0 关键寄存器覆盖 : $ra (返回地址) 被覆盖为 0x41414141 多个保存的寄存器 ( $s0 - $s8 ) 被覆盖 6. 动态分析技术 6.1 使用 Qiling 进行模拟 6.2 函数 Hook 技术 6.3 关键函数 Hook 7. 调试技巧 7.1 启用调试模式 7.2 GDB 连接 7.3 指令级跟踪 8. 漏洞验证 8.1 崩溃验证 发送特制的 HTTP 请求: 8.2 崩溃现象 程序计数器 PC 被覆盖为 0x41414140 多个寄存器被覆盖为 0x41414141 错误信息: Invalid memory read (UC_ERR_READ_UNMAPPED) 9. 漏洞总结 9.1 根本原因 不安全的 strcpy 使用导致堆缓冲区溢出 后续的 sprintf 将超长数据复制到栈缓冲区 缺乏输入长度检查导致关键寄存器被覆盖 9.2 利用思路 控制 uid= 参数的内容 精心构造溢出数据覆盖返回地址 实现任意代码执行 10. 后续步骤 在 Part II 中,我们将: 精确计算偏移量 构造 ROP 链 开发完整的漏洞利用代码 实现远程代码执行 11. 参考资料 Dlink 安全公告 Qiling 框架文档 HITB 会议材料 本教学文档详细介绍了 Dlink DIR-645 缓冲区溢出漏洞的分析过程,包括环境准备、漏洞定位、动态分析和调试技巧。在 Part II 中,我们将深入探讨如何利用此漏洞实现代码执行。