Dominando PowerShell para Ciberseguridad y Automatización
¡Qué tal hackers! Bienvenidos a un nuevo artículo.
En esta ocasión exploraremos el shell y lenguaje de scripting PowerShell, una herramienta imprescindible para cualquier profesional de TI y entusiasta de la ciberseguridad.
En el mundo de la administración de sistemas, la automatización de tareas y la seguridad informática, aprender PowerShell se ha convertido en una habilidad esencial para cualquier profesional de TI. PowerShell es una poderosa herramienta de línea de comandos y lenguaje de scripting que no solo permite realizar tareas complejas de manera más eficiente, como la administración de servidores o la automatización de procesos repetitivos, sino que también es un recurso clave en el ámbito del pentesting y la ciberseguridad.
En el contexto de la ciberseguridad, PowerShell es invaluable para realizar auditorías, identificar vulnerabilidades y ejecutar un pentest. Su capacidad para interactuar directamente con el sistema operativo, acceder a configuraciones, manipular datos y ejecutar comandos avanzados lo convierte en una herramienta ideal tanto para administradores de sistemas que buscan fortalecer sus defensas como para expertos en seguridad que necesitan evaluar la resistencia de un entorno ante posibles ataques. De hecho, PowerShell es ampliamente utilizado en simulaciones de ataques (red teaming), ya que ofrece un acceso profundo a los sistemas Windows, facilitando tareas como la enumeración de usuarios, la extracción de información sensible y la ejecución de scripts avanzados.
En esta serie de artículos, exploraremos en detalle las distintas funcionalidades de PowerShell, comenzando desde lo más básico para que puedas familiarizarte con sus comandos y conceptos fundamentales.
Mi intención es compartir lo que aprendo a medida que profundizo en el tema, con el objetivo de que podamos aprender juntos. A través de ejemplos prácticos, te guiaré paso a paso para que comprendas de manera clara y aplicable cada concepto.
Cmdlet
En primer lugar hablaremos de los Cmdlets. Un cmdlet podemos definirlo como un comando ligero que realiza una tarea específica en el entorno de PowerShell. Estos comandos están diseñados para ser simples, modulares y altamente reutilizables. A continuación, desglosamos la anatomía de un cmdlet para entender cómo se estructura y cómo funcionan.
Estructura básica de un cmdlet
La sintaxis básica de un cmdlet sigue el formato:
<Verbo-Sustantivo> [-Parámetros] [ValoresOpcionales]
Verbo-Sustantivo
El Verbo representa la acción que realizará el cmdlet. PowerShell utiliza un conjunto estándar de verbos aprobados (por ejemplo, Get, Set, New, Remove) para garantizar consistencia.
Ejemplo: Get (obtener), Set (establecer), Remove (eliminar).
Por su parte, el Sustantivo describe el objeto sobre el que actúa el verbo.
Ejemplo: Process (procesos), Service (servicios), Item (elemento de un sistema de archivos).
Por ejemplo, un cmdlet completo sería el siguiente:
Get-Process
Este cmdlet obtiene información sobre los procesos en ejecución.
Parámetros
Los parámetros son opciones que proporcionan más detalles o modifican el comportamiento del cmdlet.
- Obligatorios: Algunos cmdlets requieren ciertos parámetros para funcionar.
- Opcionales: Otros parámetros son opcionales y ajustan los resultados o el alcance.
- Alias: Algunos parámetros tienen alias (abreviaciones).
Ejemplo:
Get-Process -Name "notepad"

