Administración de sistemas Windows | unfantasmaenelsistema.com
Si CMD es el cuchillo del ejército suizo de Windows, PowerShell es el laboratorio completo. Mientras que CMD trabaja con texto plano, PowerShell trabaja con objetos .NET: cada comando devuelve objetos con propiedades tipadas que puedes filtrar, ordenar, agrupar, transformar y exportar con una precisión que CMD simplemente no puede igualar. Es la herramienta de administración por excelencia en Windows moderno y, no por casualidad, también la más usada en ataques avanzados.
Cada cmdlet de este artículo incluye la imagen visual del bloque completo con todos los ejemplos y, debajo, solo los comandos ejecutables para copiar directamente en tu terminal sin los comentarios explicativos.


PowerShell vs CMD: por qué los objetos cambian todo
La diferencia fundamental entre CMD y PowerShell no es cosmética. CMD produce texto: para extraer información de su output hay que parsear strings frágiles. PowerShell produce objetos con propiedades nombradas y tipadas: puedes acceder a cualquier campo por nombre, comparar valores numéricos, filtrar por condición compleja, y encadenar operaciones sin perder estructura.

Los 10 cmdlets: resumen

1. Get-Process — gestión de procesos con análisis avanzado
Get-Process devuelve objetos System.Diagnostics.Process con propiedades ricas: ruta del ejecutable, empresa firmante, uso de CPU, RAM, handles abiertos, tiempo de inicio… Esto permite hacer análisis que con CMD y tasklist son prácticamente imposibles, como detectar procesos sin empresa firmante, calcular el consumo de RAM en MB de forma legible, o filtrar por cualquier combinación de condiciones.

Get-Process |
Get-Process -Name powershell |
Get-Process -Name svchost* |
Get-Process | Select-Object Name, Id, Path, Company, Description | Format-Table |
Get-Process | Where-Object {$_.Path -eq $null} | Select-Object Name, Id |
Get-Process | Sort-Object CPU -Descending | Select-Object -First 15 | Select-Object Name, Id, CPU, WorkingSet | Format-Table |
Stop-Process -Name notepad -Force |
Stop-Process -Id 4821 -Force |
Get-Process | Select-Object Name, Id, Path, Company | Export-Csv procesos.csv -NoTypeInformation |
▲ Comandos copiables

2. Get-NetTCPConnection — conexiones de red con resolución de proceso
Get-NetTCPConnection es el netstat de PowerShell, pero devuelve objetos. La ventaja práctica es enorme: puedes cruzar directamente con Get-Process para resolver el nombre del proceso propietario de cada conexión, filtrar por dirección remota con expresiones regulares, y exportar a CSV en una sola línea. La combinación de ambos cmdlets en un pipeline es una de las herramientas de detección de backdoors más potentes disponibles de forma nativa en Windows.

Get-NetTCPConnection |
Get-NetTCPConnection -State Established |
Get-NetTCPConnection -State Listen |
Get-NetTCPConnection -State Established | Select-Object LocalAddress, LocalPort, RemoteAddress, RemotePort, @{Name=’Proceso’;Expression={(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).Name}}, OwningProcess | Format-Table -AutoSize |
Get-NetTCPConnection -State Established | Where-Object {$_.RemoteAddress -notmatch ‘^(192\.168|10\.|172\.1[6-9]|127\.)’} | Select-Object RemoteAddress, RemotePort, LocalPort, @{Name=’Proceso’;Expression={(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).Name}} |
Get-NetTCPConnection -RemotePort 4444 |
Get-NetTCPConnection -State Listen | Select-Object LocalPort, @{Name=’Proceso’;Expression={(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).Name}} | Sort-Object LocalPort | Format-Table |
Get-NetTCPConnection | Export-Csv conexiones.csv -NoTypeInformation |
▲ Comandos copiables
3. Get-LocalUser + Get-LocalGroupMember — auditoría de cuentas y privilegios
Get-LocalUser proporciona información detallada sobre cada cuenta del sistema: si está activa, cuándo fue el último inicio de sesión, si la contraseña caduca, cuándo se estableció por última vez. Get-LocalGroupMember permite auditar la membresía de cualquier grupo local. En una auditoría de seguridad, verificar el grupo Administradores es siempre el primer paso: cualquier cuenta no reconocida ahí es una señal de alarma inmediata.

