Communauté PowerShell francophone, à vos calendriers

Une avalanche de bonnes nouvelles pour la rentrée, c’est pas génial ? : PowerShell open-source, dispo sur Linux et MacOS,…et la création du 1er FRPSUG pour pouvoir discuter PowerShell dans la langue de Molière😀

Plusieurs MVP francophones passionnés par PowerShell ont créé ce ‘User Group’ et vous proposent 1x par mois un RDV en ligne.

C’est gratuit et 100% virtuel (diffusé et enregistré sur YouTube) parce que notre répartition géographique est très loin de se limiter à l’hexagone. Je pense à nos amis québécois, belges, suisses etc. qui sont de la partie.

J’aime PowerShell et lis ces quelques lignes > je veux pas râter ça, que dois-je faire ?

Qu’est-ce qu’il y a au menu ?



… la suite sur:

PowerShell is all about the Community

PowerShell just reached a huge milestone since Jeffrey Snover wrote the Monad Manifesto more than 10 years ago.

PowerShell is now Open-source Software (OSS) under the MIT license and available on GitHub.

  • Why so excited about this?

We’ve been waiting for it for a long time. It was made possible since Microsoft also Open sourced .Net Core and refactored PowerShell to run on top of .Net Core (aka PowerShell Core and running in Nano server).

This means that it’s more and more mature and just started to become a cross-platform community-driven configuration and automation framework able to manage both API oriented operating system (Windows) and document oriented operating systems (Linux) from anywhere. It clearly aims at providing a consistent and sustainable experience for IT pros and developers for everybody.

  • What else does that mean?

Well, if it’s open sourced, it’s about the community. Microsoft embraced the heterogeneity of both the community and the ecosystem and allows its partners and any customer anybody to be successful.
You, actually anybody running on any operating system (Linux, Microsoft and MacOS) can use these ALPHA versions of PowerShell, submit issues and participate in its development.

Friday Fun: capture pokemon using PowerShell

A few years ago, I wrote a quick function to download all the pokemon pictures from for my kids to create the equivalent of the pokedex:


Beyond that, I don’t know anything about Pokemon, so don’t ask me anything about them😛

Due to the recent success of Pokémon Go, I thought that I should extend the function, make it more friendly, accessible,… and share it, of course😀

If you like Pokemon and PowerShell, this page is for you. You’ll discover, get to know Pokemon and have them all at your finger tips in your favorite console:

The first thing to do is to capture all the pictures from the main site:

The function aims to download all the files. You can launch it, interrupt it, relaunch it. It’ll restart where it left till the end. You’ve got to have at least 720 (the current total of pokemon) jpeg files in the Pokedex folder so that the other functions work.
The Build-Pokedex function will always end by displaying how many Pokemon exist.


Now, to use the Find-Pokemon and Show-Pokemon, it’s pretty straightforward


If you just pipe the two cmdlets together, the picture will be shown:

Find-Pokemon -Name Kyurem | Show-Pokemon 


If you use the -Online switch, the default browser should open the web page corresponding to the pokemon you looked for

Find-Pokemon -Name Kyurem | Show-Pokemon -Online


To discover a new Pokemon more randomly, you can do

0..720 | Get-Random | Find-Pokemon | Show-Pokemon -Online

Enjoy and have fun😎

post-exploitation: using PS 5.0 security settings to hide code execution

I’ve started playing with all the new security features introduced in PowerShell 5.0 – ScriptBlock Logging, Protected EventLog and Transcripts mentioned in the PowerShell ♥ the Blue Team post.

All the following assumes that the target machine has already been breached, that you already have admin credentials on the box. It does not take advantage of any vulnerability.

Here’s the context of the scenario, let’s assume that:

  • the target computer owned is a Windows 10 computer
  • you’ve admin credentials on that box
  • a group policy was set and at least configures both the scriptblock logging and protected eventlog (just in case there are credentials in the code): see for example my previous post

or let’s say

  • I’m a local admin of a Windows 10 computer
  • My domain admin set a GPO that configured all the new WMF 5.0 settings: transcript, scriptblock logging and protected eventlog
  • I don’t want him or anybody to look over my shoulder

The goal is to hide the execution of a command in plain sight without touching the disk even if there’s already a Group Policy that enables scriptblock logging, protected eventlog and transcription.

How? By

  • using another another public key created on the fly that replaces the GPO settings
  • turning off transcripts if they are on
  • restoring gracefully the initial GPO parameters that configure protected eventlogs and transcripts

The first part of code when running isn’t hidden, it makes a lot of noise and can be detected by usual means.

