Lucene search
+L

Windows Gather System Information

🗓️ 24 Jan 2026 22:19:45Reported by KittySploitType 
kittysploit
 kittysploit
🔗 kittysploit.com👁 4 Views

The Windows Gather System Information module enumerates OS details, users, and processes.

Refs
Code
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from kittysploit import *
import re

class Module(Post):
    """Windows System Enumeration Module"""
    
    __info__ = {
        "name": "Windows Gather System Information",
        "description": "Enumerates Windows system information including OS details, users, processes, services, network configuration, and security settings",
        "author": "KittySploit Team",
        "platform": Platform.WINDOWS,
        "session_type": [SessionType.METERPRETER, SessionType.SHELL],
    'agent': {
        'risk': 'intrusive',
        'effects': ['active_exploitation'],
        'expected_requests': 2,
        'reversible': False,
        'approval_required': True,
        'produces': ['risk_signals'],
        'cost': 1.5,
        'noise': 0.5,
        'value': 1.0,
        'requires':         {'min_endpoints': 0,
         'min_params': 0,
         'tech_hints_any': [],
         'tech_hints_all': [],
         'specializations_any': [],
         'risk_signals_any': [],
         'auth_session': False,
         'capabilities_any': [],
         'capabilities_all': [],
         'confidence_min': {},
         'confidence_min_any': {},
         'endpoint_pattern_any': [],
         'param_any': [],
         'api_surface_ready': False},
        'chain':         {'produces_capabilities': [],
         'consumes_capabilities': [],
         'option_bindings': {},
         'suggested_followups': []},
    },
    }
    

    def _get_session_id_value(self) -> str:
        """Return the current session_id option value as a string."""
        try:
            return str(getattr(self, "session_id", "") or "").strip()
        except Exception:
            return ""
    
    def _ensure_cache_fields(self):
        """Ensure per-instance cache attributes exist."""
        if not hasattr(self, "_cached_session_id"):
            self._cached_session_id = None
        if not hasattr(self, "_cached_session"):
            self._cached_session = None
        if not hasattr(self, "_session_type_value"):
            self._session_type_value = ""
    
    def _ensure_session_context(self):
        """Load and cache the session metadata."""
        self._ensure_cache_fields()
        session_id_value = self._get_session_id_value()
        if self._cached_session_id == session_id_value and self._cached_session is not None:
            return
        
        self._cached_session_id = session_id_value
        self._cached_session = None
        self._session_type_value = ""
        
        if not session_id_value or not self.framework or not hasattr(self.framework, 'session_manager'):
            return
        
        session = self.framework.session_manager.get_session(session_id_value)
        if session:
            self._cached_session = session
            session_type = getattr(session, 'session_type', '') or ''
            self._session_type_value = session_type.lower()
    
    def _get_session(self):
        """Return the cached session object."""
        self._ensure_session_context()
        return self._cached_session
    
    def _is_meterpreter_session(self) -> bool:
        """Return True if the active session is a meterpreter session."""
        self._ensure_session_context()
        return self._session_type_value == SessionType.METERPRETER.value
    
    def _execute_meterpreter_cmd(self, command: str):
        """Execute a meterpreter-only command if the session supports it."""
        if not command or not self._is_meterpreter_session():
            return ""
        return self._execute_cmd(command)
    
    def _execute_windows_command(self, command: str):
        """
        Execute a standard Windows command across both meterpreter and classic shells.
        Automatically prefixes with 'shell' when running from meterpreter.
        """
        if not command:
            return ""
        cmd = command
        if self._is_meterpreter_session():
            cmd = f"shell {command}"
        return self._execute_cmd(cmd)
    
    def _format_bytes(self, bytes_value: int) -> str:
        """Format bytes to human-readable format"""
        if bytes_value is None or bytes_value == 0:
            return "0 B"
        
        for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
            if bytes_value < 1024.0:
                return f"{bytes_value:.2f} {unit}"
            bytes_value /= 1024.0
        return f"{bytes_value:.2f} PB"
    
    def _fix_encoding(self, text: str) -> str:
        """Fix encoding issues in text output, especially Windows-1252/CP850 to UTF-8"""
        if not text:
            return text
        
        try:
            # If it's bytes, decode it properly
            if isinstance(text, bytes):
                # Try Windows-1252 first (common Windows encoding for cmd.exe)
                try:
                    text = text.decode('windows-1252', errors='replace')
                except:
                    # Try CP850 (another common Windows encoding)
                    try:
                        text = text.decode('cp850', errors='replace')
                    except:
                        # Fallback to UTF-8
                        text = text.decode('utf-8', errors='replace')
            else:
                # If it's already a string but has encoding issues
                # Common patterns:
                # - "é" instead of "é" (UTF-8 decoded as Latin-1)
                # - "é" displayed as something else (Windows-1252/CP850 decoded as UTF-8)
                
                # Check for common mis-encoding patterns
                has_misencoded = False
                
                # Pattern 1: UTF-8 bytes decoded as Latin-1/Windows-1252
                # Examples: "é" (should be "é"), "è" (should be "è"), "à " (should be "à")
                if 'Ã' in text:
                    has_misencoded = True
                    try:
                        # Try to fix: encode as Latin-1 (preserves bytes) then decode as UTF-8
                        text = text.encode('latin1', errors='ignore').decode('utf-8', errors='replace')
                    except:
                        pass
                
                # Pattern 2: Windows-1252/CP850 characters that look wrong
                # If we see characters that are typical of Windows encodings but displayed wrong
                # Try to re-encode and decode properly
                if not has_misencoded:
                    # Check if text contains characters that suggest Windows encoding issues
                    # Common Windows-1252 characters that might be problematic: é, è, à, ç, etc.
                    # If they appear as single bytes that are invalid UTF-8, we need to fix them
                    try:
                        # Try encoding as Windows-1252 then decoding as UTF-8
                        # This handles cases where Windows-1252 text was decoded as something else
                        text_bytes = text.encode('latin1', errors='ignore')
                        # Try Windows-1252 first
                        try:
                            text = text_bytes.decode('windows-1252', errors='replace')
                        except:
                            # Try CP850
                            try:
                                text = text_bytes.decode('cp850', errors='replace')
                            except:
                                # Keep original
                                pass
                    except:
                        pass
                
                # Remove null bytes
                if '\x00' in text:
                    text = text.replace('\x00', '')
                
                # Remove other control characters that might cause issues
                text = ''.join(char for char in text if ord(char) >= 32 or char in '\n\r\t')
                
        except Exception:
            # If all else fails, just return the text as-is
            pass
        
        return text
    
    def _execute_cmd(self, command: str, description: str = None) -> str:
        """Execute a command and return output"""
        if not command:
            return ""
        try:
            if description:
                print_info(f"[*] {description}")
            output = self.cmd_execute(command)
            if output:
                # Fix encoding issues
                output = self._fix_encoding(output.strip())
            return output if output else ""
        except Exception as e:
            if description:
                print_warning(f"    Failed: {str(e)}")
            return ""
    
    def _gather_system_info(self):
        """Gather basic system information"""
        print_info("=" * 70)
        print_info("System Information")
        print_info("=" * 70)
        
        # Get system info via Meterpreter sysinfo
        print_status("Collecting system information...")
        sysinfo = self._execute_meterpreter_cmd("sysinfo")
        if sysinfo:
            print_info(sysinfo)
        else:
            # Fallback to individual commands
            hostname = self._execute_windows_command("hostname")
            os_info = self._execute_windows_command("ver")
            arch = self._execute_windows_command("wmic os get osarchitecture /value")
            
            if hostname:
                print_info(f"Hostname: {hostname}")
            if os_info:
                print_info(f"OS Version: {os_info}")
            if arch:
                print_info(f"Architecture: {arch}")
        
        print_info("")
    
    def _gather_user_info(self):
        """Gather user and privilege information"""
        print_info("=" * 70)
        print_info("User Information")
        print_info("=" * 70)
        
        # Current user
        print_status("Getting current user...")
        user = self._execute_meterpreter_cmd("getuid")
        if user:
            print_info(f"Current User: {user}")
        else:
            user = self._execute_windows_command("whoami")
            if user:
                print_info(f"Current User: {user}")
        
        # User groups
        print_status("Enumerating user groups...")
        groups = self._execute_windows_command("whoami /groups")
        if groups:
            print_info("User Groups:")
            for line in groups.split('\n')[:10]:  # Show first 10 lines
                if line.strip():
                    print_info(f"  {line}")
        
        # Privileges
        print_status("Enumerating privileges...")
        privs = self._execute_windows_command("whoami /priv")
        if privs:
            print_info("Privileges:")
            for line in privs.split('\n')[:15]:
                if line.strip():
                    print_info(f"  {line}")
        
        print_info("")
    
    def _gather_process_info(self):
        """Gather process information"""
        print_info("=" * 70)
        print_info("Process Information")
        print_info("=" * 70)
        
        # Current process
        print_status("Getting current process ID...")
        pid = self._execute_meterpreter_cmd("getpid")
        if pid:
            print_info(f"Current PID: {pid}")
        else:
            pid = self._execute_windows_command("powershell -NoLogo -NoProfile -Command \"$PID\"")
            if pid:
                print_info(f"Current PID: {pid}")
        
        # List processes
        print_status("Enumerating running processes...")
        processes = self._execute_meterpreter_cmd("ps")
        if processes:
            # Show first 20 lines
            lines = processes.split('\n')[:20]
            for line in lines:
                if line.strip():
                    print_info(f"  {line}")
            if len(processes.split('\n')) > 20:
                print_info(f"  ... ({len(processes.split('\n')) - 20} more processes)")
        else:
            # Fallback
            ps_list = self._execute_windows_command("tasklist /v")
            if ps_list:
                lines = ps_list.split('\n')[:15]
                for line in lines:
                    if line.strip():
                        print_info(f"  {line}")
        
        print_info("")
    
    def _gather_network_info(self):
        """Gather network configuration"""
        print_info("=" * 70)
        print_info("Network Configuration")
        print_info("=" * 70)
        
        # IP configuration
        print_status("Gathering network configuration...")
        ipconfig = self._execute_windows_command("ipconfig /all")
        if ipconfig:
            lines = ipconfig.split('\n')[:30]  # Show first 30 lines
            for line in lines:
                if line.strip():
                    print_info(f"  {line}")
        
        # Active connections
        print_status("Enumerating network connections...")
        netstat = self._execute_windows_command("netstat -ano")
        if netstat:
            lines = netstat.split('\n')[:20]
            for line in lines:
                if line.strip():
                    print_info(f"  {line}")
        
        print_info("")
    
    def _gather_service_info(self):
        """Gather Windows services information"""
        print_info("=" * 70)
        print_info("Windows Services")
        print_info("=" * 70)
        
        # List services
        print_status("Enumerating Windows services...")
        services = self._execute_windows_command("sc query state= all")
        if services:
            lines = services.split('\n')[:40]  # Show first 40 lines
            for line in lines:
                if line.strip():
                    print_info(f"  {line}")
        
        print_info("")
    
    def _gather_security_info(self):
        """Gather security-related information"""
        print_info("=" * 70)
        print_info("Security Information")
        print_info("=" * 70)
        
        # UAC status
        print_status("Checking UAC status...")
        uac = self._execute_windows_command("reg query HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System /v EnableLUA")
        if uac:
            print_info("UAC Configuration:")
            for line in uac.split('\n'):
                if line.strip() and 'EnableLUA' in line:
                    print_info(f"  {line}")
        
        # Password policy
        print_status("Checking password policy...")
        pass_policy = self._execute_windows_command("net accounts")
        if pass_policy:
            print_info("Password Policy:")
            for line in pass_policy.split('\n'):
                if line.strip():
                    print_info(f"  {line}")
        
        # Firewall status
        print_status("Checking firewall status...")
        firewall = self._execute_windows_command("netsh advfirewall show allprofiles state")
        if firewall:
            print_info("Firewall Status:")
            for line in firewall.split('\n'):
                line = line.strip()
                if line:
                    # Fix encoding for firewall output
                    line = self._fix_encoding(line)
                    print_info(f"  {line}")
        
        print_info("")
    
    def _gather_environment_info(self):
        """Gather environment variables"""
        print_info("=" * 70)
        print_info("Environment Variables")
        print_info("=" * 70)
        
        print_status("Gathering environment variables...")
        env = self._execute_windows_command("set")
        if env:
            # Show important environment variables
            important_vars = ['PATH', 'USERNAME', 'USERPROFILE', 'COMPUTERNAME', 
                            'SYSTEMROOT', 'TEMP', 'TMP', 'PROGRAMFILES', 'PROGRAMDATA']
            lines = env.split('\n')
            for line in lines:
                if any(var in line for var in important_vars):
                    print_info(f"  {line}")
        
        print_info("")
    
    def _gather_disk_info(self):
        """Gather disk information"""
        print_info("=" * 70)
        print_info("Disk Information")
        print_info("=" * 70)
        
        # Disk usage - use a better command that gives formatted output
        print_status("Gathering disk information...")
        disk = self._execute_windows_command("wmic logicaldisk get size,freespace,caption,volumename")
        if disk:
            lines = disk.split('\n')
            # Skip header line
            header_found = False
            for line in lines:
                line = line.strip()
                if not line:
                    continue
                
                # Skip header
                if 'Caption' in line and 'Size' in line:
                    header_found = True
                    continue
                
                if not header_found:
                    continue
                
                # Parse the line: Caption, FreeSpace, Size, VolumeName
                # Format: C:  510905020416  59336007680  Acer
                parts = re.split(r'\s+', line)
                if len(parts) >= 3:
                    drive = parts[0]
                    try:
                        # Try to parse size and freespace
                        # The order might vary, so we need to identify which is which
                        # Usually: Caption, FreeSpace, Size
                        if len(parts) >= 3:
                            # Find the largest number (size) and second largest (freespace)
                            numbers = []
                            for part in parts[1:]:
                                try:
                                    num = int(part)
                                    numbers.append(num)
                                except ValueError:
                                    continue
                            
                            if len(numbers) >= 2:
                                # Sort to find size (largest) and freespace
                                numbers.sort(reverse=True)
                                size = numbers[0]
                                freespace = numbers[1]
                                
                                used = size - freespace
                                used_percent = (used / size * 100) if size > 0 else 0
                                
                                # Get volume name if available
                                volume_name = parts[-1] if len(parts) > 3 and not parts[-1].isdigit() else ""
                                
                                disk_info = f"  {drive}:"
                                if volume_name:
                                    disk_info += f" ({volume_name})"
                                disk_info += f"\n    Total: {self._format_bytes(size)}"
                                disk_info += f"\n    Free:  {self._format_bytes(freespace)}"
                                disk_info += f"\n    Used:  {self._format_bytes(used)} ({used_percent:.1f}%)"
                                print_info(disk_info)
                            else:
                                # Fallback: just show the line as-is
                                print_info(f"  {line}")
                    except (ValueError, IndexError):
                        # If parsing fails, just show the line
                        print_info(f"  {line}")
        else:
            # Fallback to simpler command
            disk_simple = self._execute_windows_command("wmic logicaldisk get caption,freespace,size")
            if disk_simple:
                for line in disk_simple.split('\n'):
                    if line.strip() and 'Caption' not in line:
                        print_info(f"  {line}")
        
        # Current directory
        print_status("Getting current directory...")
        pwd = self._execute_meterpreter_cmd("pwd")
        if pwd:
            print_info(f"\nCurrent Directory: {pwd}")
        else:
            pwd = self._execute_windows_command("cd")
            if pwd:
                print_info(f"\nCurrent Directory: {pwd}")
        
        print_info("")
    
    def run(self):
        """Run the enumeration module"""
        try:
            session_id_value = str(self.session_id)
            
            print_info("")
            print_success("Starting Windows System Enumeration...")
            print_info("")
            
            # Gather all information
            self._gather_system_info()
            self._gather_user_info()
            self._gather_process_info()
            self._gather_network_info()
            self._gather_service_info()
            self._gather_security_info()
            self._gather_environment_info()
            self._gather_disk_info()
            
            print_info("=" * 70)
            print_success("Windows System Enumeration Complete")
            print_info("=" * 70)
            
            return True
            
        except ProcedureError as e:
            raise e
        except Exception as e:
            raise ProcedureError(FailureType.Unknown, f"Enumeration error: {str(e)}")

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

02 Aug 2026 20:51Current
5.8Medium risk
Vulners AI Score5.8
4