Skip to content

Also catch ECONNRESET from UDP sockets#21618

Merged
sjanusz-r7 merged 3 commits into
rapid7:masterfrom
zeroSteiner:fix/udp-scan-windows
Jul 1, 2026
Merged

Also catch ECONNRESET from UDP sockets#21618
sjanusz-r7 merged 3 commits into
rapid7:masterfrom
zeroSteiner:fix/udp-scan-windows

Conversation

@zeroSteiner

@zeroSteiner zeroSteiner commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Windows raises ECONNRESET not ECONNREFUSED as Linux does

Description

Related Issue: rapid7/rex-socket#85

Breaking Changes

None, this fixes a regression I intro'ed in #21562

Reviewer Notes

Verification Steps

    • Apply the patch and run Metasploit on a Windows system
    • Use the udp_sweep module and see it complete successfully with the expected results

Test Evidence

This is a Windows Server 2019 instance where I manually installed the archive of master from the 6.5.141 tag.

Old and Busted

msf auxiliary(scanner/discovery/udp_sweep) > set RHOSTS 127.0.0.1
RHOSTS => 127.0.0.1
msf auxiliary(scanner/discovery/udp_sweep) > run
[*] Sending 13 probes to 127.0.0.1->127.0.0.1 (1 hosts)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf auxiliary(scanner/discovery/udp_sweep) >

New and Fixed

msf auxiliary(scanner/discovery/udp_sweep) > set RHOSTS 127.0.0.1
RHOSTS => 127.0.0.1
msf auxiliary(scanner/discovery/udp_sweep) > run
[*] Sending 13 probes to 127.0.0.1->127.0.0.1 (1 hosts)
[*] Discovered DNS on 127.0.0.1:53 (Microsoft DNS)
[*] Discovered NTP on 127.0.0.1:123 (1c0104e900000000000a236b4c4f434ceded163a5ad760a4c54f234b71b152f3eded44ed06df62d1eded44ed06dfa79a)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf auxiliary(scanner/discovery/udp_sweep) >

Environment

Field Details
Operating System Windows Server 2019
Target Software/Hardware Windows Server 2019 (scanned the loopback interfface)
Docker Image / Vagrant Setup

AI Usage Disclosure

Pre-Submission Checklist

  • Included a corresponding documentation markdown file in documentation/modules (new modules only)
  • No sensitive information (IP addresses, credentials, API keys, hashes) in code or documentation
  • Tested on the target environment specified in the Environment section above
  • Included RSpec tests for library changes (encouraged for lib/ changes)
  • Read the CONTRIBUTING.md and module acceptance guidelines
Hardware and Complex Software Module Guidance

If your module targets specialized hardware (routers, IoT, PLCs, etc.) or complex software (licensed, multi-service, or multi-version), provide a pcap, screen recording, or video showing successful execution.

Email sanitized pcaps/recordings to msfdev@metasploit.com — remove real IPs, credentials, and hostnames before sending. If hardware/software is unavailable, explain in the PR description.

Responsiveness and PR Takeover Policy

We want every contribution to make it into the project. If approximately 2 weeks pass after a review request without a comment or code update from you, the team may take over the PR and complete the work on your behalf.

If this happens, you will remain credited as a co-author on the final commit — your contribution is always recognized.

This policy exists to keep the project moving forward. It is not a reflection on the quality of your work or your involvement. Life happens, and we would rather finish the work together than let a good contribution go stale.

Windows raises ECONNRESET not ECONNREFUSED as Linux does
@zeroSteiner zeroSteiner marked this pull request as ready for review June 29, 2026 19:27
@smcintyre-r7 smcintyre-r7 added rn-fix release notes fix library bug labels Jun 29, 2026
@smcintyre-r7 smcintyre-r7 moved this from Todo to Ready in Metasploit Kanban Jun 29, 2026
@zeroSteiner zeroSteiner changed the title Also catch ECONNRESET Also catch ECONNRESET from UDP sockets Jun 29, 2026
@sjanusz-r7

Copy link
Copy Markdown
Contributor

