lolbins.psm1
$lolbinData = Invoke-RestMethod "https://lolbas-project.github.io/api/lolbas.json" ############################################################################### # 1) Test-LOLBinPaths ############################################################################### function Test-LOLBinPaths { <# .SYNOPSIS Tests each LOLBin's known file paths to see which ones exist on the system. .DESCRIPTION Loops through $lolbinData (which must already be loaded) and verifies whether each listed path exists. Returns a filtered LOLBin object containing only the valid paths. .EXAMPLE Test-LOLBinPaths #> [CmdletBinding()] param() if (-not $lolbinData) { Write-Warning "LOLBin data not loaded. Please run Update-LOLBinData first or ensure $lolbinData is populated." return } $foundBins = @() foreach ($bin in $lolbinData) { $validPaths = @() if ($bin.Full_Path) { foreach ($pathEntry in $bin.Full_Path) { $path = $pathEntry.Path if (Test-Path $path) { $validPaths += @{ Path = $path } } } } if ($validPaths.Count -gt 0) { $filteredBin = $bin.PSObject.Copy() $filteredBin.Full_Path = $validPaths $foundBins += $filteredBin } } return $foundBins } ############################################################################### # 2) Update-LOLBinData ############################################################################### function Update-LOLBinData { <# .SYNOPSIS Refreshes $lolbinData from the LOLBAS API endpoint. .DESCRIPTION By default, downloads the JSON from the LOLBAS GitHub endpoint (https://lolbas-project.github.io/api/lolbas.json) and updates the $lolbinData variable in the current session. You can override the URL if the API changes or you have a local mirror. .EXAMPLE Update-LOLBinData # Then confirm: $lolbinData.Count #> [CmdletBinding()] param( [Parameter(ValueFromPipelineByPropertyName=$true)] [string] $Url = "https://lolbas-project.github.io/api/lolbas.json" ) try { Write-Verbose "Downloading LOLBAS data from: $Url" $global:lolbinData = Invoke-RestMethod -Uri $Url Write-Host "LOLBin data successfully updated from $Url. Total items: $($global:lolbinData.Count)" } catch { Write-Warning "Failed to update data from $Url. Error: $_" } } ############################################################################### # 3) Get-LOLBinSummary ############################################################################### function Get-LOLBinSummary { <# .SYNOPSIS Provides a concise overview of LOLBins (Name, Description, Author, etc.). .DESCRIPTION Returns core properties of a single LOLBin if -Name is specified, or of all LOLBins if not. This is a quick way to see top-level info without drilling into commands or detection details. .EXAMPLE Get-LOLBinSummary -Name "AddinUtil.exe" .EXAMPLE Get-LOLBinSummary #> [CmdletBinding()] param( [Parameter(ValueFromPipelineByPropertyName=$true)] [string] $Name ) if (-not $lolbinData) { Write-Warning "LOLBin data not loaded. Please run Update-LOLBinData first." return } $filtered = if ($Name) { $lolbinData | Where-Object { $_.Name -eq $Name } } else { $lolbinData } $filtered | ForEach-Object { [PSCustomObject]@{ Name = $_.Name Description = $_.Description Author = $_.Author Created = $_.Created Categories = ($_.Commands.Category | Sort-Object -Unique) -join ", " Privileges = ($_.Commands.Privileges | Sort-Object -Unique) -join ", " OS = ($_.Commands.OperatingSystem | Sort-Object -Unique) -join ", " } } } ############################################################################### # 4) Get-LOLBinByName ############################################################################### function Get-LOLBinByName { <# .SYNOPSIS Retrieves the raw JSON object for a specific LOLBin by Name. .DESCRIPTION Matches a LOLBin by its Name property and returns the entire JSON object, including Commands, Detection, Resources, etc. .EXAMPLE Get-LOLBinByName -Name "Certutil.exe" #> [CmdletBinding()] param( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $Name ) if (-not $lolbinData) { Write-Warning "LOLBin data not loaded." return } $lolbinData | Where-Object { $_.Name -eq $Name } } ############################################################################### # 5) Get-LOLBinUsage ############################################################################### function Get-LOLBinUsage { <# .SYNOPSIS Shows all commands and usage info for the specified LOLBin. .DESCRIPTION Each LOLBin can contain multiple command entries (in .Commands). This function returns them in a more detailed, readable format. .EXAMPLE Get-LOLBinUsage -Name "Bitsadmin.exe" #> [CmdletBinding()] param( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $Name ) if (-not $lolbinData) { Write-Warning "LOLBin data not loaded." return } $bin = $lolbinData | Where-Object { $_.Name -eq $Name } if (-not $bin) { Write-Warning "LOLBin '$Name' not found." return } return $bin.Commands | Select-Object Command, Description, Usecase, Category, Privileges, MitreID, OperatingSystem } ############################################################################### # 6) Search-LOLBin ############################################################################### function Search-LOLBin { <# .SYNOPSIS Searches LOLBins by a keyword across multiple fields. .DESCRIPTION Searches for a given keyword within each LOLBin's Description, Commands.Command text, or other optional fields if -Extended is specified. Returns matching LOLBins. .EXAMPLE Search-LOLBin -Keyword "proxy" #> [CmdletBinding()] param( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $Keyword, [switch] $Extended ) if (-not $lolbinData) { Write-Warning "LOLBin data not loaded." return } $keywordRegex = [Regex]::Escape($Keyword) # Basic search in Description or Command $results = $lolbinData | Where-Object { ($_.Description -match $keywordRegex) -or ($_.Commands.Command -match $keywordRegex) } # Optionally include advanced fields if ($Extended) { $results += $lolbinData | Where-Object { ($_.Commands.Usecase -match $keywordRegex) -or ($_.Commands.Category -match $keywordRegex) -or ($_.Commands.Tags -match $keywordRegex) } $results = $results | Sort-Object -Unique } return $results } ############################################################################### # 7) Find-LOLBinByMitreID ############################################################################### function Find-LOLBinByMitreID { <# .SYNOPSIS Finds LOLBins that reference a given MITRE ATT&CK ID in their Commands. .DESCRIPTION Checks each LOLBin's Commands array for a match in the .MitreID property. .EXAMPLE Find-LOLBinByMitreID -MitreID "T1218" #> [CmdletBinding()] param( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $MitreID ) if (-not $lolbinData) { Write-Warning "LOLBin data not loaded." return } $lolbinData | Where-Object { $_.Commands.MitreID -contains $MitreID } } ############################################################################### # 8) Find-LOLBinByTag ############################################################################### function Find-LOLBinByTag { <# .SYNOPSIS Finds LOLBins whose Commands array has a given Tag entry. .DESCRIPTION Some LOLBins have "Tags" for certain usage (e.g. "Download", "AWL Bypass"). This function returns all LOLBins that have a matching Tag anywhere in their Commands[].Tags[] array. .EXAMPLE Find-LOLBinByTag -Tag "Download" #> [CmdletBinding()] param( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $Tag ) if (-not $lolbinData) { Write-Warning "LOLBin data not loaded." return } $lolbinData | Where-Object { # Check if Commands[].Tags[] exist AND if any of them contain $Tag $_.Commands.Tags -and ( $_.Commands.Tags | Where-Object { $_.PSObject.Properties.Value -contains $Tag } ) } } ############################################################################### # 9) Get-LOLBinCategory ############################################################################### function Get-LOLBinCategory { <# .SYNOPSIS Lists all distinct categories if no parameter is specified, or returns LOLBins in a specific category if -Category is given. .DESCRIPTION Each LOLBin can have one or more categories in its Commands[].Category property. This function either returns the distinct category names or the LOLBins that match a specific category. .EXAMPLE # Get all unique category names Get-LOLBinCategory .EXAMPLE # Get all LOLBins in "Execute" category Get-LOLBinCategory -Category "Execute" #> [CmdletBinding()] param( [string] $Category ) if (-not $lolbinData) { Write-Warning "LOLBin data not loaded." return } if (-not $Category) { # Return all distinct categories across all Commands $allCats = $lolbinData.Commands.Category | Where-Object { $_ } | Sort-Object -Unique return $allCats } else { # Return LOLBins that contain the specified category return $lolbinData | Where-Object { $_.Commands.Category -contains $Category } } } ############################################################################### # 10) Get-LOLBinDetection ############################################################################### function Get-LOLBinDetection { <# .SYNOPSIS Returns detection-related info (Sigma, Splunk, Elastic, IOCs, etc.) for a given LOLBin. .DESCRIPTION Some LOLBins have an array of detection references in .Detection. This function displays them in a structured way. .EXAMPLE Get-LOLBinDetection -Name "AddinUtil.exe" #> [CmdletBinding()] param( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $Name ) if (-not $lolbinData) { Write-Warning "LOLBin data not loaded." return } $bin = $lolbinData | Where-Object { $_.Name -eq $Name } if (-not $bin) { Write-Warning "LOLBin '$Name' not found." return } # Return the raw detection objects, or flatten if needed $bin.Detection } |