You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于NSE的DCE/RPC查询脚本问题:UDP端口异常致响应丢失

问题与解决方案:NSE UDP Socket 接收任意源端口响应

问题描述

我正在使用Nmap Scripting Engine (NSE)编写脚本,通过DCE/RPC Endpoint Mapper的Lookup Request提取产品名称和物料编号。测试时遇到异常:

  • 扫描主机(IP:192.168.10.56)以随机源端口51336向UDP目标端口34964发送请求
  • 第一个西门子设备(IP:192.168.10.12)按预期以34964为源端口回复,Nmap可接收
  • 第二个设备(IP:192.168.10.21)使用随机源端口49344回复,导致Nmap无法接收响应

当前使用socket:connect(ip, 34964, "udp")指定扫描主机端口,因此出现此问题。想知道能否通过NSE创建类似“服务器端口”的socket,接收特定端口的所有传入消息?

原脚本片段:

send_udp_payload = function(ip, timeout, payload)
    local socket, try, catch

    -- create a new udp socket
    local socket = nmap.new_socket("udp")

    -- set timeout
    socket:set_timeout(tonumber(timeout))

    catch = function()
        socket:close()
    end

    -- create new try
    try = nmap.new_try(catch)

    -- connect to port on host
    try(socket:connect(ip, 34964, "udp"))

    -- send lookup packet with PNIO Interface UUID
    try(socket:send(payload))

    -- receive response
    local rcvstatus, response = socket:receive()

    -- close socket
    socket:close()

    if rcvstatus then
        return response
    else
        return nil
    end
end

解决方案

可以通过不调用socket:connect(),改用socket:sendto()发送数据包,并绑定本地端口后用socket:receivefrom()接收任意源地址/端口的响应。具体实现如下:

修改后的脚本片段

send_udp_payload = function(target_ip, timeout, payload)
    local socket, try, catch
    local local_port = 34964 -- 绑定本地这个端口来接收所有传入响应

    -- 创建UDP socket
    local socket = nmap.new_socket("udp")
    socket:set_timeout(tonumber(timeout))

    catch = function()
        socket:close()
    end
    try = nmap.new_try(catch)

    -- 绑定本地端口,所有发往该端口的UDP包都会被此socket接收
    try(socket:bind(nil, local_port, "udp"))

    -- 直接发送数据包到目标设备的34964端口
    try(socket:sendto(target_ip, 34964, payload))

    -- 循环接收响应,过滤目标设备的回复
    while true do
        local rcvstatus, response, sender_ip, sender_port = socket:receivefrom()
        if not rcvstatus then
            break -- 超时退出
        end
        -- 验证发送者是目标设备,避免干扰包
        if sender_ip == target_ip then
            socket:close()
            return response
        end
    end

    socket:close()
    return nil
end

关键说明

  • socket:bind(nil, local_port)中的nil表示绑定到所有本地IP,也可以指定扫描主机的具体IP(192.168.10.56)
  • receivefrom()会返回发送者的IP和端口,方便过滤非目标设备的响应
  • 原问题根源是connect()会让socket仅接收来自指定IP+固定端口的响应,去掉该调用即可接收任意源端口的回复

内容的提问来源于stack exchange,提问作者ckmk14

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 05:17:10