The code is available in the following gist/link

Let’s see it in action as a picture is worth a thousand words:



As you can see, I’ve added two switches to let transcription on and to export the public and private keys of the new certificate used on the fly. Without the two switches, it doesn’t touch the disk (well, forensically speaking it still does because the registry, certificate stores, eventlogs,… are modified).

If I don’t have the private key, I cannot decrypt the message in the protected eventlogs😦
But, if I import the private key left and use the code from my previous post, I can see:

As I left transcription on, I can also see:

It’s a nice convenient way to stop everybody watching what you do, isn’t it😉

Reading protected eventlogs

I’ve been working with many certificates (their private key) used to decrypt back the protected eventlogs (encrypted initially with their public key).

The good news is, you can add as many private keys as you want, they’ll be all be used along to decrypt protected messages. Microsoft did a pretty good job on the Unprotect-CmsMessage cmdlet.

Lee Holmes originally presented in the PowerShell ♥ the Blue Team post how to post-process the content of protected event log messages using the following command:

Get-WinEvent Microsoft-Windows-PowerShell/Operational |
Where-Object Id -eq 4104 | Unprotect-CmsMessage 

Get-WinEvent is a very powerful cmdlet but it doesn’t know of protected messages natively.
No problem, here’s the way to extend its ability to recognize and decrypt protected messages😀

First, I import the private keys into my Personal store like this

if (Test-Path -Path "$($HOME)\privatekey_*.pfx" -PathType Leaf) {
    Get-ChildItem -Path "$($HOME)\privatekey_*.pfx" | ForEach-Object {
        Import-PfxCertificate -FilePath "$($_.FullName)" -CertStoreLocation Cert:\currentuser\My -Password (ConvertTo-SecureString -AsPlainText '12345678' -Force)

The 2nd step consists in adding the isProtected and UnprotectedMessage properties on the fly and pass it to Out-GridView cmdlet at the end:

Everything looks normal…

Until,… Notice the second event, it’s encrypted, but I don’t have the private key loaded in my store to decrypt it. Its UnprotectedMessage property is empty.
That doesn’t sound good😉

Reading transcripts as an object

Transcription now built-in the PowerShell 5.0 engine is a great feature for watching over-the-shoulder what happens.

Unfortunately, it dumps everything into text files and PowerShell is all about objects.

Instead of just using grep (or Select-String cmdlet) and to ease forensics investigations by providing context, I wrote the following function:

Yeah, less than 200 lines😎 and tough job, here’s why:

  • The function has the ability to read a transcript file that is still active (the shell or host application didn’t exit yet).
  • It also reports when a shell (or host application) has been launched but nothing was typed-in.
  • Sometimes, there’s a new header block appended in the middle of the transcript file, usually when an error occurs as far as I can tell.
  • The function is able to parse both transcripts that have enabled “Invocation Header” or not.
  • Transcripts timestamp commands if you’ve enabled “Invocation Header” and it adds additional separators.

More info about the behavior of the above function:
-I didn’t transform the datetime data parsed from the text file into a real datetime object as I didn’t know if they are always in the yyyyMMddHHmmss format.
-If “Invocation Header” aren’t enabled the CommandStartTime property returned by the function is null.
-The CommandContext property is also null when a shell (or host application) has been launched but nothing was typed-in.
-The CommandContext property will contain one or many commands as well as their output

To see the function in action, you just do:

Get-ChildItem -Path C:\Transcripts -Include *.txt -Recurse | 
ForEach-Object {
    Get-TranscriptContent -FilePath $_.FullName -Verbose

You can even pipe the result into the Out-GridView cmdlet

Get-ChildItem -Path C:\Transcripts -Include *.txt -Recurse | 
ForEach-Object {
    Get-TranscriptContent -FilePath $_.FullName
} | Out-GridView


And you can search for whatever you want using the properties of each object sent through the pipeline:

Get-ChildItem -Path C:\Transcripts -Include *.txt -Recurse | 
ForEach-Object {
    Get-TranscriptContent -FilePath $_.FullName -Verbose
} | Where CommandContext -match "attack"


Compressing transcripts

I’ve been using PowerShell 5.0 transcripts and to save some space (2/3 actually), I’ve written the following code snippet to compress these files.

The compression ratio formula is taken from this Wikipedia page

$PSTranscripts is a string that points the location where my transcripts are stored (the same location set by GPO). It can be for example: C:\Transcripts

Now, we need the equivalent of bzgrep in the Windows world to be able to parse compressed files😉