You have a choice of several approaches. One is to create a custom Windows PowerShell launch command that includes the import-module command or calls a script that has a number of import-module commands (in addition to other environment setup options).
For example, the PowerShell launch below imports the Hyper-V module:
%windir%system32WindowsPowerShellv1.0powershell.exe -noexit -command import-module HyperV
The easiest way to create this shortcut is to copy the existing PowerShell launch shortcut, then edit the target command to include the import.
Try in Splunk Security Cloud
Description
- Type: TTP
Product: Splunk Enterprise, Splunk Enterprise Security, Splunk Cloud
- Last Updated: 2024-05-18
- Author: Michael Haag, Splunk
- ID: 85bc3f30-ca28-11eb-bd21-acde48001122
Annotations
ATT&CK
ATT&CK
ID | Technique | Tactic |
---|---|---|
T1059 | Command and Scripting Interpreter | Execution |
Kill Chain Phase
- Installation
NIST
- DE.CM
CIS20
- CIS 10
CVE
Search
1
2
3
4
5
`powershell` EventCode=4104 ScriptBlockText IN ("*[system.reflection.assembly]::load(*","*[reflection.assembly]*", "*reflection.assembly*")
| stats count min(_time) as firstTime max(_time) as lastTime by Opcode Computer UserID EventCode ScriptBlockText
| `security_content_ctime(firstTime)`
| `security_content_ctime(lastTime)`
| `powershell_loading_dotnet_into_memory_via_reflection_filter`
Macros
Required fields
List of fields required to use this analytic.
- _time
- ScriptBlockText
- Opcode
- Computer
- UserID
- EventCode
How To Implement
Known False Positives
False positives should be limited as day to day scripts do not use this method.
Associated Analytic Story
RBA
Risk Score | Impact | Confidence | Message |
---|---|---|---|
56.0 | 70 | 80 | A suspicious powershell script contains reflective class assembly command in $ScriptBlockText$ to load .net code in memory with EventCode $EventCode$ in host $Computer$ |
Reference
Test Dataset
Replay any dataset to Splunk Enterprise by using our replay.py
tool or the UI.
Alternatively you can replay a dataset into a Splunk Attack Range
Define your
class
es as part of your script’s root module (*.psm1
, referenced via theRootModule
module-manifest entry) instead of your current approach of using a*.ps1
file that is loaded into the caller’s scope via theScriptsToProcess
manifest entry.- In other words: you then won’t need a
ScriptsToProcess
entry (at least not for exporting yourclass
es andenum
s).
- In other words: you then won’t need a
The linked documentation notes (emphasis added):
Only the importer and its descendent scopes see the imported module’s
class
es (andenum
s).Because
using module
is a parse-time statement, the target module path must not contain variables, but modules discoverable via$env:PSModulePath
can be referenced by name only (e.g.using module MyModule
); relative paths are resolved against the caller’s own file-system location (rather than against the current directory).Once a module is imported with
using module
in a given session, it cannot be forcefully re-imported; that is, if you want to modify yourclass
and/orenum
definitions, you’ll need to start a new session to see the changes.
However, the Exporting classes with type accelerators section of the about_Classes help topic describes a workaround that makes classes of your choice available session-globally, in all scopes and runspaces, and also works with module auto-loading and
Import-Module
As with the
using module
-based approach, you won’t be able to reload modifiedclass
definitions in a given session – start a new session instead.Unlike with the
using module
-based approach (which you may still choose to combine with the suggested approach), the (possibly implicit) importer must not rely on theclass
es to be available at parse time, i.e. must not try to reference them via type literals inclass
definition of its own – see this answer for details.- While the type-accelerator approach technically allows you to place the
class
andenum
definitions in a nested module or a*.ps1
file dot-sourced from your root module, this is best avoided if you want your module to also support theusing module
importing technique for parse-time availability of the classes.
- While the type-accelerator approach technically allows you to place the
The linked help topic also includes event-based code for attempting to remove exported
class
definitions when the module is unloaded (Remove-Module
), however, this does not work (as of PowerShell 7.4.1), and has therefore been omitted in the code below.
Note that with either approach above, class
es and enum
s won’t be available until after your module has been imported into a given session.
That is, unlike functions and cmdlets in auto-loading modules, they aren’t discoverable prior to import.
Example *.psm1
root-module content:
# Since the quasi-exported class will be available *process-wide*
# and therefore also in *other runspaces*, be sure to define it with
# the [NoRunspaceAffinity()] attribute.
# Caveat: **v7.4+ only**
[NoRunspaceAffinity()]
class SomeClass { # Note: 'SomeClass' is both its .Name and .FullName.
[int] Get() { return 42 }
}
# Define the types to export with type accelerators.
# Note: Unlike the `using module` approach, this approach allows
# you to *selectively* export `class`es and `enum`s.
$exportableTypes = @(
[SomeClass]
)
# Get the non-public TypeAccelerators class for defining new accelerators.
$typeAcceleratorsClass = [psobject].Assembly.GetType('System.Management.Automation.TypeAccelerators')
# Add type accelerators for every exportable type.
$existingTypeAccelerators = $typeAcceleratorsClass::Get
foreach ($type in $exportableTypes) {
# !! $TypeAcceleratorsClass::Add() quietly ignores attempts to redefine existing
# !! accelerators with different target types, so we check explicitly.
$existing = $existingTypeAccelerators[$type.FullName]
if ($null -ne $existing -and $existing -ne $type) {
throw "Unable to register type accelerator [$($type.FullName)], because it is already defined with a different type ([$existing])."
}
$typeAcceleratorsClass::Add($type.FullName, $type)
}
KekMeh
- Posts: 6
- Joined: 01 Jan 2024 20:46
PowerShell appearing when the game is loading. [NOT A BUG]
I have a very strange problem with ETS2. A few days ago, when I wanted to play the game, an empty PowerShell window appeared and after about one sec, it disappeared. It’s still doing that. I thought that it’s the mods fault that I installed, so I uninstalled them and nothing changed. I also tried scanning my whole PC for viruses, nothing was found. I verified game files integrity, they’re fine. I reinstalled the game – still nothing. I deleted Euro Truck Simulator 2 folder from documents – nothing. I even tried formating all of my hard drives and reinstalling the OS (Windows 10 Pro), even that didn’t help. My friend who plays ETS2 with ProMods doesn’t experience anything like that and he never had something like this happening with his game. I also tried starting a new vanilla profile – it didn’t help. I want to know if it’s some kind of undetectable virus, or is it just a bug.
Madkine
- Global moderator
- Posts: 13630
- Joined: 08 Oct 2018 16:35
- Location: Australia
- Contact:
KekMeh
- Posts: 6
- Joined: 01 Jan 2024 20:46
Re: PowerShell appearing when the game is loading.
by KekMeh » 03 Jan 2024 05:20
Hi. Here’s my game.log and some missing info. My game runs on x64 Windows 10 Pro. Game version is 1.49.2.15s (64-bit) and there’s no updates available. The problem I described happens on every game launch when SCS logo stops spinning, if I skip the launching screen, PowerShell appears on profile selection screen. I don’t know what screenshot is needed for in such situation, but anyway, here it is: https://i.imgur.com/sibpSJ9.jpg (direct link, I couldn’t add it to this reply)
- Attachments
- game.log.txt
- (116.36 KiB) Downloaded 75 times
foddersin
- Posts: 4
- Joined: 03 Jan 2024 11:00
- Location: Gateshead, United Kingdom
- Contact:
Re: PowerShell appearing when the game is loading.
by foddersin » 03 Jan 2024 11:02
I have also began having this issue.
Game will minimise and a powershell window will open then close within seconds.
No output is given in the window to try and trace it though.
KekMeh
- Posts: 6
- Joined: 01 Jan 2024 20:46
Re: PowerShell appearing when the game is loading.
by KekMeh » 03 Jan 2024 13:04
foddersin wrote: ↑03 Jan 2024 11:02
Hi.I have also began having this issue.
Game will minimise and a powershell window will open then close within seconds.
No output is given in the window to try and trace it though.
Hi. That’s exactly what I’m facing. So, looks like it’s not only my problem.
KekMeh
- Posts: 6
- Joined: 01 Jan 2024 20:46
Madkine
- Global moderator
- Posts: 13630
- Joined: 08 Oct 2018 16:35
- Location: Australia
- Contact:
Re: PowerShell appearing when the game is loading.
by Madkine » 04 Jan 2024 20:30
At best the response you will get here is a bug no.
And at the moment there are only 2 of you reporting seeing this, so the testers may not be able to replicate this.
I personally still suspect its something specific on your machines that is the issue, not the game itself.
foddersin
- Posts: 4
- Joined: 03 Jan 2024 11:00
- Location: Gateshead, United Kingdom
- Contact:
Re: PowerShell appearing when the game is loading.
by foddersin » 06 Jan 2024 01:07
Just posting an update.
I have located the source of my issue and resolved.
Event Viewer > Applications and Service Logs > Windows PowerShell and within a minute of starting the game, I would get several similar entries such as:
Engine state is changed from None to Available.
HostName=ConsoleHost
HostVersion=5.1.22621.2506
HostId=12a0bd37-cfc6-476d-a13e-36054d40da58
HostApplication=powershell (Get-AppxPackage ASUSAmbientHal64).Version
EngineVersion=5.1.22621.2506
RunspaceId=321beca4-21b4-493e-b584-464a13057160
PipelineId=
CommandName=
CommandType=
ScriptName=
CommandPath=
CommandLine=
Uninstalling ASUS Armory Crate using their Uninstall Tool from their support site has stopped the issue from launching the game now, no window popping up.
Hope this help the Op or anyone else having this issue.
Who is online
Progress Bar GUI in PowerShell
For GUI-based progress bars, the Windows.Forms.ProgressBar .NET control can be used.
Here is a sample script:
Add-Type -AssemblyName System.Windows.Forms $progressForm = New-Object System.Windows.Forms.Form $progressForm.Width = 300 $progressForm.Height = 150 $progressForm.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedSingle $progressForm.Text = "Processing data..." $progressBar = New-Object System.Windows.Forms.ProgressBar $progressBar.Location = New-Object System.Drawing.Point(10, 50) $progressBar.Size = New-Object System.Drawing.Size(280, 20) $progressForm.Controls.Add($progressBar) $progressLabel = New-Object System.Windows.Forms.Label $progressLabel.Location = New-Object System.Drawing.Point(10, 20) $progressLabel.Size = New-Object System.Drawing.Size(280, 20) $progressLabel.Text = "0% Complete" $progressLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter $progressForm.Controls.Add($progressLabel) $progressForm.Show() $data = 1..100 $index = 1 # Loop through the data and update the progress bar foreach ($item in $data) { # Perform some operation on $item # Update the progress bar $progressPercent = ($index / $data.Count) * 100 $progressBar.Value = $progressPercent $progressLabel.Text = "$progressPercent% Complete" Start-Sleep -Milliseconds 100 $index++ } $progressForm.Close()
This creates a configurable progress bar by setting properties like minimum, maximum, and step values. The control can then be updated by incrementing $ProgressBar.Value
in your script.
Best practices for using progress bars in PowerShell
- Only use a progress bar when necessary: While progress bars can be helpful, they can also slow down your script if overused. Only use a progress bar when necessary. If a task finishes instantly or in a very short time frame, showing a progress bar might be unnecessary and even counterproductive, as it could flash on and off too quickly for the user to see.
- Update the progress bar frequently: Update the progress bar frequently to provide real-time feedback to the user. This will ensure that the user knows that the script is running and making progress.
- Use clear and concise status messages: Use the -Activity and -Status parameters to provide clear and concise information about what’s happening. Use the -CurrentOperation parameter to offer additional context, especially if it helps users understand the current task.
- Calculate Percentages Correctly: Ensure that your -PercentComplete value is accurately calculated. It should range from 0 to 100, representing the completion percentage.
- Use Nested Progress Bars for Multi-Level Tasks: If your script has tasks within tasks (like copying multiple folders where each folder has multiple files), use parent-child progress bars. Use the -Id and -ParentId parameters to manage and display nested progress bars correctly.
- Complete the Progress Bar: Use the -Completed switch to signal the end of the task, ensuring that the progress bar disappears or indicates completion. Also, Show progress at 0% before the operation starts.
- Test your script with large data sets: Test your script with large data sets to ensure that the progress bar is working properly and that it doesn’t slow down your script.
Using Progress Bar with Multiple Operations
For extensive scripts involving multiple operations, you can segment the progress bar:
Write-Progress -Activity "Main Task" -Status "Task 1 of 3" -PercentComplete 33 # Task 1 logic Start-Sleep -Seconds 1 Write-Progress -Activity "Main Task" -Status "Task 2 of 3" -PercentComplete 66 # Task 2 logic Start-Sleep -Seconds 1 Write-Progress -Activity "Main Task" -Status "Task 3 of 3" -PercentComplete 100 # Task 3 logic Start-Sleep -Seconds 1
Troubleshooting common issues with progress bars in PowerShell
While using a progress bar in PowerShell is relatively straightforward, there are a few common issues that you may encounter. Here are a few tips for troubleshooting these issues:
1. The progress bar not updating
If the progress bar is not updating, ensure you update it frequently enough. Check your -PercentComplete calculation. Ensure that it’s updating as expected within the loop or process. For loops that process items quickly, consider adding a small delay with Start-Sleep for visual clarity.
If you are updating it frequently, and it still isn’t working, try running your script in a new PowerShell window.
2. Progress bar not displaying
If the progress bar is not displaying, ensure you start it with the Write-Progress cmdlet. If you are starting it with the Write-Progress cmdlet and it still isn’t working, ensure your loop or process is not finishing too quickly. The progress bar may not appear for very fast tasks.
3. Progress bar slowing down your script
4. Error: “Write-Progress : Cannot validate argument on parameter ‘PercentComplete’.
“The 110 is greater than the maximum allowed range of 100.”
- Cause: The value for ‘PercentComplete’ parameter exceeds the maximum limit of 100.
- Solution: Ensure the ‘PercentComplete’ parameter is within the range of 0 to 100.
Here is the Official Microsoft Documentation reference for Write-Progress cmdlet!
Understanding the Write-Progress cmdlet in PowerShell
Write-Progress is a cmdlet in PowerShell that allows you to display a progress bar in the console. It has several parameters that allow you to customize the appearance of the progress bar, including the percentage complete, the status message, and the activity name. Here are the parameters that you can use with Write-Progress:
Basic Write-Progress syntax looks like:
Write-Progress [-Activity] <String> [[-Status] <String>] [-PercentComplete <Int32>] [-SecondsRemaining <Int32>] [-Id <Int32>] [-ParentId <Int32>] [-Completed] [-SourceId <Int32>] [-CurrentOperation <String>] [<CommonParameters>]
Here are the important parameters of the Write-Progress cmdlet:
Parameter | Description |
---|---|
Activity | The Activity parameter Specifies the title of the progress bar. This will appear as the first line of text. |
Status | This helps to display the current state of the activity or status of a running command in the status bar of the progress bar |
PercentComplete | 0 to 100 percent done |
SecondsRemaining | Countdown timer |
Id | Unique ID to update specific bar |
ParentId | Group child progress bars |
Write-Progres Example
- Use the
Write-Progress
cmdlet to create a new progress bar. - Specify the parameters, such as
-Activity
,-Status
,-PercentComplete
,-SecondsRemaining
, and-CurrentOperation
to customize the progress bar. - Update the progress bar periodically using the
Write-Progress
cmdlet with updated values for-PercentComplete
. - When the task is complete, use the
Complete
parameter to finish the progress bar.
To continually update the progress bar, we must place Write-Progress calls at certain points within your script’s logic, incrementing the PercentComplete each time. Here’s an example of a PowerShell script that uses the Write-Progress cmdlet to display a progress bar:
$Collection = 1..100 ForEach ($Item in $Collection) { Write-Progress -PercentComplete ($Item/100*100) -Status "Processing Items" -Activity "Item $item of 100" # Your actual script logic here Start-Sleep -Milliseconds 50 }
And here is what it looks like in PowerShell ISE:
Using Write-Progress in PowerShell is relatively straightforward. Here’s a step-by-step guide on how to use it:
Step 1: Define the variables
The first step is to define the variable or collection that you will be using in your script. These variables will have the collection of data set you’ll be processing.
Step 2: Start the progress bar and Perform Operation
The next step is to start the progress bar using the Write-Progress cmdlet and perform your target operation. You will need to specify the activity name and the status message.
Step 3: Update the progress bar
A common way to use Write-Progress is within a For loop in your script.
For($i=1; $i -le 100; $i++){ Write-Progress -Activity "Processing Files" -Status "$i% Complete" -PercentComplete $i # Perform loop action sleep -Milliseconds 100 }
This will iterate from 1 to 100, updating the progress bar each time with the current percent complete. You can update the status message to provide more context on which loop iteration is running.
Step 4: Complete the progress bar
Once your script has finished running, you have to complete the progress bar using the Write-Progress cmdlet. This will ensure that the progress bar is removed from the console.
Practical Examples of Write-Progress in PowerShell
Let’s take a look at some examples of how to use Write-Progress in PowerShell:
Example 1: Copy Files with Progress Bar
In this example, we are using Write-Progress to display the progress of a script that is copying files from one location to another.
$Files = Get-ChildItem -Path "C:\Source" $Destination = "C:\Destination" $TotalFiles = $Files.Count $Count = 0 Write-Progress -Activity "Copying Files" -Status "Starting" -PercentComplete 0 foreach ($File in $Files) { $Count++ $PercentComplete = (($Count / $TotalFiles) * 100) $Status = "Copying $($File.Name)" Write-Progress -Activity "Copying Files" -Status $Status -PercentComplete $PercentComplete Copy-Item $File.FullName $Destination -Force } Write-Progress -Activity "Copying Files" -Status "Complete" -PercentComplete 100
Example 2: Download Files with Progress Bar
In this example, we are using Write-Progress to display the progress of a script that downloads files from the internet.
$Urls = @( "https://www.microsoft.com/downloads/SharePointSP1.msi", "https://www.microsoft.com/downloads/SharePointSP2.msi", "https://www.microsoft.com/downloads/SharePointSP3.msi" ) # Destination folder $destinationFolder = "C:\Downloads" # Ensure the destination folder exists if (-not (Test-Path $destinationFolder)) { New-Item -Path $destinationFolder -ItemType Directory } # Download each file $totalUrls = $urls.Count for ($i=0; $i -lt $totalUrls; $i++) { $url = $urls[$i] $fileName = [System.IO.Path]::GetFileName($url) # Extract file name from URL $destinationPath = Join-Path -Path $destinationFolder -ChildPath $fileName # Display main progress Write-Progress -Activity "Downloading files" -Status ("Downloading " + $fileName) -PercentComplete (($i / $totalUrls) * 100) # Download file with sub-progress bar for individual file download Invoke-WebRequest -Uri $url -OutFile $destinationPath -Verbose } Write-Progress -Activity "Downloading files" -Completed -Status "All files downloaded!" Write-Host "All files downloaded successfully!" -ForegroundColor Green
Benefits of using a progress bar in PowerShell
1. Real-time Visual feedback
2. Time estimation to Track progress
A progress bar can also provide an estimate of how long your script will take to complete. This estimate can be incredibly helpful, especially when running scripts that take a long time to complete. It allows you to plan your time accordingly and ensures that you don’t waste time waiting for your script to finish.
3. Improved user experience
Progress Bar with Countdown Timer
To show a countdown timer in the progress bar, use the SecondsRemaining
parameter:
Write-Progress -Activity "Installing" -Status "Time Remaining" -SecondsRemaining $timeLeft
As $timeLeft decreases, the progress bar will visually count down the estimated time left. Here is a real-time example:
$progressParams = @{ Activity = "Processing data" Status = "In progress" PercentComplete = 0 SecondsRemaining = 60 CurrentOperation = "Initializing" } Write-Progress @progressParams $data = 1..10000 $index = 1 # Start the countdown timer $timer = [Diagnostics.Stopwatch]::StartNew() # Loop through the data and update the progress bar foreach ($item in $data) { # Perform some operation on $item # Update the progress bar $progressParams.PercentComplete = ($index / $data.Count) * 100 $progressParams.CurrentOperation = "Processing item $index of $($data.Count)" $progressParams.SecondsRemaining = (($timer.Elapsed.TotalSeconds / $index) * ($data.Count - $index)).ToString("F0") Write-Progress @progressParams $index++ } # Complete the progress bar Write-Progress -Completed -Activity "Completed"
Here is what it looks like in PowerShell ISE:
Here are a few more examples of Count down timers using the PowerShell Write-Progress cmdlet:
Function Start-Countdown { param ( [Parameter(Mandatory=$true)] [int]$Seconds ) # Countdown start time $StartTime = Get-Date $ElapsedTime =0 # While there are still seconds left While ($ElapsedTime -lt $seconds) { # Calculate elapsed time $ElapsedTime = [math]::Round(((Get-Date) - $StartTime).TotalSeconds,0) # Update the progress bar Write-Progress -Activity "Counting down..." -Status ("Time left: " + ($Seconds - $ElapsedTime) + " seconds") -PercentComplete (($elapsedTime / $Seconds) * 100) #$Seconds = $Seconds - $elapsedTime # Wait for a second Start-Sleep -Seconds 1 } # Once countdown is complete, close the progress bar Write-Progress -Activity "Counting down..." -Completed } # Call the function to start a 10-second countdown Start-Countdown -Seconds 10
Here is another example of how to show the Progress Bar in While Loop:
# Set total time for countdown timer $timeRemaining = 20 while($timeRemaining -gt 0){ # Calculate percentage $percentComplete = (($timeRemaining / 60) * 100) # Update progress bar Write-Progress -Activity "Deployment in progress" -Status "Time remaining: $timeRemaining seconds" -PercentComplete $percentComplete -SecondsRemaining $timeRemaining # Decrement timer $timeRemaining-- # Wait 1 second Start-Sleep -Seconds 1 }
Using progress bars in PowerShell ForEach loops
Using a progress bar in a foreach loop can be incredibly helpful, especially when iterating over a large number of items. Here’s an example of how to use a progress bar in a foreach loop:
$Items = 1..10000 Write-Progress -Activity "Processing Items" -Status "Starting" -PercentComplete 0 foreach ($Item in $Items) { $PercentComplete = (($Item / $Items.Count) * 100) $Status = "Processing Item $($Item)" Write-Progress -Activity "Processing Items" -Status $Status -PercentComplete $PercentComplete # Do some processing } Write-Progress -Activity "Processing Items" -Status "Complete" -PercentComplete 100
Nested (Parent-Child) Progress Bars for multi-level Operations
Parent-child progress bars are especially useful when you have a multi-level process. Here’s an example of a parent-child progress bar using Write-Progress. Let’s consider you’re processing multiple files, and for each file, you have several tasks to complete:
# Parent loop - processing files 1..5 | ForEach-Object { $fileNumber = $_ # Parent progress Write-Progress -Activity "Processing Files" -Status "File $fileNumber of 5" -PercentComplete (($fileNumber / 5) * 100) -id 0 # Simulate some file-specific tasks in a child loop 1..10 | ForEach-Object { $taskNumber = $_ # Child progress (nested within the parent) Write-Progress -Activity "Performing Task on File $fileNumber" -Status "Task $taskNumber of 10" -PercentComplete (($taskNumber / 10) * 100) -ParentId 0 # Simulating time taken for each task with sleep Start-Sleep -Milliseconds 100 } } # Completing the parent progress bar Write-Progress -Activity "Processing Files" -Completed -Status "All files processed!"
The -ParentId parameter in Write-Progress for the child progress bar tells PowerShell that this progress bar is a child of another progress bar. The ID 0 typically refers to the most recent parent Write-Progress bar. Output:
When you run the above script, you’ll see a top-level progress bar for file processing and a nested progress bar for tasks on each file.
Conclusion and final thoughts
What is a PowerShell progress bar?
Why would I use a Progress Bar in PowerShell?
How can I add a progress bar to my PowerShell script?
Is it possible to display multiple progress bars at once?
PowerShell supports nested progress bars, allowing you to display a parent progress bar and one or more child progress bars simultaneously.
How do I update the progress bar during a loop?
Inside a loop, you can update the progress bar by calling Write-Progress
with updated values for -PercentComplete
and other parameters at each iteration.
How do I remove the progress bar once the operation is complete?
The progress bar will automatically disappear once the script is completed. You can also manually remove it by calling Write-Progress
with the -Completed
parameter. For example: Write-Progress -Activity "Processing" -Status "Completed" -Completed