Get-LocalUser |
Get-LocalUser | Select-Object Name, Enabled, LastLogon, PasswordExpires, PasswordRequired, PasswordLastSet | Format-Table |
Get-LocalUser | Where-Object {$_.Enabled -eq $true} |
Get-LocalUser | Where-Object {$_.LastLogon -eq $null} |
New-LocalUser -Name ‘usuario_nuevo’ -Password (ConvertTo-SecureString ‘Passw0rd!’ -AsPlainText -Force) |
Disable-LocalUser -Name ‘Administrador’ |
Get-LocalGroup |
Get-LocalGroupMember -Group ‘Administradores’ |
Add-LocalGroupMember -Group ‘Administradores’ -Member ‘usuario_nuevo’ |
Remove-LocalGroupMember -Group ‘Administradores’ -Member ‘usuario_nuevo’ |
▲ Comandos copiables
4. Get-Service — auditoría de servicios de Windows
Get-Service lista los servicios del sistema con su estado actual, pero tiene una limitación: no muestra la ruta del ejecutable. Para auditoría de seguridad necesitamos Get-CimInstance Win32_Service, que devuelve la ruta completa del ejecutable (PathName) y el tipo de inicio. Cualquier servicio con inicio automático cuya ruta apunte fuera de System32 o Program Files merece investigación inmediata.

Get-Service |
Get-Service | Where-Object {$_.Status -eq ‘Running’} |
Get-Service | Where-Object {$_.Status -eq ‘Stopped’} |
Get-Service -Name wuauserv | Select-Object * |
Get-CimInstance Win32_Service | Select-Object Name, StartMode, PathName, State | Format-Table -AutoSize |
Get-CimInstance Win32_Service | Where-Object {$_.StartMode -eq ‘Auto’ -and $_.PathName -notmatch ‘System32|SysWOW64’} | Select-Object Name, PathName, State |
Start-Service -Name wuauserv |
Stop-Service -Name wuauserv -Force |
Set-Service -Name wuauserv -StartupType Disabled |
Set-Service -Name wuauserv -StartupType Automatic |
Get-CimInstance Win32_Service | Export-Csv servicios.csv -NoTypeInformation |
▲ Comandos copiables
5. Get-ItemProperty — registro de Windows desde PowerShell
PowerShell trata el registro de Windows como un sistema de archivos a través del proveedor Registry:. Puedes navegar por el registro con los mismos cmdlets que usas para archivos (Get-ChildItem, Get-ItemProperty, Set-ItemProperty), y combinarlos con el pipeline para búsquedas complejas que serían muy tediosas con el comando reg de CMD.

Get-ItemProperty -Path ‘HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run’ |
Get-ItemProperty ‘HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run’ |
Get-ItemProperty ‘HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run’ |
Get-ItemProperty ‘HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce’ |
Get-ItemProperty ‘HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce’ |
Get-CimInstance Win32_Service | Where-Object {$_.ImagePath -notmatch ‘System32|SysWOW64’} | Select-Object Name, ImagePath |
Set-ItemProperty -Path ‘HKCU:\SOFTWARE\MiApp’ -Name ‘ConfigKey’ -Value ‘valor’ |
New-Item -Path ‘HKCU:\SOFTWARE\MiApp’ -Force |
Remove-ItemProperty -Path ‘HKCU:\SOFTWARE\MiApp’ -Name ‘ConfigKey’ |
reg export ‘HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run’ backup_run.reg |
▲ Comandos copiables
6. Get-Acl + Set-Acl — permisos NTFS con pipeline
Get-Acl devuelve un objeto FileSecurity con la lista de control de acceso (ACL) de cualquier archivo o carpeta. Lo que lo hace especialmente potente es que puede combinarse con Get-ChildItem para auditar permisos de directorios completos en una sola operación: un nivel de análisis que en la interfaz gráfica requeriría revisar cada archivo manualmente.

Get-Acl C:\Windows\System32\cmd.exe | Format-List |
(Get-Acl C:\Windows\System32\cmd.exe).Access | Select-Object IdentityReference, FileSystemRights, AccessControlType |
Get-ChildItem C:\carpeta -Recurse | Get-Acl | Select-Object Path, Owner | Format-Table |
$acl = Get-Acl C:\archivo_fuente.txt |
Set-Acl -Path C:\archivo_destino.txt -AclObject $acl |
$acl = Get-Acl C:\datos\informe.txt |
$permiso = New-Object System.Security.AccessControl.FileSystemAccessRule(‘DOMINIO\usuario’, ‘Read’, ‘Allow’) |
$acl.AddAccessRule($permiso) |
Set-Acl -Path C:\datos\informe.txt -AclObject $acl |
▲ Comandos copiables
7. Invoke-WebRequest + Invoke-RestMethod — interacción con la web y APIs
Invoke-WebRequest es el curl de PowerShell: permite hacer cualquier tipo de petición HTTP/S, enviar datos, gestionar cabeceras y cookies, y descargar archivos. Invoke-RestMethod va un paso más allá: cuando la respuesta es JSON o XML, la convierte automáticamente en objetos PowerShell, permitiendo acceder directamente a sus propiedades. Esto hace que interactuar con cualquier API REST sea trivial.

Invoke-WebRequest -Uri ‘https://ejemplo.com/archivo.zip’ -OutFile ‘C:\temp\archivo.zip’ |
iwr ‘https://ejemplo.com/archivo.zip’ -OutFile archivo.zip |
(Invoke-WebRequest -Uri ‘https://ejemplo.com’ -Method Head).Headers |
(Invoke-WebRequest -Uri ‘https://ejemplo.com’).StatusCode |
$body = @{usuario=’admin’; password=’test’} | ConvertTo-Json |
Invoke-WebRequest -Uri ‘https://api.ejemplo.com/login’ -Method Post -Body $body -ContentType ‘application/json’ |
$respuesta = Invoke-RestMethod -Uri ‘https://api.ejemplo.com/usuarios’ |
$respuesta | Select-Object nombre, email, rol |
(Invoke-RestMethod ‘https://api.ipify.org?format=json’).ip |
Invoke-WebRequest -Uri ‘https://ejemplo.com’ -Proxy ‘http://127.0.0.1:8080’ |
Invoke-WebRequest -Uri ‘https://192.168.1.10’ -SkipCertificateCheck |
▲ Comandos copiables
8. Get-WinEvent — logs del Visor de eventos con filtros avanzados
Get-WinEvent es la forma moderna de consultar el Visor de eventos de Windows desde PowerShell. Su parámetro -FilterHashtable permite filtrar directamente en el motor de eventos (mucho más eficiente que recuperar todos los eventos y filtrar después), especificando LogName, EventId, StartTime, EndTime y Level. Es la herramienta central del análisis forense de sistemas Windows.

Get-WinEvent -LogName Security -MaxEvents 20 |
Get-WinEvent -LogName Security -FilterHashtable @{Id=4625} -MaxEvents 50 |
Get-WinEvent -LogName Security -FilterHashtable @{Id=4624} -MaxEvents 20 |
$inicio = (Get-Date).AddDays(-7) |
Get-WinEvent -LogName Security -FilterHashtable @{Id=4625; StartTime=$inicio} |
Get-WinEvent -LogName Security -MaxEvents 1000 | Where-Object {$_.Message -match ‘usuario_sospechoso’} |
Get-WinEvent -LogName Security -FilterHashtable @{Id=4625} -MaxEvents 500 | Group-Object {$_.Properties[19].Value} | Sort-Object Count -Descending | Select-Object -First 10 Name, Count |
Get-WinEvent -LogName Security -MaxEvents 100 | Select-Object TimeCreated, Id, Message | Export-Csv eventos.csv -NoTypeInformation |
▲ Comandos copiables

9. Get-FileHash — integridad de archivos y análisis forense
Get-FileHash calcula el hash criptográfico de cualquier archivo usando SHA256, SHA512, SHA1 o MD5. En el contexto de seguridad tiene dos usos fundamentales: verificar la integridad de archivos del sistema comparando contra una baseline, y identificar malware conocido comparando el hash contra bases de datos de IOCs como VirusTotal o MalwareBazaar.

Get-FileHash C:\Windows\System32\cmd.exe |
Get-FileHash archivo.exe -Algorithm MD5 |
Get-FileHash archivo.exe -Algorithm SHA512 |
Get-FileHash C:\Windows\System32\*.dll | Select-Object Hash, Path |
Get-ChildItem C:\Windows\System32\*.exe | Get-FileHash | Export-Csv baseline_system32.csv -NoTypeInformation |
$baseline = Import-Csv baseline_system32.csv |
$actual = Get-ChildItem C:\Windows\System32\*.exe | Get-FileHash |
Compare-Object $baseline $actual -Property Hash, Path |
$hash_malware = ’44d88612fea8a8f36de82e1278abb02f’ |
(Get-FileHash archivo_sospechoso.exe -Algorithm MD5).Hash -eq $hash_malware |
Get-FileHash \\servidor\share\archivo.exe -Algorithm SHA256 |
▲ Comandos copiables
10. Where-Object + pipeline — el motor de análisis de PowerShell
El pipeline de PowerShell, centrado en Where-Object, Select-Object, Sort-Object y Group-Object, es lo que convierte PowerShell en una herramienta de análisis y no solo de administración. La capacidad de encadenar cualquier cmdlet con cualquier otro, transformando y filtrando objetos en cada paso, es lo que le da su potencia real.

Get-Process | Where-Object {$_.CPU -gt 10} |
Get-Service | Where-Object {$_.Status -eq ‘Running’} |
Get-LocalUser | Where-Object {$_.Enabled -eq $true} |
Get-Process | Select-Object Name, Id, CPU, WorkingSet |
Get-Process | Select-Object Name, @{Name=’RAM_MB’;Expression={[math]::Round($_.WorkingSet/1MB,1)}} |
Get-Process | Select-Object -First 10 |
Get-Process | Sort-Object CPU -Descending |
Get-WinEvent -LogName Security -MaxEvents 100 | Sort-Object TimeCreated |
Get-Process | Group-Object Name | Sort-Object Count -Descending |
Get-Process | Export-Csv procesos.csv -NoTypeInformation |
Get-NetTCPConnection | Export-Csv conexiones.csv -NoTypeInformation |
Get-Process | Select-Object Name, Id, CPU | ConvertTo-Json | Out-File procesos.json |
Get-Process | Out-GridView |
Get-WinEvent -LogName Security -MaxEvents 500 | Out-GridView |
▲ Comandos copiables
Bonus: pipelines avanzados combinando cmdlets
Estos ejemplos combinan múltiples cmdlets de este artículo en pipelines que resuelven tareas reales de administración y auditoría de seguridad.

Get-NetTCPConnection -State Established | Where-Object {$_.RemoteAddress -notmatch ‘^(192\.168|10\.|127\.)’} | Select-Object RemoteAddress, RemotePort, @{Name=’Proceso’;Expression={(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).Name}}, @{Name=’Ruta’;Expression={(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).Path}} |
Get-LocalGroupMember -Group ‘Administradores’ | Select-Object Name, ObjectClass, PrincipalSource |
Get-WinEvent -LogName Security -FilterHashtable @{Id=4625} -MaxEvents 1000 | Group-Object {$_.Properties[19].Value} | Sort-Object Count -Descending | Select-Object -First 10 Name, Count |
Get-CimInstance Win32_Service | Where-Object {$_.StartMode -eq ‘Auto’ -and $_.PathName -notmatch ‘System32|SysWOW64|Program Files’} | Select-Object Name, PathName, State |
‘=== PROCESOS ===’ | Out-File inventario.txt |
Get-Process | Select-Object Name,Id,Path | Format-Table | Out-File inventario.txt -Append |
‘=== RED ===’ | Out-File inventario.txt -Append |
Get-NetTCPConnection -State Established | Format-Table | Out-File inventario.txt -Append |
‘=== USUARIOS ===’ | Out-File inventario.txt -Append |
Get-LocalUser | Format-Table | Out-File inventario.txt -Append |
‘=== ADMINISTRADORES ===’ | Out-File inventario.txt -Append |
Get-LocalGroupMember -Group Administradores | Format-Table | Out-File inventario.txt -Append |
$baseline = Import-Csv baseline_system32.csv |
$actual = Get-ChildItem C:\Windows\System32\*.exe | Get-FileHash |
Compare-Object $baseline $actual -Property Hash | Where-Object {$_.SideIndicator -eq ‘=>’} |
▲ Comandos copiables
Referencia rápida

Conclusión
PowerShell ha transformado la administración de sistemas Windows de la misma forma que bash transformó la de Unix: proporcionando un entorno de scripting de primera clase directamente integrado en el sistema operativo. La diferencia con bash es que trabaja con objetos en lugar de texto, lo que lo hace más preciso pero también requiere un cambio de mentalidad.
El siguiente escalón es aprender a escribir scripts .ps1 que encadenen estas operaciones de forma automatizada: un script que genere un informe de seguridad completo del sistema, que compare la baseline de hashes contra el estado actual, o que alerte cuando aparezca un nuevo administrador local. Con los 10 cmdlets de este artículo tienes todos los bloques que necesitas para construirlos.

unfantasmaenelsistema.com | Seguridad, sistemas y todo lo que no debería funcionar (pero funciona)