En este caso, -Name es un parámetro que especifica el nombre del proceso que queremos obtener.
Debemos tener en cuenta, que si no existe un proceso con el nombre notepad lanzará un error.
Valores devueltos
Un cmdlet generalmente devuelve un objeto o un conjunto de objetos como salida. PowerShell trabaja con objetos, no con texto, lo que facilita la manipulación de datos en secuencias de comandos.
Ejemplo:
Get-Process | Select-Object Name, CPU
Get-Process: Devuelve todos los procesos en ejecución.Select-Object: Filtra las propiedadesNameyCPUde los objetos devueltos.
Ciclo de vida de un cmdlet
- Entrada: Los cmdlets reciben datos a tráves de parámetros o mediante un pipeline
- Procesamiento: Ejecutan la lógica definida (ejemplo: buscar, modificar, o eliminar datos).
- Salida: Devuelven objetos al pipeline, que pueden ser procesados por otros cmdlets.
Ejemplo con pipeline:
Get-Service | Where-Object {$_.Status -eq "Running"}
Get-Service: Lista los serviciosWhere-Object: Filtra solo aquellos con estado “Running”.
Comentarios
Al igual que en muchos lenguajes de programación, PowerShell permite el uso de comentarios.
Los comentarios son esecnciales para documentar scripts, describir funciones y facilitar la comprensión del código, tanto para el propio autor como para otros usuarios. PowerShell ofrece dos formas principales de agregar comentarios.
La primera de las formas, es utilizando los llamados comentarios en linea, los cuales se utilizan para agregar una breve descripción o explicación en una sola linea.
Para agregar un comentario de este estilo, se utiliza el carácter # (hash).
Por ejemplo:
# Es es un comentario de una sola línea
echo "Hello World!"
La segunda forma es utilizando comentarios de varias lineas o llamados también comentarios de bloque. Este estilo de comentarios, se emplena para describir explicaciones extensas o documentar bloques de código.
Por ejemplo:
<#
Este es un comentario en bloque
o también llamado comentario de varias
lineas.
Podemos utilizarlo para describir scripts describir explicaciones extensas o documentar bloques de código.
#>
echo "Hello World!"
Por ultimo, podemos agregar otro tipo de comentarios que es muy util para documentar nuestras funciones o scripts en PowerShell.
Por ejemplo:
<#
.SYNOPSIS
Describe brevemente qué hace la función.
.DESCRIPTION
Explica más a fondo el propósito y cómo funciona.
.PARAMETER nombre
Describe el parámetro 'nombre'.
.EXAMPLE
Describe un ejemplo de uso:
Get-Saludo -nombre "Dean"
#>
function Get-Saludo {
param (
[string]$nombre
)
echo "Hi, $nombre"
}
Variables
Ahora toca hablar de las variables. Para lo que debemos definir en primer lugar qué es una variable.
Cuando hablamos de una variable en programación, nos referimos a un espacio de almacenamiento que permite guardar datos que pueden cambiar durante la ejecución de un programa. Cada variable tiene un nombre único y un tipo de dato asociado (como por ejemplo, números, texto, etc), lo que permite manipular esos valores en diversas operaciones a lo largo del código.
Lo primero que aprenderemos será a definir una variable. Para definir una variable en PowerShell, debemos utilizar el simbolo $ seguido del nombre de la variable.
$name = "Dean"
$age = 32
Es importante tener en cuenta que el nombre de la variable, es el identificador de esta. Puede ser cualquier nombre valido, excluyendo espacios y que no debe comenzar con una letra o guion bajo.
Como mencionamos en la definición de variable, además de un nombre que las identifica, las variables tiene asociado un tipo de variable. En PowerShell, las vairables pueden contener diferentes tipos de datos.
Números
Si queremos definir una variable numerica (Integer, Float, Decimal) podemos hacerlo de la siguiente manera:
$number = 10
$decimal = 13.51
Podemos observar, que a diferencia de otros lenguajes de programación en PowerShell no es necesario indicar de forma explicita el tipo de dato, ya que este se determina en base al valor asignado.

Cadenas
Por otra parte tenemos el tipo de dato cadena de texto (string), el cual almacena secuencias de caracteres. Podemos utilizar tanto comillas dobles como simples.
$name = "Sam"

Como las cadenas son una secuencia de caracteres, podemos acceder a los caracteres individuales/
Supongamos que tenemos la siguiente variable:
$string = "PowerShell"
Si queremos obtener el primer caracter (letra P) lo haremos de la siguiente manera:
echo $string[0]

El indice 0 (cero), representa el primer valor, en este caso, la letra P.
El segundo valor, letra o se encuentra en el indice 1.
echo $string[1]

El ultimo caracter letra l se encuentra en el indice 9.
echo $string[9]

También podemos obtener un slice o una parte de la cadena.

Si queremos conocer la cantidad de caracteres que tiene la cadena, podemos utilizar la propiedad Length.
echo $string.Length

Booleanos
Este tipo de dato almacena valores True o False.
$isActive = $true
Es importante destacar el valor asignado, el cual es $true y no true. Ya que si asignamos el valor true obtendremos un error.

Las variables $true y $false, son consideradas variables especiales y representan los valores booleanos.
Si queremos conocer el tipo de dato de una variable, podemos utilizar el método GetType:
$number.GetType()
$decimal.GetType()
$name.GetType()
$isActive.GetType()

Char
Si queremos guardar un solo caracter en una variable y que sea considerada como char, podemos hacerlo de la siguiente forma:
$char_A = [char]'A'

Casteo de Tipos
Como mencionamos anteriormente, PowerShell no es un lenguaje de tipado estricto, lo que significa que no es necesario definir explícitamente el tipo de un objeto al crear uno. Esto proporciona flexibilidad, ya que puedes convertir fácilmente entre diferentes tipos de datos, como de cadenas a números, de cadenas a fechas, o entre otros tipos compatibles.
En PowerShell, todo es un objeto. Sin embargo, no tienes que especificar de antemano el tipo exacto de objeto que deseas utilizar; PowerShell maneja automáticamente las conversiones y la creación de objetos según sea necesario, lo que facilita la manipulación de datos de manera más fluida y dinámica.
El casteo de tipos en PowerShell se refiere al proceso de convertir un valor de un tipo de dato a otro, como de una cadena de texto a un número o viceversa.
Existen dos tipos de casteo, el casteo implícito, el cual maneja de forma automática algunas conversiones de tipo en función del context, como convertir de un número a una cadena si se concatena con texto. Por otra parte, existe el casteo explícito, el cual permite convertir un tipo de dato de forma explícita utilizando el operador de tipo [type] o el cmdlet [convert].
Casteo explícito usando [type]
Sintaxis:
[type]$value
Convertir de cadena a entero
$stringValue = "2025"
$intValue = [int]$stringValue

Convertir de cadena a flotante
$stringValue = "30.55"
$floatValue = [float]$stringValue

Convertir de número a cadena
$number = 1234
$stringValue = [string]$number

Convertir de número a boolean
$intValue = 1
$boolValue = [bool]$intValue

Convertir a un tipo de fecha
$dateString = "2025-03-01"
$date = [datetime]$dateString

Cmdlet [Convert]
Convertir a un valor booleano usando [Convert]::ToBoolean.
$stringValue = "True"
$boolValue = [Convert]::ToBoolean($value)

Convertir un número a cadena usando [Convert]::ToString
$intValue = 2025
$stringValue = [Convert]::ToString($value)

Cosas a considerar sobre el casteo de tipos
Si intentas hacer una conversión que no es válida (por ejemplo, convertir una cadena de texto que no puede representarse como un número), PowerShell lanzará un error.
Por ejemplo, si intetamos realizar la siguiente conversión:
$stringValue = "xyz"
$intValue = [int]$string

Algunas conversiones son más fáciles que otras. Por ejemplo, convertir entre tipos numéricos (como de int a float) es sencillo, pero convertir texto a número solo funciona si el texto tiene un formato numérico válido.

Los valores null se pueden convertir a cualquier tipo sin errores, pero al convertirlos a números o booleanos, se asigna un valor predeterminado (0 para números, False para booleanos).

Ahora que comprendemos cómo definir variables y manipular los diferentes tipos de datos, exploraremos las operaciones que se pueden realizar con las variables.
Condicionales
En PowerShell, podemos utilizar las estructuras condicionales para controlar el flujo de la aplicación, es decir, ejecutar bloques de código basados en la evaluación de una expresión booleana. Estas condicionales permiten tomar decisiones dentro de un script o línea de comandos dependiendo de ciertas condiciones. Existen principalmente tres tipos de estructuras condicionales en PowerShell: if, else y elseif.
Estructura condicional if
La estructura condicional if ejecuta un bloque de código si la condicion que evalúa es verdadera. La sintaxos es la siguiente:
if ( condición ) {
# Aquí va el bloque de código a ejecutar si la condición se cumple
}
Ejemplo:
$age = 18
if ($age -ge 18) {
Echo "Eres mayor de edad."
}

Estructura condicional else
La estructura condicional else se usa en conjunto con if para ejecutar un bloque de código cuando la condición evaluada en el if es falsa. Su sintaxis es la siguiente:
if ( condición ) {
# Aquí va el bloque de código a ejecutar si la condición se cumple (verdadera)
} else {
# Aquí va el bloque de código a ejecutar si la condición no se cumple (falsa)
}
Ejemplo:
$age = 18
if ($age -ge 18) {
Echo "Eres mayor de edad."
} else {
Echo "Eres menor de edad."
}

Estructura condicional elseif
La estructura condicional elseif se utiliza cuando se tiene varias condiciones que se desean evaluar de manera secuencial. Si la condición if es falsa, PowerShell evalúa las condiciones del elseif en orden. Si una de ellas es verdadera, ejecuta el bloque de código correspondiente. La sintaxis es la siguiente:
if (condición1) {
# Aquí va el bloque de código a ejecutar si la condición 1 se cumple (verdadera)
} elseif (condición2) {
# Aquí va el bloque de código a ejecutar si la condición 2 se cumple (verdadera)
} else {
# Aquí va el bloque de código a ejecutar si las condiciones anteriores no se cumplen.
}
Ejemplo:
$grade = 85
if ($grade -ge 90) {
Echo "Excellent"
} elseif ($grade -ge 80) {
Echo "Very good"
} elseif ($grade -ge 70) {
Echo "Good"
} else {
Echo "You need to improve"
}

Estructura condicional switch
El condicional switch es útil cuando tienes múltiples valores posibles para una sola variable y quieres comparar contra varios valores. Su sintaxis es la siguiente:
switch ($variable) {
"value1" { # Bloque de código si la variable es igual a "value1" }
"value2" { # Bloque de código si la variable es igual a "value2" }
default { # Bloque de código si la variable no coincide con ningún valor anterior }
}
Ejemplo:
Podemos utilizar el ejemplo anterior, pero usando la condicional switch.
$grade = 75
switch ($grade) {
{$_ -ge 90} {Echo "Excellent"; break}
{$_ -ge 80} {Echo "Very good"; break}
{$_ -ge 70} {Echo "Good"; break}
default {Echo "You need to improve"}
}

En el ejemplo anterior, el switch evalúa condiciones específicas para determinar el valor de $grade. Cada case dentro del switch utiliza una expresión que compara el valor de $grade con un número determinado, y el símbolo $_ se refiere al valor actual que está siendo evaluado en cada caso. Cuando se cumple una condición, el bloque correspondiente se ejecuta y el break asegura que el switch termine, evitando que se evalúen otros casos innecesarios. Si ninguna de las condiciones anteriores es verdadera, se ejecuta el bloque default, que maneja el caso cuando el valor de $grade no cumple con las condiciones especificadas (es decir, si no es mayor o igual a 90, 80 o 70).
En este artículo hemos visto las principales estructuras de control que existen en PowerShell.
Espero que los conceptos hayan quedado claros. Si aún persisten dudas después de llegar a este punto, te sugiero considerar la posibilidad volver a leer el artículo y poner en práctica los ejemplos para reforzar tu comprensión.
Operaciones
Al igual que en otros lenguajes de programación, PowerShell permite realizar operaciones. Si bien la mayoría de los operadores son comunes en todos los lenguajes de programación, PowerShell incluye algunos operadores que difieren de los que se encuentran en otros lenguajes.
Operadores Aritméticos
| Operador | Significado |
|---|---|
+ |
Suma |
- |
Sustracción |
/ |
División |
* |
Multiplicación |
% |
Módulo |
Ejemplos

Además de estos operadores aritméticos, existen otros operadores de gran utilidad.
| Operador | Significado | Descripción |
|---|---|---|
++ |
Incremento | Aumenta en uno el valor de la variable. |
-- |
Decremento | Disminuye en uno el valor de la variable. |
+= |
Asignación de suma | Suma un valor al operador de la izquierda y asigna el resultado al operador de la izquierda. |
=- |
Asignación de resta | Resta un valor del operando de la izquierda y asigna el resultado al operando de la izquierda. |
*= |
Asignación de multiplicación | Multiplica el valor del operando de la izquierda por un valor y asigna el resultado al operando de la izquierda. |
/= |
Asignación de división | Divide el operando de la izquierda por un valor y asigna el resultado al operando de la izquierda. |
%= |
Asignación de módulo | Asigna el residuo de la división al operando de la izquierda. |
Operadores relacionales
| Operador | Significado |
|---|---|
-eq |
Equal (Igual) En otros lenguajes hace referencia al simbolo ==. |
-ne |
Not-Equal (No Igual - Diferente - Distinto) En otros lenguajes el simbolo es != |
-gt |
Greater-Than (Mayor que) En otros lenguajes el simbolo es > |
-lt |
Less-Than (Menor que) En otros lenguajes es < |
-ge |
Greater-Than-Or-Equal (Mayor que o Igual que) En otros lenguajes el simbolo es >= |
-le |
Less-Than-Or-Equal (Menor que o Igual que) En otros lenguajes el sibolo es <= |
Ejemplos

Pipes
Las Tuberías (Pipes) en PowerShell o también llamadas pipes, son un mecanismo poderoso para encadenar cmdlets y permite que la salida de un comando se utilice como la entrda de otro cmdlet. Esto permite gran flexibilidad y modularidad en la manipulación de datos.
En PowerShell, la tubería se representa con el símbolo | (una barra vertical). Su función es tomar la salida de un cmdlet y pasarla directamente como entrada de otro cmdlet, permitiendo un procesamiento secuencial de datos.
PowerShell no pasa texto plano por la tubería, sino objetos que pueden ser manipulados de manera más estructurada. Por ejemplo, el cmdlet Get-Process devuelve una lista de objetos Process, que contienen varias propiedades, como son Name, ID, CPU, entre otras.
A su vez, las tuberías permiten realizar selección y filtrado de datos. Cmdlets como Select-Object y Where-Object son comúnmente usados en tuberías para filtrar o seleccionar propiedades específicas de los objetos que se están pasando a través de la tubería.
Ejemplo

Al momento de utilizar las tuberías en PowerShell debemos tener algunas consideraciones imporantes.
En primer lugar, como ya mencionamos anteriormente las tuberías pasan objetos entre los cmdlets, no texto plano. Esto quiere decir que podemos usar objetos en lugar de solo manipular cadenas de texto.
En cuanto al simbolo $_, representa el objeto actual en el flujo de la tubería. Se utiliza dentro de los Cmdlets como ForEach-Object y Where-Object para acceder a las propiedades de los objetos en la tubería.
Por ultimo, podemos destacar la eficiencia de las tuberías. PowerShell permite lo que se llama el “procesamiento perezoso” (lazy evaluation) a través de las tuberías. Esto significa que los cmdlets de la tubería no procesan todos los objetos a la vez, sino que se procesan a medida que son necesarios. Esto mejora el rendimiento en el manejo de grandes volúmenes de datos.
Anteriormente dijimos que PowerShell maneja objetos de forma predeterminada, pero también podemos utilizar las tuberías con cmdlets que generan texto, como es el caso de Echo o Write-Output. Esto nos puede servir en caso de querer realizar operaciones de texto.
Ejemplo
1..10 | Where-Object { $_ % 2 -eq 0 }

1..10 genera una secuencia de números del 1 al 10, lo que en PowerShell se utiliza para crear un rango. A continuación, mediante Where-Object { $_ % 2 -eq 0 } filtramos esta secuencia para obtener solo los números pares (aquellos divisibles por 2 sin dejar residuo). Es importante recordar que la variable $_ hace referencia al objeto actual en el flujo de la tubería. La expresión $_ % 2 -eq 0 verifica si el número actual ($_) es divisible por 2. Si la condición se cumple, el número se pasa a la siguiente etapa de la tubería.
El cmdlet Where-Object se utiliza para filtrar objetos basados en condiciones específicas. Se emplea dentro de un pipeline para seleccionar solo los elementos que cumplen un criterio determinado.
La sintaxis básica es la siguiente:
Where-Object { condición }
La condición dentro de las llaves puede ser cualquier expresión que devuelve un valor booleano (verdadero o falso). Los objetos que cumplan con la condición se pasarán al siguiente comando del pipeline.
Ejemplos
1..10 | Where-Object { $_ -gt 5 }

Get-ChildItem files | Where-Object { $_.Extension -eq ".txt" }

Alias
En PowerShell, un alias es un nombre corto o alternativo para un cmdlet, una función, un script u otro comando. Los alias facilitan escribir y recordar comandos, especialemente para tareas comunes.
Veamos un simple ejemplo.
El cmdlet Get-ChildItem se utiliza para listar archivos y directorios. Su alias más corto es ls.
Para obtener los alias de un cmdlet, podemos usar el siguiente comando:
Get-Alias -Definition Get-ChildItem

Uso del cmdlet completo:
Get-ChildItem

Usando el alias
ls

Ambos comandos producen el mismo resultado porque ls es un alias de Get-ChildItem.
También, podemos ver que existe alias gci:

Otro ejemplo de alias son Echo y Write, que corresponden al cmdlet Write-Output. Este cmdlet envía datos a la salida estándar (por defecto, la pantalla), pero también permite redirigir la salida. Esto significa que el resultado de un comando puede usarse como entrada para otro comando o asignarse directamente a una variable.

Alias personalizado
Además de los alias integrados, también podemos crear nuestros propios alias para aquellos comandos que usamos con frecuencia usando el cmdlet Set-Alias.
Por ejemplo, podemos crear un alias del comando Select-String llamado buscar:
Set-Alias buscar Select-String
Podemos usar el alias para buscar “error” en todos los archivos .log
buscar "error" *.log

Los alias son prácticos, pero no se guardan automáticamente entre sesiones, a menos que los agregues a tu perfil de PowerShell.
Para que el alias persista entre sesiones, lo podemos agregar a nuestro perfil de PowerShell de la siguiente manera:
notepad $PROFILE
Agregamos el alias al archivo:
Set-Alias buscar Select-String
De este modo, siempre estará disponible al iniciar PowerShell.
Espero que los conceptos hayan quedado claros. Si aún persisten dudas después de llegar a este punto, te sugiero considerar la posibilidad de revisitar el artículo para reforzar tu comprensión.
¡Gracias por tu lectura!
¡Happy Hacking!
Referencias
- https://learn.microsoft.com/es-es/PowerShell/scripting/PowerShell-commands?view=PowerShell-7.4
- https://learn.microsoft.com/es-es/PowerShell/scripting/discover-PowerShell?view=PowerShell-7.4#PowerShell-cmdlets
- https://learn.microsoft.com/en-us/PowerShell/scripting/developer/cmdlet/approved-verbs-for-windows-PowerShell-commands?view=PowerShell-7.4&ref=benheater.com
- https://learn.microsoft.com/es-es/PowerShell/module/microsoft.PowerShell.core/about/about_comment_based_help?view=PowerShell-7.4
- Everything you wanted to know about the if statement
- Everything you ever wanted to know about the switch statement
- about_Arithmetic_Operators
- about_Pipelines
- https://learn.microsoft.com/en-us/PowerShell/module/microsoft.PowerShell.core/about/about_aliases?view=PowerShell-7.4