Normal view

There are new articles available, click to refresh the page.
Before yesterdayMain stream

PowerShell: Moving from Bash to PowerShell

20 October 2025 at 11:55

Welcome back, hackers!

When moving from Bash to PowerShell, people often run into difficulties simply because they do not know which tools in PowerShell serve as equivalents and how to use them. For example, I personally like Bash for its straightforward logic. If you need to grab only certain lines from a text file, you know you can call on cat and grep. But when you try to type something similar in PowerShell, it often feels like hitting a wall. You know the logic, you know it should be just a one-liner, yet you get stuck on how to actually do it. That is exactly what we are going to sort out today. 

This article serves as an addition to PowerShell for Hackers: Basics and aims to show more of PowerShell’s capabilities by mapping familiar Bash commands to their PowerShell equivalents. If you haven’t read PowerShell for Hackers: Basics, we highly recommend starting there. This guide is written for people who know the Linux command line and want practical examples for their workflows in PowerShell.

General Rules of the Game

Let’s start with the most basic thing, which is still very important, it is working with variables. In Bash, declaring a variable is as simple as writing foo=1. In PowerShell, you need to add a dollar sign: $foo=1. To print the value of a variable to the screen, you can use the universal echo or the PowerShell-specific cmdlet Write-Host. Is it longer? Definitely. But the benefit is that with Write-Host you can control the output in interesting ways:

PS > Write-Host (2,4,6,8,10,12) -Separator "->" -ForegroundColor DarkMagenta -BackgroundColor White

working with flags in powershell

This snippet will print the sequence of numbers inside the parentheses, place a -> between them, and also change both the text and the background colors. For a quick throwaway script this isn’t necessary, but for a daily report it might be quite useful.

If you need to compare something PowerShell has a full set of operators, familiar to anyone coming from Linux.

working with powershell operators

If comparison operators and logical conditions are more or less clear, let’s look at a very simple but practical example with data types. Suppose we want to measure the average response time from a website like google.com. To do this we need to send several pings and calculate the average. Here’s a short script:

