I work with text files all the time. My friend Ron Bowes once told me that pen tests feel like 80% converting data from one format to another. I agree, and finishing up my first week of #monthofpowershell, I still feel lost when I can't reach for awk/grep/cut/sed/tr. Here's an example I needed to figure out:
PS /home/sec504> Get-Content ~/msolspray.txt Valid user, but invalid password : Ciel.Britch@falsimentis.com Valid user, but invalid password : Donovan.Lea@falsimentis.com Valid user, but invalid password : Fidelity.Passo@falsimentis.com Valid user, but invalid password : Irvine.Obbard@falsimentis.com Valid user, but invalid password : Jeremy.Lengthorn@falsimentis.com Valid user, but invalid password : Jillana.Walcott@falsimentis.com Valid user, but invalid password : Kala.Edwinson@falsimentis.com Valid user, but invalid password : Lukas.Dolman@falsimentis.com Valid user, but invalid password : Pembroke.Trouel@falsimentis.com Valid user, but invalid password : Rollins.Hows@falsimentis.com
I need to get the email address in a file by itself for use in subsequent password spray attacks. This is what I came up with:
PS /home/sec504> Get-Content /home/sec504/msolspray.txt | ForEach-Object { $elements = $_ -split ' '; $elements[6] } Ciel.Britch@falsimentis.com Donovan.Lea@falsimentis.com Fidelity.Passo@falsimentis.com Irvine.Obbard@falsimentis.com Jeremy.Lengthorn@falsimentis.com Jillana.Walcott@falsimentis.com Kala.Edwinson@falsimentis.com Lukas.Dolman@falsimentis.com Pembroke.Trouel@falsimentis.com Rollins.Hows@falsimentis.com
Let's break this command down step-by-step:
- Get-Content /home/sec504/msolspray.txt |: Retrieve the contents of the file shown above, start a pipeline
- ForEach-Object {: For each line in the file, execute the following code block
- \(elements = $_ -split ' ';: Create an array variable $elements that take the current line (\)_) and splits it into multiple pieces using a space (' ')
- $elements[6]: Retrieve the 7th element in the attack (6th element offset)
- }: End the loop
After proudly showing off my work I was admonished for the unnecessary creation of the $elements variable. This is a similar but more compact version that accomplishes the same task using the Grouping Operator code:
PS /home/sec504> Get-Content ~/msolspray.txt | ForEach-Object {($_ -split ' ')[6]}
Instead of declaring an array of elements by name, we create the array object by adding code around the split, accessing the 7th element of the array.
Note that tools like awk start counting elements at 1, while PowerShell and most other programming languages count elements starting at 0. When I was working this out, I admit I tried to access the 7th (nonexistent) array element, stuck in my awk ways. I will make that same mistake at least 8099 more times, in the near future.
This solution gets the job done, but it feels a little ... un-PowerShell-ey. The more I work with PowerShell, the more I realize it's more than a syntax shift from Bash and other shells, it's a conceptual shift as well. Instead of treating the file as text, I could opt to treat it as a PowerShell object instead using ConvertFrom-StringData:
S /home/sec504> Get-Content /home/sec504/msolspray.txt | ConvertFrom-StringData -Delimiter ':' Name Value ---- ----- Valid user, but invalid passw… Ciel.Britch@falsimentis.com Valid user, but invalid passw… Donovan.Lea@falsimentis.com Valid user, but invalid passw… Fidelity.Passo@falsimentis.com Valid user, but invalid passw… Irvine.Obbard@falsimentis.com Valid user, but invalid passw… Jeremy.Lengthorn@falsimentis.com Valid user, but invalid passw… Jillana.Walcott@falsimentis.com Valid user, but invalid passw… Kala.Edwinson@falsimentis.com Valid user, but invalid passw… Lukas.Dolman@falsimentis.com Valid user, but invalid passw… Pembroke.Trouel@falsimentis.com Valid user, but invalid passw… Rollins.Hows@falsimentis.com PS /home/sec504> Get-Content /home/sec504/msolspray.txt | ConvertFrom-StringData -Delimiter ':' | Select-Object -Property * Valid user, but invalid password -------------------------------- Ciel.Britch@falsimentis.com Donovan.Lea@falsimentis.com Fidelity.Passo@falsimentis.com Irvine.Obbard@falsimentis.com Jeremy.Lengthorn@falsimentis.com Jillana.Walcott@falsimentis.com Kala.Edwinson@falsimentis.com Lukas.Dolman@falsimentis.com Pembroke.Trouel@falsimentis.com Rollins.Hows@falsimentis.com
By specifying the delimiter : in the file, ConvertFrom-StringData converts each line into a PowerShell object, allowing me to retrieve the email addresses as an object property, instead of parsing the string output.
This also does feel quite-right, but it's time to get back to the pen test. In a future article I'll dig more into the ConvertFrom family of commands, and how we can use them to take structured and unstructured data, and convert it to standard PowerShell objects.
-Joshua Wright
Joshua Wright is the author of SANS SEC504: Hacker Tools, Techniques, and Incident Handling, a faculty fellow for the SANS Institute, and a senior technical director at Counter Hack.