Worked for my Windows 10 VM:

Before

msf auxiliary(scanner/discovery/udp_sweep) > run rhost=...
[*] Sending 13 probes to x->x (1 hosts)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

After

[*] Sending 13 probes to x->x (1 hosts)
[*] Discovered DNS on x:53 (Microsoft DNS)
[*] Discovered NTP on x:123 (foo)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

However there might be more places that need the change. An AI overview:

- bind_udp.rb (~line 153) -> Only rescues Errno::ECONNREFUSED in the response-read loop
- netbios_spoof.rb (~line 74) -> Only rescues Errno::ECONNREFUSED during the UDP send loop
- netbios_spoof_nat.rb (~line 140) -> Same pattern
- cisco_sdwan_auth_bypass.rb (~line 170)
- cisco_sdwan_vhub_auth_bypass.rb (~line 187) -> Same pattern as above
- rpcbomb.rb (~line 72)
- snmp_enum_hp_laserjet.rb (~line 142)
- chargen_probe.rb (~line 65) -> Uses ::Rex::ConnectionRefused (which is separate from Errno::ECONNREFUSED) but still misses ECONNRESET

A quick test shows that those might be correct:

cisco sdwan auth bypass

msf auxiliary(admin/networking/cisco_sdwan_auth_bypass) > run rhost=x
...
[*] Running module against x
[*] Phase 1: DTLS handshake with self-signed certificate
[-] Auxiliary failed: Errno::ECONNRESET An existing connection was forcibly closed by the remote host. - recvfrom(2)
[-] Call stack:
[-]   C:/Ruby33-x64/lib/ruby/3.3.0/socket.rb:542:in `__recvfrom_nonblock'
[-]   C:/Ruby33-x64/lib/ruby/3.3.0/socket.rb:542:in `recvfrom_nonblock'
[-]   C:/Users/win10/.local/share/gem/ruby/3.3.0/gems/rex-socket-0.1.69/lib/rex/socket/udp.rb:153:in `recvfrom'
[-]   C:/Users/win10/Desktop/Programming/metasploit-framework/modules/auxiliary/admin/networking/cisco_sdwan_auth_bypass.rb:625:in `block in do_dtls_handshake'
[-]   <internal:kernel>:187:in `loop'
[-]   C:/Users/win10/Desktop/Programming/metasploit-framework/modules/auxiliary/admin/networking/cisco_sdwan_auth_bypass.rb:612:in `do_dtls_handshake'
[-]   C:/Users/win10/Desktop/Programming/metasploit-framework/modules/auxiliary/admin/networking/cisco_sdwan_auth_bypass.rb:165:in `phase1_dtls_handshake'
[-]   C:/Users/win10/Desktop/Programming/metasploit-framework/modules/auxiliary/admin/networking/cisco_sdwan_auth_bypass.rb:98:in `perform_auth_bypass'
[-]   C:/Users/win10/Desktop/Programming/metasploit-framework/modules/auxiliary/admin/networking/cisco_sdwan_auth_bypass.rb:81:in `run'
[*] Auxiliary module execution completed

cisco sdwan vhub auth bypass

Same as above:

[*] Running module against x
[*] Phase 1: DTLS handshake with self-signed certificate
[-] Auxiliary failed: Errno::ECONNRESET An existing connection was forcibly closed by the remote host. - recvfrom(2)
[-] Call stack:
[-]   C:/Ruby33-x64/lib/ruby/3.3.0/socket.rb:542:in `__recvfrom_nonblock'
[-]   C:/Ruby33-x64/lib/ruby/3.3.0/socket.rb:542:in `recvfrom_nonblock'
[-]   C:/Users/win10/.local/share/gem/ruby/3.3.0/gems/rex-socket-0.1.69/lib/rex/socket/udp.rb:153:in `recvfrom'
[-]   C:/Users/win10/Desktop/Programming/metasploit-framework/modules/auxiliary/admin/networking/cisco_sdwan_vhub_auth_bypass.rb:660:in `block in do_dtls_handshake'
[-]   <internal:kernel>:187:in `loop'
[-]   C:/Users/win10/Desktop/Programming/metasploit-framework/modules/auxiliary/admin/networking/cisco_sdwan_vhub_auth_bypass.rb:647:in `do_dtls_handshake'
[-]   C:/Users/win10/Desktop/Programming/metasploit-framework/modules/auxiliary/admin/networking/cisco_sdwan_vhub_auth_bypass.rb:182:in `phase1_dtls_handshake'
[-]   C:/Users/win10/Desktop/Programming/metasploit-framework/modules/auxiliary/admin/networking/cisco_sdwan_vhub_auth_bypass.rb:112:in `perform_auth_bypass'
[-]   C:/Users/win10/Desktop/Programming/metasploit-framework/modules/auxiliary/admin/networking/cisco_sdwan_vhub_auth_bypass.rb:87:in `run'
[*] Auxiliary module execution completed