Write-Host `n "Waiting for test ..."
$Avg = 0
$Site = "www.google.com"
$PingSite = Test-Connection -Count 5 $Site
$Avg = ($PingSite | Measure-Object ResponseTime -Average)
$Calc = ($Avg.Average) -as [int]
Clear-Host
Write-Host "Average response time to $Site is $Calc ms"

working with powershell variables

If we don’t cast the value to an integer, we get a floating-point number, which isn’t very convenient for this purpose.
This is one of the instances where a PowerShell command is actually stronger than the classic Linux ping. The Test-Connection cmdlet outputs structured objects that already contain response times, status, and other useful properties. That means you can pipe the results directly into tools like Measure-Object and do math on them without needing to parse text with awk or grep. In Linux, ping is text-based, so you often need extra commands to extract the numbers. PowerShell skips that step

Aliases

To make PowerShell easier to use, you can create aliases. It’s worth checking the aliases already available on your system with:

PS > Get-Alias

listing aliases

Aliases can even point to programs. For example, let’s make an alias for launching the calculator:

PS > Set-Alias -Name calc -Value calc.exe

setting a new alias in powershell

Now typing calc will start the calculator. If you want your alias to represent a command with parameters, you need to wrap it in a function:

function AL01 { Test-Connection -Count 2 google.com }
Set-Alias ping AL01

Now when you type ping, it will perform two pings to google.com. To remove an alias, use:

PS > Remove-Item alias:ping

Note, once you close PowerShell, all aliases you created this way disappear. To keep them permanently, you need to save them in your profile. PowerShell actually has four possible profiles. You can see them with:

PS > $profile | Format-List -Force

listing powershell proiflees

To check if they exist on your system:

PS > $profile | Format-List -Force | ForEach-Object { Test-Path $_ }

If the result is False, the file simply doesn’t exist. You can create it, for example, at this path:

PS > notepad.exe C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1

And add your aliases inside it:

function AL01 { Test-Connection -Count 2 google.com }
Set-Alias ping AL01

creating a powershell profile

After saving and restarting PowerShell, your aliases will load automatically.

One important note. By default, Windows blocks the execution of external scripts. This means your profile file might be ignored. To check the current policy, run:

PS > Get-ExecutionPolicy

Most likely it will return Restricted, which means all scripts are blocked. To allow your profile script to run, you need to open PowerShell as Administrator and set:

PS > Set-ExecutionPolicy Unrestricted

setting execution policy to unrestricted

After confirmation, scripts will run normally, including your profile file.

using aliases in powershell

Going Deeper

Now let’s move on to the most popular Linux tools and their PowerShell equivalents, from simple to more advanced.

cd

Navigation between directories. You can use the familiar cd alias or the cmdlet Set-Location:

PS > Set-Location Windows

This moves you to the Windows folder in the current directory. PowerShell even lets you navigate the registry the same way:

PS > Set-Location -Path "HKLM:"

PS > Set-Location -Path "HKEY_LOCAL_MACHINE\SYSTEM\Software\Microsoft\CTF"

using cd in powershell

ls

To view the contents of a directory, use ls, dir, or the cmdlet Get-ChildItem:

PS > Get-ChildItem C:\

listing files in powershell

This shows everything on the C: drive. To sort results by modification time (like ls -ltr in Linux):

PS > Get-ChildItem $env:USERPROFILE\Documents | Sort-Object -Property LastWriteTime

using sort in powershell

For recursive searches:

PS > Get-ChildItem -Path C:\ -Force -Recurse

mkdir

To create directories, use New-Item:

PS > New-Item -ItemType Directory -Name intel

Or to create a subfolder:

PS > New-Item -ItemType "directory" -Path "c:\intel\papers"

creating directories with powershell

You can even create a text file with content in one command:

PS > New-Item -Path . -Name "key.txt" -ItemType "file" -Value "HSDAF8KL"

creating files with ontent in powershell

touch

Creating files also uses New-Item:

PS > New-Item -ItemType "file" -Path "c:\temp\file.txt", "C:\intel\papers\classified.txt"

This makes two files in different folders.

cp

Copying files is done with Copy-Item:

PS > Copy-Item -Path C:\intel\classified.txt -Destination C:\important\

It also works over the network:

PS > Copy-Item -Path C:\key.txt -Destination '\\file-srv\f$\key.txt'

rm

Deleting files is Remove-Item. The dangerous rm -rf equivalent is:

PS > Remove-Item -Recurse -Force

Like in Linux, it’s one of the most dangerous commands. A single mistake can wipe entire directories. It’s a good practice to first preview what will be deleted with Get-ChildItem, or even rename files instead of deleting them to make recovery easier.

You can also delete by masks:

PS > Remove-Item *.txt

Or specific files:

PS > Remove-Item C:\dir1\records, C:\dir1\photos, C:\dir2\interrogations

find

To search for files, use Get-ChildItem with filters. For example:

PS > Get-ChildItem C:\ -Include *.exe -Recurse

This found all .exe files on C:\ but you can also limit depth:

PS > Get-ChildItem -Path "C:\Files\*.exe" -Filter "*software*" -Depth 2 -Exclude "*server*" -Recurse

Notice how flexible the filtering is. Often you don’t need regular expressions.

cat

To read files use Get-Content or gc:

PS > Get-Content -Path C:\case\script.txt

tail

To see the last ten lines of a file:

PS > Get-Content c:\logs\log.txt -TotalCount 10

To monitor in real time:

PS > Get-Content "C:\logs\log.txt" -Wait | Where { $_ -Match "Error" }

This shows new lines containing “Error” as they appear.

grep

PowerShell doesn’t have a perfect grep equivalent, but there are alternatives. To filter objects, use Where-Object.

List processes using more than 100 MB of memory:

PS > Get-Process | Where-Object { $_.WorkingSet -gt 104857600 }

using grep in powershell

For text searches, use Select-String to find the string that mentions your keyword:

PS > Select-String -Path C:\logs\*.log -Pattern "error"

Or combine with Get-Content:

PS > Get-Content -Path C:\scripts\script.txt | Select-String -Pattern "alias"

uname

To display system information:

PS > $Properties = 'Caption', 'CSName', 'Version', 'BuildType', 'OSArchitecture'; Get-CimInstance Win32_OperatingSystem | Select-Object $Properties | Format-Table -AutoSize

Longer than uname -a, but you can alias it if needed. At the end of the day, you don’t really use it much.

mkfs

To create filesystems, PowerShell has New-Volume and Format-Volume:

PS > New-Volume -StoragePoolName "CompanyData" -FriendlyName "TestVolume" -Size 10GB -ResiliencySettingName "Mirror" -FileSystem NTFS -AccessPath "M:" -ProvisioningType Fixed

Be careful, as misuse can destroy your data. Always test on a safe machine first.

ping

The classic ping equivalent is Test-Connection:

PS > Test-Connection google.com

cut

To extract only certain fields, use Select-Object. For example, to list text files in your user folder but only show names and sizes:

PS > Get-ChildItem $env:USERPROFILE -Filter "*.txt" | Select-Object -Property 'Name', 'Length'

man

The man equivalent is Get-Help:

PS > Get-Help Get-ChildItem

You can also use wildcards:

PS > Get-Help Get-*

Conclusion

As you can see, almost every Linux command has a worthy PowerShell counterpart. Some of them are less elegant or more verbose, but in return they often give you more power through structured objects and richer filtering. Bash and PowerShell approach the same problems from different angles. Bash is all about short, sharp one-liners, a language of quick hacks and piping small tools together. PowerShell takes more words to get going, but it pays you back with depth. Its cmdlets work with objects instead of plain text, which means more precision and flexibility. A job that takes three or four utilities strung together in Bash can sometimes be handled by a single cmdlet.

The transition isn’t painless. The syntax can feel verbose and the patterns unfamiliar. It looks like you’re doing more typing for the same result. In the end, it all comes down to habit and practice. PowerShell is essentially a full toolbox, while Bash is a handy pocket knife. The more you experiment and analyze, the more natural it will feel.

The post PowerShell: Moving from Bash to PowerShell first appeared on Hackers Arise.

PowerShell for Hackers – Survival Edition, Part 2: Advanced Recon

2 October 2025 at 10:46

Welcome back, aspiring hackers!

Today we’re continuing the survival sequence and taking a closer look at PowerShell as your main tool. The beauty of PowerShell is that you don’t need to memorize a massive list of commands, it’s both a toolbox and a guide. It’s designed to help you figure things out as you go, so instead of wasting time searching online you can experiment and learn directly in the shell. If you let PowerShell handle the heavy lifting, you’ll work faster and stay under the radar. The integrated survival kit that not only has the tools you need, but also shows you how to use them step by step.

We will also cover Active Directory modules and dsquery which are incredibly useful during pentests. You will learn what to run, why it matters, and what to watch for if your goal is to stay quiet and keep access.

Remember, recon comes first, actions later. If you map the terrain carefully, you minimize surprises and reduce the chance of getting kicked out. Let’s dive in!

Dsquery

dsquery is a classic Windows tool, which is simple, fast, and present on domain-managing machines or admin workstations. At a high level, dsquery talks LDAP to AD, applies filters, and returns object lists like users, computers, OUs, groups, and whatever you ask for.

On well-configured domains, dsquery runs quickly and gives structured output that’s easy to parse. It’s also convenient when you don’t want to load or rely on larger modules or tools.

It is a system binary in the sense that it’s part of the Windows AD tooling set so it is legitimate for endpoint monitoring. Defenders may not immediately flag a dsquery invocation, but broad or repetitive queries against AD can still generate logs and attract attention. Large domain enumerations, wildcard queries that return thousands of objects, or repeated use from an unusual host are all detectable. Since stealth is the goal, favor targeted queries and avoid blasting the directory with exhaustive requests. Also note, that not every machine has dsquery installed, but it’s often present on domain controllers and admin workstations. On locked-down hosts it may be absent.

Find Users

This returns user accounts both active and inactive. Useful to get the initial scope of identities to investigate. Mainly we prioritize service and admin accounts first. Common name patterns like svc, adm, and others may give them away.

PS > dsquery user

finding users with dsquery

Find Computers

Computer objects reveal server names, DEV hosts, backups, SQL, EXCH, etc. This variety gives you potential vectors of compromise. Well-managed environments place servers in OUs, which can tell you where critical infrastructure lives and help you refine your scope quickly.

PS > dsquery computer

finding computers with dsquery

Find groups

Inspect groups like Domain Admins, Enterprise Admins, Backup Operators and other potentially valuable. They point you to high-value targets and to people who matter inside the organization.

PS > dsquery * "CN=Users,DC=DOMAIN,DC=LOCAL"

finding groups with dsquery

Password-not-required accounts

This searches for users with the PASSWORD_NOT_REQUIRED flag. It’s uncommon on privileged accounts, but every once in a while you’ll find legacy or misconfigured accounts that are worth investigating.

PS > dsquery * -filter "(&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=32))" -attr distinguishedName userAccountControl

finding password not required accounts with dsquery

An account that looks unprivileged at first can still own or be granted rights that make it a pivot to more interesting objects. Low-profile privilege pathways that are laterally exploitable. Tools like BloodHound help visualize those relationships if you’re collecting data to analyze later.

Domain Controllers

Knowing DC names and their IPs is important. They’re the gatekeepers. LDAP, Kerberos, and replication insights come from them, and they host the crown jewels of domain authentication.

PS > dsquery * -filter "(userAccountControl:1.2.840.113556.1.4.804:=8192)" -limit 5 -attr sAMAccountName

finding domain controllers with dsquery

User-related data

We won’t rehash registry or user history investigations here, since that has been covered in PowerShell for Hackers: Basics. This chapter is focused on directory and module-based recon. If you need detailed user-artifact techniques, refer back to that article.

Remote Command Execution With PowerShell

There are many ways to execute commands remotely. Some require installing third-party binaries, others use native capabilities. Malicious third-party tools are noisy and signatured, while native execution can be quieter. Here’s the canonical PowerShell remote execution pattern:

PS > Invoke-Command -ComputerName DC -ScriptBlock { hostname }

remote command execution with Invoke-Command of one command

You can also run several commands at once. Here is how you would import a module and run an AD query:

PS > Invoke-Command -ComputerName DC -ScriptBlock { Import-Module ActiveDirectory; Get-ADUser -Filter * }

remote command execution with Invoke-Command of multiple commands

Now you can run modules on remote hosts and pull back results without leaving large traces. 

Active Directory Modules and Documentation

Active Directory modules are incredibly convenient for both defenders and pentesters. They expose AD query and management commands  in a readable, scriptable way. Importing the module is a legitimate action, which makes it less suspicious. Many teams don’t actively monitor every module load. That said, module use is logged, and the patterns of use matter. If you import ActiveDirectory and immediately run a large enumeration from a workstation that never runs those commands, defenders may notice.

Imagine you’re on a physical pentest and you find a machine with PowerShell but no internet access. Memorizing every command helps, but there are too many across different operating systems to rely on memory alone. In this case, PowerShell’s built-in help and a module’s own documentation have your back. Microsoft provided a solid help system that you can learn from.

Available modules

List what’s on the system before importing anything:

PS > Get-Module -ListAvailable

listing available powershell modules

Check whether the Active Directory module is present:

PS > Get-Module ActiveDirectory

If it’s available, import it:

PS > Import-Module ActiveDirectory

checking if a powershell module is available and importing it

Once imported, list the commands available in the module. There are a lot. Don’t attempt to memorize them all, but focus on those that return identity, group, and computer information, and the ones that let you scope queries efficiently.

PS > Get-Command -Module ActiveDirectory

listing commands of a powershell module

Get-Help is one of the useful survival tools you’ll have when offline. It shows command syntax, parameters, examples, and deeper usage notes, right in the session you’re running. Two flags we commonly use are -Examples and -Full:

See examples:

PS > Get-Help Enable-ADAccount -Example

using get-help to get help on a command in powershell to show examples of use

See full documentation:

PS > Get-Help Enable-ADAccount -Full

using get-help to get help on a command in powershell to show full command info

Help can also be updated, when the computer is connected to the internet:

PS > Update-Help

Take some time to explore the other commands PowerShell has in the Active Directory module. Doing this will prepare you for the variety of environments you’ll encounter during your pentests.

Summary

PowerShell is both your tool and your guide. It lets you learn about the environment in the shell, as you can get information without relying on external resources. Tools like dsquery and the Active Directory module help you map users, computers, and groups. These built-in binaries let you work from the host itself, even without internet access, which is good for keeping a lower profile. Careful and targeted recon reduces the risk of detection. Although everything can be detected, it really depends where the defender is looking at. Normally, detecting every possible move a hacker can make is unreal. By using the tools the defenders and system administrators use for legitimate purposes, you blend in with the environment so well. 

In the next chapter we’ll cover how defenders spot suspicious activity and offer high-level recommendations for maintaining operational security and minimizing unnecessary noise.

The post PowerShell for Hackers – Survival Edition, Part 2: Advanced Recon first appeared on Hackers Arise.

❌
❌