chargen probe

I believe this actually works okay from my testing?

snmp enum hp laserjet

this raises the uncaught exception

[*] Connecting to x
C:/Users/win10/Desktop/Programming/metasploit-framework/lib/snmp/manager.rb:62: warning: Socket#sendto is deprecated; use send(mesg, flags, host, port) instead
[-] x, Unknown error: Errno::ECONNRESET An existing connection was forcibly closed by the remote host. - recvfrom(2)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

netbios spoof nat

This actually has a separate issue:

msf auxiliary(server/netbios_spoof_nat) > run
[-] Auxiliary failed: NameError undefined local variable or method `srvhost' for #<Msf::Modules::Auxiliary__Server__Netbios_spoof_nat::MetasploitModule:0x0000024c8e6f9b18>
[-] Call stack:
[-]   C:/Users/win10/Desktop/Programming/metasploit-framework/modules/auxiliary/server/netbios_spoof_nat.rb:72:in `netbios_service'
[-]   C:/Users/win10/Desktop/Programming/metasploit-framework/modules/auxiliary/server/netbios_spoof_nat.rb:150:in `block in run'
[-]   <internal:kernel>:187:in `loop'
[-]   C:/Users/win10/Desktop/Programming/metasploit-framework/modules/auxiliary/server/netbios_spoof_nat.rb:150:in `run'
Interrupt: use the 'exit' command to quit

netbios spoof

I wasn't able to trigger the exception here; but I may have not been testing this correctly?

@zeroSteiner

zeroSteiner commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

Yeah thanks for calling out those 8 spots. cisco_sdwan_auth_bypass is one that does use #recvfrom which now raises, so you're right it should be updated and I'll make that change. bind_udp.rb however does not. That uses #get which eventually gets to #sysread. If that's broken today, it was probably broken before the #recvfrom changes since #recvfrom is not part of the chain. Seems reasonable enough though to just update all the instances of rescue Errno::ECONNREFUSED to also rescue Errno::ECONNRESET.

@zeroSteiner

zeroSteiner commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

Added ECONNRESET to all the instances you called out except for chargen_probe.rb which calls #timed_recvfrom and thus won't need it once rapid7/rex-socket#86 is landed. I suggest you land that first, then I'll bump rex-socket in this PR so chargen_probe.rb is covered along with the rest.

@github-project-automation github-project-automation Bot moved this from Ready to In Progress in Metasploit Kanban Jul 1, 2026
@sjanusz-r7

sjanusz-r7 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

The failing mysql CI test is unrelated to this change. Merging now 🚀

Works as expected

msf auxiliary(scanner/discovery/udp_sweep) > run rhost=x
[*] Sending 13 probes to x->x (1 hosts)
[*] Discovered NTP on x:123 (foo)
[*] Discovered DNS on x:53 (Microsoft DNS)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

@sjanusz-r7 sjanusz-r7 merged commit 535a186 into rapid7:master Jul 1, 2026
64 of 66 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Metasploit Kanban Jul 1, 2026
@adfoster-r7

adfoster-r7 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Release Notes

Fixes a crash when running the scanner/discovery/udp_sweep module on Windows environments

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug library rn-fix release notes fix

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants